From 6225a16a071c8636e9f6257183bb501479ad23c2 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sun, 3 Jan 2016 16:05:02 +1100 Subject: atari_scsi: Fix SCSI host ID setting The NVRAM location of this byte is 16, as documented in http://toshyp.atari.org/en/004009.html This was confirmed by Michael Schmitz, by setting the SCSI host ID under EmuTOS and then checking the value in /proc/driver/nvram and /dev/nvram under Linux. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Michael Schmitz Signed-off-by: Martin K. Petersen --- drivers/scsi/atari_scsi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/atari_scsi.c b/drivers/scsi/atari_scsi.c index 5ede3daa93dc..1852ed6e8a48 100644 --- a/drivers/scsi/atari_scsi.c +++ b/drivers/scsi/atari_scsi.c @@ -880,7 +880,7 @@ static int __init atari_scsi_probe(struct platform_device *pdev) } else { /* Test if a host id is set in the NVRam */ if (ATARIHW_PRESENT(TT_CLK) && nvram_check_checksum()) { - unsigned char b = nvram_read_byte(14); + unsigned char b = nvram_read_byte(16); /* Arbitration enabled? (for TOS) * If yes, use configured host ID -- cgit From d5f7e65df0d41982b1e9cbba9df04003ebb2178d Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sun, 3 Jan 2016 16:05:03 +1100 Subject: ncr5380: Remove redundant static variable initializers Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Ondrej Zary Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.c | 2 +- drivers/scsi/dtc.c | 4 ++-- drivers/scsi/g_NCR5380.c | 4 ++-- drivers/scsi/pas16.c | 10 +++++----- drivers/scsi/sun3_scsi.c | 8 ++++---- drivers/scsi/t128.c | 4 ++-- 6 files changed, 16 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index a777e5c412df..ed8346fcd516 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -534,7 +534,7 @@ static void NCR5380_set_timer(struct NCR5380_hostdata *hostdata, unsigned long t } -static int probe_irq __initdata = 0; +static int probe_irq __initdata; /** * probe_intr - helper for IRQ autoprobe diff --git a/drivers/scsi/dtc.c b/drivers/scsi/dtc.c index 4c74c7ba2dff..99164d60df13 100644 --- a/drivers/scsi/dtc.c +++ b/drivers/scsi/dtc.c @@ -150,7 +150,7 @@ static const struct signature { static int __init dtc_setup(char *str) { - static int commandline_current = 0; + static int commandline_current; int i; int ints[10]; @@ -188,7 +188,7 @@ __setup("dtc=", dtc_setup); static int __init dtc_detect(struct scsi_host_template * tpnt) { - static int current_override = 0, current_base = 0; + static int current_override, current_base; struct Scsi_Host *instance; unsigned int addr; void __iomem *base; diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c index f8d2478b11cc..c2507475518e 100644 --- a/drivers/scsi/g_NCR5380.c +++ b/drivers/scsi/g_NCR5380.c @@ -121,7 +121,7 @@ static struct override { static void __init internal_setup(int board, char *str, int *ints) { - static int commandline_current = 0; + static int commandline_current; switch (board) { case BOARD_NCR5380: if (ints[0] != 2 && ints[0] != 3) { @@ -251,7 +251,7 @@ static int __init do_DTC3181E_setup(char *str) static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt) { - static int current_override = 0; + static int current_override; int count; unsigned int *ports; #ifndef SCSI_G_NCR5380_MEM diff --git a/drivers/scsi/pas16.c b/drivers/scsi/pas16.c index e81eadd08afc..1549bc97777e 100644 --- a/drivers/scsi/pas16.c +++ b/drivers/scsi/pas16.c @@ -87,8 +87,8 @@ #include "NCR5380.h" -static unsigned short pas16_addr = 0; -static int pas16_irq = 0; +static unsigned short pas16_addr; +static int pas16_irq; static const int scsi_irq_translate[] = @@ -305,7 +305,7 @@ static int __init static int __init pas16_setup(char *str) { - static int commandline_current = 0; + static int commandline_current; int i; int ints[10]; @@ -344,8 +344,8 @@ __setup("pas16=", pas16_setup); static int __init pas16_detect(struct scsi_host_template *tpnt) { - static int current_override = 0; - static unsigned short current_base = 0; + static int current_override; + static unsigned short current_base; struct Scsi_Host *instance; unsigned short io_port; int count; diff --git a/drivers/scsi/sun3_scsi.c b/drivers/scsi/sun3_scsi.c index 22a42836d193..836f5ca6d209 100644 --- a/drivers/scsi/sun3_scsi.c +++ b/drivers/scsi/sun3_scsi.c @@ -100,10 +100,10 @@ static struct scsi_cmnd *sun3_dma_setup_done; static unsigned char *sun3_scsi_regp; static volatile struct sun3_dma_regs *dregs; static struct sun3_udc_regs *udc_regs; -static unsigned char *sun3_dma_orig_addr = NULL; -static unsigned long sun3_dma_orig_count = 0; -static int sun3_dma_active = 0; -static unsigned long last_residual = 0; +static unsigned char *sun3_dma_orig_addr; +static unsigned long sun3_dma_orig_count; +static int sun3_dma_active; +static unsigned long last_residual; static struct Scsi_Host *default_instance; /* diff --git a/drivers/scsi/t128.c b/drivers/scsi/t128.c index 87828acbf7c6..eb7fae277fc6 100644 --- a/drivers/scsi/t128.c +++ b/drivers/scsi/t128.c @@ -126,7 +126,7 @@ static struct signature { static int __init t128_setup(char *str) { - static int commandline_current = 0; + static int commandline_current; int i; int ints[10]; @@ -165,7 +165,7 @@ __setup("t128=", t128_setup); static int __init t128_detect(struct scsi_host_template *tpnt) { - static int current_override = 0, current_base = 0; + static int current_override, current_base; struct Scsi_Host *instance; unsigned long base; void __iomem *p; -- cgit From 2f7dba9f7d8f8ece8f224bf26e9b2a06da2ed15c Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sun, 3 Jan 2016 16:05:04 +1100 Subject: ncr5380: Eliminate PDEBUG*, TDEBUG* and DTCDEBUG* macros Replace {P,T,DTC}DEBUG_INIT with NDEBUG_INIT. Remove dead debugging code, including code that's conditional upon *DEBUG_TRANSFER. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/dtc.c | 18 ++++++------------ drivers/scsi/dtc.h | 27 --------------------------- drivers/scsi/pas16.c | 21 +++++++-------------- drivers/scsi/pas16.h | 16 ---------------- drivers/scsi/t128.c | 18 ++++++------------ drivers/scsi/t128.h | 16 ---------------- 6 files changed, 19 insertions(+), 97 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/dtc.c b/drivers/scsi/dtc.c index 99164d60df13..38325f979b90 100644 --- a/drivers/scsi/dtc.c +++ b/drivers/scsi/dtc.c @@ -205,9 +205,8 @@ static int __init dtc_detect(struct scsi_host_template * tpnt) addr = 0; } else for (; !addr && (current_base < NO_BASES); ++current_base) { -#if (DTCDEBUG & DTCDEBUG_INIT) - printk(KERN_DEBUG "scsi-dtc : probing address %08x\n", bases[current_base].address); -#endif + dprintk(NDEBUG_INIT, "dtc: probing address 0x%08x\n", + (unsigned int)bases[current_base].address); if (bases[current_base].noauto) continue; base = ioremap(bases[current_base].address, 0x2000); @@ -216,18 +215,14 @@ static int __init dtc_detect(struct scsi_host_template * tpnt) for (sig = 0; sig < NO_SIGNATURES; ++sig) { if (check_signature(base + signatures[sig].offset, signatures[sig].string, strlen(signatures[sig].string))) { addr = bases[current_base].address; -#if (DTCDEBUG & DTCDEBUG_INIT) - printk(KERN_DEBUG "scsi-dtc : detected board.\n"); -#endif + dprintk(NDEBUG_INIT, "dtc: detected board\n"); goto found; } } iounmap(base); } -#if defined(DTCDEBUG) && (DTCDEBUG & DTCDEBUG_INIT) - printk(KERN_DEBUG "scsi-dtc : base = %08x\n", addr); -#endif + dprintk(NDEBUG_INIT, "dtc: addr = 0x%08x\n", addr); if (!addr) break; @@ -271,9 +266,8 @@ found: printk(KERN_WARNING "scsi%d : interrupts not used. Might as well not jumper it.\n", instance->host_no); instance->irq = NO_IRQ; #endif -#if defined(DTCDEBUG) && (DTCDEBUG & DTCDEBUG_INIT) - printk("scsi%d : irq = %d\n", instance->host_no, instance->irq); -#endif + dprintk(NDEBUG_INIT, "scsi%d : irq = %d\n", + instance->host_no, instance->irq); ++current_override; ++count; diff --git a/drivers/scsi/dtc.h b/drivers/scsi/dtc.h index 78a2332e9064..46483b280046 100644 --- a/drivers/scsi/dtc.h +++ b/drivers/scsi/dtc.h @@ -10,10 +10,6 @@ #ifndef DTC3280_H #define DTC3280_H -#define DTCDEBUG 0 -#define DTCDEBUG_INIT 0x1 -#define DTCDEBUG_TRANSFER 0x2 - #ifndef CMD_PER_LUN #define CMD_PER_LUN 2 #endif @@ -33,31 +29,8 @@ #define DTC_address(reg) (base + DTC_5380_OFFSET + reg) -#define dbNCR5380_read(reg) \ - (rval=readb(DTC_address(reg)), \ - (((unsigned char) printk("DTC : read register %d at addr %p is: %02x\n"\ - , (reg), DTC_address(reg), rval)), rval ) ) - -#define dbNCR5380_write(reg, value) do { \ - printk("DTC : write %02x to register %d at address %p\n", \ - (value), (reg), DTC_address(reg)); \ - writeb(value, DTC_address(reg));} while(0) - - -#if !(DTCDEBUG & DTCDEBUG_TRANSFER) #define NCR5380_read(reg) (readb(DTC_address(reg))) #define NCR5380_write(reg, value) (writeb(value, DTC_address(reg))) -#else -#define NCR5380_read(reg) (readb(DTC_address(reg))) -#define xNCR5380_read(reg) \ - (((unsigned char) printk("DTC : read register %d at address %p\n"\ - , (reg), DTC_address(reg))), readb(DTC_address(reg))) - -#define NCR5380_write(reg, value) do { \ - printk("DTC : write %02x to register %d at address %p\n", \ - (value), (reg), DTC_address(reg)); \ - writeb(value, DTC_address(reg));} while(0) -#endif #define NCR5380_intr dtc_intr #define NCR5380_queue_command dtc_queue_command diff --git a/drivers/scsi/pas16.c b/drivers/scsi/pas16.c index 1549bc97777e..62bf1b43b646 100644 --- a/drivers/scsi/pas16.c +++ b/drivers/scsi/pas16.c @@ -1,6 +1,5 @@ #define PSEUDO_DMA #define UNSAFE /* Not unsafe for PAS16 -- use it */ -#define PDEBUG 0 /* * This driver adapted from Drew Eckhardt's Trantor T128 driver @@ -377,23 +376,18 @@ static int __init pas16_detect(struct scsi_host_template *tpnt) } else for (; !io_port && (current_base < NO_BASES); ++current_base) { -#if (PDEBUG & PDEBUG_INIT) - printk("scsi-pas16 : probing io_port %04x\n", (unsigned int) bases[current_base].io_port); -#endif + dprintk(NDEBUG_INIT, "pas16: probing io_port 0x%04x\n", + (unsigned int)bases[current_base].io_port); if ( !bases[current_base].noauto && pas16_hw_detect( current_base ) ){ io_port = bases[current_base].io_port; init_board( io_port, default_irqs[ current_base ], 0 ); -#if (PDEBUG & PDEBUG_INIT) - printk("scsi-pas16 : detected board.\n"); -#endif + dprintk(NDEBUG_INIT, "pas16: detected board\n"); } } - -#if defined(PDEBUG) && (PDEBUG & PDEBUG_INIT) - printk("scsi-pas16 : io_port = %04x\n", (unsigned int) io_port); -#endif + dprintk(NDEBUG_INIT, "pas16: io_port = 0x%04x\n", + (unsigned int)io_port); if (!io_port) break; @@ -431,9 +425,8 @@ static int __init pas16_detect(struct scsi_host_template *tpnt) outb( (inb(io_port + IO_CONFIG_3) & 0x0f), io_port + IO_CONFIG_3 ); } -#if defined(PDEBUG) && (PDEBUG & PDEBUG_INIT) - printk("scsi%d : irq = %d\n", instance->host_no, instance->irq); -#endif + dprintk(NDEBUG_INIT, "scsi%d : irq = %d\n", + instance->host_no, instance->irq); ++current_override; ++count; diff --git a/drivers/scsi/pas16.h b/drivers/scsi/pas16.h index c6109c80050b..1fc7c049d0a1 100644 --- a/drivers/scsi/pas16.h +++ b/drivers/scsi/pas16.h @@ -24,9 +24,6 @@ #ifndef PAS16_H #define PAS16_H -#define PDEBUG_INIT 0x1 -#define PDEBUG_TRANSFER 0x2 - #define PAS16_DEFAULT_BASE_1 0x388 #define PAS16_DEFAULT_BASE_2 0x384 #define PAS16_DEFAULT_BASE_3 0x38c @@ -120,21 +117,8 @@ #define PAS16_io_port(reg) ( io_port + pas16_offset[(reg)] ) -#if !(PDEBUG & PDEBUG_TRANSFER) #define NCR5380_read(reg) ( inb(PAS16_io_port(reg)) ) #define NCR5380_write(reg, value) ( outb((value),PAS16_io_port(reg)) ) -#else -#define NCR5380_read(reg) \ - (((unsigned char) printk("scsi%d : read register %d at io_port %04x\n"\ - , instance->hostno, (reg), PAS16_io_port(reg))), inb( PAS16_io_port(reg)) ) - -#define NCR5380_write(reg, value) \ - (printk("scsi%d : write %02x to register %d at io_port %04x\n", \ - instance->hostno, (value), (reg), PAS16_io_port(reg)), \ - outb( (value),PAS16_io_port(reg) ) ) - -#endif - #define NCR5380_intr pas16_intr #define do_NCR5380_intr do_pas16_intr diff --git a/drivers/scsi/t128.c b/drivers/scsi/t128.c index eb7fae277fc6..339f018f8950 100644 --- a/drivers/scsi/t128.c +++ b/drivers/scsi/t128.c @@ -182,9 +182,8 @@ static int __init t128_detect(struct scsi_host_template *tpnt) base = 0; } else for (; !base && (current_base < NO_BASES); ++current_base) { -#if (TDEBUG & TDEBUG_INIT) - printk("scsi-t128 : probing address %08x\n", bases[current_base].address); -#endif + dprintk(NDEBUG_INIT, "t128: probing address 0x%08x\n", + bases[current_base].address); if (bases[current_base].noauto) continue; p = ioremap(bases[current_base].address, 0x2000); @@ -195,17 +194,13 @@ static int __init t128_detect(struct scsi_host_template *tpnt) signatures[sig].string, strlen(signatures[sig].string))) { base = bases[current_base].address; -#if (TDEBUG & TDEBUG_INIT) - printk("scsi-t128 : detected board.\n"); -#endif + dprintk(NDEBUG_INIT, "t128: detected board\n"); goto found; } iounmap(p); } -#if defined(TDEBUG) && (TDEBUG & TDEBUG_INIT) - printk("scsi-t128 : base = %08x\n", (unsigned int) base); -#endif + dprintk(NDEBUG_INIT, "t128: base = 0x%08x\n", (unsigned int)base); if (!base) break; @@ -242,9 +237,8 @@ found: printk("scsi%d : please jumper the board for a free IRQ.\n", instance->host_no); } -#if defined(TDEBUG) && (TDEBUG & TDEBUG_INIT) - printk("scsi%d : irq = %d\n", instance->host_no, instance->irq); -#endif + dprintk(NDEBUG_INIT, "scsi%d: irq = %d\n", + instance->host_no, instance->irq); ++current_override; ++count; diff --git a/drivers/scsi/t128.h b/drivers/scsi/t128.h index 2c7371454dfd..40c2fe7771e7 100644 --- a/drivers/scsi/t128.h +++ b/drivers/scsi/t128.h @@ -23,10 +23,6 @@ #ifndef T128_H #define T128_H -#define TDEBUG 0 -#define TDEBUG_INIT 0x1 -#define TDEBUG_TRANSFER 0x2 - /* * The trantor boards are memory mapped. They use an NCR5380 or * equivalent (my sample board had part second sourced from ZILOG). @@ -92,20 +88,8 @@ #define T128_address(reg) (base + T_5380_OFFSET + ((reg) * 0x20)) -#if !(TDEBUG & TDEBUG_TRANSFER) #define NCR5380_read(reg) readb(T128_address(reg)) #define NCR5380_write(reg, value) writeb((value),(T128_address(reg))) -#else -#define NCR5380_read(reg) \ - (((unsigned char) printk("scsi%d : read register %d at address %08x\n"\ - , instance->hostno, (reg), T128_address(reg))), readb(T128_address(reg))) - -#define NCR5380_write(reg, value) { \ - printk("scsi%d : write %02x to register %d at address %08x\n", \ - instance->hostno, (value), (reg), T128_address(reg)); \ - writeb((value), (T128_address(reg))); \ -} -#endif #define NCR5380_intr t128_intr #define do_NCR5380_intr do_t128_intr -- cgit From c0965e6371fa50fdf5cc2291915de97412fb1ec9 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sun, 3 Jan 2016 16:05:05 +1100 Subject: ncr5380: Remove more pointless macros ASM macro is never defined. rtrc in pas16.c is not used. NCR5380_map_config, do_NCR5380_intr, do_t128_intr and do_pas16_intr are unused. NCR_NOT_SET harms readability. Remove them. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Ondrej Zary Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.h | 3 --- drivers/scsi/g_NCR5380.c | 29 ++++++++++++++--------------- drivers/scsi/g_NCR5380.h | 5 ----- drivers/scsi/pas16.c | 16 ---------------- drivers/scsi/pas16.h | 5 ----- drivers/scsi/t128.h | 4 ---- 6 files changed, 14 insertions(+), 48 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/NCR5380.h b/drivers/scsi/NCR5380.h index 162112dd1bf8..24c784140db6 100644 --- a/drivers/scsi/NCR5380.h +++ b/drivers/scsi/NCR5380.h @@ -244,8 +244,6 @@ #define FLAG_LATE_DMA_SETUP 32 /* Setup NCR before DMA H/W */ #define FLAG_TAGGED_QUEUING 64 /* as X3T9.2 spelled it */ -#ifndef ASM - #ifdef SUPPORT_TAGS struct tag_alloc { DECLARE_BITMAP(allocated, MAX_TAGS); @@ -443,5 +441,4 @@ static __inline__ int NCR5380_pc_dma_residual(struct Scsi_Host *instance) #endif /* defined(i386) || defined(__alpha__) */ #endif /* defined(REAL_DMA) */ #endif /* __KERNEL__ */ -#endif /* ndef ASM */ #endif /* NCR5380_H */ diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c index c2507475518e..4cca9734175e 100644 --- a/drivers/scsi/g_NCR5380.c +++ b/drivers/scsi/g_NCR5380.c @@ -82,14 +82,13 @@ #include #include -#define NCR_NOT_SET 0 -static int ncr_irq = NCR_NOT_SET; -static int ncr_dma = NCR_NOT_SET; -static int ncr_addr = NCR_NOT_SET; -static int ncr_5380 = NCR_NOT_SET; -static int ncr_53c400 = NCR_NOT_SET; -static int ncr_53c400a = NCR_NOT_SET; -static int dtc_3181e = NCR_NOT_SET; +static int ncr_irq; +static int ncr_dma; +static int ncr_addr; +static int ncr_5380; +static int ncr_53c400; +static int ncr_53c400a; +static int dtc_3181e; static struct override { NCR5380_map_type NCR5380_map_name; @@ -271,19 +270,19 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt) void __iomem *iomem; #endif - if (ncr_irq != NCR_NOT_SET) + if (ncr_irq) overrides[0].irq = ncr_irq; - if (ncr_dma != NCR_NOT_SET) + if (ncr_dma) overrides[0].dma = ncr_dma; - if (ncr_addr != NCR_NOT_SET) + if (ncr_addr) overrides[0].NCR5380_map_name = (NCR5380_map_type) ncr_addr; - if (ncr_5380 != NCR_NOT_SET) + if (ncr_5380) overrides[0].board = BOARD_NCR5380; - else if (ncr_53c400 != NCR_NOT_SET) + else if (ncr_53c400) overrides[0].board = BOARD_NCR53C400; - else if (ncr_53c400a != NCR_NOT_SET) + else if (ncr_53c400a) overrides[0].board = BOARD_NCR53C400A; - else if (dtc_3181e != NCR_NOT_SET) + else if (dtc_3181e) overrides[0].board = BOARD_DTC3181E; #ifndef SCSI_G_NCR5380_MEM if (!current_override && isapnp_present()) { diff --git a/drivers/scsi/g_NCR5380.h b/drivers/scsi/g_NCR5380.h index bea1a3b9b862..6669a906a4f7 100644 --- a/drivers/scsi/g_NCR5380.h +++ b/drivers/scsi/g_NCR5380.h @@ -21,8 +21,6 @@ #define NCR5380_BIOSPARAM NULL #endif -#ifndef ASM - #ifndef CMD_PER_LUN #define CMD_PER_LUN 2 #endif @@ -36,7 +34,6 @@ #ifndef SCSI_G_NCR5380_MEM -#define NCR5380_map_config port #define NCR5380_map_type int #define NCR5380_map_name port #define NCR5380_instance_name io_port @@ -64,7 +61,6 @@ #else /* therefore SCSI_G_NCR5380_MEM */ -#define NCR5380_map_config memory #define NCR5380_map_type unsigned long #define NCR5380_map_name base #define NCR5380_instance_name base @@ -103,6 +99,5 @@ #define BOARD_NCR53C400A 2 #define BOARD_DTC3181E 3 -#endif /* ndef ASM */ #endif /* GENERIC_NCR5380_H */ diff --git a/drivers/scsi/pas16.c b/drivers/scsi/pas16.c index 62bf1b43b646..bf471a3c4e33 100644 --- a/drivers/scsi/pas16.c +++ b/drivers/scsi/pas16.c @@ -145,22 +145,6 @@ static const unsigned short pas16_offset[ 8 ] = * START_DMA_INITIATOR_RECEIVE_REG wo */ }; -/*----------------------------------------------------------------*/ -/* the following will set the monitor border color (useful to find - where something crashed or gets stuck at */ -/* 1 = blue - 2 = green - 3 = cyan - 4 = red - 5 = magenta - 6 = yellow - 7 = white -*/ -#if 1 -#define rtrc(i) {inb(0x3da); outb(0x31, 0x3c0); outb((i), 0x3c0);} -#else -#define rtrc(i) {} -#endif /* diff --git a/drivers/scsi/pas16.h b/drivers/scsi/pas16.h index 1fc7c049d0a1..3634f3fc0325 100644 --- a/drivers/scsi/pas16.h +++ b/drivers/scsi/pas16.h @@ -95,9 +95,6 @@ #define OPERATION_MODE_1 0xec03 #define IO_CONFIG_3 0xf002 - -#ifndef ASM - #ifndef CMD_PER_LUN #define CMD_PER_LUN 2 #endif @@ -121,7 +118,6 @@ #define NCR5380_write(reg, value) ( outb((value),PAS16_io_port(reg)) ) #define NCR5380_intr pas16_intr -#define do_NCR5380_intr do_pas16_intr #define NCR5380_queue_command pas16_queue_command #define NCR5380_abort pas16_abort #define NCR5380_bus_reset pas16_bus_reset @@ -134,5 +130,4 @@ #define PAS16_IRQS 0xd4a8 -#endif /* ndef ASM */ #endif /* PAS16_H */ diff --git a/drivers/scsi/t128.h b/drivers/scsi/t128.h index 40c2fe7771e7..cdcde3e672fa 100644 --- a/drivers/scsi/t128.h +++ b/drivers/scsi/t128.h @@ -67,8 +67,6 @@ #define T_DATA_REG_OFFSET 0x1e00 /* rw 512 bytes long */ -#ifndef ASM - #ifndef CMD_PER_LUN #define CMD_PER_LUN 2 #endif @@ -92,7 +90,6 @@ #define NCR5380_write(reg, value) writeb((value),(T128_address(reg))) #define NCR5380_intr t128_intr -#define do_NCR5380_intr do_t128_intr #define NCR5380_queue_command t128_queue_command #define NCR5380_abort t128_abort #define NCR5380_bus_reset t128_bus_reset @@ -105,5 +102,4 @@ #define T128_IRQS 0xc4a8 -#endif /* ndef ASM */ #endif /* T128_H */ -- cgit From 54d8fe4425c9d3fdf8473c1833c6807b61c6e70e Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sun, 3 Jan 2016 16:05:06 +1100 Subject: ncr5380: Remove NCR5380_local_declare and NCR5380_setup macros The NCR5380_local_declare and NCR5380_setup macros exist to define and initialize a particular local variable, to provide the address of the chip registers needed for the driver's implementation of its NCR5380_read/write register access macros. In cumana_1 and macscsi, these macros generate pointless code like this, struct Scsi_Host *_instance; _instance = instance; In pas16, the use of NCR5380_read/write in pas16_hw_detect() requires that the io_port local variable has been defined and initialized, but the NCR5380_local_declare and NCR5380_setup macros can't be used for that purpose because the Scsi_Host struct has not yet been instantiated. Moreover, these macros were removed from atari_NCR5380.c long ago and now they constitute yet another discrepancy between the two core driver forks. Remove these "optimizations". Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Ondrej Zary Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.c | 60 +++++++-------------------------------------- drivers/scsi/arm/cumana_1.c | 6 ++--- drivers/scsi/arm/oak.c | 9 ++++--- drivers/scsi/dmx3191d.c | 6 ++--- drivers/scsi/dtc.c | 14 ++++------- drivers/scsi/dtc.h | 9 ++----- drivers/scsi/g_NCR5380.c | 27 ++++++++++---------- drivers/scsi/g_NCR5380.h | 30 +++++++++-------------- drivers/scsi/mac_scsi.c | 15 ++---------- drivers/scsi/pas16.c | 16 ++++++------ drivers/scsi/pas16.h | 11 ++------- drivers/scsi/t128.c | 26 ++++++++++---------- drivers/scsi/t128.h | 9 ++----- 13 files changed, 77 insertions(+), 161 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index ed8346fcd516..e4cd85e1ea5b 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -230,11 +230,6 @@ * USLEEP_POLL - amount of time, in jiffies, to poll * * These macros MUST be defined : - * NCR5380_local_declare() - declare any local variables needed for your - * transfer routines. - * - * NCR5380_setup(instance) - initialize any local variables needed from a given - * instance of the host adapter for NCR5380_{read,write,pread,pwrite} * * NCR5380_read(register) - read from the specified register * @@ -267,8 +262,8 @@ * possible) function may be used. */ -static int do_abort(struct Scsi_Host *host); -static void do_reset(struct Scsi_Host *host); +static int do_abort(struct Scsi_Host *); +static void do_reset(struct Scsi_Host *); /* * initialize_SCp - init the scsi pointer field @@ -313,12 +308,9 @@ static inline void initialize_SCp(struct scsi_cmnd *cmd) static int NCR5380_poll_politely(struct Scsi_Host *instance, int reg, int bit, int val, int t) { - NCR5380_local_declare(); int n = 500; /* At about 8uS a cycle for the cpu access */ unsigned long end = jiffies + t; int r; - - NCR5380_setup(instance); while( n-- > 0) { @@ -406,9 +398,7 @@ mrs[] = { static void NCR5380_print(struct Scsi_Host *instance) { - NCR5380_local_declare(); unsigned char status, data, basr, mr, icr, i; - NCR5380_setup(instance); data = NCR5380_read(CURRENT_SCSI_DATA_REG); status = NCR5380_read(STATUS_REG); @@ -447,10 +437,8 @@ static void NCR5380_print(struct Scsi_Host *instance) static void NCR5380_print_phase(struct Scsi_Host *instance) { - NCR5380_local_declare(); unsigned char status; int i; - NCR5380_setup(instance); status = NCR5380_read(STATUS_REG); if (!(status & SR_REQ)) @@ -566,11 +554,9 @@ static irqreturn_t __init probe_intr(int irq, void *dev_id) static int __init __maybe_unused NCR5380_probe_irq(struct Scsi_Host *instance, int possible) { - NCR5380_local_declare(); struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) instance->hostdata; unsigned long timeout; int trying_irqs, i, mask; - NCR5380_setup(instance); for (trying_irqs = 0, i = 1, mask = 2; i < 16; ++i, mask <<= 1) if ((mask & possible) && (request_irq(i, &probe_intr, 0, "NCR-probe", NULL) == 0)) @@ -791,7 +777,6 @@ static void lprint_opcode(int opcode, struct seq_file *m) static int NCR5380_init(struct Scsi_Host *instance, int flags) { - NCR5380_local_declare(); int i, pass; unsigned long timeout; struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) instance->hostdata; @@ -808,8 +793,6 @@ static int NCR5380_init(struct Scsi_Host *instance, int flags) instance->NCR5380_instance_name += NCR53C400_address_adjust; #endif - NCR5380_setup(instance); - hostdata->aborted = 0; hostdata->id_mask = 1 << instance->this_id; for (i = hostdata->id_mask; i <= 0x80; i <<= 1) @@ -1100,7 +1083,6 @@ static void NCR5380_main(struct work_struct *work) static irqreturn_t NCR5380_intr(int dummy, void *dev_id) { - NCR5380_local_declare(); struct Scsi_Host *instance = dev_id; struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) instance->hostdata; int done; @@ -1114,7 +1096,6 @@ static irqreturn_t NCR5380_intr(int dummy, void *dev_id) done = 1; spin_lock_irqsave(instance->host_lock, flags); /* Look for pending interrupts */ - NCR5380_setup(instance); basr = NCR5380_read(BUS_AND_STATUS_REG); /* XXX dispatch to appropriate routine if found and done=0 */ if (basr & BASR_IRQ) { @@ -1205,7 +1186,6 @@ static irqreturn_t NCR5380_intr(int dummy, void *dev_id) static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd) { - NCR5380_local_declare(); struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) instance->hostdata; unsigned char tmp[3], phase; unsigned char *data; @@ -1213,7 +1193,6 @@ static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd) unsigned long timeout; unsigned char value; int err; - NCR5380_setup(instance); if (hostdata->selecting) goto part2; @@ -1487,7 +1466,6 @@ failed: */ static int NCR5380_transfer_pio(struct Scsi_Host *instance, unsigned char *phase, int *count, unsigned char **data) { - NCR5380_local_declare(); unsigned char p = *phase, tmp; int c = *count; unsigned char *d = *data; @@ -1496,7 +1474,6 @@ static int NCR5380_transfer_pio(struct Scsi_Host *instance, unsigned char *phase */ int break_allowed = 0; struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) instance->hostdata; - NCR5380_setup(instance); if (!(p & SR_IO)) dprintk(NDEBUG_PIO, "scsi%d : pio write %d bytes\n", instance->host_no, c); @@ -1623,10 +1600,8 @@ static int NCR5380_transfer_pio(struct Scsi_Host *instance, unsigned char *phase * Locks: caller holds queue lock */ -static void do_reset(struct Scsi_Host *host) { - NCR5380_local_declare(); - NCR5380_setup(host); - +static void do_reset(struct Scsi_Host *instance) +{ NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(NCR5380_read(STATUS_REG) & PHASE_MASK)); NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_RST); udelay(25); @@ -1645,13 +1620,11 @@ static void do_reset(struct Scsi_Host *host) { * FIXME: sort this out and get new_eh running */ -static int do_abort(struct Scsi_Host *host) { - NCR5380_local_declare(); +static int do_abort(struct Scsi_Host *instance) +{ unsigned char *msgptr, phase, tmp; int len; int rc; - NCR5380_setup(host); - /* Request message out phase */ NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN); @@ -1666,7 +1639,7 @@ static int do_abort(struct Scsi_Host *host) { * the target sees, so we just handshake. */ - rc = NCR5380_poll_politely(host, STATUS_REG, SR_REQ, SR_REQ, 60 * HZ); + rc = NCR5380_poll_politely(instance, STATUS_REG, SR_REQ, SR_REQ, 60 * HZ); if(rc < 0) return -1; @@ -1677,7 +1650,7 @@ static int do_abort(struct Scsi_Host *host) { if ((tmp & PHASE_MASK) != PHASE_MSGOUT) { NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN | ICR_ASSERT_ACK); - rc = NCR5380_poll_politely(host, STATUS_REG, SR_REQ, 0, 3*HZ); + rc = NCR5380_poll_politely(instance, STATUS_REG, SR_REQ, 0, 3 * HZ); NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN); if(rc == -1) return -1; @@ -1686,7 +1659,7 @@ static int do_abort(struct Scsi_Host *host) { msgptr = &tmp; len = 1; phase = PHASE_MSGOUT; - NCR5380_transfer_pio(host, &phase, &len, &msgptr); + NCR5380_transfer_pio(instance, &phase, &len, &msgptr); /* * If we got here, and the command completed successfully, @@ -1719,7 +1692,6 @@ static int do_abort(struct Scsi_Host *host) { static int NCR5380_transfer_dma(struct Scsi_Host *instance, unsigned char *phase, int *count, unsigned char **data) { - NCR5380_local_declare(); register int c = *count; register unsigned char p = *phase; register unsigned char *d = *data; @@ -1732,8 +1704,6 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, unsigned char *phase struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) instance->hostdata; - NCR5380_setup(instance); - if ((tmp = (NCR5380_read(STATUS_REG) & PHASE_MASK)) != p) { *phase = tmp; return -1; @@ -2000,7 +1970,6 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, unsigned char *phase */ static void NCR5380_information_transfer(struct Scsi_Host *instance) { - NCR5380_local_declare(); struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *)instance->hostdata; unsigned char msgout = NOP; int sink = 0; @@ -2014,8 +1983,6 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { /* RvC: we need to set the end of the polling time */ unsigned long poll_time = jiffies + USLEEP_POLL; - NCR5380_setup(instance); - while (1) { tmp = NCR5380_read(STATUS_REG); /* We only have a valid SCSI phase when REQ is asserted */ @@ -2406,7 +2373,6 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { */ static void NCR5380_reselect(struct Scsi_Host *instance) { - NCR5380_local_declare(); struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) instance->hostdata; unsigned char target_mask; @@ -2416,7 +2382,6 @@ static void NCR5380_reselect(struct Scsi_Host *instance) { unsigned char *data; struct scsi_cmnd *tmp = NULL, *prev; int abort = 0; - NCR5380_setup(instance); /* * Disable arbitration, etc. since the host adapter obviously @@ -2525,10 +2490,8 @@ static void NCR5380_reselect(struct Scsi_Host *instance) { #ifdef REAL_DMA static void NCR5380_dma_complete(NCR5380_instance * instance) { - NCR5380_local_declare(); struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) instance->hostdata; int transferred; - NCR5380_setup(instance); /* * XXX this might not be right. @@ -2581,7 +2544,6 @@ static void NCR5380_dma_complete(NCR5380_instance * instance) { static int NCR5380_abort(struct scsi_cmnd *cmd) { - NCR5380_local_declare(); struct Scsi_Host *instance = cmd->device->host; struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) instance->hostdata; struct scsi_cmnd *tmp, **prev; @@ -2590,8 +2552,6 @@ static int NCR5380_abort(struct scsi_cmnd *cmd) NCR5380_print_status(instance); - NCR5380_setup(instance); - dprintk(NDEBUG_ABORT, "scsi%d : abort called\n", instance->host_no); dprintk(NDEBUG_ABORT, " basr 0x%X, sr 0x%X\n", NCR5380_read(BUS_AND_STATUS_REG), NCR5380_read(STATUS_REG)); @@ -2737,8 +2697,6 @@ static int NCR5380_bus_reset(struct scsi_cmnd *cmd) { struct Scsi_Host *instance = cmd->device->host; - NCR5380_local_declare(); - NCR5380_setup(instance); NCR5380_print_status(instance); spin_lock_irq(instance->host_lock); diff --git a/drivers/scsi/arm/cumana_1.c b/drivers/scsi/arm/cumana_1.c index d28d6c0f18c0..8996a6ccc08f 100644 --- a/drivers/scsi/arm/cumana_1.c +++ b/drivers/scsi/arm/cumana_1.c @@ -20,10 +20,8 @@ #define PSEUDO_DMA #define priv(host) ((struct NCR5380_hostdata *)(host)->hostdata) -#define NCR5380_local_declare() struct Scsi_Host *_instance -#define NCR5380_setup(instance) _instance = instance -#define NCR5380_read(reg) cumanascsi_read(_instance, reg) -#define NCR5380_write(reg, value) cumanascsi_write(_instance, reg, value) +#define NCR5380_read(reg) cumanascsi_read(instance, reg) +#define NCR5380_write(reg, value) cumanascsi_write(instance, reg, value) #define NCR5380_intr cumanascsi_intr #define NCR5380_queue_command cumanascsi_queue_command #define NCR5380_info cumanascsi_info diff --git a/drivers/scsi/arm/oak.c b/drivers/scsi/arm/oak.c index 7c6fa1479c9c..aa5310bef9b7 100644 --- a/drivers/scsi/arm/oak.c +++ b/drivers/scsi/arm/oak.c @@ -20,11 +20,12 @@ #define DONT_USE_INTR #define priv(host) ((struct NCR5380_hostdata *)(host)->hostdata) -#define NCR5380_local_declare() void __iomem *_base -#define NCR5380_setup(host) _base = priv(host)->base -#define NCR5380_read(reg) readb(_base + ((reg) << 2)) -#define NCR5380_write(reg, value) writeb(value, _base + ((reg) << 2)) +#define NCR5380_read(reg) \ + readb(priv(instance)->base + ((reg) << 2)) +#define NCR5380_write(reg, value) \ + writeb(value, priv(instance)->base + ((reg) << 2)) + #define NCR5380_queue_command oakscsi_queue_command #define NCR5380_info oakscsi_info #define NCR5380_show_info oakscsi_show_info diff --git a/drivers/scsi/dmx3191d.c b/drivers/scsi/dmx3191d.c index 3e088125a8be..8d2984d7fa9c 100644 --- a/drivers/scsi/dmx3191d.c +++ b/drivers/scsi/dmx3191d.c @@ -36,12 +36,10 @@ #define DONT_USE_INTR -#define NCR5380_read(reg) inb(port + reg) -#define NCR5380_write(reg, value) outb(value, port + reg) +#define NCR5380_read(reg) inb(instance->io_port + reg) +#define NCR5380_write(reg, value) outb(value, instance->io_port + reg) #define NCR5380_implementation_fields /* none */ -#define NCR5380_local_declare() unsigned int port -#define NCR5380_setup(instance) port = instance->io_port /* * Includes needed for NCR5380.[ch] (XXX: Move them to NCR5380.h) diff --git a/drivers/scsi/dtc.c b/drivers/scsi/dtc.c index 38325f979b90..43c1739639ba 100644 --- a/drivers/scsi/dtc.c +++ b/drivers/scsi/dtc.c @@ -325,8 +325,6 @@ static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst, unsigned char *d = dst; int i; /* For counting time spent in the poll-loop */ struct NCR5380_hostdata *hostdata = shost_priv(instance); - NCR5380_local_declare(); - NCR5380_setup(instance); i = 0; NCR5380_read(RESET_PARITY_INTERRUPT_REG); @@ -342,7 +340,7 @@ static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst, while (NCR5380_read(DTC_CONTROL_REG) & CSR_HOST_BUF_NOT_RDY) ++i; rtrc(3); - memcpy_fromio(d, base + DTC_DATA_BUF, 128); + memcpy_fromio(d, hostdata->base + DTC_DATA_BUF, 128); d += 128; len -= 128; rtrc(7); @@ -377,8 +375,6 @@ static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src, { int i; struct NCR5380_hostdata *hostdata = shost_priv(instance); - NCR5380_local_declare(); - NCR5380_setup(instance); NCR5380_read(RESET_PARITY_INTERRUPT_REG); NCR5380_write(MODE_REG, MR_ENABLE_EOP_INTR | MR_DMA_MODE); @@ -394,7 +390,7 @@ static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src, while (NCR5380_read(DTC_CONTROL_REG) & CSR_HOST_BUF_NOT_RDY) ++i; rtrc(3); - memcpy_toio(base + DTC_DATA_BUF, src, 128); + memcpy_toio(hostdata->base + DTC_DATA_BUF, src, 128); src += 128; len -= 128; } @@ -420,15 +416,15 @@ MODULE_LICENSE("GPL"); static int dtc_release(struct Scsi_Host *shost) { - NCR5380_local_declare(); - NCR5380_setup(shost); + struct NCR5380_hostdata *hostdata = shost_priv(shost); + if (shost->irq != NO_IRQ) free_irq(shost->irq, shost); NCR5380_exit(shost); if (shost->io_port && shost->n_io_port) release_region(shost->io_port, shost->n_io_port); scsi_unregister(shost); - iounmap(base); + iounmap(hostdata->base); return 0; } diff --git a/drivers/scsi/dtc.h b/drivers/scsi/dtc.h index 46483b280046..07b0ac98817c 100644 --- a/drivers/scsi/dtc.h +++ b/drivers/scsi/dtc.h @@ -21,13 +21,8 @@ #define NCR5380_implementation_fields \ void __iomem *base -#define NCR5380_local_declare() \ - void __iomem *base - -#define NCR5380_setup(instance) \ - base = ((struct NCR5380_hostdata *)(instance)->hostdata)->base - -#define DTC_address(reg) (base + DTC_5380_OFFSET + reg) +#define DTC_address(reg) \ + (((struct NCR5380_hostdata *)shost_priv(instance))->base + DTC_5380_OFFSET + reg) #define NCR5380_read(reg) (readb(DTC_address(reg))) #define NCR5380_write(reg, value) (writeb(value, DTC_address(reg))) diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c index 4cca9734175e..21f8236df48f 100644 --- a/drivers/scsi/g_NCR5380.c +++ b/drivers/scsi/g_NCR5380.c @@ -459,9 +459,6 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt) static int generic_NCR5380_release_resources(struct Scsi_Host *instance) { - NCR5380_local_declare(); - NCR5380_setup(instance); - if (instance->irq != NO_IRQ) free_irq(instance->irq, instance); NCR5380_exit(instance); @@ -520,13 +517,13 @@ generic_NCR5380_biosparam(struct scsi_device *sdev, struct block_device *bdev, static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst, int len) { +#ifdef SCSI_G_NCR5380_MEM + struct NCR5380_hostdata *hostdata = shost_priv(instance); +#endif int blocks = len / 128; int start = 0; int bl; - NCR5380_local_declare(); - NCR5380_setup(instance); - NCR5380_write(C400_CONTROL_STATUS_REG, CSR_BASE | CSR_TRANS_DIR); NCR5380_write(C400_BLOCK_COUNTER_REG, blocks); while (1) { @@ -547,7 +544,8 @@ static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst, } #else /* implies SCSI_G_NCR5380_MEM */ - memcpy_fromio(dst + start, iomem + NCR53C400_host_buffer, 128); + memcpy_fromio(dst + start, + hostdata->iomem + NCR53C400_host_buffer, 128); #endif start += 128; blocks--; @@ -567,7 +565,8 @@ static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst, } #else /* implies SCSI_G_NCR5380_MEM */ - memcpy_fromio(dst + start, iomem + NCR53C400_host_buffer, 128); + memcpy_fromio(dst + start, + hostdata->iomem + NCR53C400_host_buffer, 128); #endif start += 128; blocks--; @@ -604,14 +603,14 @@ static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst, static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src, int len) { +#ifdef SCSI_G_NCR5380_MEM + struct NCR5380_hostdata *hostdata = shost_priv(instance); +#endif int blocks = len / 128; int start = 0; int bl; int i; - NCR5380_local_declare(); - NCR5380_setup(instance); - NCR5380_write(C400_CONTROL_STATUS_REG, CSR_BASE); NCR5380_write(C400_BLOCK_COUNTER_REG, blocks); while (1) { @@ -632,7 +631,8 @@ static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src, } #else /* implies SCSI_G_NCR5380_MEM */ - memcpy_toio(iomem + NCR53C400_host_buffer, src + start, 128); + memcpy_toio(hostdata->iomem + NCR53C400_host_buffer, + src + start, 128); #endif start += 128; blocks--; @@ -648,7 +648,8 @@ static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src, } #else /* implies SCSI_G_NCR5380_MEM */ - memcpy_toio(iomem + NCR53C400_host_buffer, src + start, 128); + memcpy_toio(hostdata->iomem + NCR53C400_host_buffer, + src + start, 128); #endif start += 128; blocks--; diff --git a/drivers/scsi/g_NCR5380.h b/drivers/scsi/g_NCR5380.h index 6669a906a4f7..883c003394cf 100644 --- a/drivers/scsi/g_NCR5380.h +++ b/drivers/scsi/g_NCR5380.h @@ -46,17 +46,12 @@ #define NCR5380_region_size 8 #endif -#define NCR5380_read(reg) (inb(NCR5380_map_name + (reg))) -#define NCR5380_write(reg, value) (outb((value), (NCR5380_map_name + (reg)))) +#define NCR5380_read(reg) \ + inb(instance->io_port + (reg)) +#define NCR5380_write(reg, value) \ + outb(value, instance->io_port + (reg)) -#define NCR5380_implementation_fields \ - NCR5380_map_type NCR5380_map_name - -#define NCR5380_local_declare() \ - register NCR5380_implementation_fields - -#define NCR5380_setup(instance) \ - NCR5380_map_name = (NCR5380_map_type)((instance)->NCR5380_instance_name) +#define NCR5380_implementation_fields /* none */ #else /* therefore SCSI_G_NCR5380_MEM */ @@ -70,19 +65,16 @@ #define NCR53C400_host_buffer 0x3900 #define NCR5380_region_size 0x3a00 -#define NCR5380_read(reg) readb(iomem + NCR53C400_mem_base + (reg)) -#define NCR5380_write(reg, value) writeb(value, iomem + NCR53C400_mem_base + (reg)) +#define NCR5380_read(reg) \ + readb(((struct NCR5380_hostdata *)shost_priv(instance))->iomem + \ + NCR53C400_mem_base + (reg)) +#define NCR5380_write(reg, value) \ + writeb(value, ((struct NCR5380_hostdata *)shost_priv(instance))->iomem + \ + NCR53C400_mem_base + (reg)) #define NCR5380_implementation_fields \ - NCR5380_map_type NCR5380_map_name; \ void __iomem *iomem; -#define NCR5380_local_declare() \ - register void __iomem *iomem - -#define NCR5380_setup(instance) \ - iomem = (((struct NCR5380_hostdata *)(instance)->hostdata)->iomem) - #endif #define NCR5380_intr generic_NCR5380_intr diff --git a/drivers/scsi/mac_scsi.c b/drivers/scsi/mac_scsi.c index d64a769b8155..e49a9b1d7c3d 100644 --- a/drivers/scsi/mac_scsi.c +++ b/drivers/scsi/mac_scsi.c @@ -32,11 +32,9 @@ #define PSEUDO_DMA #define NCR5380_implementation_fields unsigned char *pdma_base -#define NCR5380_local_declare() struct Scsi_Host *_instance -#define NCR5380_setup(instance) _instance = instance -#define NCR5380_read(reg) macscsi_read(_instance, reg) -#define NCR5380_write(reg, value) macscsi_write(_instance, reg, value) +#define NCR5380_read(reg) macscsi_read(instance, reg) +#define NCR5380_write(reg, value) macscsi_write(instance, reg, value) #define NCR5380_pread macscsi_pread #define NCR5380_pwrite macscsi_pwrite @@ -129,9 +127,6 @@ static void mac_scsi_reset_boot(struct Scsi_Host *instance) { unsigned long end; - NCR5380_local_declare(); - NCR5380_setup(instance); - /* * Do a SCSI reset to clean up the bus during initialization. No messing * with the queues, interrupts, or locks necessary here. @@ -235,9 +230,6 @@ static int macscsi_pread(struct Scsi_Host *instance, unsigned char *d; unsigned char *s; - NCR5380_local_declare(); - NCR5380_setup(instance); - s = hostdata->pdma_base + (INPUT_DATA_REG << 4); d = dst; @@ -329,9 +321,6 @@ static int macscsi_pwrite(struct Scsi_Host *instance, unsigned char *s; unsigned char *d; - NCR5380_local_declare(); - NCR5380_setup(instance); - s = src; d = hostdata->pdma_base + (OUTPUT_DATA_REG << 4); diff --git a/drivers/scsi/pas16.c b/drivers/scsi/pas16.c index bf471a3c4e33..e147f5667f27 100644 --- a/drivers/scsi/pas16.c +++ b/drivers/scsi/pas16.c @@ -188,7 +188,7 @@ static void __init outb( 0x01, io_port + P_TIMEOUT_STATUS_REG_OFFSET ); /* Reset TC */ outb( 0x01, io_port + WAIT_STATE ); /* 1 Wait state */ - NCR5380_read( RESET_PARITY_INTERRUPT_REG ); + inb(io_port + pas16_offset[RESET_PARITY_INTERRUPT_REG]); /* Set the SCSI interrupt pointer without mucking up the sound * interrupt pointer in the same byte. @@ -263,13 +263,13 @@ static int __init * put in an additional test to try to weed them out. */ - outb( 0x01, io_port + WAIT_STATE ); /* 1 Wait state */ - NCR5380_write( MODE_REG, 0x20 ); /* Is it really SCSI? */ - if( NCR5380_read( MODE_REG ) != 0x20 ) /* Write to a reg. */ - return 0; /* and try to read */ - NCR5380_write( MODE_REG, 0x00 ); /* it back. */ - if( NCR5380_read( MODE_REG ) != 0x00 ) - return 0; + outb(0x01, io_port + WAIT_STATE); /* 1 Wait state */ + outb(0x20, io_port + pas16_offset[MODE_REG]); /* Is it really SCSI? */ + if (inb(io_port + pas16_offset[MODE_REG]) != 0x20) /* Write to a reg. */ + return 0; /* and try to read */ + outb(0x00, io_port + pas16_offset[MODE_REG]); /* it back. */ + if (inb(io_port + pas16_offset[MODE_REG]) != 0x00) + return 0; return 1; } diff --git a/drivers/scsi/pas16.h b/drivers/scsi/pas16.h index 3634f3fc0325..7247b67fb111 100644 --- a/drivers/scsi/pas16.h +++ b/drivers/scsi/pas16.h @@ -103,16 +103,9 @@ #define CAN_QUEUE 32 #endif -#define NCR5380_implementation_fields \ - volatile unsigned short io_port +#define NCR5380_implementation_fields /* none */ -#define NCR5380_local_declare() \ - volatile unsigned short io_port - -#define NCR5380_setup(instance) \ - io_port = (instance)->io_port - -#define PAS16_io_port(reg) ( io_port + pas16_offset[(reg)] ) +#define PAS16_io_port(reg) (instance->io_port + pas16_offset[(reg)]) #define NCR5380_read(reg) ( inb(PAS16_io_port(reg)) ) #define NCR5380_write(reg, value) ( outb((value),PAS16_io_port(reg)) ) diff --git a/drivers/scsi/t128.c b/drivers/scsi/t128.c index 339f018f8950..d06ae1d11ca4 100644 --- a/drivers/scsi/t128.c +++ b/drivers/scsi/t128.c @@ -248,15 +248,15 @@ found: static int t128_release(struct Scsi_Host *shost) { - NCR5380_local_declare(); - NCR5380_setup(shost); + struct NCR5380_hostdata *hostdata = shost_priv(shost); + if (shost->irq != NO_IRQ) free_irq(shost->irq, shost); NCR5380_exit(shost); if (shost->io_port && shost->n_io_port) release_region(shost->io_port, shost->n_io_port); scsi_unregister(shost); - iounmap(base); + iounmap(hostdata->base); return 0; } @@ -302,14 +302,14 @@ static int t128_biosparam(struct scsi_device *sdev, struct block_device *bdev, * timeout. */ -static inline int NCR5380_pread (struct Scsi_Host *instance, unsigned char *dst, - int len) { - NCR5380_local_declare(); - void __iomem *reg; +static inline int +NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst, int len) +{ + struct NCR5380_hostdata *hostdata = shost_priv(instance); + void __iomem *reg, *base = hostdata->base; unsigned char *d = dst; register int i = len; - NCR5380_setup(instance); reg = base + T_DATA_REG_OFFSET; #if 0 @@ -348,14 +348,14 @@ static inline int NCR5380_pread (struct Scsi_Host *instance, unsigned char *dst, * timeout. */ -static inline int NCR5380_pwrite (struct Scsi_Host *instance, unsigned char *src, - int len) { - NCR5380_local_declare(); - void __iomem *reg; +static inline int +NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src, int len) +{ + struct NCR5380_hostdata *hostdata = shost_priv(instance); + void __iomem *reg, *base = hostdata->base; unsigned char *s = src; register int i = len; - NCR5380_setup(instance); reg = base + T_DATA_REG_OFFSET; #if 0 diff --git a/drivers/scsi/t128.h b/drivers/scsi/t128.h index cdcde3e672fa..ca93c97cf4ba 100644 --- a/drivers/scsi/t128.h +++ b/drivers/scsi/t128.h @@ -78,13 +78,8 @@ #define NCR5380_implementation_fields \ void __iomem *base -#define NCR5380_local_declare() \ - void __iomem *base - -#define NCR5380_setup(instance) \ - base = ((struct NCR5380_hostdata *)(instance->hostdata))->base - -#define T128_address(reg) (base + T_5380_OFFSET + ((reg) * 0x20)) +#define T128_address(reg) \ + (((struct NCR5380_hostdata *)shost_priv(instance))->base + T_5380_OFFSET + ((reg) * 0x20)) #define NCR5380_read(reg) readb(T128_address(reg)) #define NCR5380_write(reg, value) writeb((value),(T128_address(reg))) -- cgit From b01ec34895720348dab7eae6bfb28a5799130bce Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sun, 3 Jan 2016 16:05:07 +1100 Subject: ncr5380: Remove NCR5380_instance_name macro This macro makes the code cryptic. Remove it. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Ondrej Zary Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.c | 2 +- drivers/scsi/g_NCR5380.c | 7 ++++--- drivers/scsi/g_NCR5380.h | 2 -- 3 files changed, 5 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index e4cd85e1ea5b..78d7858c4404 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -790,7 +790,7 @@ static int NCR5380_init(struct Scsi_Host *instance, int flags) #ifdef NCR53C400 if (flags & FLAG_NCR53C400) - instance->NCR5380_instance_name += NCR53C400_address_adjust; + instance->io_port += NCR53C400_address_adjust; #endif hostdata->aborted = 0; diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c index 21f8236df48f..4559fbc7f342 100644 --- a/drivers/scsi/g_NCR5380.c +++ b/drivers/scsi/g_NCR5380.c @@ -412,10 +412,11 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt) continue; } - instance->NCR5380_instance_name = overrides[current_override].NCR5380_map_name; #ifndef SCSI_G_NCR5380_MEM + instance->io_port = overrides[current_override].NCR5380_map_name; instance->n_io_port = region_size; #else + instance->base = overrides[current_override].NCR5380_map_name; ((struct NCR5380_hostdata *)instance->hostdata)->iomem = iomem; #endif @@ -464,10 +465,10 @@ static int generic_NCR5380_release_resources(struct Scsi_Host *instance) NCR5380_exit(instance); #ifndef SCSI_G_NCR5380_MEM - release_region(instance->NCR5380_instance_name, instance->n_io_port); + release_region(instance->io_port, instance->n_io_port); #else iounmap(((struct NCR5380_hostdata *)instance->hostdata)->iomem); - release_mem_region(instance->NCR5380_instance_name, NCR5380_region_size); + release_mem_region(instance->base, NCR5380_region_size); #endif diff --git a/drivers/scsi/g_NCR5380.h b/drivers/scsi/g_NCR5380.h index 883c003394cf..c2d072aabd31 100644 --- a/drivers/scsi/g_NCR5380.h +++ b/drivers/scsi/g_NCR5380.h @@ -36,7 +36,6 @@ #define NCR5380_map_type int #define NCR5380_map_name port -#define NCR5380_instance_name io_port #define NCR53C400_register_offset 0 #define NCR53C400_address_adjust 8 @@ -58,7 +57,6 @@ #define NCR5380_map_type unsigned long #define NCR5380_map_name base -#define NCR5380_instance_name base #define NCR53C400_register_offset 0x108 #define NCR53C400_address_adjust 0 #define NCR53C400_mem_base 0x3880 -- cgit From b6488f97d3b5b602a066956e58a1ba282456d79b Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sun, 3 Jan 2016 16:05:08 +1100 Subject: ncr5380: Split NCR5380_init() into two functions This patch splits the NCR5380_init() function into two parts, similar to the scheme used with atari_NCR5380.c. This avoids two problems. Firstly, NCR5380_init() may perform a bus reset, which would cause the chip to assert IRQ. The chip is unable to mask its bus reset interrupt. Drivers can't call request_irq() before calling NCR5380_init(), because initialization must happen before the interrupt handler executes. If driver initialization causes an interrupt it may be problematic on some platforms. To avoid that, first move the bus reset code into NCR5380_maybe_reset_bus(). Secondly, NCR5380_init() contains some board-specific interrupt setup code for the NCR53C400 that does not belong in the core driver. In moving this code, better not re-order interrupt initialization and bus reset. Again, the solution is to move the bus reset code into NCR5380_maybe_reset_bus(). Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Ondrej Zary Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.c | 34 ++++++++++++++++++++-------------- drivers/scsi/NCR5380.h | 1 + drivers/scsi/arm/cumana_1.c | 2 ++ drivers/scsi/arm/oak.c | 2 ++ drivers/scsi/dmx3191d.c | 2 ++ drivers/scsi/dtc.c | 2 ++ drivers/scsi/g_NCR5380.c | 2 ++ drivers/scsi/pas16.c | 2 ++ drivers/scsi/t128.c | 2 ++ 9 files changed, 35 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index 78d7858c4404..1f9028a0e7ea 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -777,8 +777,7 @@ static void lprint_opcode(int opcode, struct seq_file *m) static int NCR5380_init(struct Scsi_Host *instance, int flags) { - int i, pass; - unsigned long timeout; + int i; struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) instance->hostdata; if(in_interrupt()) @@ -831,18 +830,26 @@ static int NCR5380_init(struct Scsi_Host *instance, int flags) NCR5380_write(C400_CONTROL_STATUS_REG, CSR_BASE); } #endif + return 0; +} - /* - * Detect and correct bus wedge problems. - * - * If the system crashed, it may have crashed in a state - * where a SCSI command was still executing, and the - * SCSI bus is not in a BUS FREE STATE. - * - * If this is the case, we'll try to abort the currently - * established nexus which we know nothing about, and that - * failing, do a hard reset of the SCSI bus - */ +/** + * NCR5380_maybe_reset_bus - Detect and correct bus wedge problems. + * @instance: adapter to check + * + * If the system crashed, it may have crashed with a connected target and + * the SCSI bus busy. Check for BUS FREE phase. If not, try to abort the + * currently established nexus, which we know nothing about. Failing that + * do a bus reset. + * + * Note that a bus reset will cause the chip to assert IRQ. + * + * Returns 0 if successful, otherwise -ENXIO. + */ + +static int NCR5380_maybe_reset_bus(struct Scsi_Host *instance) +{ + int pass; for (pass = 1; (NCR5380_read(STATUS_REG) & SR_BSY) && pass <= 6; ++pass) { switch (pass) { @@ -850,7 +857,6 @@ static int NCR5380_init(struct Scsi_Host *instance, int flags) case 3: case 5: printk(KERN_INFO "scsi%d: SCSI bus busy, waiting up to five seconds\n", instance->host_no); - timeout = jiffies + 5 * HZ; NCR5380_poll_politely(instance, STATUS_REG, SR_BSY, 0, 5*HZ); break; case 2: diff --git a/drivers/scsi/NCR5380.h b/drivers/scsi/NCR5380.h index 24c784140db6..2057eaa66c20 100644 --- a/drivers/scsi/NCR5380.h +++ b/drivers/scsi/NCR5380.h @@ -318,6 +318,7 @@ static void NCR5380_print(struct Scsi_Host *instance); static int NCR5380_probe_irq(struct Scsi_Host *instance, int possible); #endif static int NCR5380_init(struct Scsi_Host *instance, int flags); +static int NCR5380_maybe_reset_bus(struct Scsi_Host *); static void NCR5380_exit(struct Scsi_Host *instance); static void NCR5380_information_transfer(struct Scsi_Host *instance); #ifndef DONT_USE_INTR diff --git a/drivers/scsi/arm/cumana_1.c b/drivers/scsi/arm/cumana_1.c index 8996a6ccc08f..c7dc65e39cdb 100644 --- a/drivers/scsi/arm/cumana_1.c +++ b/drivers/scsi/arm/cumana_1.c @@ -240,6 +240,8 @@ static int cumanascsi1_probe(struct expansion_card *ec, NCR5380_init(host, 0); + NCR5380_maybe_reset_bus(host); + priv(host)->ctrl = 0; writeb(0, priv(host)->base + CTRL); diff --git a/drivers/scsi/arm/oak.c b/drivers/scsi/arm/oak.c index aa5310bef9b7..ca0f31d22f43 100644 --- a/drivers/scsi/arm/oak.c +++ b/drivers/scsi/arm/oak.c @@ -145,6 +145,8 @@ static int oakscsi_probe(struct expansion_card *ec, const struct ecard_id *id) NCR5380_init(host, 0); + NCR5380_maybe_reset_bus(host); + ret = scsi_add_host(host, &ec->dev); if (ret) goto out_unmap; diff --git a/drivers/scsi/dmx3191d.c b/drivers/scsi/dmx3191d.c index 8d2984d7fa9c..2c0fd7641075 100644 --- a/drivers/scsi/dmx3191d.c +++ b/drivers/scsi/dmx3191d.c @@ -97,6 +97,8 @@ static int dmx3191d_probe_one(struct pci_dev *pdev, NCR5380_init(shost, FLAG_NO_PSEUDO_DMA | FLAG_DTC3181E); + NCR5380_maybe_reset_bus(shost); + pci_set_drvdata(pdev, shost); error = scsi_add_host(shost, &pdev->dev); diff --git a/drivers/scsi/dtc.c b/drivers/scsi/dtc.c index 43c1739639ba..02a5532f4267 100644 --- a/drivers/scsi/dtc.c +++ b/drivers/scsi/dtc.c @@ -237,6 +237,8 @@ found: NCR5380_init(instance, 0); + NCR5380_maybe_reset_bus(instance); + NCR5380_write(DTC_CONTROL_REG, CSR_5380_INTR); /* Enable int's */ if (overrides[current_override].irq != IRQ_AUTO) instance->irq = overrides[current_override].irq; diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c index 4559fbc7f342..6f5fdf642296 100644 --- a/drivers/scsi/g_NCR5380.c +++ b/drivers/scsi/g_NCR5380.c @@ -422,6 +422,8 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt) NCR5380_init(instance, flags); + NCR5380_maybe_reset_bus(instance); + if (overrides[current_override].irq != IRQ_AUTO) instance->irq = overrides[current_override].irq; else diff --git a/drivers/scsi/pas16.c b/drivers/scsi/pas16.c index e147f5667f27..c316ff7ffef6 100644 --- a/drivers/scsi/pas16.c +++ b/drivers/scsi/pas16.c @@ -384,6 +384,8 @@ static int __init pas16_detect(struct scsi_host_template *tpnt) NCR5380_init(instance, 0); + NCR5380_maybe_reset_bus(instance); + if (overrides[current_override].irq != IRQ_AUTO) instance->irq = overrides[current_override].irq; else diff --git a/drivers/scsi/t128.c b/drivers/scsi/t128.c index d06ae1d11ca4..d5e6b676d75e 100644 --- a/drivers/scsi/t128.c +++ b/drivers/scsi/t128.c @@ -215,6 +215,8 @@ found: NCR5380_init(instance, 0); + NCR5380_maybe_reset_bus(instance); + if (overrides[current_override].irq != IRQ_AUTO) instance->irq = overrides[current_override].irq; else -- cgit From 4d8c08c71ea261a31855e4919fa8b875cd507ef3 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sun, 3 Jan 2016 16:05:09 +1100 Subject: ncr5380: Move NCR53C400-specific code Move board-specific code like this, NCR5380_write(C400_CONTROL_STATUS_REG, CSR_BASE); from the core driver to the board driver. Eliminate the NCR53C400 macro from the core driver. Removal of all macros like this one will be necessary in order to have one core driver that can support all kinds of boards. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Ondrej Zary Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.c | 18 ------------------ drivers/scsi/g_NCR5380.c | 21 ++++++++++++++++----- drivers/scsi/g_NCR5380.h | 6 ++---- 3 files changed, 18 insertions(+), 27 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index 1f9028a0e7ea..7457bd33e965 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -653,9 +653,6 @@ static void prepare_info(struct Scsi_Host *instance) #endif #ifdef UNSAFE "UNSAFE " -#endif -#ifdef NCR53C400 - "NCR53C400 " #endif ""); } @@ -782,15 +779,6 @@ static int NCR5380_init(struct Scsi_Host *instance, int flags) if(in_interrupt()) printk(KERN_ERR "NCR5380_init called with interrupts off!\n"); - /* - * On NCR53C400 boards, NCR5380 registers are mapped 8 past - * the base address. - */ - -#ifdef NCR53C400 - if (flags & FLAG_NCR53C400) - instance->io_port += NCR53C400_address_adjust; -#endif hostdata->aborted = 0; hostdata->id_mask = 1 << instance->this_id; @@ -824,12 +812,6 @@ static int NCR5380_init(struct Scsi_Host *instance, int flags) NCR5380_write(MODE_REG, MR_BASE); NCR5380_write(TARGET_COMMAND_REG, 0); NCR5380_write(SELECT_ENABLE_REG, 0); - -#ifdef NCR53C400 - if (hostdata->flags & FLAG_NCR53C400) { - NCR5380_write(C400_CONTROL_STATUS_REG, CSR_BASE); - } -#endif return 0; } diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c index 6f5fdf642296..ffbb07b0e9e8 100644 --- a/drivers/scsi/g_NCR5380.c +++ b/drivers/scsi/g_NCR5380.c @@ -64,9 +64,7 @@ #define AUTOPROBE_IRQ #ifdef CONFIG_SCSI_GENERIC_NCR53C400 -#define NCR53C400_PSEUDO_DMA 1 #define PSEUDO_DMA -#define NCR53C400 #endif #include @@ -263,7 +261,7 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt) static unsigned int __initdata dtc_3181e_ports[] = { 0x220, 0x240, 0x280, 0x2a0, 0x2c0, 0x300, 0x320, 0x340, 0 }; - int flags = 0; + int flags; struct Scsi_Host *instance; #ifdef SCSI_G_NCR5380_MEM unsigned long base; @@ -324,12 +322,15 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt) continue; ports = NULL; + flags = 0; switch (overrides[current_override].board) { case BOARD_NCR5380: flags = FLAG_NO_PSEUDO_DMA; break; case BOARD_NCR53C400: +#ifdef PSEUDO_DMA flags = FLAG_NCR53C400; +#endif break; case BOARD_NCR53C400A: flags = FLAG_NO_PSEUDO_DMA; @@ -415,6 +416,13 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt) #ifndef SCSI_G_NCR5380_MEM instance->io_port = overrides[current_override].NCR5380_map_name; instance->n_io_port = region_size; + + /* + * On NCR53C400 boards, NCR5380 registers are mapped 8 past + * the base address. + */ + if (overrides[current_override].board == BOARD_NCR53C400) + instance->io_port += 8; #else instance->base = overrides[current_override].NCR5380_map_name; ((struct NCR5380_hostdata *)instance->hostdata)->iomem = iomem; @@ -422,6 +430,9 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt) NCR5380_init(instance, flags); + if (overrides[current_override].board == BOARD_NCR53C400) + NCR5380_write(C400_CONTROL_STATUS_REG, CSR_BASE); + NCR5380_maybe_reset_bus(instance); if (overrides[current_override].irq != IRQ_AUTO) @@ -506,7 +517,7 @@ generic_NCR5380_biosparam(struct scsi_device *sdev, struct block_device *bdev, } #endif -#ifdef NCR53C400_PSEUDO_DMA +#ifdef PSEUDO_DMA /** * NCR5380_pread - pseudo DMA read @@ -690,7 +701,7 @@ static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src, ; // TIMEOUT return 0; } -#endif /* PSEUDO_DMA */ +#endif /* PSEUDO_DMA */ /* * Include the NCR5380 core code that we build our driver around diff --git a/drivers/scsi/g_NCR5380.h b/drivers/scsi/g_NCR5380.h index c2d072aabd31..5c656f163beb 100644 --- a/drivers/scsi/g_NCR5380.h +++ b/drivers/scsi/g_NCR5380.h @@ -14,7 +14,7 @@ #ifndef GENERIC_NCR5380_H #define GENERIC_NCR5380_H -#ifdef NCR53C400 +#ifdef CONFIG_SCSI_GENERIC_NCR53C400 #define BIOSPARAM #define NCR5380_BIOSPARAM generic_NCR5380_biosparam #else @@ -37,9 +37,8 @@ #define NCR5380_map_type int #define NCR5380_map_name port #define NCR53C400_register_offset 0 -#define NCR53C400_address_adjust 8 -#ifdef NCR53C400 +#ifdef CONFIG_SCSI_GENERIC_NCR53C400 #define NCR5380_region_size 16 #else #define NCR5380_region_size 8 @@ -58,7 +57,6 @@ #define NCR5380_map_type unsigned long #define NCR5380_map_name base #define NCR53C400_register_offset 0x108 -#define NCR53C400_address_adjust 0 #define NCR53C400_mem_base 0x3880 #define NCR53C400_host_buffer 0x3900 #define NCR5380_region_size 0x3a00 -- cgit From 636b1ec8575a60fb305ad6e3ede5e79d287754b6 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sun, 3 Jan 2016 16:05:10 +1100 Subject: atari_NCR5380: Reset bus on driver initialization if required Merge the bus reset code from NCR5380.c into atari_NCR5380.c. This allows for removal of a lot of duplicated code conditional on the RESET_BOOT macro (in the next patch). The atari_NCR5380.c fork lacks the do_reset() and NCR5380_poll_politely() routines from NCR5380.c, so introduce them. They are indispensible. Keep the two implementations in sync. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Ondrej Zary Tested-by: Michael Schmitz Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.c | 33 ++++++++----- drivers/scsi/atari_NCR5380.c | 113 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 134 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index 7457bd33e965..391ee8db5de1 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -838,19 +838,20 @@ static int NCR5380_maybe_reset_bus(struct Scsi_Host *instance) case 1: case 3: case 5: - printk(KERN_INFO "scsi%d: SCSI bus busy, waiting up to five seconds\n", instance->host_no); - NCR5380_poll_politely(instance, STATUS_REG, SR_BSY, 0, 5*HZ); + shost_printk(KERN_ERR, instance, "SCSI bus busy, waiting up to five seconds\n"); + NCR5380_poll_politely(instance, + STATUS_REG, SR_BSY, 0, 5 * HZ); break; case 2: - printk(KERN_WARNING "scsi%d: bus busy, attempting abort\n", instance->host_no); + shost_printk(KERN_ERR, instance, "bus busy, attempting abort\n"); do_abort(instance); break; case 4: - printk(KERN_WARNING "scsi%d: bus busy, attempting reset\n", instance->host_no); + shost_printk(KERN_ERR, instance, "bus busy, attempting reset\n"); do_reset(instance); break; case 6: - printk(KERN_ERR "scsi%d: bus locked solid or invalid override\n", instance->host_no); + shost_printk(KERN_ERR, instance, "bus locked solid\n"); return -ENXIO; } } @@ -1579,21 +1580,29 @@ static int NCR5380_transfer_pio(struct Scsi_Host *instance, unsigned char *phase } /** - * do_reset - issue a reset command - * @host: adapter to reset + * do_reset - issue a reset command + * @instance: adapter to reset * - * Issue a reset sequence to the NCR5380 and try and get the bus - * back into sane shape. + * Issue a reset sequence to the NCR5380 and try and get the bus + * back into sane shape. * - * Locks: caller holds queue lock + * This clears the reset interrupt flag because there may be no handler for + * it. When the driver is initialized, the NCR5380_intr() handler has not yet + * been installed. And when in EH we may have released the ST DMA interrupt. */ static void do_reset(struct Scsi_Host *instance) { - NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(NCR5380_read(STATUS_REG) & PHASE_MASK)); + unsigned long flags; + + local_irq_save(flags); + NCR5380_write(TARGET_COMMAND_REG, + PHASE_SR_TO_TCR(NCR5380_read(STATUS_REG) & PHASE_MASK)); NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_RST); - udelay(25); + udelay(50); NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); + (void)NCR5380_read(RESET_PARITY_INTERRUPT_REG); + local_irq_restore(flags); } /* diff --git a/drivers/scsi/atari_NCR5380.c b/drivers/scsi/atari_NCR5380.c index db87ece6edb2..a15b655aa2b0 100644 --- a/drivers/scsi/atari_NCR5380.c +++ b/drivers/scsi/atari_NCR5380.c @@ -234,6 +234,9 @@ #define HOSTNO instance->host_no #define H_NO(cmd) (cmd)->device->host->host_no +static int do_abort(struct Scsi_Host *); +static void do_reset(struct Scsi_Host *); + #ifdef SUPPORT_TAGS /* @@ -475,6 +478,47 @@ static inline void initialize_SCp(struct scsi_cmnd *cmd) } } +/** + * NCR5380_poll_politely - wait for NCR5380 status bits + * @instance: controller to poll + * @reg: 5380 register to poll + * @bit: Bitmask to check + * @val: Value required to exit + * + * Polls the NCR5380 in a reasonably efficient manner waiting for + * an event to occur, after a short quick poll we begin giving the + * CPU back in non IRQ contexts + * + * Returns the value of the register or a negative error code. + */ + +static int NCR5380_poll_politely(struct Scsi_Host *instance, + int reg, int bit, int val, int t) +{ + int n = 500; + unsigned long end = jiffies + t; + int r; + + while (n-- > 0) { + r = NCR5380_read(reg); + if ((r & bit) == val) + return 0; + cpu_relax(); + } + + /* t time yet ? */ + while (time_before(jiffies, end)) { + r = NCR5380_read(reg); + if ((r & bit) == val) + return 0; + if (!in_interrupt()) + cond_resched(); + else + cpu_relax(); + } + return -ETIMEDOUT; +} + #include #if NDEBUG @@ -800,6 +844,49 @@ static int __init NCR5380_init(struct Scsi_Host *instance, int flags) return 0; } +/** + * NCR5380_maybe_reset_bus - Detect and correct bus wedge problems. + * @instance: adapter to check + * + * If the system crashed, it may have crashed with a connected target and + * the SCSI bus busy. Check for BUS FREE phase. If not, try to abort the + * currently established nexus, which we know nothing about. Failing that + * do a bus reset. + * + * Note that a bus reset will cause the chip to assert IRQ. + * + * Returns 0 if successful, otherwise -ENXIO. + */ + +static int NCR5380_maybe_reset_bus(struct Scsi_Host *instance) +{ + int pass; + + for (pass = 1; (NCR5380_read(STATUS_REG) & SR_BSY) && pass <= 6; ++pass) { + switch (pass) { + case 1: + case 3: + case 5: + shost_printk(KERN_ERR, instance, "SCSI bus busy, waiting up to five seconds\n"); + NCR5380_poll_politely(instance, + STATUS_REG, SR_BSY, 0, 5 * HZ); + break; + case 2: + shost_printk(KERN_ERR, instance, "bus busy, attempting abort\n"); + do_abort(instance); + break; + case 4: + shost_printk(KERN_ERR, instance, "bus busy, attempting reset\n"); + do_reset(instance); + break; + case 6: + shost_printk(KERN_ERR, instance, "bus locked solid\n"); + return -ENXIO; + } + } + return 0; +} + /** * NCR5380_exit - remove an NCR5380 * @instance: adapter to remove @@ -1741,6 +1828,32 @@ static int NCR5380_transfer_pio(struct Scsi_Host *instance, return -1; } +/** + * do_reset - issue a reset command + * @instance: adapter to reset + * + * Issue a reset sequence to the NCR5380 and try and get the bus + * back into sane shape. + * + * This clears the reset interrupt flag because there may be no handler for + * it. When the driver is initialized, the NCR5380_intr() handler has not yet + * been installed. And when in EH we may have released the ST DMA interrupt. + */ + +static void do_reset(struct Scsi_Host *instance) +{ + unsigned long flags; + + local_irq_save(flags); + NCR5380_write(TARGET_COMMAND_REG, + PHASE_SR_TO_TCR(NCR5380_read(STATUS_REG) & PHASE_MASK)); + NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_RST); + udelay(50); + NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); + (void)NCR5380_read(RESET_PARITY_INTERRUPT_REG); + local_irq_restore(flags); +} + /* * Function : do_abort (Scsi_Host *host) * -- cgit From 9c3f0e2b52ada30fe72beec27b83e91e12566609 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sun, 3 Jan 2016 16:05:11 +1100 Subject: atari_NCR5380: Remove RESET_BOOT, CONFIG_ATARI_SCSI_TOSHIBA_DELAY and CONFIG_ATARI_SCSI_RESET_BOOT The atari_NCR5380.c core driver now takes care of bus reset upon driver initialization if required (same as NCR5380.c). Move the Toshiba CD-ROM support into the core driver, enabled with a host flag, so that all NCR5380 drivers can make use of it. Drop the RESET_BOOT macros and the ATARI_SCSI_RESET_BOOT and ATARI_SCSI_TOSHIBA_DELAY Kconfig symbols, which are now redundant. Remove the atari_scsi_reset_boot(), mac_scsi_reset_boot() and sun3_scsi_reset_boot() routines. None of this duplicated code is needed now that all drivers can use NCR5380_maybe_reset_bus(). This brings atari_scsi, mac_scsi and sun3_scsi into line with all of the other NCR5380 drivers. The bus reset may raise an interrupt. That would be new behaviour for atari_scsi only when CONFIG_ATARI_SCSI_RESET_BOOT=n. The ST DMA interrupt is not assigned to atari_scsi at this stage, so CONFIG_ATARI_SCSI_RESET_BOOT=y may well be problematic already. Regardless, do_reset() now raises and clears the interrupt within local_irq_save/restore which should avoid problems. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Ondrej Zary Tested-by: Michael Schmitz Signed-off-by: Martin K. Petersen --- drivers/scsi/Kconfig | 17 ------------ drivers/scsi/NCR5380.c | 17 ++++++++++-- drivers/scsi/NCR5380.h | 1 + drivers/scsi/atari_NCR5380.c | 22 ++++++++++----- drivers/scsi/atari_scsi.c | 60 ++++++---------------------------------- drivers/scsi/mac_scsi.c | 65 +++++++------------------------------------- drivers/scsi/sun3_scsi.c | 47 +------------------------------- 7 files changed, 51 insertions(+), 178 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 37dce2380a52..abdd4360e219 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -1617,23 +1617,6 @@ config ATARI_SCSI ST-DMA, replacing ACSI). It does NOT support other schemes, like in the Hades (without DMA). -config ATARI_SCSI_TOSHIBA_DELAY - bool "Long delays for Toshiba CD-ROMs" - depends on ATARI_SCSI - help - This option increases the delay after a SCSI arbitration to - accommodate some flaky Toshiba CD-ROM drives. Say Y if you intend to - use a Toshiba CD-ROM drive; otherwise, the option is not needed and - would impact performance a bit, so say N. - -config ATARI_SCSI_RESET_BOOT - bool "Reset SCSI-devices at boottime" - depends on ATARI_SCSI - help - Reset the devices on your Atari whenever it boots. This makes the - boot process fractionally longer but may assist recovery from errors - that leave the devices with SCSI operations partway completed. - config MAC_SCSI tristate "Macintosh NCR5380 SCSI" depends on MAC && SCSI=y diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index 391ee8db5de1..7ccf2e37b6ad 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -618,7 +618,7 @@ static void prepare_info(struct Scsi_Host *instance) "base 0x%lx, irq %d, " "can_queue %d, cmd_per_lun %d, " "sg_tablesize %d, this_id %d, " - "flags { %s%s%s}, " + "flags { %s%s%s%s}, " #if defined(USLEEP_POLL) && defined(USLEEP_WAITLONG) "USLEEP_POLL %lu, USLEEP_WAITLONG %lu, " #endif @@ -630,6 +630,7 @@ static void prepare_info(struct Scsi_Host *instance) hostdata->flags & FLAG_NCR53C400 ? "NCR53C400 " : "", hostdata->flags & FLAG_DTC3181E ? "DTC3181E " : "", hostdata->flags & FLAG_NO_PSEUDO_DMA ? "NO_PSEUDO_DMA " : "", + hostdata->flags & FLAG_TOSHIBA_DELAY ? "TOSHIBA_DELAY " : "", #if defined(USLEEP_POLL) && defined(USLEEP_WAITLONG) USLEEP_POLL, USLEEP_WAITLONG, #endif @@ -831,6 +832,7 @@ static int NCR5380_init(struct Scsi_Host *instance, int flags) static int NCR5380_maybe_reset_bus(struct Scsi_Host *instance) { + struct NCR5380_hostdata *hostdata = shost_priv(instance); int pass; for (pass = 1; (NCR5380_read(STATUS_REG) & SR_BSY) && pass <= 6; ++pass) { @@ -849,6 +851,14 @@ static int NCR5380_maybe_reset_bus(struct Scsi_Host *instance) case 4: shost_printk(KERN_ERR, instance, "bus busy, attempting reset\n"); do_reset(instance); + /* Wait after a reset; the SCSI standard calls for + * 250ms, we wait 500ms to be on the safe side. + * But some Toshiba CD-ROMs need ten times that. + */ + if (hostdata->flags & FLAG_TOSHIBA_DELAY) + msleep(2500); + else + msleep(500); break; case 6: shost_printk(KERN_ERR, instance, "bus locked solid\n"); @@ -1253,7 +1263,10 @@ static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd) * a minimum so we'll udelay ceil(1.2) */ - udelay(2); + if (hostdata->flags & FLAG_TOSHIBA_DELAY) + udelay(15); + else + udelay(2); dprintk(NDEBUG_ARBITRATION, "scsi%d : won arbitration\n", instance->host_no); diff --git a/drivers/scsi/NCR5380.h b/drivers/scsi/NCR5380.h index 2057eaa66c20..f2f737a5f75a 100644 --- a/drivers/scsi/NCR5380.h +++ b/drivers/scsi/NCR5380.h @@ -243,6 +243,7 @@ #define FLAG_DTC3181E 16 /* DTC3181E */ #define FLAG_LATE_DMA_SETUP 32 /* Setup NCR before DMA H/W */ #define FLAG_TAGGED_QUEUING 64 /* as X3T9.2 spelled it */ +#define FLAG_TOSHIBA_DELAY 128 /* Allow for borken CD-ROMs */ #ifdef SUPPORT_TAGS struct tag_alloc { diff --git a/drivers/scsi/atari_NCR5380.c b/drivers/scsi/atari_NCR5380.c index a15b655aa2b0..de53cda4b153 100644 --- a/drivers/scsi/atari_NCR5380.c +++ b/drivers/scsi/atari_NCR5380.c @@ -674,13 +674,14 @@ static void prepare_info(struct Scsi_Host *instance) "base 0x%lx, irq %d, " "can_queue %d, cmd_per_lun %d, " "sg_tablesize %d, this_id %d, " - "flags { %s}, " + "flags { %s%s}, " "options { %s} ", instance->hostt->name, instance->io_port, instance->n_io_port, instance->base, instance->irq, instance->can_queue, instance->cmd_per_lun, instance->sg_tablesize, instance->this_id, hostdata->flags & FLAG_TAGGED_QUEUING ? "TAGGED_QUEUING " : "", + hostdata->flags & FLAG_TOSHIBA_DELAY ? "TOSHIBA_DELAY " : "", #ifdef DIFFERENTIAL "DIFFERENTIAL " #endif @@ -860,6 +861,7 @@ static int __init NCR5380_init(struct Scsi_Host *instance, int flags) static int NCR5380_maybe_reset_bus(struct Scsi_Host *instance) { + struct NCR5380_hostdata *hostdata = shost_priv(instance); int pass; for (pass = 1; (NCR5380_read(STATUS_REG) & SR_BSY) && pass <= 6; ++pass) { @@ -878,6 +880,14 @@ static int NCR5380_maybe_reset_bus(struct Scsi_Host *instance) case 4: shost_printk(KERN_ERR, instance, "bus busy, attempting reset\n"); do_reset(instance); + /* Wait after a reset; the SCSI standard calls for + * 250ms, we wait 500ms to be on the safe side. + * But some Toshiba CD-ROMs need ten times that. + */ + if (hostdata->flags & FLAG_TOSHIBA_DELAY) + msleep(2500); + else + msleep(500); break; case 6: shost_printk(KERN_ERR, instance, "bus locked solid\n"); @@ -1493,12 +1503,10 @@ static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd) * a minimum so we'll udelay ceil(1.2) */ -#ifdef CONFIG_ATARI_SCSI_TOSHIBA_DELAY - /* ++roman: But some targets (see above :-) seem to need a bit more... */ - udelay(15); -#else - udelay(2); -#endif + if (hostdata->flags & FLAG_TOSHIBA_DELAY) + udelay(15); + else + udelay(2); if (hostdata->connected) { NCR5380_write(MODE_REG, MR_BASE); diff --git a/drivers/scsi/atari_scsi.c b/drivers/scsi/atari_scsi.c index 1852ed6e8a48..5b233ccae962 100644 --- a/drivers/scsi/atari_scsi.c +++ b/drivers/scsi/atari_scsi.c @@ -164,15 +164,6 @@ static inline unsigned long SCSI_DMA_GETADR(void) #define HOSTDATA_DMALEN (((struct NCR5380_hostdata *) \ (atari_scsi_host->hostdata))->dma_len) -/* Time (in jiffies) to wait after a reset; the SCSI standard calls for 250ms, - * we usually do 0.5s to be on the safe side. But Toshiba CD-ROMs once more - * need ten times the standard value... */ -#ifndef CONFIG_ATARI_SCSI_TOSHIBA_DELAY -#define AFTER_RESET_DELAY (HZ/2) -#else -#define AFTER_RESET_DELAY (5*HZ/2) -#endif - #ifdef REAL_DMA static void atari_scsi_fetch_restbytes(void); #endif @@ -208,12 +199,12 @@ static int setup_cmd_per_lun = -1; module_param(setup_cmd_per_lun, int, 0); static int setup_sg_tablesize = -1; module_param(setup_sg_tablesize, int, 0); -#ifdef SUPPORT_TAGS static int setup_use_tagged_queuing = -1; module_param(setup_use_tagged_queuing, int, 0); -#endif static int setup_hostid = -1; module_param(setup_hostid, int, 0); +static int setup_toshiba_delay = -1; +module_param(setup_toshiba_delay, int, 0); #if defined(REAL_DMA) @@ -488,7 +479,7 @@ static int __init atari_scsi_setup(char *str) * Defaults depend on TT or Falcon, determined at run time. * Negative values mean don't change. */ - int ints[6]; + int ints[8]; get_options(str, ARRAY_SIZE(ints), ints); @@ -504,10 +495,11 @@ static int __init atari_scsi_setup(char *str) setup_sg_tablesize = ints[3]; if (ints[0] >= 4) setup_hostid = ints[4]; -#ifdef SUPPORT_TAGS if (ints[0] >= 5) setup_use_tagged_queuing = ints[5]; -#endif + /* ints[6] (use_pdma) is ignored */ + if (ints[0] >= 7) + setup_toshiba_delay = ints[7]; return 1; } @@ -516,38 +508,6 @@ __setup("atascsi=", atari_scsi_setup); #endif /* !MODULE */ -#ifdef CONFIG_ATARI_SCSI_RESET_BOOT -static void __init atari_scsi_reset_boot(void) -{ - unsigned long end; - - /* - * Do a SCSI reset to clean up the bus during initialization. No messing - * with the queues, interrupts, or locks necessary here. - */ - - printk("Atari SCSI: resetting the SCSI bus..."); - - /* get in phase */ - NCR5380_write(TARGET_COMMAND_REG, - PHASE_SR_TO_TCR(NCR5380_read(STATUS_REG))); - - /* assert RST */ - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_RST); - /* The min. reset hold time is 25us, so 40us should be enough */ - udelay(50); - /* reset RST and interrupt */ - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - NCR5380_read(RESET_PARITY_INTERRUPT_REG); - - end = jiffies + AFTER_RESET_DELAY; - while (time_before(jiffies, end)) - barrier(); - - printk(" done\n"); -} -#endif - #if defined(REAL_DMA) static unsigned long atari_scsi_dma_setup(struct Scsi_Host *instance, @@ -917,17 +877,13 @@ static int __init atari_scsi_probe(struct platform_device *pdev) } atari_scsi_host = instance; -#ifdef CONFIG_ATARI_SCSI_RESET_BOOT - atari_scsi_reset_boot(); -#endif - instance->irq = irq->start; host_flags |= IS_A_TT() ? 0 : FLAG_LATE_DMA_SETUP; - #ifdef SUPPORT_TAGS host_flags |= setup_use_tagged_queuing > 0 ? FLAG_TAGGED_QUEUING : 0; #endif + host_flags |= setup_toshiba_delay > 0 ? FLAG_TOSHIBA_DELAY : 0; NCR5380_init(instance, host_flags); @@ -975,6 +931,8 @@ static int __init atari_scsi_probe(struct platform_device *pdev) #endif } + NCR5380_maybe_reset_bus(instance); + error = scsi_add_host(instance, NULL); if (error) goto fail_host; diff --git a/drivers/scsi/mac_scsi.c b/drivers/scsi/mac_scsi.c index e49a9b1d7c3d..4d26ef93e656 100644 --- a/drivers/scsi/mac_scsi.c +++ b/drivers/scsi/mac_scsi.c @@ -49,8 +49,6 @@ #include "NCR5380.h" -#define RESET_BOOT - static int setup_can_queue = -1; module_param(setup_can_queue, int, 0); static int setup_cmd_per_lun = -1; @@ -63,17 +61,8 @@ static int setup_use_tagged_queuing = -1; module_param(setup_use_tagged_queuing, int, 0); static int setup_hostid = -1; module_param(setup_hostid, int, 0); - -/* Time (in jiffies) to wait after a reset; the SCSI standard calls for 250ms, - * we usually do 0.5s to be on the safe side. But Toshiba CD-ROMs once more - * need ten times the standard value... */ -#define TOSHIBA_DELAY - -#ifdef TOSHIBA_DELAY -#define AFTER_RESET_DELAY (5*HZ/2) -#else -#define AFTER_RESET_DELAY (HZ/2) -#endif +static int setup_toshiba_delay = -1; +module_param(setup_toshiba_delay, int, 0); /* * NCR 5380 register access functions @@ -92,12 +81,12 @@ static inline void macscsi_write(struct Scsi_Host *instance, int reg, int value) #ifndef MODULE static int __init mac_scsi_setup(char *str) { - int ints[7]; + int ints[8]; (void)get_options(str, ARRAY_SIZE(ints), ints); - if (ints[0] < 1 || ints[0] > 6) { - pr_err("Usage: mac5380=[,[,[,[,[,]]]]]\n"); + if (ints[0] < 1) { + pr_err("Usage: mac5380=[,[,[,[,[,[,]]]]]]\n"); return 0; } if (ints[0] >= 1) @@ -112,47 +101,14 @@ static int __init mac_scsi_setup(char *str) setup_use_tagged_queuing = ints[5]; if (ints[0] >= 6) setup_use_pdma = ints[6]; + if (ints[0] >= 7) + setup_toshiba_delay = ints[7]; return 1; } __setup("mac5380=", mac_scsi_setup); #endif /* !MODULE */ -#ifdef RESET_BOOT -/* - * Our 'bus reset on boot' function - */ - -static void mac_scsi_reset_boot(struct Scsi_Host *instance) -{ - unsigned long end; - - /* - * Do a SCSI reset to clean up the bus during initialization. No messing - * with the queues, interrupts, or locks necessary here. - */ - - printk(KERN_INFO "Macintosh SCSI: resetting the SCSI bus..." ); - - /* get in phase */ - NCR5380_write( TARGET_COMMAND_REG, - PHASE_SR_TO_TCR( NCR5380_read(STATUS_REG) )); - - /* assert RST */ - NCR5380_write( INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_RST ); - /* The min. reset hold time is 25us, so 40us should be enough */ - udelay( 50 ); - /* reset RST and interrupt */ - NCR5380_write( INITIATOR_COMMAND_REG, ICR_BASE ); - NCR5380_read( RESET_PARITY_INTERRUPT_REG ); - - for( end = jiffies + AFTER_RESET_DELAY; time_before(jiffies, end); ) - barrier(); - - printk(KERN_INFO " done\n" ); -} -#endif - #ifdef PSEUDO_DMA /* Pseudo-DMA: (Ove Edlund) @@ -421,13 +377,10 @@ static int __init mac_scsi_probe(struct platform_device *pdev) } else host_flags |= FLAG_NO_PSEUDO_DMA; -#ifdef RESET_BOOT - mac_scsi_reset_boot(instance); -#endif - #ifdef SUPPORT_TAGS host_flags |= setup_use_tagged_queuing > 0 ? FLAG_TAGGED_QUEUING : 0; #endif + host_flags |= setup_toshiba_delay > 0 ? FLAG_TOSHIBA_DELAY : 0; NCR5380_init(instance, host_flags); @@ -438,6 +391,8 @@ static int __init mac_scsi_probe(struct platform_device *pdev) goto fail_irq; } + NCR5380_maybe_reset_bus(instance); + error = scsi_add_host(instance, NULL); if (error) goto fail_host; diff --git a/drivers/scsi/sun3_scsi.c b/drivers/scsi/sun3_scsi.c index 836f5ca6d209..9376b3d8bfdc 100644 --- a/drivers/scsi/sun3_scsi.c +++ b/drivers/scsi/sun3_scsi.c @@ -86,10 +86,6 @@ module_param(setup_use_tagged_queuing, int, 0); static int setup_hostid = -1; module_param(setup_hostid, int, 0); -/* #define RESET_BOOT */ - -#define AFTER_RESET_DELAY (HZ/2) - /* ms to wait after hitting dma regs */ #define SUN3_DMA_DELAY 10 @@ -144,45 +140,6 @@ static inline void sun3_udc_write(unsigned short val, unsigned char reg) } #endif -#ifdef RESET_BOOT -static void sun3_scsi_reset_boot(struct Scsi_Host *instance) -{ - unsigned long end; - - /* - * Do a SCSI reset to clean up the bus during initialization. No - * messing with the queues, interrupts, or locks necessary here. - */ - - printk( "Sun3 SCSI: resetting the SCSI bus..." ); - - /* switch off SCSI IRQ - catch an interrupt without IRQ bit set else */ -// sun3_disable_irq( IRQ_SUN3_SCSI ); - - /* get in phase */ - NCR5380_write( TARGET_COMMAND_REG, - PHASE_SR_TO_TCR( NCR5380_read(STATUS_REG) )); - - /* assert RST */ - NCR5380_write( INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_RST ); - - /* The min. reset hold time is 25us, so 40us should be enough */ - udelay( 50 ); - - /* reset RST and interrupt */ - NCR5380_write( INITIATOR_COMMAND_REG, ICR_BASE ); - NCR5380_read( RESET_PARITY_INTERRUPT_REG ); - - for( end = jiffies + AFTER_RESET_DELAY; time_before(jiffies, end); ) - barrier(); - - /* switch on SCSI IRQ again */ -// sun3_enable_irq( IRQ_SUN3_SCSI ); - - printk( " done\n" ); -} -#endif - // safe bits for the CSR #define CSR_GOOD 0x060f @@ -631,9 +588,7 @@ static int __init sun3_scsi_probe(struct platform_device *pdev) dregs->ivect = VME_DATA24 | (instance->irq & 0xff); #endif -#ifdef RESET_BOOT - sun3_scsi_reset_boot(instance); -#endif + NCR5380_maybe_reset_bus(instance); error = scsi_add_host(instance, NULL); if (error) -- cgit From 3be1b3ea6de93b6b58c37dc3fafcf3ec228880ed Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sun, 3 Jan 2016 16:05:12 +1100 Subject: ncr5380: Simplify bus reset handlers Make use of do_reset() in the bus reset handler in atari_NCR5380.c. The version in NCR5380.c already does so. Keep them in sync. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Ondrej Zary Tested-by: Michael Schmitz Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.c | 20 +++++++++++--------- drivers/scsi/atari_NCR5380.c | 30 ++++++++++++------------------ 2 files changed, 23 insertions(+), 27 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index 7ccf2e37b6ad..b9755000b48f 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -668,7 +668,7 @@ static void prepare_info(struct Scsi_Host *instance) * Locks: called functions disable irqs */ -static void NCR5380_print_status(struct Scsi_Host *instance) +static void __maybe_unused NCR5380_print_status(struct Scsi_Host *instance) { NCR5380_dprint(NDEBUG_ANY, instance); NCR5380_dprint_phase(NDEBUG_ANY, instance); @@ -2693,24 +2693,26 @@ static int NCR5380_abort(struct scsi_cmnd *cmd) } -/* - * Function : int NCR5380_bus_reset (struct scsi_cmnd *cmd) - * - * Purpose : reset the SCSI bus. - * - * Returns : SUCCESS +/** + * NCR5380_bus_reset - reset the SCSI bus + * @cmd: SCSI command undergoing EH * - * Locks: host lock taken by caller + * Returns SUCCESS */ static int NCR5380_bus_reset(struct scsi_cmnd *cmd) { struct Scsi_Host *instance = cmd->device->host; + spin_lock_irq(instance->host_lock); + +#if (NDEBUG & NDEBUG_ANY) + scmd_printk(KERN_INFO, cmd, "performing bus reset\n"); NCR5380_print_status(instance); +#endif - spin_lock_irq(instance->host_lock); do_reset(instance); + spin_unlock_irq(instance->host_lock); return SUCCESS; diff --git a/drivers/scsi/atari_NCR5380.c b/drivers/scsi/atari_NCR5380.c index de53cda4b153..5a9974e1943c 100644 --- a/drivers/scsi/atari_NCR5380.c +++ b/drivers/scsi/atari_NCR5380.c @@ -719,7 +719,7 @@ static void lprint_Scsi_Cmnd(struct scsi_cmnd *cmd) printk("\n"); } -static void NCR5380_print_status(struct Scsi_Host *instance) +static void __maybe_unused NCR5380_print_status(struct Scsi_Host *instance) { struct NCR5380_hostdata *hostdata; struct scsi_cmnd *ptr; @@ -2982,13 +2982,11 @@ int NCR5380_abort(struct scsi_cmnd *cmd) } -/* - * Function : int NCR5380_reset (struct scsi_cmnd *cmd) - * - * Purpose : reset the SCSI bus. - * - * Returns : SUCCESS or FAILURE +/** + * NCR5380_bus_reset - reset the SCSI bus + * @cmd: SCSI command undergoing EH * + * Returns SUCCESS */ static int NCR5380_bus_reset(struct scsi_cmnd *cmd) @@ -2998,22 +2996,19 @@ static int NCR5380_bus_reset(struct scsi_cmnd *cmd) int i; unsigned long flags; + local_irq_save(flags); + +#if (NDEBUG & NDEBUG_ANY) + scmd_printk(KERN_INFO, cmd, "performing bus reset\n"); NCR5380_print_status(instance); +#endif + + do_reset(instance); - /* get in phase */ - NCR5380_write(TARGET_COMMAND_REG, - PHASE_SR_TO_TCR(NCR5380_read(STATUS_REG))); - /* assert RST */ - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_RST); - udelay(40); /* reset NCR registers */ - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); NCR5380_write(MODE_REG, MR_BASE); NCR5380_write(TARGET_COMMAND_REG, 0); NCR5380_write(SELECT_ENABLE_REG, 0); - /* ++roman: reset interrupt condition! otherwise no interrupts don't get - * through anymore ... */ - (void)NCR5380_read(RESET_PARITY_INTERRUPT_REG); /* After the reset, there are no more connected or disconnected commands * and no busy units; so clear the low-level status here to avoid @@ -3028,7 +3023,6 @@ static int NCR5380_bus_reset(struct scsi_cmnd *cmd) if (hostdata->disconnected_queue) dprintk(NDEBUG_ABORT, "scsi%d: reset aborted disconnected command(s)\n", H_NO(cmd)); - local_irq_save(flags); hostdata->issue_queue = NULL; hostdata->connected = NULL; hostdata->disconnected_queue = NULL; -- cgit From 9b68d3415b0838a80f9a32dbedd385bf5d83bef8 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sun, 3 Jan 2016 16:05:13 +1100 Subject: ncr5380: Remove unused hostdata->aborted flag The aborted flag was introduced in v1.1.38 but never used. Remove it. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Ondrej Zary Tested-by: Michael Schmitz Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.c | 2 -- drivers/scsi/NCR5380.h | 1 - drivers/scsi/atari_NCR5380.c | 2 -- 3 files changed, 5 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index b9755000b48f..663773e66872 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -781,7 +781,6 @@ static int NCR5380_init(struct Scsi_Host *instance, int flags) if(in_interrupt()) printk(KERN_ERR "NCR5380_init called with interrupts off!\n"); - hostdata->aborted = 0; hostdata->id_mask = 1 << instance->this_id; for (i = hostdata->id_mask; i <= 0x80; i <<= 1) if (i > hostdata->id_mask) @@ -2574,7 +2573,6 @@ static int NCR5380_abort(struct scsi_cmnd *cmd) if (hostdata->connected == cmd) { dprintk(NDEBUG_ABORT, "scsi%d : aborting connected command\n", instance->host_no); - hostdata->aborted = 1; /* * We should perform BSY checking, and make sure we haven't slipped * into BUS FREE. diff --git a/drivers/scsi/NCR5380.h b/drivers/scsi/NCR5380.h index f2f737a5f75a..4a31f41b6027 100644 --- a/drivers/scsi/NCR5380.h +++ b/drivers/scsi/NCR5380.h @@ -271,7 +271,6 @@ struct NCR5380_hostdata { volatile int restart_select; /* we have disconnected, used to restart NCR5380_select() */ - volatile unsigned aborted:1; /* flag, says aborted */ int flags; unsigned long time_expires; /* in jiffies, set prior to sleeping */ int select_time; /* timer in select for target response */ diff --git a/drivers/scsi/atari_NCR5380.c b/drivers/scsi/atari_NCR5380.c index 5a9974e1943c..463d2d47661a 100644 --- a/drivers/scsi/atari_NCR5380.c +++ b/drivers/scsi/atari_NCR5380.c @@ -813,7 +813,6 @@ static int __init NCR5380_init(struct Scsi_Host *instance, int flags) SETUP_HOSTDATA(instance); hostdata->host = instance; - hostdata->aborted = 0; hostdata->id_mask = 1 << instance->this_id; hostdata->id_higher_mask = 0; for (i = hostdata->id_mask; i <= 0x80; i <<= 1) @@ -2834,7 +2833,6 @@ int NCR5380_abort(struct scsi_cmnd *cmd) */ if (do_abort(instance) == 0) { - hostdata->aborted = 1; hostdata->connected = NULL; cmd->result = DID_ABORT << 16; #ifdef SUPPORT_TAGS -- cgit From 206cc031ad591f2759ba4e82d35fbb2050a2648b Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sun, 3 Jan 2016 16:05:14 +1100 Subject: ncr5380: Remove redundant register writes Remove the duplicate write to the Select Enable Register that appeared in v1.1.38. Also remove the redundant write to Initiator Command Register prior to calling do_abort(). Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Ondrej Zary Tested-by: Michael Schmitz Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.c | 2 -- drivers/scsi/atari_NCR5380.c | 3 --- 2 files changed, 5 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index 663773e66872..b75c92967d6e 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -1384,7 +1384,6 @@ part2: cmd->scsi_done(cmd); NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); dprintk(NDEBUG_SELECTION, "scsi%d : target did not respond within 250ms\n", instance->host_no); - NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); return 0; } hostdata->targets_present |= (1 << scmd_id(cmd)); @@ -2076,7 +2075,6 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { scmd_printk(KERN_INFO, cmd, "switching to slow handshake\n"); cmd->device->borken = 1; - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN); sink = 1; do_abort(instance); cmd->result = DID_ERROR << 16; diff --git a/drivers/scsi/atari_NCR5380.c b/drivers/scsi/atari_NCR5380.c index 463d2d47661a..df42610df6e4 100644 --- a/drivers/scsi/atari_NCR5380.c +++ b/drivers/scsi/atari_NCR5380.c @@ -1640,7 +1640,6 @@ static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd) cmd->scsi_done(cmd); NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); dprintk(NDEBUG_SELECTION, "scsi%d: target did not respond within 250ms\n", HOSTNO); - NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); return 0; } @@ -2192,8 +2191,6 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) scmd_printk(KERN_INFO, cmd, "switching to slow handshake\n"); cmd->device->borken = 1; - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | - ICR_ASSERT_ATN); sink = 1; do_abort(instance); cmd->result = DID_ERROR << 16; -- cgit From 6323876f5539e808a293395b1960427c62d2436d Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sun, 3 Jan 2016 16:05:15 +1100 Subject: ncr5380: Use return instead of goto in NCR5380_select() The "failed" label in NCR5380_select() is not helpful. Some failures return 0, others -1. Use return instead of goto to improve clarity and brevity, like atari_NCR5380.c does. Fix the relevant comments. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Ondrej Zary Tested-by: Michael Schmitz Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.c | 30 ++++++++---------------------- drivers/scsi/atari_NCR5380.c | 6 +++--- 2 files changed, 11 insertions(+), 25 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index b75c92967d6e..ce80a5c65eb3 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -997,16 +997,6 @@ static void NCR5380_main(struct work_struct *work) */ dprintk(NDEBUG_MAIN|NDEBUG_QUEUES, "scsi%d : main() : command for target %d lun %llu removed from issue_queue\n", instance->host_no, tmp->device->id, tmp->device->lun); - /* - * A successful selection is defined as one that - * leaves us with the command connected and - * in hostdata->connected, OR has terminated the - * command. - * - * With successful commands, we fall through - * and see if we can do an information transfer, - * with failures we will restart. - */ hostdata->selecting = NULL; /* RvC: have to preset this to indicate a new command is being performed */ @@ -1162,9 +1152,10 @@ static irqreturn_t NCR5380_intr(int dummy, void *dev_id) * Inputs : instance - instantiation of the 5380 driver on which this * target lives, cmd - SCSI command to execute. * - * Returns : -1 if selection could not execute for some reason, - * 0 if selection succeeded or failed because the target - * did not respond. + * Returns : -1 if selection failed but should be retried. + * 0 if selection failed and should not be retried. + * 0 if selection succeeded completely (hostdata->connected == cmd). + * 0 if selection in progress (hostdata->selecting == cmd). * * Side effects : * If bus busy, arbitration failed, etc, NCR5380_select() will exit @@ -1224,7 +1215,7 @@ static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd) printk(KERN_DEBUG "scsi: arbitration timeout at %d\n", __LINE__); NCR5380_write(MODE_REG, MR_BASE); NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); - goto failed; + return -1; } dprintk(NDEBUG_ARBITRATION, "scsi%d : arbitration complete\n", instance->host_no); @@ -1242,7 +1233,7 @@ static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd) if ((NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_LOST) || (NCR5380_read(CURRENT_SCSI_DATA_REG) & hostdata->id_higher_mask) || (NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_LOST)) { NCR5380_write(MODE_REG, MR_BASE); dprintk(NDEBUG_ARBITRATION, "scsi%d : lost arbitration, deasserting MR_ARBITRATE\n", instance->host_no); - goto failed; + return -1; } NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_SEL); @@ -1255,7 +1246,7 @@ static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd) NCR5380_write(MODE_REG, MR_BASE); NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); dprintk(NDEBUG_ARBITRATION, "scsi%d : lost arbitration, deasserting ICR_ASSERT_SEL\n", instance->host_no); - goto failed; + return -1; } /* * Again, bus clear + bus settle time is 1.2us, however, this is @@ -1412,7 +1403,7 @@ part2: if(err) { printk(KERN_ERR "scsi%d: timeout at NCR5380.c:%d\n", instance->host_no, __LINE__); NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); - goto failed; + return -1; } dprintk(NDEBUG_SELECTION, "scsi%d : target %d selected, going into MESSAGE OUT phase.\n", instance->host_no, cmd->device->id); @@ -1433,11 +1424,6 @@ part2: initialize_SCp(cmd); return 0; - - /* Selection failed */ -failed: - return -1; - } /* diff --git a/drivers/scsi/atari_NCR5380.c b/drivers/scsi/atari_NCR5380.c index df42610df6e4..6c382d1c67ff 100644 --- a/drivers/scsi/atari_NCR5380.c +++ b/drivers/scsi/atari_NCR5380.c @@ -1382,9 +1382,9 @@ static irqreturn_t NCR5380_intr(int irq, void *dev_id) * Inputs : instance - instantiation of the 5380 driver on which this * target lives, cmd - SCSI command to execute. * - * Returns : -1 if selection could not execute for some reason, - * 0 if selection succeeded or failed because the target - * did not respond. + * Returns : -1 if selection failed but should be retried. + * 0 if selection failed and should not be retried. + * 0 if selection succeeded completely (hostdata->connected == cmd). * * Side effects : * If bus busy, arbitration failed, etc, NCR5380_select() will exit -- cgit From ac9399d09544525ff4713ab942cb44a7cea29a84 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sun, 3 Jan 2016 16:05:16 +1100 Subject: ncr5380: Always escalate bad target time-out in NCR5380_select() Remove the restart_select and targets_present variables introduced in Linux v1.1.38. The former was used only for a questionable debug printk and the latter "so we can call a select failure a retryable condition". Well, retrying select failure in general is a different problem to a target that doesn't assert BSY. We need to handle these two cases differently; the latter case can be left to the SCSI ML. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Ondrej Zary Tested-by: Michael Schmitz Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.c | 13 ------------- drivers/scsi/NCR5380.h | 6 ------ drivers/scsi/atari_NCR5380.c | 13 ------------- 3 files changed, 32 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index ce80a5c65eb3..051684b08a77 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -790,7 +790,6 @@ static int NCR5380_init(struct Scsi_Host *instance, int flags) #ifdef REAL_DMA hostdata->dmalen = 0; #endif - hostdata->targets_present = 0; hostdata->connected = NULL; hostdata->issue_queue = NULL; hostdata->disconnected_queue = NULL; @@ -1186,8 +1185,6 @@ static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd) if (hostdata->selecting) goto part2; - hostdata->restart_select = 0; - NCR5380_dprint(NDEBUG_ARBITRATION, instance); dprintk(NDEBUG_ARBITRATION, "scsi%d : starting arbitration, id = %d\n", instance->host_no, instance->this_id); @@ -1363,21 +1360,12 @@ part2: if (!(NCR5380_read(STATUS_REG) & SR_BSY)) { NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - if (hostdata->targets_present & (1 << scmd_id(cmd))) { - printk(KERN_DEBUG "scsi%d : weirdness\n", instance->host_no); - if (hostdata->restart_select) - printk(KERN_DEBUG "\trestart select\n"); - NCR5380_dprint(NDEBUG_SELECTION, instance); - NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); - return -1; - } cmd->result = DID_BAD_TARGET << 16; cmd->scsi_done(cmd); NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); dprintk(NDEBUG_SELECTION, "scsi%d : target did not respond within 250ms\n", instance->host_no); return 0; } - hostdata->targets_present |= (1 << scmd_id(cmd)); /* * Since we followed the SCSI spec, and raised ATN while SEL @@ -2382,7 +2370,6 @@ static void NCR5380_reselect(struct Scsi_Host *instance) { */ NCR5380_write(MODE_REG, MR_BASE); - hostdata->restart_select = 1; target_mask = NCR5380_read(CURRENT_SCSI_DATA_REG) & ~(hostdata->id_mask); dprintk(NDEBUG_SELECTION, "scsi%d : reselect\n", instance->host_no); diff --git a/drivers/scsi/NCR5380.h b/drivers/scsi/NCR5380.h index 4a31f41b6027..25e28add0db8 100644 --- a/drivers/scsi/NCR5380.h +++ b/drivers/scsi/NCR5380.h @@ -257,9 +257,6 @@ struct NCR5380_hostdata { NCR5380_implementation_fields; /* implementation specific */ struct Scsi_Host *host; /* Host backpointer */ unsigned char id_mask, id_higher_mask; /* 1 << id, all bits greater */ - unsigned char targets_present; /* targets we have connected - to, so we can call a select - failure a retryable condition */ volatile unsigned char busy[8]; /* index = target, bit = lun */ #if defined(REAL_DMA) || defined(REAL_DMA_POLL) volatile int dma_len; /* requested length of DMA */ @@ -268,9 +265,6 @@ struct NCR5380_hostdata { volatile struct scsi_cmnd *connected; /* currently connected command */ volatile struct scsi_cmnd *issue_queue; /* waiting to be issued */ volatile struct scsi_cmnd *disconnected_queue; /* waiting for reconnect */ - volatile int restart_select; /* we have disconnected, - used to restart - NCR5380_select() */ int flags; unsigned long time_expires; /* in jiffies, set prior to sleeping */ int select_time; /* timer in select for target response */ diff --git a/drivers/scsi/atari_NCR5380.c b/drivers/scsi/atari_NCR5380.c index 6c382d1c67ff..80f6830d9f3c 100644 --- a/drivers/scsi/atari_NCR5380.c +++ b/drivers/scsi/atari_NCR5380.c @@ -826,7 +826,6 @@ static int __init NCR5380_init(struct Scsi_Host *instance, int flags) #if defined (REAL_DMA) hostdata->dma_len = 0; #endif - hostdata->targets_present = 0; hostdata->connected = NULL; hostdata->issue_queue = NULL; hostdata->disconnected_queue = NULL; @@ -1409,7 +1408,6 @@ static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd) unsigned long timeout; unsigned long flags; - hostdata->restart_select = 0; NCR5380_dprint(NDEBUG_ARBITRATION, instance); dprintk(NDEBUG_ARBITRATION, "scsi%d: starting arbitration, id = %d\n", HOSTNO, instance->this_id); @@ -1625,14 +1623,6 @@ static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd) if (!(NCR5380_read(STATUS_REG) & SR_BSY)) { NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - if (hostdata->targets_present & (1 << cmd->device->id)) { - printk(KERN_ERR "scsi%d: weirdness\n", HOSTNO); - if (hostdata->restart_select) - printk(KERN_NOTICE "\trestart select\n"); - NCR5380_dprint(NDEBUG_ANY, instance); - NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); - return -1; - } cmd->result = DID_BAD_TARGET << 16; #ifdef SUPPORT_TAGS cmd_free_tag(cmd); @@ -1643,8 +1633,6 @@ static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd) return 0; } - hostdata->targets_present |= (1 << cmd->device->id); - /* * Since we followed the SCSI spec, and raised ATN while SEL * was true but before BSY was false during selection, the information @@ -2605,7 +2593,6 @@ static void NCR5380_reselect(struct Scsi_Host *instance) */ NCR5380_write(MODE_REG, MR_BASE); - hostdata->restart_select = 1; target_mask = NCR5380_read(CURRENT_SCSI_DATA_REG) & ~(hostdata->id_mask); -- cgit From 1f1b0c74dfaf6264d239823ed5aeb8dcdd62838c Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sun, 3 Jan 2016 16:05:17 +1100 Subject: ncr5380: Proceed with next command after NCR5380_select() calls scsi_done If a target disappears from the SCSI bus, NCR5380_select() may subsequently fail with a time-out. In this situation, scsi_done is called and NCR5380_select() returns 0. Both hostdata->connected and hostdata->selecting are NULL and the main loop should proceed with the next command in the issue queue. Clarify this logic. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Ondrej Zary Tested-by: Michael Schmitz Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.c | 8 ++++++-- drivers/scsi/atari_NCR5380.c | 8 ++++---- 2 files changed, 10 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index 051684b08a77..4ef4fc7bd6eb 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -1007,14 +1007,18 @@ static void NCR5380_main(struct work_struct *work) */ if (!NCR5380_select(instance, tmp)) { - break; + /* OK or bad target */ } else { + /* Need to retry */ LIST(tmp, hostdata->issue_queue); tmp->host_scribble = (unsigned char *) hostdata->issue_queue; hostdata->issue_queue = tmp; done = 0; dprintk(NDEBUG_MAIN|NDEBUG_QUEUES, "scsi%d : main(): select() failed, returned to issue_queue\n", instance->host_no); } + if (hostdata->connected || + hostdata->selecting) + break; /* lock held here still */ } /* if target/lun is not busy */ } /* for */ @@ -1024,7 +1028,7 @@ static void NCR5380_main(struct work_struct *work) tmp = (struct scsi_cmnd *) hostdata->selecting; /* Selection will drop and retake the lock */ if (!NCR5380_select(instance, tmp)) { - /* Ok ?? */ + /* OK or bad target */ } else { /* RvC: device failed, so we wait a long time this is needed for Mustek scanners, that diff --git a/drivers/scsi/atari_NCR5380.c b/drivers/scsi/atari_NCR5380.c index 80f6830d9f3c..bedc7e2efa1d 100644 --- a/drivers/scsi/atari_NCR5380.c +++ b/drivers/scsi/atari_NCR5380.c @@ -1139,13 +1139,13 @@ static void NCR5380_main(struct work_struct *work) cmd_get_tag(tmp, tmp->cmnd[0] != REQUEST_SENSE); #endif if (!NCR5380_select(instance, tmp)) { + /* OK or bad target */ local_irq_disable(); hostdata->retain_dma_intr--; - /* release if target did not response! */ maybe_release_dma_irq(instance); local_irq_restore(flags); - break; } else { + /* Need to retry */ local_irq_disable(); LIST(tmp, hostdata->issue_queue); SET_NEXT(tmp, hostdata->issue_queue); @@ -1157,9 +1157,9 @@ static void NCR5380_main(struct work_struct *work) local_irq_restore(flags); dprintk(NDEBUG_MAIN, "scsi%d: main(): select() failed, " "returned to issue_queue\n", HOSTNO); - if (hostdata->connected) - break; } + if (hostdata->connected) + break; } /* if target/lun/target queue is not busy */ } /* for issue_queue */ } /* if (!hostdata->connected) */ -- cgit From cf13b0837d7da2f3dce96e1f364fade13c8648ba Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sun, 3 Jan 2016 16:05:18 +1100 Subject: ncr5380: Keep BSY asserted when entering SELECTION phase NCR5380.c is not compliant with the SCSI-2 standard (at least, not with the draft revision 10L that I have to refer to). The selection algorithm in atari_NCR5380.c is correct, so use that. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Ondrej Zary Tested-by: Michael Schmitz Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.c | 8 +++++++- drivers/scsi/atari_NCR5380.c | 7 ++++--- 2 files changed, 11 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index 4ef4fc7bd6eb..d51aad3a3bfa 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -1236,7 +1236,13 @@ static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd) dprintk(NDEBUG_ARBITRATION, "scsi%d : lost arbitration, deasserting MR_ARBITRATE\n", instance->host_no); return -1; } - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_SEL); + + /* After/during arbitration, BSY should be asserted. + * IBM DPES-31080 Version S31Q works now + * Tnx to Thomas_Roesch@m2.maus.de for finding this! (Roman) + */ + NCR5380_write(INITIATOR_COMMAND_REG, + ICR_BASE | ICR_ASSERT_SEL | ICR_ASSERT_BSY); if (!(hostdata->flags & FLAG_DTC3181E) && /* RvC: DTC3181E has some trouble with this diff --git a/drivers/scsi/atari_NCR5380.c b/drivers/scsi/atari_NCR5380.c index bedc7e2efa1d..1dd341ef89d4 100644 --- a/drivers/scsi/atari_NCR5380.c +++ b/drivers/scsi/atari_NCR5380.c @@ -1480,9 +1480,10 @@ static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd) return -1; } - /* after/during arbitration, BSY should be asserted. - IBM DPES-31080 Version S31Q works now */ - /* Tnx to Thomas_Roesch@m2.maus.de for finding this! (Roman) */ + /* After/during arbitration, BSY should be asserted. + * IBM DPES-31080 Version S31Q works now + * Tnx to Thomas_Roesch@m2.maus.de for finding this! (Roman) + */ NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_SEL | ICR_ASSERT_BSY); -- cgit From 4d029e9ae9c382b149b16632f49970d8b215e2da Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sun, 3 Jan 2016 16:05:19 +1100 Subject: ncr5380: Eliminate USLEEP_WAITLONG delay Linux 2.1.105 introduced the USLEEP_WAITLONG delay, apparently "needed for Mustek scanners". It is intended to stall the issue queue for 5 seconds. There are a number of problems with this. 1. Only g_NCR5380 enables the delay, which implies that the other five drivers using the NCR5380.c core driver remain incompatible with Mustek scanners. 2. The delay is not implemented by atari_NCR5380.c, which is problematic for re-unifying the two core driver forks. 3. The delay is implemented using NCR5380_set_timer() which makes it unreliable. A new command queued by the mid-layer cancels the delay. 4. The delay is applied indiscriminately in several situations in which NCR5380_select() returns -1. These are-- reselection by the target, failure of the target to assert BSY, and failure of the target to assert REQ. It's clear from the comments that USLEEP_WAITLONG is not relevant to the reselection case. And reportedly, these scanners do not disconnect. 5. atari_NCR5380.c was forked before Linux 2.1.105, so it was spared some of the damage done to NCR5380.c. In this case, the atari_NCR5380.c core driver was more standard-compliant and may not have needed any workaround like the USLEEP_WAITLONG kludge. The compliance issue was addressed in the previous patch. If these scanners still don't work, we need a better solution. Retrying selection until EH aborts a command offers equivalent robustness. Bugs in the existing driver prevent EH working correctly but this is addressed in a subsequent patch. Remove USLEEP_WAITLONG. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Ondrej Zary Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.c | 19 +++++-------------- drivers/scsi/g_NCR5380.c | 1 - 2 files changed, 5 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index d51aad3a3bfa..103c23e6d565 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -468,10 +468,6 @@ static void NCR5380_print_phase(struct Scsi_Host *instance) #ifndef USLEEP_POLL #define USLEEP_POLL msecs_to_jiffies(200) #endif -#ifndef USLEEP_WAITLONG -/* RvC: (reasonable time to wait on select error) */ -#define USLEEP_WAITLONG USLEEP_SLEEP -#endif /* * Function : int should_disconnect (unsigned char cmd) @@ -619,8 +615,8 @@ static void prepare_info(struct Scsi_Host *instance) "can_queue %d, cmd_per_lun %d, " "sg_tablesize %d, this_id %d, " "flags { %s%s%s%s}, " -#if defined(USLEEP_POLL) && defined(USLEEP_WAITLONG) - "USLEEP_POLL %lu, USLEEP_WAITLONG %lu, " +#if defined(USLEEP_POLL) && defined(USLEEP_SLEEP) + "USLEEP_POLL %lu, USLEEP_SLEEP %lu, " #endif "options { %s} ", instance->hostt->name, instance->io_port, instance->n_io_port, @@ -631,8 +627,8 @@ static void prepare_info(struct Scsi_Host *instance) hostdata->flags & FLAG_DTC3181E ? "DTC3181E " : "", hostdata->flags & FLAG_NO_PSEUDO_DMA ? "NO_PSEUDO_DMA " : "", hostdata->flags & FLAG_TOSHIBA_DELAY ? "TOSHIBA_DELAY " : "", -#if defined(USLEEP_POLL) && defined(USLEEP_WAITLONG) - USLEEP_POLL, USLEEP_WAITLONG, +#if defined(USLEEP_POLL) && defined(USLEEP_SLEEP) + USLEEP_POLL, USLEEP_SLEEP, #endif #ifdef AUTOPROBE_IRQ "AUTOPROBE_IRQ " @@ -1030,15 +1026,10 @@ static void NCR5380_main(struct work_struct *work) if (!NCR5380_select(instance, tmp)) { /* OK or bad target */ } else { - /* RvC: device failed, so we wait a long time - this is needed for Mustek scanners, that - do not respond to commands immediately - after a scan */ - printk(KERN_DEBUG "scsi%d: device %d did not respond in time\n", instance->host_no, tmp->device->id); LIST(tmp, hostdata->issue_queue); tmp->host_scribble = (unsigned char *) hostdata->issue_queue; hostdata->issue_queue = tmp; - NCR5380_set_timer(hostdata, USLEEP_WAITLONG); + done = 0; } } /* if hostdata->selecting */ if (hostdata->connected diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c index ffbb07b0e9e8..fa9f6d41548b 100644 --- a/drivers/scsi/g_NCR5380.c +++ b/drivers/scsi/g_NCR5380.c @@ -59,7 +59,6 @@ /* settings for DTC3181E card with only Mustek scanner attached */ #define USLEEP_POLL msecs_to_jiffies(10) #define USLEEP_SLEEP msecs_to_jiffies(200) -#define USLEEP_WAITLONG msecs_to_jiffies(5000) #define AUTOPROBE_IRQ -- cgit From e52bbd5ccf53d2a73e524adb26b6d8a4f810ccb4 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sun, 3 Jan 2016 16:05:20 +1100 Subject: ncr5380: Cleanup bogus {request,release}_region() calls Commit 8b801ead3d7a ("[ARM] rpc: update Acorn SCSI drivers to modern ecard interfaces") neglected to remove a request_region() call in cumana_1.c. Commit eda32612f7b2 ("[PATCH] give all LLDD driver a ->release method") in history/history.git added some pointless release_region() calls in dtc.c, pas16.c and t128.c. Fix these issues. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/arm/cumana_1.c | 6 ------ drivers/scsi/dtc.c | 2 -- drivers/scsi/pas16.c | 2 -- drivers/scsi/t128.c | 2 -- 4 files changed, 12 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/arm/cumana_1.c b/drivers/scsi/arm/cumana_1.c index c7dc65e39cdb..3b5ff105f1d6 100644 --- a/drivers/scsi/arm/cumana_1.c +++ b/drivers/scsi/arm/cumana_1.c @@ -245,12 +245,6 @@ static int cumanascsi1_probe(struct expansion_card *ec, priv(host)->ctrl = 0; writeb(0, priv(host)->base + CTRL); - host->n_io_port = 255; - if (!(request_region(host->io_port, host->n_io_port, "CumanaSCSI-1"))) { - ret = -EBUSY; - goto out_unmap; - } - ret = request_irq(host->irq, cumanascsi_intr, 0, "CumanaSCSI-1", host); if (ret) { diff --git a/drivers/scsi/dtc.c b/drivers/scsi/dtc.c index 02a5532f4267..698bea067af9 100644 --- a/drivers/scsi/dtc.c +++ b/drivers/scsi/dtc.c @@ -423,8 +423,6 @@ static int dtc_release(struct Scsi_Host *shost) if (shost->irq != NO_IRQ) free_irq(shost->irq, shost); NCR5380_exit(shost); - if (shost->io_port && shost->n_io_port) - release_region(shost->io_port, shost->n_io_port); scsi_unregister(shost); iounmap(hostdata->base); return 0; diff --git a/drivers/scsi/pas16.c b/drivers/scsi/pas16.c index c316ff7ffef6..e5c76eefa5e0 100644 --- a/drivers/scsi/pas16.c +++ b/drivers/scsi/pas16.c @@ -540,8 +540,6 @@ static int pas16_release(struct Scsi_Host *shost) if (shost->irq != NO_IRQ) free_irq(shost->irq, shost); NCR5380_exit(shost); - if (shost->io_port && shost->n_io_port) - release_region(shost->io_port, shost->n_io_port); scsi_unregister(shost); return 0; } diff --git a/drivers/scsi/t128.c b/drivers/scsi/t128.c index d5e6b676d75e..3adcae1150d2 100644 --- a/drivers/scsi/t128.c +++ b/drivers/scsi/t128.c @@ -255,8 +255,6 @@ static int t128_release(struct Scsi_Host *shost) if (shost->irq != NO_IRQ) free_irq(shost->irq, shost); NCR5380_exit(shost); - if (shost->io_port && shost->n_io_port) - release_region(shost->io_port, shost->n_io_port); scsi_unregister(shost); iounmap(hostdata->base); return 0; -- cgit From 0ad0eff98fec3c940ec199047ff580abaaa5bb1a Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sun, 3 Jan 2016 16:05:21 +1100 Subject: ncr5380: Introduce unbound workqueue Allocate a work queue that will permit busy waiting and sleeping. This means NCR5380_init() can potentially fail, so add this error path. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Ondrej Zary Tested-by: Michael Schmitz Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.c | 15 +++++++++++---- drivers/scsi/NCR5380.h | 1 + drivers/scsi/arm/cumana_1.c | 8 ++++++-- drivers/scsi/arm/oak.c | 8 ++++++-- drivers/scsi/atari_NCR5380.c | 8 +++++++- drivers/scsi/atari_scsi.c | 5 ++++- drivers/scsi/dmx3191d.c | 17 +++++++++++------ drivers/scsi/dtc.c | 11 +++++++++-- drivers/scsi/g_NCR5380.c | 31 +++++++++++++++---------------- drivers/scsi/mac_scsi.c | 5 ++++- drivers/scsi/pas16.c | 10 ++++++++-- drivers/scsi/sun3_scsi.c | 5 ++++- drivers/scsi/t128.c | 13 ++++++++++--- 13 files changed, 96 insertions(+), 41 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index 103c23e6d565..a66fffc83475 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -514,7 +514,7 @@ static int should_disconnect(unsigned char cmd) static void NCR5380_set_timer(struct NCR5380_hostdata *hostdata, unsigned long timeout) { hostdata->time_expires = jiffies + timeout; - schedule_delayed_work(&hostdata->coroutine, timeout); + queue_delayed_work(hostdata->work_q, &hostdata->coroutine, timeout); } @@ -791,7 +791,12 @@ static int NCR5380_init(struct Scsi_Host *instance, int flags) hostdata->disconnected_queue = NULL; INIT_DELAYED_WORK(&hostdata->coroutine, NCR5380_main); - + hostdata->work_q = alloc_workqueue("ncr5380_%d", + WQ_UNBOUND | WQ_MEM_RECLAIM, + 1, instance->host_no); + if (!hostdata->work_q) + return -ENOMEM; + /* The CHECK code seems to break the 53C400. Will check it later maybe */ if (flags & FLAG_NCR53C400) hostdata->flags = FLAG_HAS_LAST_BYTE_SENT | flags; @@ -872,6 +877,7 @@ static void NCR5380_exit(struct Scsi_Host *instance) struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) instance->hostdata; cancel_delayed_work_sync(&hostdata->coroutine); + destroy_workqueue(hostdata->work_q); } /** @@ -932,7 +938,7 @@ static int NCR5380_queue_command_lck(struct scsi_cmnd *cmd, void (*done) (struct /* Run the coroutine if it isn't already running. */ /* Kick off command processing */ - schedule_delayed_work(&hostdata->coroutine, 0); + queue_delayed_work(hostdata->work_q, &hostdata->coroutine, 0); return 0; } @@ -1128,7 +1134,8 @@ static irqreturn_t NCR5380_intr(int dummy, void *dev_id) } /* if BASR_IRQ */ spin_unlock_irqrestore(instance->host_lock, flags); if(!done) - schedule_delayed_work(&hostdata->coroutine, 0); + queue_delayed_work(hostdata->work_q, + &hostdata->coroutine, 0); } while (!done); return IRQ_HANDLED; } diff --git a/drivers/scsi/NCR5380.h b/drivers/scsi/NCR5380.h index 25e28add0db8..f9c861d083d0 100644 --- a/drivers/scsi/NCR5380.h +++ b/drivers/scsi/NCR5380.h @@ -284,6 +284,7 @@ struct NCR5380_hostdata { unsigned spin_max_r; unsigned spin_max_w; #endif + struct workqueue_struct *work_q; }; #ifdef __KERNEL__ diff --git a/drivers/scsi/arm/cumana_1.c b/drivers/scsi/arm/cumana_1.c index 3b5ff105f1d6..0d0cb62b8cdb 100644 --- a/drivers/scsi/arm/cumana_1.c +++ b/drivers/scsi/arm/cumana_1.c @@ -238,7 +238,9 @@ static int cumanascsi1_probe(struct expansion_card *ec, host->irq = ec->irq; - NCR5380_init(host, 0); + ret = NCR5380_init(host, 0); + if (ret) + goto out_unmap; NCR5380_maybe_reset_bus(host); @@ -250,7 +252,7 @@ static int cumanascsi1_probe(struct expansion_card *ec, if (ret) { printk("scsi%d: IRQ%d not free: %d\n", host->host_no, host->irq, ret); - goto out_unmap; + goto out_exit; } ret = scsi_add_host(host, &ec->dev); @@ -262,6 +264,8 @@ static int cumanascsi1_probe(struct expansion_card *ec, out_free_irq: free_irq(host->irq, host); + out_exit: + NCR5380_exit(host); out_unmap: iounmap(priv(host)->base); iounmap(priv(host)->dma); diff --git a/drivers/scsi/arm/oak.c b/drivers/scsi/arm/oak.c index ca0f31d22f43..db337b998299 100644 --- a/drivers/scsi/arm/oak.c +++ b/drivers/scsi/arm/oak.c @@ -143,17 +143,21 @@ static int oakscsi_probe(struct expansion_card *ec, const struct ecard_id *id) host->irq = NO_IRQ; host->n_io_port = 255; - NCR5380_init(host, 0); + ret = NCR5380_init(host, 0); + if (ret) + goto out_unmap; NCR5380_maybe_reset_bus(host); ret = scsi_add_host(host, &ec->dev); if (ret) - goto out_unmap; + goto out_exit; scsi_scan_host(host); goto out; + out_exit: + NCR5380_exit(host); out_unmap: iounmap(priv(host)->base); unreg: diff --git a/drivers/scsi/atari_NCR5380.c b/drivers/scsi/atari_NCR5380.c index 1dd341ef89d4..0b0a225167bc 100644 --- a/drivers/scsi/atari_NCR5380.c +++ b/drivers/scsi/atari_NCR5380.c @@ -643,7 +643,7 @@ static inline void queue_main(struct NCR5380_hostdata *hostdata) queue it on the 'immediate' task queue, to be processed immediately after the current interrupt processing has finished. */ - schedule_work(&hostdata->main_task); + queue_work(hostdata->work_q, &hostdata->main_task); } /* else: nothing to do: the running NCR5380_main() will pick up any newly queued command. */ @@ -832,6 +832,11 @@ static int __init NCR5380_init(struct Scsi_Host *instance, int flags) hostdata->flags = flags; INIT_WORK(&hostdata->main_task, NCR5380_main); + hostdata->work_q = alloc_workqueue("ncr5380_%d", + WQ_UNBOUND | WQ_MEM_RECLAIM, + 1, instance->host_no); + if (!hostdata->work_q) + return -ENOMEM; prepare_info(instance); @@ -907,6 +912,7 @@ static void NCR5380_exit(struct Scsi_Host *instance) struct NCR5380_hostdata *hostdata = shost_priv(instance); cancel_work_sync(&hostdata->main_task); + destroy_workqueue(hostdata->work_q); } /** diff --git a/drivers/scsi/atari_scsi.c b/drivers/scsi/atari_scsi.c index 5b233ccae962..1c6c4ca0a82f 100644 --- a/drivers/scsi/atari_scsi.c +++ b/drivers/scsi/atari_scsi.c @@ -885,7 +885,9 @@ static int __init atari_scsi_probe(struct platform_device *pdev) #endif host_flags |= setup_toshiba_delay > 0 ? FLAG_TOSHIBA_DELAY : 0; - NCR5380_init(instance, host_flags); + error = NCR5380_init(instance, host_flags); + if (error) + goto fail_init; if (IS_A_TT()) { error = request_irq(instance->irq, scsi_tt_intr, 0, @@ -947,6 +949,7 @@ fail_host: free_irq(instance->irq, instance); fail_irq: NCR5380_exit(instance); +fail_init: scsi_host_put(instance); fail_alloc: if (atari_dma_buffer) diff --git a/drivers/scsi/dmx3191d.c b/drivers/scsi/dmx3191d.c index 2c0fd7641075..db415359fee8 100644 --- a/drivers/scsi/dmx3191d.c +++ b/drivers/scsi/dmx3191d.c @@ -95,7 +95,9 @@ static int dmx3191d_probe_one(struct pci_dev *pdev, */ shost->irq = NO_IRQ; - NCR5380_init(shost, FLAG_NO_PSEUDO_DMA | FLAG_DTC3181E); + error = NCR5380_init(shost, FLAG_NO_PSEUDO_DMA | FLAG_DTC3181E); + if (error) + goto out_host_put; NCR5380_maybe_reset_bus(shost); @@ -103,11 +105,15 @@ static int dmx3191d_probe_one(struct pci_dev *pdev, error = scsi_add_host(shost, &pdev->dev); if (error) - goto out_release_region; + goto out_exit; scsi_scan_host(shost); return 0; +out_exit: + NCR5380_exit(shost); +out_host_put: + scsi_host_put(shost); out_release_region: release_region(io, DMX3191D_REGION_LEN); out_disable_device: @@ -119,15 +125,14 @@ static int dmx3191d_probe_one(struct pci_dev *pdev, static void dmx3191d_remove_one(struct pci_dev *pdev) { struct Scsi_Host *shost = pci_get_drvdata(pdev); + unsigned long io = shost->io_port; scsi_remove_host(shost); NCR5380_exit(shost); - - release_region(shost->io_port, DMX3191D_REGION_LEN); - pci_disable_device(pdev); - scsi_host_put(shost); + release_region(io, DMX3191D_REGION_LEN); + pci_disable_device(pdev); } static struct pci_device_id dmx3191d_pci_tbl[] = { diff --git a/drivers/scsi/dtc.c b/drivers/scsi/dtc.c index 698bea067af9..bc856c8ba0dd 100644 --- a/drivers/scsi/dtc.c +++ b/drivers/scsi/dtc.c @@ -230,12 +230,13 @@ static int __init dtc_detect(struct scsi_host_template * tpnt) found: instance = scsi_register(tpnt, sizeof(struct NCR5380_hostdata)); if (instance == NULL) - break; + goto out_unmap; instance->base = addr; ((struct NCR5380_hostdata *)(instance)->hostdata)->base = base; - NCR5380_init(instance, 0); + if (NCR5380_init(instance, 0)) + goto out_unregister; NCR5380_maybe_reset_bus(instance); @@ -275,6 +276,12 @@ found: ++count; } return count; + +out_unregister: + scsi_unregister(instance); +out_unmap: + iounmap(base); + return count; } /* diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c index fa9f6d41548b..afd092ff0c2e 100644 --- a/drivers/scsi/g_NCR5380.c +++ b/drivers/scsi/g_NCR5380.c @@ -239,9 +239,6 @@ static int __init do_DTC3181E_setup(char *str) * and DTC436(ISAPnP) controllers. If overrides have been set we use * them. * - * The caller supplied NCR5380_init function is invoked from here, before - * the interrupt line is taken. - * * Locks: none */ @@ -402,15 +399,8 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt) } #endif instance = scsi_register(tpnt, sizeof(struct NCR5380_hostdata)); - if (instance == NULL) { -#ifndef SCSI_G_NCR5380_MEM - release_region(overrides[current_override].NCR5380_map_name, region_size); -#else - iounmap(iomem); - release_mem_region(base, NCR5380_region_size); -#endif - continue; - } + if (instance == NULL) + goto out_release; #ifndef SCSI_G_NCR5380_MEM instance->io_port = overrides[current_override].NCR5380_map_name; @@ -427,7 +417,8 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt) ((struct NCR5380_hostdata *)instance->hostdata)->iomem = iomem; #endif - NCR5380_init(instance, flags); + if (NCR5380_init(instance, flags)) + goto out_unregister; if (overrides[current_override].board == BOARD_NCR53C400) NCR5380_write(C400_CONTROL_STATUS_REG, CSR_BASE); @@ -459,6 +450,17 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt) ++count; } return count; + +out_unregister: + scsi_unregister(instance); +out_release: +#ifndef SCSI_G_NCR5380_MEM + release_region(overrides[current_override].NCR5380_map_name, region_size); +#else + iounmap(iomem); + release_mem_region(base, NCR5380_region_size); +#endif + return count; } /** @@ -475,15 +477,12 @@ static int generic_NCR5380_release_resources(struct Scsi_Host *instance) if (instance->irq != NO_IRQ) free_irq(instance->irq, instance); NCR5380_exit(instance); - #ifndef SCSI_G_NCR5380_MEM release_region(instance->io_port, instance->n_io_port); #else iounmap(((struct NCR5380_hostdata *)instance->hostdata)->iomem); release_mem_region(instance->base, NCR5380_region_size); #endif - - return 0; } diff --git a/drivers/scsi/mac_scsi.c b/drivers/scsi/mac_scsi.c index 4d26ef93e656..1317f54bab92 100644 --- a/drivers/scsi/mac_scsi.c +++ b/drivers/scsi/mac_scsi.c @@ -382,7 +382,9 @@ static int __init mac_scsi_probe(struct platform_device *pdev) #endif host_flags |= setup_toshiba_delay > 0 ? FLAG_TOSHIBA_DELAY : 0; - NCR5380_init(instance, host_flags); + error = NCR5380_init(instance, host_flags); + if (error) + goto fail_init; if (instance->irq != NO_IRQ) { error = request_irq(instance->irq, macscsi_intr, IRQF_SHARED, @@ -407,6 +409,7 @@ fail_host: free_irq(instance->irq, instance); fail_irq: NCR5380_exit(instance); +fail_init: scsi_host_put(instance); return error; } diff --git a/drivers/scsi/pas16.c b/drivers/scsi/pas16.c index e5c76eefa5e0..5e57ee01093c 100644 --- a/drivers/scsi/pas16.c +++ b/drivers/scsi/pas16.c @@ -378,11 +378,12 @@ static int __init pas16_detect(struct scsi_host_template *tpnt) instance = scsi_register (tpnt, sizeof(struct NCR5380_hostdata)); if(instance == NULL) - break; + goto out; instance->io_port = io_port; - NCR5380_init(instance, 0); + if (NCR5380_init(instance, 0)) + goto out_unregister; NCR5380_maybe_reset_bus(instance); @@ -418,6 +419,11 @@ static int __init pas16_detect(struct scsi_host_template *tpnt) ++count; } return count; + +out_unregister: + scsi_unregister(instance); +out: + return count; } /* diff --git a/drivers/scsi/sun3_scsi.c b/drivers/scsi/sun3_scsi.c index 9376b3d8bfdc..c4fcf2fa74fc 100644 --- a/drivers/scsi/sun3_scsi.c +++ b/drivers/scsi/sun3_scsi.c @@ -557,7 +557,9 @@ static int __init sun3_scsi_probe(struct platform_device *pdev) host_flags |= setup_use_tagged_queuing > 0 ? FLAG_TAGGED_QUEUING : 0; #endif - NCR5380_init(instance, host_flags); + error = NCR5380_init(instance, host_flags); + if (error) + goto fail_init; error = request_irq(instance->irq, scsi_sun3_intr, 0, "NCR5380", instance); @@ -604,6 +606,7 @@ fail_host: free_irq(instance->irq, instance); fail_irq: NCR5380_exit(instance); +fail_init: scsi_host_put(instance); fail_alloc: if (udc_regs) diff --git a/drivers/scsi/t128.c b/drivers/scsi/t128.c index 3adcae1150d2..3dac6d7f5d22 100644 --- a/drivers/scsi/t128.c +++ b/drivers/scsi/t128.c @@ -208,12 +208,13 @@ static int __init t128_detect(struct scsi_host_template *tpnt) found: instance = scsi_register (tpnt, sizeof(struct NCR5380_hostdata)); if(instance == NULL) - break; - + goto out_unmap; + instance->base = base; ((struct NCR5380_hostdata *)instance->hostdata)->base = p; - NCR5380_init(instance, 0); + if (NCR5380_init(instance, 0)) + goto out_unregister; NCR5380_maybe_reset_bus(instance); @@ -246,6 +247,12 @@ found: ++count; } return count; + +out_unregister: + scsi_unregister(instance); +out_unmap: + iounmap(p); + return count; } static int t128_release(struct Scsi_Host *shost) -- cgit From 2f854b82b001b5d05b4e1c81acb947f7bd9cee9f Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sun, 3 Jan 2016 16:05:22 +1100 Subject: ncr5380: Sleep when polling, if possible When in process context, sleep during polling if doing so won't add significant latency. In interrupt context or if the lock is held, poll briefly then give up. Keep both core drivers in sync. Calibrate busy-wait iterations to allow for variation in chip register access times between different 5380 hardware implementations. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Ondrej Zary Tested-by: Michael Schmitz Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.c | 84 +++++++++++++++++++++++++++----------------- drivers/scsi/NCR5380.h | 1 + drivers/scsi/atari_NCR5380.c | 62 +++++++++++++++++++++----------- 3 files changed, 94 insertions(+), 53 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index a66fffc83475..a1c7901791f8 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -293,44 +293,48 @@ static inline void initialize_SCp(struct scsi_cmnd *cmd) } /** - * NCR5380_poll_politely - wait for NCR5380 status bits - * @instance: controller to poll - * @reg: 5380 register to poll - * @bit: Bitmask to check - * @val: Value required to exit - * - * Polls the NCR5380 in a reasonably efficient manner waiting for - * an event to occur, after a short quick poll we begin giving the - * CPU back in non IRQ contexts - * - * Returns the value of the register or a negative error code. + * NCR5380_poll_politely - wait for chip register value + * @instance: controller to poll + * @reg: 5380 register to poll + * @bit: Bitmask to check + * @val: Value required to exit + * @wait: Time-out in jiffies + * + * Polls the chip in a reasonably efficient manner waiting for an + * event to occur. After a short quick poll we begin to yield the CPU + * (if possible). In irq contexts the time-out is arbitrarily limited. + * Callers may hold locks as long as they are held in irq mode. + * + * Returns 0 if event occurred otherwise -ETIMEDOUT. */ - -static int NCR5380_poll_politely(struct Scsi_Host *instance, int reg, int bit, int val, int t) + +static int NCR5380_poll_politely(struct Scsi_Host *instance, + int reg, int bit, int val, int wait) { - int n = 500; /* At about 8uS a cycle for the cpu access */ - unsigned long end = jiffies + t; - int r; - - while( n-- > 0) - { - r = NCR5380_read(reg); - if((r & bit) == val) + struct NCR5380_hostdata *hostdata = shost_priv(instance); + unsigned long deadline = jiffies + wait; + unsigned long n; + + /* Busy-wait for up to 10 ms */ + n = min(10000U, jiffies_to_usecs(wait)); + n *= hostdata->accesses_per_ms; + n /= 1000; + do { + if ((NCR5380_read(reg) & bit) == val) return 0; cpu_relax(); - } - - /* t time yet ? */ - while(time_before(jiffies, end)) - { - r = NCR5380_read(reg); - if((r & bit) == val) + } while (n--); + + if (irqs_disabled() || in_interrupt()) + return -ETIMEDOUT; + + /* Repeatedly sleep for 1 ms until deadline */ + while (time_is_after_jiffies(deadline)) { + schedule_timeout_uninterruptible(1); + if ((NCR5380_read(reg) & bit) == val) return 0; - if(!in_interrupt()) - cond_resched(); - else - cpu_relax(); } + return -ETIMEDOUT; } @@ -773,6 +777,7 @@ static int NCR5380_init(struct Scsi_Host *instance, int flags) { int i; struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) instance->hostdata; + unsigned long deadline; if(in_interrupt()) printk(KERN_ERR "NCR5380_init called with interrupts off!\n"); @@ -812,6 +817,21 @@ static int NCR5380_init(struct Scsi_Host *instance, int flags) NCR5380_write(MODE_REG, MR_BASE); NCR5380_write(TARGET_COMMAND_REG, 0); NCR5380_write(SELECT_ENABLE_REG, 0); + + /* Calibrate register polling loop */ + i = 0; + deadline = jiffies + 1; + do { + cpu_relax(); + } while (time_is_after_jiffies(deadline)); + deadline += msecs_to_jiffies(256); + do { + NCR5380_read(STATUS_REG); + ++i; + cpu_relax(); + } while (time_is_after_jiffies(deadline)); + hostdata->accesses_per_ms = i / 256; + return 0; } diff --git a/drivers/scsi/NCR5380.h b/drivers/scsi/NCR5380.h index f9c861d083d0..412a344ac676 100644 --- a/drivers/scsi/NCR5380.h +++ b/drivers/scsi/NCR5380.h @@ -285,6 +285,7 @@ struct NCR5380_hostdata { unsigned spin_max_w; #endif struct workqueue_struct *work_q; + unsigned long accesses_per_ms; /* chip register accesses per ms */ }; #ifdef __KERNEL__ diff --git a/drivers/scsi/atari_NCR5380.c b/drivers/scsi/atari_NCR5380.c index 0b0a225167bc..8b4e321b8399 100644 --- a/drivers/scsi/atari_NCR5380.c +++ b/drivers/scsi/atari_NCR5380.c @@ -479,43 +479,48 @@ static inline void initialize_SCp(struct scsi_cmnd *cmd) } /** - * NCR5380_poll_politely - wait for NCR5380 status bits + * NCR5380_poll_politely - wait for chip register value * @instance: controller to poll * @reg: 5380 register to poll * @bit: Bitmask to check * @val: Value required to exit + * @wait: Time-out in jiffies * - * Polls the NCR5380 in a reasonably efficient manner waiting for - * an event to occur, after a short quick poll we begin giving the - * CPU back in non IRQ contexts + * Polls the chip in a reasonably efficient manner waiting for an + * event to occur. After a short quick poll we begin to yield the CPU + * (if possible). In irq contexts the time-out is arbitrarily limited. + * Callers may hold locks as long as they are held in irq mode. * - * Returns the value of the register or a negative error code. + * Returns 0 if event occurred otherwise -ETIMEDOUT. */ static int NCR5380_poll_politely(struct Scsi_Host *instance, - int reg, int bit, int val, int t) + int reg, int bit, int val, int wait) { - int n = 500; - unsigned long end = jiffies + t; - int r; + struct NCR5380_hostdata *hostdata = shost_priv(instance); + unsigned long deadline = jiffies + wait; + unsigned long n; - while (n-- > 0) { - r = NCR5380_read(reg); - if ((r & bit) == val) + /* Busy-wait for up to 10 ms */ + n = min(10000U, jiffies_to_usecs(wait)); + n *= hostdata->accesses_per_ms; + n /= 1000; + do { + if ((NCR5380_read(reg) & bit) == val) return 0; cpu_relax(); - } + } while (n--); - /* t time yet ? */ - while (time_before(jiffies, end)) { - r = NCR5380_read(reg); - if ((r & bit) == val) + if (irqs_disabled() || in_interrupt()) + return -ETIMEDOUT; + + /* Repeatedly sleep for 1 ms until deadline */ + while (time_is_after_jiffies(deadline)) { + schedule_timeout_uninterruptible(1); + if ((NCR5380_read(reg) & bit) == val) return 0; - if (!in_interrupt()) - cond_resched(); - else - cpu_relax(); } + return -ETIMEDOUT; } @@ -811,6 +816,7 @@ static int __init NCR5380_init(struct Scsi_Host *instance, int flags) { int i; SETUP_HOSTDATA(instance); + unsigned long deadline; hostdata->host = instance; hostdata->id_mask = 1 << instance->this_id; @@ -845,6 +851,20 @@ static int __init NCR5380_init(struct Scsi_Host *instance, int flags) NCR5380_write(TARGET_COMMAND_REG, 0); NCR5380_write(SELECT_ENABLE_REG, 0); + /* Calibrate register polling loop */ + i = 0; + deadline = jiffies + 1; + do { + cpu_relax(); + } while (time_is_after_jiffies(deadline)); + deadline += msecs_to_jiffies(256); + do { + NCR5380_read(STATUS_REG); + ++i; + cpu_relax(); + } while (time_is_after_jiffies(deadline)); + hostdata->accesses_per_ms = i / 256; + return 0; } -- cgit From ae753a3387504daa11b8779a00d37923f971c6d0 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sun, 3 Jan 2016 16:05:23 +1100 Subject: ncr5380: Eliminate selecting state Linux v2.1.105 changed the algorithm for polling for the BSY signal in NCR5380_select() and NCR5380_main(). Presently, this code has a bug. Back then, NCR5380_set_timer(hostdata, 1) meant reschedule main() after sleeping for 10 ms. Repeated 25 times this provided the recommended 250 ms selection time-out delay. This got broken when HZ became configurable. We could fix this but there's no need to reschedule the main loop. This BSY polling presently happens when the NCR5380_main() work queue item calls NCR5380_select(), which in turn schedules NCR5380_main(), which calls NCR5380_select() again, and so on. This algorithm is a deviation from the simpler one in atari_NCR5380.c. The extra complexity and state is pointless. There's no reason to stop selection half-way and return to to the main loop when the main loop can do nothing useful until selection completes. So just poll for BSY. We can sleep while polling now that we have a suitable workqueue. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Ondrej Zary Tested-by: Michael Schmitz Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.c | 74 +++++++++----------------------------------- drivers/scsi/NCR5380.h | 2 -- drivers/scsi/atari_NCR5380.c | 49 +++++++++-------------------- 3 files changed, 29 insertions(+), 96 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index a1c7901791f8..3ea8809600cc 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -988,7 +988,7 @@ static void NCR5380_main(struct work_struct *work) do { /* Lock held here */ done = 1; - if (!hostdata->connected && !hostdata->selecting) { + if (!hostdata->connected) { dprintk(NDEBUG_MAIN, "scsi%d : not connected\n", instance->host_no); /* * Search through the issue_queue for a command destined @@ -1018,9 +1018,6 @@ static void NCR5380_main(struct work_struct *work) */ dprintk(NDEBUG_MAIN|NDEBUG_QUEUES, "scsi%d : main() : command for target %d lun %llu removed from issue_queue\n", instance->host_no, tmp->device->id, tmp->device->lun); - hostdata->selecting = NULL; - /* RvC: have to preset this to indicate a new command is being performed */ - /* * REQUEST SENSE commands are issued without tagged * queueing, even on SCSI-II devices because the @@ -1038,26 +1035,13 @@ static void NCR5380_main(struct work_struct *work) done = 0; dprintk(NDEBUG_MAIN|NDEBUG_QUEUES, "scsi%d : main(): select() failed, returned to issue_queue\n", instance->host_no); } - if (hostdata->connected || - hostdata->selecting) + if (hostdata->connected) break; /* lock held here still */ } /* if target/lun is not busy */ } /* for */ /* exited locked */ } /* if (!hostdata->connected) */ - if (hostdata->selecting) { - tmp = (struct scsi_cmnd *) hostdata->selecting; - /* Selection will drop and retake the lock */ - if (!NCR5380_select(instance, tmp)) { - /* OK or bad target */ - } else { - LIST(tmp, hostdata->issue_queue); - tmp->host_scribble = (unsigned char *) hostdata->issue_queue; - hostdata->issue_queue = tmp; - done = 0; - } - } /* if hostdata->selecting */ if (hostdata->connected #ifdef REAL_DMA && !hostdata->dmalen @@ -1176,7 +1160,6 @@ static irqreturn_t NCR5380_intr(int dummy, void *dev_id) * Returns : -1 if selection failed but should be retried. * 0 if selection failed and should not be retried. * 0 if selection succeeded completely (hostdata->connected == cmd). - * 0 if selection in progress (hostdata->selecting == cmd). * * Side effects : * If bus busy, arbitration failed, etc, NCR5380_select() will exit @@ -1200,13 +1183,8 @@ static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd) unsigned char tmp[3], phase; unsigned char *data; int len; - unsigned long timeout; - unsigned char value; int err; - if (hostdata->selecting) - goto part2; - NCR5380_dprint(NDEBUG_ARBITRATION, instance); dprintk(NDEBUG_ARBITRATION, "scsi%d : starting arbitration, id = %d\n", instance->host_no, instance->this_id); @@ -1342,33 +1320,9 @@ static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd) * selection. */ - timeout = jiffies + msecs_to_jiffies(250); + err = NCR5380_poll_politely(instance, STATUS_REG, SR_BSY, SR_BSY, + msecs_to_jiffies(250)); - /* - * XXX very interesting - we're seeing a bounce where the BSY we - * asserted is being reflected / still asserted (propagation delay?) - * and it's detecting as true. Sigh. - */ - - hostdata->select_time = 0; /* we count the clock ticks at which we polled */ - hostdata->selecting = cmd; - -part2: - /* RvC: here we enter after a sleeping period, or immediately after - execution of part 1 - we poll only once ech clock tick */ - value = NCR5380_read(STATUS_REG) & (SR_BSY | SR_IO); - - if (!value && (hostdata->select_time < HZ/4)) { - /* RvC: we still must wait for a device response */ - hostdata->select_time++; /* after 25 ticks the device has failed */ - NCR5380_set_timer(hostdata, 1); - return 0; /* RvC: we return here with hostdata->selecting set, - to go to sleep */ - } - - hostdata->selecting = NULL;/* clear this pointer, because we passed the - waiting period */ if ((NCR5380_read(STATUS_REG) & (SR_SEL | SR_IO)) == (SR_SEL | SR_IO)) { NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); NCR5380_reselect(instance); @@ -1376,6 +1330,17 @@ part2: NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); return -1; } + + if (err < 0) { + NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); + cmd->result = DID_BAD_TARGET << 16; + cmd->scsi_done(cmd); + NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); + dprintk(NDEBUG_SELECTION, "scsi%d : target did not respond within 250ms\n", + instance->host_no); + return 0; + } + /* * No less than two deskew delays after the initiator detects the * BSY signal is true, it shall release the SEL signal and may @@ -1386,15 +1351,6 @@ part2: NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN); - if (!(NCR5380_read(STATUS_REG) & SR_BSY)) { - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - cmd->result = DID_BAD_TARGET << 16; - cmd->scsi_done(cmd); - NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); - dprintk(NDEBUG_SELECTION, "scsi%d : target did not respond within 250ms\n", instance->host_no); - return 0; - } - /* * Since we followed the SCSI spec, and raised ATN while SEL * was true but before BSY was false during selection, the information diff --git a/drivers/scsi/NCR5380.h b/drivers/scsi/NCR5380.h index 412a344ac676..ee084e90e25c 100644 --- a/drivers/scsi/NCR5380.h +++ b/drivers/scsi/NCR5380.h @@ -267,8 +267,6 @@ struct NCR5380_hostdata { volatile struct scsi_cmnd *disconnected_queue; /* waiting for reconnect */ int flags; unsigned long time_expires; /* in jiffies, set prior to sleeping */ - int select_time; /* timer in select for target response */ - volatile struct scsi_cmnd *selecting; struct delayed_work coroutine; /* our co-routine */ struct scsi_eh_save ses; char info[256]; diff --git a/drivers/scsi/atari_NCR5380.c b/drivers/scsi/atari_NCR5380.c index 8b4e321b8399..34cf4d938589 100644 --- a/drivers/scsi/atari_NCR5380.c +++ b/drivers/scsi/atari_NCR5380.c @@ -1431,7 +1431,7 @@ static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd) unsigned char tmp[3], phase; unsigned char *data; int len; - unsigned long timeout; + int err; unsigned long flags; NCR5380_dprint(NDEBUG_ARBITRATION, instance); @@ -1605,25 +1605,8 @@ static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd) * selection. */ - timeout = jiffies + msecs_to_jiffies(250); - - /* - * XXX very interesting - we're seeing a bounce where the BSY we - * asserted is being reflected / still asserted (propagation delay?) - * and it's detecting as true. Sigh. - */ - -#if 0 - /* ++roman: If a target conformed to the SCSI standard, it wouldn't assert - * IO while SEL is true. But again, there are some disks out the in the - * world that do that nevertheless. (Somebody claimed that this announces - * reselection capability of the target.) So we better skip that test and - * only wait for BSY... (Famous german words: Der Klügere gibt nach :-) - */ - - while (time_before(jiffies, timeout) && - !(NCR5380_read(STATUS_REG) & (SR_BSY | SR_IO))) - ; + err = NCR5380_poll_politely(instance, STATUS_REG, SR_BSY, SR_BSY, + msecs_to_jiffies(250)); if ((NCR5380_read(STATUS_REG) & (SR_SEL | SR_IO)) == (SR_SEL | SR_IO)) { NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); @@ -1633,22 +1616,8 @@ static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd) NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); return -1; } -#else - while (time_before(jiffies, timeout) && !(NCR5380_read(STATUS_REG) & SR_BSY)) - ; -#endif - - /* - * No less than two deskew delays after the initiator detects the - * BSY signal is true, it shall release the SEL signal and may - * change the DATA BUS. -wingel - */ - - udelay(1); - - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN); - if (!(NCR5380_read(STATUS_REG) & SR_BSY)) { + if (err < 0) { NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); cmd->result = DID_BAD_TARGET << 16; #ifdef SUPPORT_TAGS @@ -1660,6 +1629,16 @@ static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd) return 0; } + /* + * No less than two deskew delays after the initiator detects the + * BSY signal is true, it shall release the SEL signal and may + * change the DATA BUS. -wingel + */ + + udelay(1); + + NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN); + /* * Since we followed the SCSI spec, and raised ATN while SEL * was true but before BSY was false during selection, the information -- cgit From 1d3db59d59861481349437231c263b6c7a0eef78 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sun, 3 Jan 2016 16:05:24 +1100 Subject: ncr5380: Always retry arbitration and selection If NCR5380_select() returns -1, it means arbitration was lost or selection failed and should be retried. If the main loop simply terminates when there are still commands on the issue queue, they will remain queued until they expire. Fix this by clearing the 'done' flag after selection failure or lost arbitration. The "else break" clause in NCR5380_main() that gets removed here appears to be a vestige of a long-gone loop that iterated over host instances. See commit 491447e1fcff ("[PATCH] next NCR5380 updates") in history/history.git. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Ondrej Zary Tested-by: Michael Schmitz Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.c | 3 +-- drivers/scsi/atari_NCR5380.c | 1 + 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index 3ea8809600cc..6a030139b41f 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -1052,8 +1052,7 @@ static void NCR5380_main(struct work_struct *work) NCR5380_information_transfer(instance); dprintk(NDEBUG_MAIN, "scsi%d : main() : done set false\n", instance->host_no); done = 0; - } else - break; + } } while (!done); spin_unlock_irq(instance->host_lock); diff --git a/drivers/scsi/atari_NCR5380.c b/drivers/scsi/atari_NCR5380.c index 34cf4d938589..64ee92090de3 100644 --- a/drivers/scsi/atari_NCR5380.c +++ b/drivers/scsi/atari_NCR5380.c @@ -1181,6 +1181,7 @@ static void NCR5380_main(struct work_struct *work) #endif hostdata->retain_dma_intr--; local_irq_restore(flags); + done = 0; dprintk(NDEBUG_MAIN, "scsi%d: main(): select() failed, " "returned to issue_queue\n", HOSTNO); } -- cgit From ff3d4578840fd96a50558edf02ca0178b9ebb652 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sun, 3 Jan 2016 16:05:25 +1100 Subject: ncr5380: Implement NCR5380_dma_xfer_len and remove LIMIT_TRANSFERSIZE macro Follow the example of the atari_NCR5380.c core driver and adopt the NCR5380_dma_xfer_len() hook. Implement NCR5380_dma_xfer_len() for dtc.c and g_NCR5380.c to take care of the limitations of these cards. Keep the default for drivers using PSEUDO_DMA. Eliminate the unused macro LIMIT_TRANSFERSIZE. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Ondrej Zary Tested-by: Michael Schmitz Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.c | 34 ++++++---------------------------- drivers/scsi/arm/cumana_1.c | 3 +++ drivers/scsi/arm/oak.c | 2 ++ drivers/scsi/atari_NCR5380.c | 8 +++++--- drivers/scsi/dtc.c | 14 ++++++++++++++ drivers/scsi/dtc.h | 3 +++ drivers/scsi/g_NCR5380.c | 15 +++++++++++++++ drivers/scsi/g_NCR5380.h | 3 +++ drivers/scsi/mac_scsi.c | 1 + drivers/scsi/pas16.h | 2 ++ drivers/scsi/t128.h | 2 ++ 11 files changed, 56 insertions(+), 31 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index 6a030139b41f..91eac63b5239 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -201,11 +201,6 @@ * DONT_USE_INTR - if defined, never use interrupts, even if we probe or * override-configure an IRQ. * - * LIMIT_TRANSFERSIZE - if defined, limit the pseudo-dma transfers to 512 - * bytes at a time. Since interrupts are disabled by default during - * these transfers, we might need this to give reasonable interrupt - * service time if the transfer size gets too large. - * * LINKED - if defined, linked commands are supported. * * PSEUDO_DMA - if defined, PSEUDO DMA is used during the data transfer phases. @@ -2000,29 +1995,12 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { */ #if defined(PSEUDO_DMA) || defined(REAL_DMA_POLL) - /* KLL - * PSEUDO_DMA is defined here. If this is the g_NCR5380 - * driver then it will always be defined, so the - * FLAG_NO_PSEUDO_DMA is used to inhibit PDMA in the base - * NCR5380 case. I think this is a fairly clean solution. - * We supplement these 2 if's with the flag. - */ -#ifdef NCR5380_dma_xfer_len - if (!cmd->device->borken && !(hostdata->flags & FLAG_NO_PSEUDO_DMA) && (transfersize = NCR5380_dma_xfer_len(instance, cmd)) != 0) { -#else - transfersize = cmd->transfersize; - -#ifdef LIMIT_TRANSFERSIZE /* If we have problems with interrupt service */ - if (transfersize > 512) - transfersize = 512; -#endif /* LIMIT_TRANSFERSIZE */ - - if (!cmd->device->borken && transfersize && !(hostdata->flags & FLAG_NO_PSEUDO_DMA) && cmd->SCp.this_residual && !(cmd->SCp.this_residual % transfersize)) { - /* Limit transfers to 32K, for xx400 & xx406 - * pseudoDMA that transfers in 128 bytes blocks. */ - if (transfersize > 32 * 1024) - transfersize = 32 * 1024; -#endif + transfersize = 0; + if (!cmd->device->borken && + !(hostdata->flags & FLAG_NO_PSEUDO_DMA)) + transfersize = NCR5380_dma_xfer_len(instance, cmd, phase); + + if (transfersize) { len = transfersize; if (NCR5380_transfer_dma(instance, &phase, &len, (unsigned char **) &cmd->SCp.ptr)) { /* diff --git a/drivers/scsi/arm/cumana_1.c b/drivers/scsi/arm/cumana_1.c index 0d0cb62b8cdb..f9fb8dabdbbd 100644 --- a/drivers/scsi/arm/cumana_1.c +++ b/drivers/scsi/arm/cumana_1.c @@ -22,6 +22,9 @@ #define priv(host) ((struct NCR5380_hostdata *)(host)->hostdata) #define NCR5380_read(reg) cumanascsi_read(instance, reg) #define NCR5380_write(reg, value) cumanascsi_write(instance, reg, value) + +#define NCR5380_dma_xfer_len(instance, cmd, phase) (cmd->transfersize) + #define NCR5380_intr cumanascsi_intr #define NCR5380_queue_command cumanascsi_queue_command #define NCR5380_info cumanascsi_info diff --git a/drivers/scsi/arm/oak.c b/drivers/scsi/arm/oak.c index db337b998299..d95a1d4f4e02 100644 --- a/drivers/scsi/arm/oak.c +++ b/drivers/scsi/arm/oak.c @@ -26,6 +26,8 @@ #define NCR5380_write(reg, value) \ writeb(value, priv(instance)->base + ((reg) << 2)) +#define NCR5380_dma_xfer_len(instance, cmd, phase) (cmd->transfersize) + #define NCR5380_queue_command oakscsi_queue_command #define NCR5380_info oakscsi_info #define NCR5380_show_info oakscsi_show_info diff --git a/drivers/scsi/atari_NCR5380.c b/drivers/scsi/atari_NCR5380.c index 64ee92090de3..59b378057198 100644 --- a/drivers/scsi/atari_NCR5380.c +++ b/drivers/scsi/atari_NCR5380.c @@ -2170,11 +2170,13 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) */ #if defined(REAL_DMA) - if ( #if !defined(CONFIG_SUN3) - !cmd->device->borken && + transfersize = 0; + if (!cmd->device->borken) #endif - (transfersize = NCR5380_dma_xfer_len(instance, cmd, phase)) >= DMA_MIN_SIZE) { + transfersize = NCR5380_dma_xfer_len(instance, cmd, phase); + + if (transfersize >= DMA_MIN_SIZE) { len = transfersize; cmd->SCp.phase = phase; if (NCR5380_transfer_dma(instance, &phase, diff --git a/drivers/scsi/dtc.c b/drivers/scsi/dtc.c index bc856c8ba0dd..010d9b13aae7 100644 --- a/drivers/scsi/dtc.c +++ b/drivers/scsi/dtc.c @@ -419,6 +419,20 @@ static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src, return (0); } +static int dtc_dma_xfer_len(struct scsi_cmnd *cmd) +{ + int transfersize = cmd->transfersize; + + /* Limit transfers to 32K, for xx400 & xx406 + * pseudoDMA that transfers in 128 bytes blocks. + */ + if (transfersize > 32 * 1024 && cmd->SCp.this_residual && + !(cmd->SCp.this_residual % transfersize)) + transfersize = 32 * 1024; + + return transfersize; +} + MODULE_LICENSE("GPL"); #include "NCR5380.c" diff --git a/drivers/scsi/dtc.h b/drivers/scsi/dtc.h index 07b0ac98817c..e6c09a9174ce 100644 --- a/drivers/scsi/dtc.h +++ b/drivers/scsi/dtc.h @@ -27,6 +27,9 @@ #define NCR5380_read(reg) (readb(DTC_address(reg))) #define NCR5380_write(reg, value) (writeb(value, DTC_address(reg))) +#define NCR5380_dma_xfer_len(instance, cmd, phase) \ + dtc_dma_xfer_len(cmd) + #define NCR5380_intr dtc_intr #define NCR5380_queue_command dtc_queue_command #define NCR5380_abort dtc_abort diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c index afd092ff0c2e..5b3e03ad50ce 100644 --- a/drivers/scsi/g_NCR5380.c +++ b/drivers/scsi/g_NCR5380.c @@ -699,6 +699,21 @@ static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src, ; // TIMEOUT return 0; } + +static int generic_NCR5380_dma_xfer_len(struct scsi_cmnd *cmd) +{ + int transfersize = cmd->transfersize; + + /* Limit transfers to 32K, for xx400 & xx406 + * pseudoDMA that transfers in 128 bytes blocks. + */ + if (transfersize > 32 * 1024 && cmd->SCp.this_residual && + !(cmd->SCp.this_residual % transfersize)) + transfersize = 32 * 1024; + + return transfersize; +} + #endif /* PSEUDO_DMA */ /* diff --git a/drivers/scsi/g_NCR5380.h b/drivers/scsi/g_NCR5380.h index 5c656f163beb..0056790a9cbe 100644 --- a/drivers/scsi/g_NCR5380.h +++ b/drivers/scsi/g_NCR5380.h @@ -73,6 +73,9 @@ #endif +#define NCR5380_dma_xfer_len(instance, cmd, phase) \ + generic_NCR5380_dma_xfer_len(cmd) + #define NCR5380_intr generic_NCR5380_intr #define NCR5380_queue_command generic_NCR5380_queue_command #define NCR5380_abort generic_NCR5380_abort diff --git a/drivers/scsi/mac_scsi.c b/drivers/scsi/mac_scsi.c index 1317f54bab92..f8ed2acd1456 100644 --- a/drivers/scsi/mac_scsi.c +++ b/drivers/scsi/mac_scsi.c @@ -38,6 +38,7 @@ #define NCR5380_pread macscsi_pread #define NCR5380_pwrite macscsi_pwrite +#define NCR5380_dma_xfer_len(instance, cmd, phase) (cmd->transfersize) #define NCR5380_intr macscsi_intr #define NCR5380_queue_command macscsi_queue_command diff --git a/drivers/scsi/pas16.h b/drivers/scsi/pas16.h index 7247b67fb111..a827a7c1c133 100644 --- a/drivers/scsi/pas16.h +++ b/drivers/scsi/pas16.h @@ -110,6 +110,8 @@ #define NCR5380_read(reg) ( inb(PAS16_io_port(reg)) ) #define NCR5380_write(reg, value) ( outb((value),PAS16_io_port(reg)) ) +#define NCR5380_dma_xfer_len(instance, cmd, phase) (cmd->transfersize) + #define NCR5380_intr pas16_intr #define NCR5380_queue_command pas16_queue_command #define NCR5380_abort pas16_abort diff --git a/drivers/scsi/t128.h b/drivers/scsi/t128.h index ca93c97cf4ba..16691d5fb81b 100644 --- a/drivers/scsi/t128.h +++ b/drivers/scsi/t128.h @@ -84,6 +84,8 @@ #define NCR5380_read(reg) readb(T128_address(reg)) #define NCR5380_write(reg, value) writeb((value),(T128_address(reg))) +#define NCR5380_dma_xfer_len(instance, cmd, phase) (cmd->transfersize) + #define NCR5380_intr t128_intr #define NCR5380_queue_command t128_queue_command #define NCR5380_abort t128_abort -- cgit From 686f3990e6a9111f97f2d385f4d1c1a5b0628c15 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sun, 3 Jan 2016 16:05:26 +1100 Subject: ncr5380: Rework disconnect versus poll logic The atari_NCR5380.c and NCR5380.c core drivers differ in their handling of target disconnection. This is partly because atari_NCR5380.c had all of the polling and sleeping removed to become entirely interrupt-driven, and it is partly because of damage done to NCR5380.c after atari_NCR5380.c was forked. See commit 37cd23b44929 ("Linux 2.1.105") in history/history.git. The polling changes that were made in v2.1.105 are questionable at best: if REQ is not already asserted when NCR5380_transfer_pio() is invoked, and if the expected phase is DATA IN or DATA OUT, the function will schedule main() to execute after USLEEP_SLEEP jiffies and then return. The problems here are the expected REQ timing and the sleep interval*. Avoid this issue by using NCR5380_poll_politely() instead of scheduling main(). The atari_NCR5380.c core driver requires the use of the chip interrupt and always permits target disconnection. It sets the cmd->device->disconnect flag when a device disconnects, but never tests this flag. The NCR5380.c core driver permits disconnection only when instance->irq != NO_IRQ. It sets the cmd->device->disconnect flag when a device disconnects and it tests this flag in a couple of places: 1. During NCR5380_information_transfer(), following COMMAND OUT phase, if !cmd->device->disconnect, the initiator will take a guess as to whether or not the target will then choose to go to MESSAGE IN phase and disconnect. If the driver guesses "yes", it will schedule main() to execute after USLEEP_SLEEP jiffies and then return there. Unfortunately the driver may guess "yes" even after it has denied the target the disconnection privilege. When the target does not disconnect, the sleep can be beneficial, assuming the sleep interval is appropriate (mostly it is not*). And even if the driver guesses "yes" correctly, and the target would then disconnect, the driver still has to go through the MESSAGE IN phase in order to get to BUS FREE phase. The main loop can do nothing useful until BUS FREE, and sleeping just delays the phase transition. 2. If !cmd->device->disconnect and REQ is not already asserted when NCR5380_information_transfer() is invoked, the function polls for REQ for USLEEP_POLL jiffies. If REQ is not asserted, it then schedules main() to execute after USLEEP_SLEEP jiffies and returns. The idea is apparently to yeild the CPU while waiting for REQ. This is conditional upon !cmd->device->disconnect, but there seems to be no rhyme or reason for that. For example, the flag may be unset because disconnection privilege was denied because the driver has no IRQ. Or the flag may be unset because the device has never needed to disconnect before. Or if the flag is set, disconnection may have no relevance to the present bus phase. Another deficiency of the existing algorithm is as follows. When the driver has no IRQ, it prevents disconnection, and generally polls and sleeps more than it would normally. Now, if the driver is going to poll anyway, why not allow the target to disconnect? That way the driver can do something useful with the bus instead of polling unproductively! Avoid this pointless latency, complexity and guesswork by using NCR5380_poll_politely() instead of scheduling main(). * For g_NCR5380, the time intervals for USLEEP_SLEEP and USLEEP_POLL are 200 ms and 10 ms, respectively. They are 20 ms and 200 ms respectively for the other NCR5380 drivers. There doesn't seem to be any reason for this discrepancy. The timing seems to have no relation to the type of adapter. Bizarrely, the timing in g_NCR5380 seems to relate only to one particular type of target device. This patch attempts to solve the problem for all NCR5380 drivers and all target devices. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Ondrej Zary Tested-by: Michael Schmitz Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.c | 137 +++---------------------------------------- drivers/scsi/NCR5380.h | 11 ---- drivers/scsi/atari_NCR5380.c | 24 +++----- drivers/scsi/g_NCR5380.c | 4 -- 4 files changed, 15 insertions(+), 161 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index 91eac63b5239..23bb7fe8b13b 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -139,17 +139,7 @@ * piece of hardware that requires you to sit in a loop polling for * the REQ signal as long as you are connected. Some devices are * brain dead (ie, many TEXEL CD ROM drives) and won't disconnect - * while doing long seek operations. - * - * The workaround for this is to keep track of devices that have - * disconnected. If the device hasn't disconnected, for commands that - * should disconnect, we do something like - * - * while (!REQ is asserted) { sleep for N usecs; poll for M usecs } - * - * Some tweaking of N and M needs to be done. An algorithm based - * on "time to data" would give the best results as long as short time - * to datas (ie, on the same track) were considered, however these + * while doing long seek operations. [...] These * broken devices are the exception rather than the rule and I'd rather * spend my time optimizing for the normal case. * @@ -220,10 +210,6 @@ * Defaults for these will be provided although the user may want to adjust * these to allocate CPU resources to the SCSI driver or "real" code. * - * USLEEP_SLEEP - amount of time, in jiffies, to sleep - * - * USLEEP_POLL - amount of time, in jiffies, to poll - * * These macros MUST be defined : * * NCR5380_read(register) - read from the specified register @@ -449,73 +435,6 @@ static void NCR5380_print_phase(struct Scsi_Host *instance) } #endif -/* - * These need tweaking, and would probably work best as per-device - * flags initialized differently for disk, tape, cd, etc devices. - * People with broken devices are free to experiment as to what gives - * the best results for them. - * - * USLEEP_SLEEP should be a minimum seek time. - * - * USLEEP_POLL should be a maximum rotational latency. - */ -#ifndef USLEEP_SLEEP -/* 20 ms (reasonable hard disk speed) */ -#define USLEEP_SLEEP msecs_to_jiffies(20) -#endif -/* 300 RPM (floppy speed) */ -#ifndef USLEEP_POLL -#define USLEEP_POLL msecs_to_jiffies(200) -#endif - -/* - * Function : int should_disconnect (unsigned char cmd) - * - * Purpose : decide whether a command would normally disconnect or - * not, since if it won't disconnect we should go to sleep. - * - * Input : cmd - opcode of SCSI command - * - * Returns : DISCONNECT_LONG if we should disconnect for a really long - * time (ie always, sleep, look for REQ active, sleep), - * DISCONNECT_TIME_TO_DATA if we would only disconnect for a normal - * time-to-data delay, DISCONNECT_NONE if this command would return - * immediately. - * - * Future sleep algorithms based on time to data can exploit - * something like this so they can differentiate between "normal" - * (ie, read, write, seek) and unusual commands (ie, * format). - * - * Note : We don't deal with commands that handle an immediate disconnect, - * - */ - -static int should_disconnect(unsigned char cmd) -{ - switch (cmd) { - case READ_6: - case WRITE_6: - case SEEK_6: - case READ_10: - case WRITE_10: - case SEEK_10: - return DISCONNECT_TIME_TO_DATA; - case FORMAT_UNIT: - case SEARCH_HIGH: - case SEARCH_LOW: - case SEARCH_EQUAL: - return DISCONNECT_LONG; - default: - return DISCONNECT_NONE; - } -} - -static void NCR5380_set_timer(struct NCR5380_hostdata *hostdata, unsigned long timeout) -{ - hostdata->time_expires = jiffies + timeout; - queue_delayed_work(hostdata->work_q, &hostdata->coroutine, timeout); -} - static int probe_irq __initdata; @@ -614,9 +533,6 @@ static void prepare_info(struct Scsi_Host *instance) "can_queue %d, cmd_per_lun %d, " "sg_tablesize %d, this_id %d, " "flags { %s%s%s%s}, " -#if defined(USLEEP_POLL) && defined(USLEEP_SLEEP) - "USLEEP_POLL %lu, USLEEP_SLEEP %lu, " -#endif "options { %s} ", instance->hostt->name, instance->io_port, instance->n_io_port, instance->base, instance->irq, @@ -626,9 +542,6 @@ static void prepare_info(struct Scsi_Host *instance) hostdata->flags & FLAG_DTC3181E ? "DTC3181E " : "", hostdata->flags & FLAG_NO_PSEUDO_DMA ? "NO_PSEUDO_DMA " : "", hostdata->flags & FLAG_TOSHIBA_DELAY ? "TOSHIBA_DELAY " : "", -#if defined(USLEEP_POLL) && defined(USLEEP_SLEEP) - USLEEP_POLL, USLEEP_SLEEP, -#endif #ifdef AUTOPROBE_IRQ "AUTOPROBE_IRQ " #endif @@ -804,7 +717,6 @@ static int NCR5380_init(struct Scsi_Host *instance, int flags) hostdata->flags = FLAG_CHECK_LAST_BYTE_SENT | flags; hostdata->host = instance; - hostdata->time_expires = 0; prepare_info(instance); @@ -1041,7 +953,6 @@ static void NCR5380_main(struct work_struct *work) #ifdef REAL_DMA && !hostdata->dmalen #endif - && (!hostdata->time_expires || time_before_eq(hostdata->time_expires, jiffies)) ) { dprintk(NDEBUG_MAIN, "scsi%d : main() : performing information transfer\n", instance->host_no); NCR5380_information_transfer(instance); @@ -1421,11 +1332,6 @@ static int NCR5380_transfer_pio(struct Scsi_Host *instance, unsigned char *phase unsigned char p = *phase, tmp; int c = *count; unsigned char *d = *data; - /* - * RvC: some administrative data to process polling time - */ - int break_allowed = 0; - struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) instance->hostdata; if (!(p & SR_IO)) dprintk(NDEBUG_PIO, "scsi%d : pio write %d bytes\n", instance->host_no, c); @@ -1440,35 +1346,19 @@ static int NCR5380_transfer_pio(struct Scsi_Host *instance, unsigned char *phase NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(p)); - /* RvC: don't know if this is necessary, but other SCSI I/O is short - * so breaks are not necessary there - */ - if ((p == PHASE_DATAIN) || (p == PHASE_DATAOUT)) { - break_allowed = 1; - } do { /* * Wait for assertion of REQ, after which the phase bits will be * valid */ - /* RvC: we simply poll once, after that we stop temporarily - * and let the device buffer fill up - * if breaking is not allowed, we keep polling as long as needed - */ - - /* FIXME */ - while (!((tmp = NCR5380_read(STATUS_REG)) & SR_REQ) && !break_allowed); - if (!(tmp & SR_REQ)) { - /* timeout condition */ - NCR5380_set_timer(hostdata, USLEEP_SLEEP); + if (NCR5380_poll_politely(instance, STATUS_REG, SR_REQ, SR_REQ, HZ) < 0) break; - } dprintk(NDEBUG_HANDSHAKE, "scsi%d : REQ detected\n", instance->host_no); /* Check for phase mismatch */ - if ((tmp & PHASE_MASK) != p) { + if ((NCR5380_read(STATUS_REG) & PHASE_MASK) != p) { dprintk(NDEBUG_HANDSHAKE, "scsi%d : phase mismatch\n", instance->host_no); NCR5380_dprint_phase(NDEBUG_HANDSHAKE, instance); break; @@ -1940,8 +1830,6 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { unsigned char *data; unsigned char phase, tmp, extended_msg[10], old_phase = 0xff; struct scsi_cmnd *cmd = (struct scsi_cmnd *) hostdata->connected; - /* RvC: we need to set the end of the polling time */ - unsigned long poll_time = jiffies + USLEEP_POLL; while (1) { tmp = NCR5380_read(STATUS_REG); @@ -2141,7 +2029,6 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { case DISCONNECT:{ /* Accept message by clearing ACK */ NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - cmd->device->disconnect = 1; LIST(cmd, hostdata->disconnected_queue); cmd->host_scribble = (unsigned char *) hostdata->disconnected_queue; @@ -2273,11 +2160,6 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { * use the dma transfer function. */ NCR5380_transfer_pio(instance, &phase, &len, &data); - if (!cmd->device->disconnect && should_disconnect(cmd->cmnd[0])) { - NCR5380_set_timer(hostdata, USLEEP_SLEEP); - dprintk(NDEBUG_USLEEP, "scsi%d : issued command, sleeping until %lu\n", instance->host_no, hostdata->time_expires); - return; - } break; case PHASE_STATIN: len = 1; @@ -2289,15 +2171,10 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { printk("scsi%d : unknown phase\n", instance->host_no); NCR5380_dprint(NDEBUG_ANY, instance); } /* switch(phase) */ - } /* if (tmp * SR_REQ) */ - else { - /* RvC: go to sleep if polling time expired - */ - if (!cmd->device->disconnect && time_after_eq(jiffies, poll_time)) { - NCR5380_set_timer(hostdata, USLEEP_SLEEP); - dprintk(NDEBUG_USLEEP, "scsi%d : poll timed out, sleeping until %lu\n", instance->host_no, hostdata->time_expires); - return; - } + } else { + spin_unlock_irq(instance->host_lock); + NCR5380_poll_politely(instance, STATUS_REG, SR_REQ, SR_REQ, HZ); + spin_lock_irq(instance->host_lock); } } /* while (1) */ } diff --git a/drivers/scsi/NCR5380.h b/drivers/scsi/NCR5380.h index ee084e90e25c..9b7d7671d123 100644 --- a/drivers/scsi/NCR5380.h +++ b/drivers/scsi/NCR5380.h @@ -205,16 +205,6 @@ #define PHASE_SR_TO_TCR(phase) ((phase) >> 2) -/* - * The internal should_disconnect() function returns these based on the - * expected length of a disconnect if a device supports disconnect/ - * reconnect. - */ - -#define DISCONNECT_NONE 0 -#define DISCONNECT_TIME_TO_DATA 1 -#define DISCONNECT_LONG 2 - /* * "Special" value for the (unsigned char) command tag, to indicate * I_T_L nexus instead of I_T_L_Q. @@ -266,7 +256,6 @@ struct NCR5380_hostdata { volatile struct scsi_cmnd *issue_queue; /* waiting to be issued */ volatile struct scsi_cmnd *disconnected_queue; /* waiting for reconnect */ int flags; - unsigned long time_expires; /* in jiffies, set prior to sleeping */ struct delayed_work coroutine; /* our co-routine */ struct scsi_eh_save ses; char info[256]; diff --git a/drivers/scsi/atari_NCR5380.c b/drivers/scsi/atari_NCR5380.c index 59b378057198..dc283f50e4ac 100644 --- a/drivers/scsi/atari_NCR5380.c +++ b/drivers/scsi/atari_NCR5380.c @@ -126,17 +126,7 @@ * piece of hardware that requires you to sit in a loop polling for * the REQ signal as long as you are connected. Some devices are * brain dead (ie, many TEXEL CD ROM drives) and won't disconnect - * while doing long seek operations. - * - * The workaround for this is to keep track of devices that have - * disconnected. If the device hasn't disconnected, for commands that - * should disconnect, we do something like - * - * while (!REQ is asserted) { sleep for N usecs; poll for M usecs } - * - * Some tweaking of N and M needs to be done. An algorithm based - * on "time to data" would give the best results as long as short time - * to datas (ie, on the same track) were considered, however these + * while doing long seek operations. [...] These * broken devices are the exception rather than the rule and I'd rather * spend my time optimizing for the normal case. * @@ -1740,13 +1730,14 @@ static int NCR5380_transfer_pio(struct Scsi_Host *instance, * Wait for assertion of REQ, after which the phase bits will be * valid */ - while (!((tmp = NCR5380_read(STATUS_REG)) & SR_REQ)) - ; + + if (NCR5380_poll_politely(instance, STATUS_REG, SR_REQ, SR_REQ, HZ) < 0) + break; dprintk(NDEBUG_HANDSHAKE, "scsi%d: REQ detected\n", HOSTNO); /* Check for phase mismatch */ - if ((tmp & PHASE_MASK) != p) { + if ((NCR5380_read(STATUS_REG) & PHASE_MASK) != p) { dprintk(NDEBUG_PIO, "scsi%d: phase mismatch\n", HOSTNO); NCR5380_dprint_phase(NDEBUG_PIO, instance); break; @@ -2399,7 +2390,6 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) /* Accept message by clearing ACK */ NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); local_irq_save(flags); - cmd->device->disconnect = 1; LIST(cmd,hostdata->disconnected_queue); SET_NEXT(cmd, hostdata->disconnected_queue); hostdata->connected = NULL; @@ -2564,7 +2554,9 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) printk("scsi%d: unknown phase\n", HOSTNO); NCR5380_dprint(NDEBUG_ANY, instance); } /* switch(phase) */ - } /* if (tmp * SR_REQ) */ + } else { + NCR5380_poll_politely(instance, STATUS_REG, SR_REQ, SR_REQ, HZ); + } } /* while (1) */ } diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c index 5b3e03ad50ce..258bc2ff0d1c 100644 --- a/drivers/scsi/g_NCR5380.c +++ b/drivers/scsi/g_NCR5380.c @@ -56,10 +56,6 @@ * */ -/* settings for DTC3181E card with only Mustek scanner attached */ -#define USLEEP_POLL msecs_to_jiffies(10) -#define USLEEP_SLEEP msecs_to_jiffies(200) - #define AUTOPROBE_IRQ #ifdef CONFIG_SCSI_GENERIC_NCR53C400 -- cgit From a2edc4a63b4f89016053fe5da3fdac3798f3e2ae Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sun, 3 Jan 2016 16:05:27 +1100 Subject: ncr5380: Fix NCR5380_transfer_pio() result According to the SCSI-2 draft revision 10L, atari_NCR5380.c is correct when it says that the phase lines are valid up until ACK is negated following the transmission of the last byte in MESSAGE IN phase. This is true for all information transfer phases, from target to initiator. Sample the phase bits in STATUS_REG so that NCR5380_transfer_pio() can return the correct result. The return value is presently unused (perhaps because of bugs like this) but this change at least fixes the caller's phase variable, which is passed by reference. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Ondrej Zary Tested-by: Michael Schmitz Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.c | 12 +++++++++--- drivers/scsi/atari_NCR5380.c | 11 ++++++----- 2 files changed, 15 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index 23bb7fe8b13b..9b437e19b7a1 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -1393,8 +1393,10 @@ static int NCR5380_transfer_pio(struct Scsi_Host *instance, unsigned char *phase NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ACK); } - /* FIXME - if this fails bus reset ?? */ - NCR5380_poll_politely(instance, STATUS_REG, SR_REQ, 0, 5*HZ); + if (NCR5380_poll_politely(instance, + STATUS_REG, SR_REQ, 0, 5 * HZ) < 0) + break; + dprintk(NDEBUG_HANDSHAKE, "scsi%d : req false, handshake complete\n", instance->host_no); /* @@ -1421,7 +1423,11 @@ static int NCR5380_transfer_pio(struct Scsi_Host *instance, unsigned char *phase *count = c; *data = d; tmp = NCR5380_read(STATUS_REG); - if (tmp & SR_REQ) + /* The phase read from the bus is valid if either REQ is (already) + * asserted or if ACK hasn't been released yet. The latter applies if + * we're in MSG IN, DATA IN or STATUS and all bytes have been received. + */ + if ((tmp & SR_REQ) || ((tmp & SR_IO) && c == 0)) *phase = tmp & PHASE_MASK; else *phase = PHASE_UNKNOWN; diff --git a/drivers/scsi/atari_NCR5380.c b/drivers/scsi/atari_NCR5380.c index dc283f50e4ac..ca39dc623c34 100644 --- a/drivers/scsi/atari_NCR5380.c +++ b/drivers/scsi/atari_NCR5380.c @@ -1776,8 +1776,9 @@ static int NCR5380_transfer_pio(struct Scsi_Host *instance, NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ACK); } - while (NCR5380_read(STATUS_REG) & SR_REQ) - ; + if (NCR5380_poll_politely(instance, + STATUS_REG, SR_REQ, 0, 5 * HZ) < 0) + break; dprintk(NDEBUG_HANDSHAKE, "scsi%d: req false, handshake complete\n", HOSTNO); @@ -1806,10 +1807,10 @@ static int NCR5380_transfer_pio(struct Scsi_Host *instance, *data = d; tmp = NCR5380_read(STATUS_REG); /* The phase read from the bus is valid if either REQ is (already) - * asserted or if ACK hasn't been released yet. The latter is the case if - * we're in MSGIN and all wanted bytes have been received. + * asserted or if ACK hasn't been released yet. The latter applies if + * we're in MSG IN, DATA IN or STATUS and all bytes have been received. */ - if ((tmp & SR_REQ) || (p == PHASE_MSGIN && c == 0)) + if ((tmp & SR_REQ) || ((tmp & SR_IO) && c == 0)) *phase = tmp & PHASE_MASK; else *phase = PHASE_UNKNOWN; -- cgit From 9dafbd939a224b96868fd8db6909662a4cab5957 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sun, 3 Jan 2016 16:05:28 +1100 Subject: ncr5380: Add missing lock in eh_abort_handler The host spin lock needs to be acquired by NCR5380_abort() before it calls NCR5380_select(). This patch doesn't actually fix the EH issues in this driver but it does avoid this: BUG: spinlock already unlocked on CPU#0, kworker/u4:1/14 lock: 0xc0c0f834, .magic: dead4ead, .owner: /-1, .owner_cpu: -1 CPU: 0 PID: 14 Comm: kworker/u4:1 Not tainted 3.15.5 #5 Workqueue: scsi_tmf_4 scmd_eh_abort_handler Call Trace: [ef885d70] [c0008acc] show_stack+0x70/0x1bc (unreliable) [ef885db0] [c0492a00] dump_stack+0x84/0x684 [ef885dc0] [c006f314] spin_dump+0xd0/0xe8 [ef885dd0] [c006f460] do_raw_spin_unlock+0xd4/0xd8 [ef885df0] [c0491c8c] _raw_spin_unlock_irq+0x10/0x3c [ef885e00] [f381fe3c] NCR5380_select+0x3e4/0x6e8 [dmx3191d] [ef885e40] [f382026c] NCR5380_abort+0x12c/0x190 [dmx3191d] [ef885e60] [c02fec9c] scmd_eh_abort_handler+0x100/0x460 [ef885e80] [c0046470] process_one_work+0x16c/0x420 [ef885ea0] [c0046870] worker_thread+0x14c/0x430 [ef885ed0] [c004e4f4] kthread+0xd8/0xec [ef885f40] [c00124d4] ret_from_kernel_thread+0x5c/0x64 Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Ondrej Zary Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index 9b437e19b7a1..b46efaf1fffb 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -2374,6 +2374,7 @@ static int NCR5380_abort(struct scsi_cmnd *cmd) scmd_printk(KERN_WARNING, cmd, "aborting command\n"); + spin_lock_irq(instance->host_lock); NCR5380_print_status(instance); dprintk(NDEBUG_ABORT, "scsi%d : abort called\n", instance->host_no); @@ -2420,6 +2421,7 @@ static int NCR5380_abort(struct scsi_cmnd *cmd) REMOVE(5, *prev, tmp, tmp->host_scribble); (*prev) = (struct scsi_cmnd *) tmp->host_scribble; tmp->host_scribble = NULL; + spin_unlock_irq(instance->host_lock); tmp->result = DID_ABORT << 16; dprintk(NDEBUG_ABORT, "scsi%d : abort removed command from issue queue.\n", instance->host_no); tmp->scsi_done(tmp); @@ -2443,6 +2445,7 @@ static int NCR5380_abort(struct scsi_cmnd *cmd) */ if (hostdata->connected) { + spin_unlock_irq(instance->host_lock); dprintk(NDEBUG_ABORT, "scsi%d : abort failed, command connected.\n", instance->host_no); return FAILED; } @@ -2475,8 +2478,10 @@ static int NCR5380_abort(struct scsi_cmnd *cmd) if (cmd == tmp) { dprintk(NDEBUG_ABORT, "scsi%d : aborting disconnected command.\n", instance->host_no); - if (NCR5380_select(instance, cmd)) + if (NCR5380_select(instance, cmd)) { + spin_unlock_irq(instance->host_lock); return FAILED; + } dprintk(NDEBUG_ABORT, "scsi%d : nexus reestablished.\n", instance->host_no); do_abort(instance); @@ -2486,6 +2491,7 @@ static int NCR5380_abort(struct scsi_cmnd *cmd) REMOVE(5, *prev, tmp, tmp->host_scribble); *prev = (struct scsi_cmnd *) tmp->host_scribble; tmp->host_scribble = NULL; + spin_unlock_irq(instance->host_lock); tmp->result = DID_ABORT << 16; tmp->scsi_done(tmp); return SUCCESS; @@ -2500,6 +2506,7 @@ static int NCR5380_abort(struct scsi_cmnd *cmd) * so we won't panic, but we will notify the user in case something really * broke. */ + spin_unlock_irq(instance->host_lock); printk(KERN_WARNING "scsi%d : warning : SCSI command probably completed successfully\n" " before abortion\n", instance->host_no); return FAILED; -- cgit From 1bb40589ea377894478653beb4c92b1b1b8a0659 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sun, 3 Jan 2016 16:05:29 +1100 Subject: ncr5380: Drop DEF_SCSI_QCMD macro Remove the DEF_SCSI_QCMD macro (already removed from atari_NCR5380.c). The lock provided by DEF_SCSI_QCMD is only needed for queue data structures. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Ondrej Zary Tested-by: Michael Schmitz Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.c | 30 +++++++++++++++--------------- drivers/scsi/atari_NCR5380.c | 2 +- 2 files changed, 16 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index b46efaf1fffb..cd2065e4f70a 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -808,22 +808,21 @@ static void NCR5380_exit(struct Scsi_Host *instance) } /** - * NCR5380_queue_command - queue a command - * @cmd: SCSI command - * @done: completion handler + * NCR5380_queue_command - queue a command + * @instance: the relevant SCSI adapter + * @cmd: SCSI command * - * cmd is added to the per instance issue_queue, with minor - * twiddling done to the host specific fields of cmd. If the - * main coroutine is not running, it is restarted. - * - * Locks: host lock taken by caller + * cmd is added to the per-instance issue queue, with minor + * twiddling done to the host specific fields of cmd. If the + * main coroutine is not running, it is restarted. */ -static int NCR5380_queue_command_lck(struct scsi_cmnd *cmd, void (*done) (struct scsi_cmnd *)) +static int NCR5380_queue_command(struct Scsi_Host *instance, + struct scsi_cmnd *cmd) { - struct Scsi_Host *instance = cmd->device->host; - struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) instance->hostdata; + struct NCR5380_hostdata *hostdata = shost_priv(instance); struct scsi_cmnd *tmp; + unsigned long flags; #if (NDEBUG & NDEBUG_NO_WRITE) switch (cmd->cmnd[0]) { @@ -831,7 +830,7 @@ static int NCR5380_queue_command_lck(struct scsi_cmnd *cmd, void (*done) (struct case WRITE_10: printk("scsi%d : WRITE attempted with NO_WRITE debugging flag set\n", instance->host_no); cmd->result = (DID_ERROR << 16); - done(cmd); + cmd->scsi_done(cmd); return 0; } #endif /* (NDEBUG & NDEBUG_NO_WRITE) */ @@ -842,9 +841,10 @@ static int NCR5380_queue_command_lck(struct scsi_cmnd *cmd, void (*done) (struct */ cmd->host_scribble = NULL; - cmd->scsi_done = done; cmd->result = 0; + spin_lock_irqsave(instance->host_lock, flags); + /* * Insert the cmd into the issue queue. Note that REQUEST SENSE * commands are added to the head of the queue since any command will @@ -861,6 +861,8 @@ static int NCR5380_queue_command_lck(struct scsi_cmnd *cmd, void (*done) (struct LIST(cmd, tmp); tmp->host_scribble = (unsigned char *) cmd; } + spin_unlock_irqrestore(instance->host_lock, flags); + dprintk(NDEBUG_QUEUES, "scsi%d : command added to %s of queue\n", instance->host_no, (cmd->cmnd[0] == REQUEST_SENSE) ? "head" : "tail"); /* Run the coroutine if it isn't already running. */ @@ -869,8 +871,6 @@ static int NCR5380_queue_command_lck(struct scsi_cmnd *cmd, void (*done) (struct return 0; } -static DEF_SCSI_QCMD(NCR5380_queue_command) - /** * NCR5380_main - NCR state machines * diff --git a/drivers/scsi/atari_NCR5380.c b/drivers/scsi/atari_NCR5380.c index ca39dc623c34..bd832fb273bf 100644 --- a/drivers/scsi/atari_NCR5380.c +++ b/drivers/scsi/atari_NCR5380.c @@ -930,7 +930,7 @@ static void NCR5380_exit(struct Scsi_Host *instance) * @instance: the relevant SCSI adapter * @cmd: SCSI command * - * cmd is added to the per instance issue_queue, with minor + * cmd is added to the per-instance issue queue, with minor * twiddling done to the host specific fields of cmd. If the * main coroutine is not running, it is restarted. */ -- cgit From 2f10e47ccf26301c7ca1127e2f6c3dfce45ff634 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Sun, 3 Jan 2016 16:05:30 +1100 Subject: ncr5380: Remove references to linked commands Some old drivers partially implemented support for linked commands using a "proposed" next_link pointer in struct scsi_cmnd that never actually existed. Remove this code. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Ondrej Zary Tested-by: Michael Schmitz Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.c | 42 ------------------------------- drivers/scsi/atari_NCR5380.c | 60 -------------------------------------------- 2 files changed, 102 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index cd2065e4f70a..9b7c67f17f4b 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -78,9 +78,6 @@ * * 4. Test SCSI-II tagged queueing (I have no devices which support * tagged queueing) - * - * 5. Test linked command handling code after Eric is ready with - * the high level code. */ #include #include @@ -94,7 +91,6 @@ #endif #ifndef notyet -#undef LINKED #undef REAL_DMA #endif @@ -191,8 +187,6 @@ * DONT_USE_INTR - if defined, never use interrupts, even if we probe or * override-configure an IRQ. * - * LINKED - if defined, linked commands are supported. - * * PSEUDO_DMA - if defined, PSEUDO DMA is used during the data transfer phases. * * REAL_DMA - if defined, REAL DMA is used during the data transfer phases. @@ -1923,42 +1917,6 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { cmd->SCp.Message = tmp; switch (tmp) { - /* - * Linking lets us reduce the time required to get the - * next command out to the device, hopefully this will - * mean we don't waste another revolution due to the delays - * required by ARBITRATION and another SELECTION. - * - * In the current implementation proposal, low level drivers - * merely have to start the next command, pointed to by - * next_link, done() is called as with unlinked commands. - */ -#ifdef LINKED - case LINKED_CMD_COMPLETE: - case LINKED_FLG_CMD_COMPLETE: - /* Accept message by clearing ACK */ - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - dprintk(NDEBUG_LINKED, "scsi%d : target %d lun %llu linked command complete.\n", instance->host_no, cmd->device->id, cmd->device->lun); - /* - * Sanity check : A linked command should only terminate with - * one of these messages if there are more linked commands - * available. - */ - if (!cmd->next_link) { - printk("scsi%d : target %d lun %llu linked command complete, no next_link\n" instance->host_no, cmd->device->id, cmd->device->lun); - sink = 1; - do_abort(instance); - return; - } - initialize_SCp(cmd->next_link); - /* The next command is still part of this process */ - cmd->next_link->tag = cmd->tag; - cmd->result = cmd->SCp.Status | (cmd->SCp.Message << 8); - dprintk(NDEBUG_LINKED, "scsi%d : target %d lun %llu linked request done, calling scsi_done().\n", instance->host_no, cmd->device->id, cmd->device->lun); - cmd->scsi_done(cmd); - cmd = hostdata->connected; - break; -#endif /* def LINKED */ case ABORT: case COMMAND_COMPLETE: /* Accept message by clearing ACK */ diff --git a/drivers/scsi/atari_NCR5380.c b/drivers/scsi/atari_NCR5380.c index bd832fb273bf..528e0b62fb28 100644 --- a/drivers/scsi/atari_NCR5380.c +++ b/drivers/scsi/atari_NCR5380.c @@ -66,12 +66,6 @@ * */ -/* - * Further development / testing that should be done : - * 1. Test linked command handling code after Eric is ready with - * the high level code. - */ - /* Adapted for the sun3 by Sam Creasey. */ #include @@ -98,10 +92,6 @@ #define REMOVE(w,x,y,z) #endif -#ifndef notyet -#undef LINKED -#endif - /* * Design * @@ -172,8 +162,6 @@ * DIFFERENTIAL - if defined, NCR53c81 chips will use external differential * transceivers. * - * LINKED - if defined, linked commands are supported. - * * REAL_DMA - if defined, REAL DMA is used during the data transfer phases. * * SUPPORT_TAGS - if defined, SCSI-2 tagged queuing is used where possible @@ -2216,54 +2204,6 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) cmd->SCp.Message = tmp; switch (tmp) { - /* - * Linking lets us reduce the time required to get the - * next command out to the device, hopefully this will - * mean we don't waste another revolution due to the delays - * required by ARBITRATION and another SELECTION. - * - * In the current implementation proposal, low level drivers - * merely have to start the next command, pointed to by - * next_link, done() is called as with unlinked commands. - */ -#ifdef LINKED - case LINKED_CMD_COMPLETE: - case LINKED_FLG_CMD_COMPLETE: - /* Accept message by clearing ACK */ - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - - dprintk(NDEBUG_LINKED, "scsi%d: target %d lun %llu linked command " - "complete.\n", HOSTNO, cmd->device->id, cmd->device->lun); - - /* Enable reselect interrupts */ - NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); - /* - * Sanity check : A linked command should only terminate - * with one of these messages if there are more linked - * commands available. - */ - - if (!cmd->next_link) { - printk(KERN_NOTICE "scsi%d: target %d lun %llu " - "linked command complete, no next_link\n", - HOSTNO, cmd->device->id, cmd->device->lun); - sink = 1; - do_abort(instance); - return; - } - - initialize_SCp(cmd->next_link); - /* The next command is still part of this process; copy it - * and don't free it! */ - cmd->next_link->tag = cmd->tag; - cmd->result = cmd->SCp.Status | (cmd->SCp.Message << 8); - dprintk(NDEBUG_LINKED, "scsi%d: target %d lun %llu linked request " - "done, calling scsi_done().\n", - HOSTNO, cmd->device->id, cmd->device->lun); - cmd->scsi_done(cmd); - cmd = hostdata->connected; - break; -#endif /* def LINKED */ case ABORT: case COMMAND_COMPLETE: /* Accept message by clearing ACK */ -- cgit From 340b96126d8abf859aa8af2fed31ed11ef9f4600 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sun, 3 Jan 2016 16:05:31 +1100 Subject: ncr5380: Add missing break after case MESSAGE_REJECT MESSAGE REJECT does not imply DISCONNECT: the target is about to enter MESSAGE IN or MESSAGE OUT phase. This bug fix comes from atari_NCR5380.c. Unfortunately it never made it into the original NCR5380.c core driver. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Ondrej Zary Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index 9b7c67f17f4b..97100a1e3f80 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -1990,6 +1990,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { default: break; } + break; case DISCONNECT:{ /* Accept message by clearing ACK */ NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); -- cgit From 1cc160e1ba938d34581181517221913683031d29 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sun, 3 Jan 2016 16:05:32 +1100 Subject: ncr5380: Fix !REQ timeout in do_abort() NCR5380_poll_politely() never returns -1. That means do_abort() can fail to handle a timeout after waiting for the target to negate REQ. Fix this and cleanup other NCR5380_poll_politely() call sites. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Ondrej Zary Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index 97100a1e3f80..baa8785ff22b 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -1271,7 +1271,7 @@ static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd) err = NCR5380_poll_politely(instance, STATUS_REG, SR_REQ, SR_REQ, HZ); spin_lock_irq(instance->host_lock); - if(err) { + if (err < 0) { printk(KERN_ERR "scsi%d: timeout at NCR5380.c:%d\n", instance->host_no, __LINE__); NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); return -1; @@ -1490,8 +1490,7 @@ static int do_abort(struct Scsi_Host *instance) */ rc = NCR5380_poll_politely(instance, STATUS_REG, SR_REQ, SR_REQ, 60 * HZ); - - if(rc < 0) + if (rc < 0) return -1; tmp = (unsigned char)rc; @@ -1502,7 +1501,7 @@ static int do_abort(struct Scsi_Host *instance) NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN | ICR_ASSERT_ACK); rc = NCR5380_poll_politely(instance, STATUS_REG, SR_REQ, 0, 3 * HZ); NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN); - if(rc == -1) + if (rc < 0) return -1; } tmp = ABORT; @@ -2199,7 +2198,8 @@ static void NCR5380_reselect(struct Scsi_Host *instance) { * FIXME: timeout needed and fail to work queeu */ - if(NCR5380_poll_politely(instance, STATUS_REG, SR_REQ, SR_REQ, 2*HZ)) + if (NCR5380_poll_politely(instance, + STATUS_REG, SR_REQ, SR_REQ, 2 * HZ) < 0) abort = 1; len = 1; -- cgit From f35d34744c85b2ea31a3fe624616c10229ff1fb3 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sun, 3 Jan 2016 16:05:33 +1100 Subject: ncr5380: Fix bus phase in do_abort() NCR5380_poll_politely() returns either 0 (success) or -ETIMEDOUT. However, in do_abort(), the return value is incorrectly taken to be the status register value. This means that the bus is put into DATA OUT phase instead of MESSAGE OUT. Fix this. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Ondrej Zary Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index baa8785ff22b..334d253fe75a 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -1493,11 +1493,11 @@ static int do_abort(struct Scsi_Host *instance) if (rc < 0) return -1; - tmp = (unsigned char)rc; + tmp = NCR5380_read(STATUS_REG) & PHASE_MASK; NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(tmp)); - if ((tmp & PHASE_MASK) != PHASE_MSGOUT) { + if (tmp != PHASE_MSGOUT) { NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN | ICR_ASSERT_ACK); rc = NCR5380_poll_politely(instance, STATUS_REG, SR_REQ, 0, 3 * HZ); NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN); -- cgit From 80d3eb6df46603e0b7e9a7361fe5b98383182c7f Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sun, 3 Jan 2016 16:05:34 +1100 Subject: atari_NCR5380: Set do_abort() timeouts Use timeouts in do_abort() in atari_NCR5380.c instead of infinite loops. Also fix the kernel-doc comment. Keep the two core driver forks in sync. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Ondrej Zary Tested-by: Michael Schmitz Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.c | 26 +++++++++++++------------- drivers/scsi/atari_NCR5380.c | 34 +++++++++++++++++++++------------- 2 files changed, 34 insertions(+), 26 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index 334d253fe75a..973ea5189dd4 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -1458,16 +1458,12 @@ static void do_reset(struct Scsi_Host *instance) local_irq_restore(flags); } -/* - * Function : do_abort (Scsi_Host *host) - * - * Purpose : abort the currently established nexus. Should only be - * called from a routine which can drop into a - * - * Returns : 0 on success, -1 on failure. +/** + * do_abort - abort the currently established nexus by going to + * MESSAGE OUT phase and sending an ABORT message. + * @instance: relevant scsi host instance * - * Locks: queue lock held by caller - * FIXME: sort this out and get new_eh running + * Returns 0 on success, -1 on failure. */ static int do_abort(struct Scsi_Host *instance) @@ -1489,9 +1485,9 @@ static int do_abort(struct Scsi_Host *instance) * the target sees, so we just handshake. */ - rc = NCR5380_poll_politely(instance, STATUS_REG, SR_REQ, SR_REQ, 60 * HZ); + rc = NCR5380_poll_politely(instance, STATUS_REG, SR_REQ, SR_REQ, 10 * HZ); if (rc < 0) - return -1; + goto timeout; tmp = NCR5380_read(STATUS_REG) & PHASE_MASK; @@ -1500,9 +1496,9 @@ static int do_abort(struct Scsi_Host *instance) if (tmp != PHASE_MSGOUT) { NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN | ICR_ASSERT_ACK); rc = NCR5380_poll_politely(instance, STATUS_REG, SR_REQ, 0, 3 * HZ); - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN); if (rc < 0) - return -1; + goto timeout; + NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN); } tmp = ABORT; msgptr = &tmp; @@ -1516,6 +1512,10 @@ static int do_abort(struct Scsi_Host *instance) */ return len ? -1 : 0; + +timeout: + NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); + return -1; } #if defined(REAL_DMA) || defined(PSEUDO_DMA) || defined (REAL_DMA_POLL) diff --git a/drivers/scsi/atari_NCR5380.c b/drivers/scsi/atari_NCR5380.c index 528e0b62fb28..a3c0968c8eef 100644 --- a/drivers/scsi/atari_NCR5380.c +++ b/drivers/scsi/atari_NCR5380.c @@ -1835,19 +1835,19 @@ static void do_reset(struct Scsi_Host *instance) local_irq_restore(flags); } -/* - * Function : do_abort (Scsi_Host *host) - * - * Purpose : abort the currently established nexus. Should only be - * called from a routine which can drop into a +/** + * do_abort - abort the currently established nexus by going to + * MESSAGE OUT phase and sending an ABORT message. + * @instance: relevant scsi host instance * - * Returns : 0 on success, -1 on failure. + * Returns 0 on success, -1 on failure. */ static int do_abort(struct Scsi_Host *instance) { unsigned char tmp, *msgptr, phase; int len; + int rc; /* Request message out phase */ NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN); @@ -1862,16 +1862,20 @@ static int do_abort(struct Scsi_Host *instance) * the target sees, so we just handshake. */ - while (!((tmp = NCR5380_read(STATUS_REG)) & SR_REQ)) - ; + rc = NCR5380_poll_politely(instance, STATUS_REG, SR_REQ, SR_REQ, 10 * HZ); + if (rc < 0) + goto timeout; + + tmp = NCR5380_read(STATUS_REG) & PHASE_MASK; NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(tmp)); - if ((tmp & PHASE_MASK) != PHASE_MSGOUT) { - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN | - ICR_ASSERT_ACK); - while (NCR5380_read(STATUS_REG) & SR_REQ) - ; + if (tmp != PHASE_MSGOUT) { + NCR5380_write(INITIATOR_COMMAND_REG, + ICR_BASE | ICR_ASSERT_ATN | ICR_ASSERT_ACK); + rc = NCR5380_poll_politely(instance, STATUS_REG, SR_REQ, 0, 3 * HZ); + if (rc < 0) + goto timeout; NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN); } @@ -1887,6 +1891,10 @@ static int do_abort(struct Scsi_Host *instance) */ return len ? -1 : 0; + +timeout: + NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); + return -1; } #if defined(REAL_DMA) -- cgit From 55500d9b08295e3b6016b53879dea1cb7787f1b0 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sun, 3 Jan 2016 16:05:35 +1100 Subject: atari_NCR5380: Use arbitration timeout Allow target selection to fail with a timeout instead of waiting in infinite loops. This gets rid of the unused NCR_TIMEOUT macro, it is more defensive and has proved helpful in debugging. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Ondrej Zary Tested-by: Michael Schmitz Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.c | 44 ++++++++++++++++++---------------- drivers/scsi/atari_NCR5380.c | 57 +++++++++++++++++++------------------------- 2 files changed, 49 insertions(+), 52 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index 973ea5189dd4..97975cb27337 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -1083,6 +1083,7 @@ static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd) unsigned char *data; int len; int err; + unsigned long timeout; NCR5380_dprint(NDEBUG_ARBITRATION, instance); dprintk(NDEBUG_ARBITRATION, "scsi%d : starting arbitration, id = %d\n", instance->host_no, instance->this_id); @@ -1101,28 +1102,31 @@ static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd) NCR5380_write(OUTPUT_DATA_REG, hostdata->id_mask); NCR5380_write(MODE_REG, MR_ARBITRATE); + /* The chip now waits for BUS FREE phase. Then after the 800 ns + * Bus Free Delay, arbitration will begin. + */ - /* We can be relaxed here, interrupts are on, we are - in workqueue context, the birds are singing in the trees */ spin_unlock_irq(instance->host_lock); - err = NCR5380_poll_politely(instance, INITIATOR_COMMAND_REG, ICR_ARBITRATION_PROGRESS, ICR_ARBITRATION_PROGRESS, 5*HZ); - spin_lock_irq(instance->host_lock); - if (err < 0) { - printk(KERN_DEBUG "scsi: arbitration timeout at %d\n", __LINE__); - NCR5380_write(MODE_REG, MR_BASE); - NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); - return -1; + timeout = jiffies + HZ; + while (1) { + if (time_is_before_jiffies(timeout)) { + NCR5380_write(MODE_REG, MR_BASE); + shost_printk(KERN_ERR, instance, + "select: arbitration timeout\n"); + spin_lock_irq(instance->host_lock); + return -1; + } + spin_lock_irq(instance->host_lock); + if (!(NCR5380_read(MODE_REG) & MR_ARBITRATE)) { + /* Reselection interrupt */ + return -1; + } + if (NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_PROGRESS) + break; + spin_unlock_irq(instance->host_lock); } - dprintk(NDEBUG_ARBITRATION, "scsi%d : arbitration complete\n", instance->host_no); - - /* - * The arbitration delay is 2.2us, but this is a minimum and there is - * no maximum so we can safely sleep for ceil(2.2) usecs to accommodate - * the integral nature of udelay(). - * - */ - + /* The SCSI-2 arbitration delay is 2.4 us */ udelay(3); /* Check for lost arbitration */ @@ -1270,9 +1274,9 @@ static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd) spin_unlock_irq(instance->host_lock); err = NCR5380_poll_politely(instance, STATUS_REG, SR_REQ, SR_REQ, HZ); spin_lock_irq(instance->host_lock); - if (err < 0) { - printk(KERN_ERR "scsi%d: timeout at NCR5380.c:%d\n", instance->host_no, __LINE__); + shost_printk(KERN_ERR, instance, "select: REQ timeout\n"); + NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); return -1; } diff --git a/drivers/scsi/atari_NCR5380.c b/drivers/scsi/atari_NCR5380.c index a3c0968c8eef..a92e4a531d34 100644 --- a/drivers/scsi/atari_NCR5380.c +++ b/drivers/scsi/atari_NCR5380.c @@ -1412,6 +1412,7 @@ static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd) int len; int err; unsigned long flags; + unsigned long timeout; NCR5380_dprint(NDEBUG_ARBITRATION, instance); dprintk(NDEBUG_ARBITRATION, "scsi%d: starting arbitration, id = %d\n", HOSTNO, @@ -1436,42 +1437,28 @@ static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd) NCR5380_write(OUTPUT_DATA_REG, hostdata->id_mask); NCR5380_write(MODE_REG, MR_ARBITRATE); - local_irq_restore(flags); - - /* Wait for arbitration logic to complete */ -#if defined(NCR_TIMEOUT) - { - unsigned long timeout = jiffies + 2*NCR_TIMEOUT; + /* The chip now waits for BUS FREE phase. Then after the 800 ns + * Bus Free Delay, arbitration will begin. + */ - while (!(NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_PROGRESS) && - time_before(jiffies, timeout) && !hostdata->connected) - ; - if (time_after_eq(jiffies, timeout)) { - printk("scsi : arbitration timeout at %d\n", __LINE__); + local_irq_restore(flags); + timeout = jiffies + HZ; + while (1) { + if (time_is_before_jiffies(timeout)) { NCR5380_write(MODE_REG, MR_BASE); - NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); + shost_printk(KERN_ERR, instance, + "select: arbitration timeout\n"); return -1; } + if (!(NCR5380_read(MODE_REG) & MR_ARBITRATE)) { + /* Reselection interrupt */ + return -1; + } + if (NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_PROGRESS) + break; } -#else /* NCR_TIMEOUT */ - while (!(NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_PROGRESS) && - !hostdata->connected) - ; -#endif - - dprintk(NDEBUG_ARBITRATION, "scsi%d: arbitration complete\n", HOSTNO); - - if (hostdata->connected) { - NCR5380_write(MODE_REG, MR_BASE); - return -1; - } - /* - * The arbitration delay is 2.2us, but this is a minimum and there is - * no maximum so we can safely sleep for ceil(2.2) usecs to accommodate - * the integral nature of udelay(). - * - */ + /* The SCSI-2 arbitration delay is 2.4 us */ udelay(3); /* Check for lost arbitration */ @@ -1634,8 +1621,14 @@ static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd) */ /* Wait for start of REQ/ACK handshake */ - while (!(NCR5380_read(STATUS_REG) & SR_REQ)) - ; + + err = NCR5380_poll_politely(instance, STATUS_REG, SR_REQ, SR_REQ, HZ); + if (err < 0) { + shost_printk(KERN_ERR, instance, "select: REQ timeout\n"); + NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); + NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); + return -1; + } dprintk(NDEBUG_SELECTION, "scsi%d: target %d selected, going into MESSAGE OUT phase.\n", HOSTNO, cmd->device->id); -- cgit From 401e79fe8d9f0151ad99e6fd7c1bd2e178c84d25 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sun, 3 Jan 2016 16:05:36 +1100 Subject: ncr5380: Dont wait for BUS FREE after disconnect When there is a queued command and no connected command, NCR5380_select() is called and arbitration begins. The chip waits for BUS FREE once the MR_ARBITRATE bit in the mode register is enabled. That means there is no need to wait for BUS FREE after disconnecting. There is presently no polling for BUS FREE after sending an ABORT or other message that might lead to disconnection. It only happens after COMMAND COMPLETE or DISCONNECT messages, which seems inconsistent. Remove the polling for !BSY in the COMMAND COMPLETE and DISCONNECT cases. BTW, the comments say "avoid nasty timeouts" and perhaps BUS FREE polling was somehow helpful back in Linux v0.99.14u, when it was introduced. The relevant timeout is presently 1 second (for bus arbitration). Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Ondrej Zary Tested-by: Michael Schmitz Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.c | 7 ------- drivers/scsi/atari_NCR5380.c | 11 ----------- 2 files changed, 18 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index 97975cb27337..a64b298eeb55 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -1976,9 +1976,6 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { * arbitration can resume. */ NCR5380_write(TARGET_COMMAND_REG, 0); - - while ((NCR5380_read(STATUS_REG) & SR_BSY) && !hostdata->connected) - barrier(); return; case MESSAGE_REJECT: /* Accept message by clearing ACK */ @@ -2011,10 +2008,6 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { /* Enable reselect interrupts */ NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); - /* Wait for bus free to avoid nasty timeouts - FIXME timeout !*/ - /* NCR538_poll_politely(instance, STATUS_REG, SR_BSY, 0, 30 * HZ); */ - while ((NCR5380_read(STATUS_REG) & SR_BSY) && !hostdata->connected) - barrier(); return; } /* diff --git a/drivers/scsi/atari_NCR5380.c b/drivers/scsi/atari_NCR5380.c index a92e4a531d34..437e1e59b905 100644 --- a/drivers/scsi/atari_NCR5380.c +++ b/drivers/scsi/atari_NCR5380.c @@ -2213,7 +2213,6 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) "completed\n", HOSTNO, cmd->device->id, cmd->device->lun); local_irq_save(flags); - hostdata->retain_dma_intr++; hostdata->connected = NULL; #ifdef SUPPORT_TAGS cmd_free_tag(cmd); @@ -2282,8 +2281,6 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) cmd->scsi_done(cmd); } - local_irq_restore(flags); - NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); /* * Restore phase bits to 0 so an interrupted selection, @@ -2291,11 +2288,6 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) */ NCR5380_write(TARGET_COMMAND_REG, 0); - while ((NCR5380_read(STATUS_REG) & SR_BSY) && !hostdata->connected) - barrier(); - - local_irq_save(flags); - hostdata->retain_dma_intr--; /* ++roman: For Falcon SCSI, release the lock on the * ST-DMA here if no other commands are waiting on the * disconnected queue. @@ -2349,9 +2341,6 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) /* Enable reselect interrupts */ NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); - /* Wait for bus free to avoid nasty timeouts */ - while ((NCR5380_read(STATUS_REG) & SR_BSY) && !hostdata->connected) - barrier(); #ifdef SUN3_SCSI_VME dregs->csr |= CSR_DMA_ENABLE; #endif -- cgit From 8d8601a757688386e914b922cc267a9244e0fdc9 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sun, 3 Jan 2016 16:05:37 +1100 Subject: ncr5380: Use work_struct instead of delayed_work Each host instance now has it's own work queue so the main() work item can sleep when necessary. That means we can use a simple work item rather than a delayed work item. This brings NCR5380.c closer to atari_NCR5380.c. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Ondrej Zary Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.c | 12 +++++------- drivers/scsi/NCR5380.h | 1 - 2 files changed, 5 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index a64b298eeb55..8ff59509585c 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -697,7 +697,7 @@ static int NCR5380_init(struct Scsi_Host *instance, int flags) hostdata->issue_queue = NULL; hostdata->disconnected_queue = NULL; - INIT_DELAYED_WORK(&hostdata->coroutine, NCR5380_main); + INIT_WORK(&hostdata->main_task, NCR5380_main); hostdata->work_q = alloc_workqueue("ncr5380_%d", WQ_UNBOUND | WQ_MEM_RECLAIM, 1, instance->host_no); @@ -797,7 +797,7 @@ static void NCR5380_exit(struct Scsi_Host *instance) { struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) instance->hostdata; - cancel_delayed_work_sync(&hostdata->coroutine); + cancel_work_sync(&hostdata->main_task); destroy_workqueue(hostdata->work_q); } @@ -859,9 +859,8 @@ static int NCR5380_queue_command(struct Scsi_Host *instance, dprintk(NDEBUG_QUEUES, "scsi%d : command added to %s of queue\n", instance->host_no, (cmd->cmnd[0] == REQUEST_SENSE) ? "head" : "tail"); - /* Run the coroutine if it isn't already running. */ /* Kick off command processing */ - queue_delayed_work(hostdata->work_q, &hostdata->coroutine, 0); + queue_work(hostdata->work_q, &hostdata->main_task); return 0; } @@ -880,7 +879,7 @@ static int NCR5380_queue_command(struct Scsi_Host *instance, static void NCR5380_main(struct work_struct *work) { struct NCR5380_hostdata *hostdata = - container_of(work, struct NCR5380_hostdata, coroutine.work); + container_of(work, struct NCR5380_hostdata, main_task); struct Scsi_Host *instance = hostdata->host; struct scsi_cmnd *tmp, *prev; int done; @@ -1037,8 +1036,7 @@ static irqreturn_t NCR5380_intr(int dummy, void *dev_id) } /* if BASR_IRQ */ spin_unlock_irqrestore(instance->host_lock, flags); if(!done) - queue_delayed_work(hostdata->work_q, - &hostdata->coroutine, 0); + queue_work(hostdata->work_q, &hostdata->main_task); } while (!done); return IRQ_HANDLED; } diff --git a/drivers/scsi/NCR5380.h b/drivers/scsi/NCR5380.h index 9b7d7671d123..7ffcb0c33a22 100644 --- a/drivers/scsi/NCR5380.h +++ b/drivers/scsi/NCR5380.h @@ -256,7 +256,6 @@ struct NCR5380_hostdata { volatile struct scsi_cmnd *issue_queue; /* waiting to be issued */ volatile struct scsi_cmnd *disconnected_queue; /* waiting for reconnect */ int flags; - struct delayed_work coroutine; /* our co-routine */ struct scsi_eh_save ses; char info[256]; int read_overruns; /* number of bytes to cut from a -- cgit From 010e89d18c4e66ab69d64bab439eba988d16fcc9 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sun, 3 Jan 2016 16:05:38 +1100 Subject: ncr5380: Standardize work queueing algorithm The complex main_running/queue_main mechanism is peculiar to atari_NCR5380.c. It isn't SMP safe and offers little value given that the work queue already offers concurrency management. Remove this complexity to bring atari_NCR5380.c closer to NCR5380.c. It is not a good idea to call the information transfer state machine from queuecommand because, according to Documentation/scsi/scsi_mid_low_api.txt that could happen in soft irq context. Fix this. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Michael Schmitz Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.h | 1 - drivers/scsi/atari_NCR5380.c | 80 ++++---------------------------------------- 2 files changed, 6 insertions(+), 75 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/NCR5380.h b/drivers/scsi/NCR5380.h index 7ffcb0c33a22..78af75142342 100644 --- a/drivers/scsi/NCR5380.h +++ b/drivers/scsi/NCR5380.h @@ -262,7 +262,6 @@ struct NCR5380_hostdata { * transfer to handle chip overruns */ int retain_dma_intr; struct work_struct main_task; - volatile int main_running; #ifdef SUPPORT_TAGS struct tag_alloc TagAlloc[8][8]; /* 8 targets and 8 LUNs */ #endif diff --git a/drivers/scsi/atari_NCR5380.c b/drivers/scsi/atari_NCR5380.c index 437e1e59b905..48e3d76e39e3 100644 --- a/drivers/scsi/atari_NCR5380.c +++ b/drivers/scsi/atari_NCR5380.c @@ -602,36 +602,6 @@ static void NCR5380_print_phase(struct Scsi_Host *instance) #endif -/* - * ++roman: New scheme of calling NCR5380_main() - * - * If we're not in an interrupt, we can call our main directly, it cannot be - * already running. Else, we queue it on a task queue, if not 'main_running' - * tells us that a lower level is already executing it. This way, - * 'main_running' needs not be protected in a special way. - * - * queue_main() is a utility function for putting our main onto the task - * queue, if main_running is false. It should be called only from a - * interrupt or bottom half. - */ - -#include -#include -#include - -static inline void queue_main(struct NCR5380_hostdata *hostdata) -{ - if (!hostdata->main_running) { - /* If in interrupt and NCR5380_main() not already running, - queue it on the 'immediate' task queue, to be processed - immediately after the current interrupt processing has - finished. */ - queue_work(hostdata->work_q, &hostdata->main_task); - } - /* else: nothing to do: the running NCR5380_main() will pick up - any newly queued command. */ -} - /** * NCR58380_info - report driver and host information * @instance: relevant scsi host instance @@ -714,8 +684,6 @@ static void __maybe_unused NCR5380_print_status(struct Scsi_Host *instance) hostdata = (struct NCR5380_hostdata *)instance->hostdata; local_irq_save(flags); - printk("NCR5380: coroutine is%s running.\n", - hostdata->main_running ? "" : "n't"); if (!hostdata->connected) printk("scsi%d: no currently connected command\n", HOSTNO); else @@ -757,8 +725,6 @@ static int __maybe_unused NCR5380_show_info(struct seq_file *m, hostdata = (struct NCR5380_hostdata *)instance->hostdata; local_irq_save(flags); - seq_printf(m, "NCR5380: coroutine is%s running.\n", - hostdata->main_running ? "" : "n't"); if (!hostdata->connected) seq_printf(m, "scsi%d: no currently connected command\n", HOSTNO); else @@ -997,17 +963,8 @@ static int NCR5380_queue_command(struct Scsi_Host *instance, dprintk(NDEBUG_QUEUES, "scsi%d: command added to %s of queue\n", H_NO(cmd), (cmd->cmnd[0] == REQUEST_SENSE) ? "head" : "tail"); - /* If queue_command() is called from an interrupt (real one or bottom - * half), we let queue_main() do the job of taking care about main. If it - * is already running, this is a no-op, else main will be queued. - * - * If we're not in an interrupt, we can call NCR5380_main() - * unconditionally, because it cannot be already running. - */ - if (in_interrupt() || irqs_disabled()) - queue_main(hostdata); - else - NCR5380_main(&hostdata->main_task); + /* Kick off command processing */ + queue_work(hostdata->work_q, &hostdata->main_task); return 0; } @@ -1044,30 +1001,11 @@ static void NCR5380_main(struct work_struct *work) unsigned long flags; /* - * We run (with interrupts disabled) until we're sure that none of - * the host adapters have anything that can be done, at which point - * we set main_running to 0 and exit. - * - * Interrupts are enabled before doing various other internal - * instructions, after we've decided that we need to run through - * the loop again. - * - * this should prevent any race conditions. - * * ++roman: Just disabling the NCR interrupt isn't sufficient here, * because also a timer int can trigger an abort or reset, which can * alter queues and touch the Falcon lock. */ - /* Tell int handlers main() is now already executing. Note that - no races are possible here. If an int comes in before - 'main_running' is set here, and queues/executes main via the - task queue, it doesn't do any harm, just this instance of main - won't find any work left to do. */ - if (hostdata->main_running) - return; - hostdata->main_running = 1; - local_save_flags(flags); do { local_irq_disable(); /* Freeze request queues */ @@ -1182,11 +1120,6 @@ static void NCR5380_main(struct work_struct *work) done = 0; } } while (!done); - - /* Better allow ints _after_ 'main_running' has been cleared, else - an interrupt could believe we'll pick up the work it left for - us, but we won't see it anymore here... */ - hostdata->main_running = 0; local_irq_restore(flags); } @@ -1299,6 +1232,7 @@ static void NCR5380_dma_complete(struct Scsi_Host *instance) static irqreturn_t NCR5380_intr(int irq, void *dev_id) { struct Scsi_Host *instance = dev_id; + struct NCR5380_hostdata *hostdata = shost_priv(instance); int done = 1, handled = 0; unsigned char basr; @@ -1367,11 +1301,9 @@ static irqreturn_t NCR5380_intr(int irq, void *dev_id) #endif } - if (!done) { - dprintk(NDEBUG_INTR, "scsi%d: in int routine, calling main\n", HOSTNO); - /* Put a call to NCR5380_main() on the queue... */ - queue_main(shost_priv(instance)); - } + if (!done) + queue_work(hostdata->work_q, &hostdata->main_task); + return IRQ_RETVAL(handled); } -- cgit From d1af9c7f4a69824440d2d755ddc3b861712ef024 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sun, 3 Jan 2016 16:05:39 +1100 Subject: ncr5380: Remove UNSAFE macro Configuring core drivers using macros like this one prevents re-unifying the core driver forks, and prevents implementing the core driver as a library or a platform driver. The UNSAFE macro in particular is a poor workaround for the problem of interrupt latency. Releasing the locks complicates things because then we would have to handle the possibility of EH handler invocation during a PDMA transfer. The comments say that instead of using this macro, "you're going to be better off twiddling with transfersize". I agree. Remove this stuff. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Ondrej Zary Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.c | 15 --------------- drivers/scsi/dtc.c | 2 -- drivers/scsi/pas16.c | 1 - 3 files changed, 18 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index 8ff59509585c..1a6562b94bf7 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -195,12 +195,6 @@ * rely on phase mismatch and EOP interrupts to determine end * of phase. * - * UNSAFE - leave interrupts enabled during pseudo-DMA transfers. You - * only really want to use this if you're having a problem with - * dropped characters during high speed communications, and even - * then, you're going to be better off twiddling with transfersize - * in the high level code. - * * Defaults for these will be provided although the user may want to adjust * these to allocate CPU resources to the SCSI driver or "real" code. * @@ -553,9 +547,6 @@ static void prepare_info(struct Scsi_Host *instance) #endif #ifdef PSEUDO_DMA "PSEUDO_DMA " -#endif -#ifdef UNSAFE - "UNSAFE " #endif ""); } @@ -1582,9 +1573,6 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, unsigned char *phase * before the setting of DMA mode to after transfer of the last byte. */ -#if defined(PSEUDO_DMA) && defined(UNSAFE) - spin_unlock_irq(instance->host_lock); -#endif /* KLL May need eop and parity in 53c400 */ if (hostdata->flags & FLAG_NCR53C400) NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE | @@ -1793,9 +1781,6 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, unsigned char *phase *data = d + c; *count = 0; *phase = NCR5380_read(STATUS_REG) & PHASE_MASK; -#if defined(PSEUDO_DMA) && defined(UNSAFE) - spin_lock_irq(instance->host_lock); -#endif /* defined(REAL_DMA_POLL) */ return foo; #endif /* def REAL_DMA */ } diff --git a/drivers/scsi/dtc.c b/drivers/scsi/dtc.c index 010d9b13aae7..60bffb34ecfb 100644 --- a/drivers/scsi/dtc.c +++ b/drivers/scsi/dtc.c @@ -1,7 +1,5 @@ - #define PSEUDO_DMA #define DONT_USE_INTR -#define UNSAFE /* Leave interrupts enabled during pseudo-dma I/O */ #define DMA_WORKS_RIGHT diff --git a/drivers/scsi/pas16.c b/drivers/scsi/pas16.c index 5e57ee01093c..4570536187d8 100644 --- a/drivers/scsi/pas16.c +++ b/drivers/scsi/pas16.c @@ -1,5 +1,4 @@ #define PSEUDO_DMA -#define UNSAFE /* Not unsafe for PAS16 -- use it */ /* * This driver adapted from Drew Eckhardt's Trantor T128 driver -- cgit From cd400825c95d4b883232614255c4f35c53bf3582 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sun, 3 Jan 2016 16:05:40 +1100 Subject: ncr5380: Standardize interrupt handling Because interrupt handling is crucial to the core driver(s), all wrapper drivers need to agree on this code. This patch removes discrepancies. NCR5380_intr() in NCR5380.c has the following pointless loop that differs from the code in atari_NCR5380.c. done = 1; do { /* ... */ } while (!done); The 'done' flag gets cleared when a reconnected command is to be processed from the work queue. But in NCR5380.c, the flag is also used to cause the interrupt conditions to be re-examined. Perhaps this was because NCR5380_reselect() was expected to cause another interrupt, or perhaps the remaining present interrupt conditions need to be handled after the NCR5380_reselect() call? Actually, both possibilities are bogus, as is the loop itself. It seems have been overlooked in the hit-and-miss removal of scsi host instance list iteration many years ago; see history/history.git commit 491447e1fcff ("[PATCH] next NCR5380 updates") and commit 69e1a9482e57 ("[PATCH] fix up NCR5380 private data"). See also my earlier patch, "Always retry arbitration and selection". The datasheet says, "IRQ can be reset simply by reading the Reset Parity/Interrupt Register". So don't treat the chip IRQ like a level-triggered interrupt. Of the conditions that set the IRQ flag, some are level-triggered and some are edge-triggered, which means IRQ itself must be edge-triggered. Some interrupt conditions are latched and some are not. Before clearing the chip IRQ flag, clear all state that may cause it to be raised. That means clearing the DMA Mode and Busy Monitor bits in the Mode Register and clearing the host ID in the Select Enable register. Also clean up some printk's and some comments. Keep atari_NCR5380.c and NCR5380.c in agreement. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Ondrej Zary Tested-by: Michael Schmitz Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.c | 185 ++++++++++++++++++++++++------------------- drivers/scsi/atari_NCR5380.c | 154 ++++++++++++++++++----------------- drivers/scsi/dtc.c | 8 -- drivers/scsi/g_NCR5380.c | 2 - 4 files changed, 178 insertions(+), 171 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index 1a6562b94bf7..8567d69709ce 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -951,85 +951,114 @@ static void NCR5380_main(struct work_struct *work) #ifndef DONT_USE_INTR /** - * NCR5380_intr - generic NCR5380 irq handler - * @irq: interrupt number - * @dev_id: device info - * - * Handle interrupts, reestablishing I_T_L or I_T_L_Q nexuses - * from the disconnected queue, and restarting NCR5380_main() - * as required. - * - * Locks: takes the needed instance locks + * NCR5380_intr - generic NCR5380 irq handler + * @irq: interrupt number + * @dev_id: device info + * + * Handle interrupts, reestablishing I_T_L or I_T_L_Q nexuses + * from the disconnected queue, and restarting NCR5380_main() + * as required. + * + * The chip can assert IRQ in any of six different conditions. The IRQ flag + * is then cleared by reading the Reset Parity/Interrupt Register (RPIR). + * Three of these six conditions are latched in the Bus and Status Register: + * - End of DMA (cleared by ending DMA Mode) + * - Parity error (cleared by reading RPIR) + * - Loss of BSY (cleared by reading RPIR) + * Two conditions have flag bits that are not latched: + * - Bus phase mismatch (non-maskable in DMA Mode, cleared by ending DMA Mode) + * - Bus reset (non-maskable) + * The remaining condition has no flag bit at all: + * - Selection/reselection + * + * Hence, establishing the cause(s) of any interrupt is partly guesswork. + * In "The DP8490 and DP5380 Comparison Guide", National Semiconductor + * claimed that "the design of the [DP8490] interrupt logic ensures + * interrupts will not be lost (they can be on the DP5380)." + * The L5380/53C80 datasheet from LOGIC Devices has more details. + * + * Checking for bus reset by reading RST is futile because of interrupt + * latency, but a bus reset will reset chip logic. Checking for parity error + * is unnecessary because that interrupt is never enabled. A Loss of BSY + * condition will clear DMA Mode. We can tell when this occurs because the + * the Busy Monitor interrupt is enabled together with DMA Mode. */ -static irqreturn_t NCR5380_intr(int dummy, void *dev_id) +static irqreturn_t NCR5380_intr(int irq, void *dev_id) { struct Scsi_Host *instance = dev_id; - struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) instance->hostdata; - int done; + struct NCR5380_hostdata *hostdata = shost_priv(instance); + int handled = 0; unsigned char basr; unsigned long flags; - dprintk(NDEBUG_INTR, "scsi : NCR5380 irq %d triggered\n", - instance->irq); + spin_lock_irqsave(instance->host_lock, flags); + + basr = NCR5380_read(BUS_AND_STATUS_REG); + if (basr & BASR_IRQ) { + unsigned char mr = NCR5380_read(MODE_REG); + unsigned char sr = NCR5380_read(STATUS_REG); + + dprintk(NDEBUG_INTR, "scsi%d: IRQ %d, BASR 0x%02x, SR 0x%02x, MR 0x%02x\n", + instance->host_no, irq, basr, sr, mr); - do { - done = 1; - spin_lock_irqsave(instance->host_lock, flags); - /* Look for pending interrupts */ - basr = NCR5380_read(BUS_AND_STATUS_REG); - /* XXX dispatch to appropriate routine if found and done=0 */ - if (basr & BASR_IRQ) { - NCR5380_dprint(NDEBUG_INTR, instance); - if ((NCR5380_read(STATUS_REG) & (SR_SEL | SR_IO)) == (SR_SEL | SR_IO)) { - done = 0; - dprintk(NDEBUG_INTR, "scsi%d : SEL interrupt\n", instance->host_no); - NCR5380_reselect(instance); - (void) NCR5380_read(RESET_PARITY_INTERRUPT_REG); - } else if (basr & BASR_PARITY_ERROR) { - dprintk(NDEBUG_INTR, "scsi%d : PARITY interrupt\n", instance->host_no); - (void) NCR5380_read(RESET_PARITY_INTERRUPT_REG); - } else if ((NCR5380_read(STATUS_REG) & SR_RST) == SR_RST) { - dprintk(NDEBUG_INTR, "scsi%d : RESET interrupt\n", instance->host_no); - (void) NCR5380_read(RESET_PARITY_INTERRUPT_REG); - } else { #if defined(REAL_DMA) - /* - * We should only get PHASE MISMATCH and EOP interrupts - * if we have DMA enabled, so do a sanity check based on - * the current setting of the MODE register. - */ + if ((mr & MR_DMA_MODE) || (mr & MR_MONITOR_BSY)) { + /* Probably End of DMA, Phase Mismatch or Loss of BSY. + * We ack IRQ after clearing Mode Register. Workarounds + * for End of DMA errata need to happen in DMA Mode. + */ - if ((NCR5380_read(MODE_REG) & MR_DMA) && ((basr & BASR_END_DMA_TRANSFER) || !(basr & BASR_PHASE_MATCH))) { - int transferred; + dprintk(NDEBUG_INTR, "scsi%d: interrupt in DMA mode\n", intance->host_no); - if (!hostdata->connected) - panic("scsi%d : received end of DMA interrupt with no connected cmd\n", instance->hostno); + int transferred; - transferred = (hostdata->dmalen - NCR5380_dma_residual(instance)); - hostdata->connected->SCp.this_residual -= transferred; - hostdata->connected->SCp.ptr += transferred; - hostdata->dmalen = 0; + if (!hostdata->connected) + panic("scsi%d : DMA interrupt with no connected cmd\n", + instance->hostno); - (void) NCR5380_read(RESET_PARITY_INTERRUPT_REG); - - /* FIXME: we need to poll briefly then defer a workqueue task ! */ - NCR5380_poll_politely(hostdata, BUS_AND_STATUS_REG, BASR_ACK, 0, 2*HZ); + transferred = hostdata->dmalen - NCR5380_dma_residual(instance); + hostdata->connected->SCp.this_residual -= transferred; + hostdata->connected->SCp.ptr += transferred; + hostdata->dmalen = 0; - NCR5380_write(MODE_REG, MR_BASE); - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - } -#else - dprintk(NDEBUG_INTR, "scsi : unknown interrupt, BASR 0x%X, MR 0x%X, SR 0x%x\n", basr, NCR5380_read(MODE_REG), NCR5380_read(STATUS_REG)); - (void) NCR5380_read(RESET_PARITY_INTERRUPT_REG); -#endif + /* FIXME: we need to poll briefly then defer a workqueue task ! */ + NCR5380_poll_politely(hostdata, BUS_AND_STATUS_REG, BASR_ACK, 0, 2 * HZ); + + NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); + NCR5380_write(MODE_REG, MR_BASE); + NCR5380_read(RESET_PARITY_INTERRUPT_REG); + } else +#endif /* REAL_DMA */ + if ((NCR5380_read(CURRENT_SCSI_DATA_REG) & hostdata->id_mask) && + (sr & (SR_SEL | SR_IO | SR_BSY | SR_RST)) == (SR_SEL | SR_IO)) { + /* Probably reselected */ + NCR5380_write(SELECT_ENABLE_REG, 0); + NCR5380_read(RESET_PARITY_INTERRUPT_REG); + + dprintk(NDEBUG_INTR, "scsi%d: interrupt with SEL and IO\n", + instance->host_no); + + if (!hostdata->connected) { + NCR5380_reselect(instance); + queue_work(hostdata->work_q, &hostdata->main_task); } - } /* if BASR_IRQ */ - spin_unlock_irqrestore(instance->host_lock, flags); - if(!done) - queue_work(hostdata->work_q, &hostdata->main_task); - } while (!done); - return IRQ_HANDLED; + if (!hostdata->connected) + NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); + } else { + /* Probably Bus Reset */ + NCR5380_read(RESET_PARITY_INTERRUPT_REG); + + dprintk(NDEBUG_INTR, "scsi%d: unknown interrupt\n", instance->host_no); + } + handled = 1; + } else { + shost_printk(KERN_NOTICE, instance, "interrupt without IRQ bit\n"); + } + + spin_unlock_irqrestore(instance->host_lock, flags); + + return IRQ_RETVAL(handled); } #endif @@ -1218,8 +1247,9 @@ static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd) if ((NCR5380_read(STATUS_REG) & (SR_SEL | SR_IO)) == (SR_SEL | SR_IO)) { NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); NCR5380_reselect(instance); + if (!hostdata->connected) + NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); printk("scsi%d : reselection after won arbitration?\n", instance->host_no); - NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); return -1; } @@ -1563,9 +1593,10 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, unsigned char *phase NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(p)); #ifdef REAL_DMA - NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE | MR_ENABLE_EOP_INTR | MR_MONITOR_BSY); + NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE | MR_MONITOR_BSY | + MR_ENABLE_EOP_INTR); #elif defined(REAL_DMA_POLL) - NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE); + NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE | MR_MONITOR_BSY); #else /* * Note : on my sample board, watch-dog timeouts occurred when interrupts @@ -1573,13 +1604,11 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, unsigned char *phase * before the setting of DMA mode to after transfer of the last byte. */ - /* KLL May need eop and parity in 53c400 */ if (hostdata->flags & FLAG_NCR53C400) - NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE | - MR_ENABLE_PAR_CHECK | MR_ENABLE_PAR_INTR | - MR_ENABLE_EOP_INTR | MR_MONITOR_BSY); + NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE | MR_MONITOR_BSY | + MR_ENABLE_EOP_INTR); else - NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE); + NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE | MR_MONITOR_BSY); #endif /* def REAL_DMA */ dprintk(NDEBUG_DMA, "scsi%d : mode reg = 0x%X\n", instance->host_no, NCR5380_read(MODE_REG)); @@ -1768,16 +1797,7 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, unsigned char *phase } NCR5380_write(MODE_REG, MR_BASE); NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - - if ((!(p & SR_IO)) && (hostdata->flags & FLAG_NCR53C400)) { - dprintk(NDEBUG_C400_PWRITE, "53C400w: Checking for IRQ\n"); - if (NCR5380_read(BUS_AND_STATUS_REG) & BASR_IRQ) { - dprintk(NDEBUG_C400_PWRITE, "53C400w: got it, reading reset interrupt reg\n"); - NCR5380_read(RESET_PARITY_INTERRUPT_REG); - } else { - printk("53C400w: IRQ NOT THERE!\n"); - } - } + NCR5380_read(RESET_PARITY_INTERRUPT_REG); *data = d + c; *count = 0; *phase = NCR5380_read(STATUS_REG) & PHASE_MASK; @@ -2269,7 +2289,6 @@ static void NCR5380_dma_complete(NCR5380_instance * instance) { NCR5380_poll_politely(instance, BUS_AND_STATUS_REG, BASR_ACK, 0, 5*HZ); - NCR5380_write(MODE_REG, MR_BASE); NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); /* diff --git a/drivers/scsi/atari_NCR5380.c b/drivers/scsi/atari_NCR5380.c index 48e3d76e39e3..c8c216a9f448 100644 --- a/drivers/scsi/atari_NCR5380.c +++ b/drivers/scsi/atari_NCR5380.c @@ -1144,12 +1144,6 @@ static void NCR5380_dma_complete(struct Scsi_Host *instance) int saved_data = 0, overrun = 0; unsigned char p; - if (!hostdata->connected) { - printk(KERN_WARNING "scsi%d: received end of DMA interrupt with " - "no connected cmd\n", HOSTNO); - return; - } - if (hostdata->read_overruns) { p = hostdata->connected->SCp.phase; if (p & SR_IO) { @@ -1164,10 +1158,6 @@ static void NCR5380_dma_complete(struct Scsi_Host *instance) } } - dprintk(NDEBUG_DMA, "scsi%d: real DMA transfer complete, basr 0x%X, sr 0x%X\n", - HOSTNO, NCR5380_read(BUS_AND_STATUS_REG), - NCR5380_read(STATUS_REG)); - #if defined(CONFIG_SUN3) if ((sun3scsi_dma_finish(rq_data_dir(hostdata->connected->request)))) { pr_err("scsi%d: overrun in UDC counter -- not prepared to deal with this!\n", @@ -1186,9 +1176,9 @@ static void NCR5380_dma_complete(struct Scsi_Host *instance) } #endif - (void)NCR5380_read(RESET_PARITY_INTERRUPT_REG); NCR5380_write(MODE_REG, MR_BASE); NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); + NCR5380_read(RESET_PARITY_INTERRUPT_REG); transferred = hostdata->dma_len - NCR5380_dma_residual(instance); hostdata->dma_len = 0; @@ -1227,83 +1217,97 @@ static void NCR5380_dma_complete(struct Scsi_Host *instance) * Handle interrupts, reestablishing I_T_L or I_T_L_Q nexuses * from the disconnected queue, and restarting NCR5380_main() * as required. + * + * The chip can assert IRQ in any of six different conditions. The IRQ flag + * is then cleared by reading the Reset Parity/Interrupt Register (RPIR). + * Three of these six conditions are latched in the Bus and Status Register: + * - End of DMA (cleared by ending DMA Mode) + * - Parity error (cleared by reading RPIR) + * - Loss of BSY (cleared by reading RPIR) + * Two conditions have flag bits that are not latched: + * - Bus phase mismatch (non-maskable in DMA Mode, cleared by ending DMA Mode) + * - Bus reset (non-maskable) + * The remaining condition has no flag bit at all: + * - Selection/reselection + * + * Hence, establishing the cause(s) of any interrupt is partly guesswork. + * In "The DP8490 and DP5380 Comparison Guide", National Semiconductor + * claimed that "the design of the [DP8490] interrupt logic ensures + * interrupts will not be lost (they can be on the DP5380)." + * The L5380/53C80 datasheet from LOGIC Devices has more details. + * + * Checking for bus reset by reading RST is futile because of interrupt + * latency, but a bus reset will reset chip logic. Checking for parity error + * is unnecessary because that interrupt is never enabled. A Loss of BSY + * condition will clear DMA Mode. We can tell when this occurs because the + * the Busy Monitor interrupt is enabled together with DMA Mode. */ static irqreturn_t NCR5380_intr(int irq, void *dev_id) { struct Scsi_Host *instance = dev_id; struct NCR5380_hostdata *hostdata = shost_priv(instance); - int done = 1, handled = 0; + int handled = 0; unsigned char basr; - dprintk(NDEBUG_INTR, "scsi%d: NCR5380 irq triggered\n", HOSTNO); - - /* Look for pending interrupts */ basr = NCR5380_read(BUS_AND_STATUS_REG); - dprintk(NDEBUG_INTR, "scsi%d: BASR=%02x\n", HOSTNO, basr); - /* dispatch to appropriate routine if found and done=0 */ if (basr & BASR_IRQ) { - NCR5380_dprint(NDEBUG_INTR, instance); - if ((NCR5380_read(STATUS_REG) & (SR_SEL|SR_IO)) == (SR_SEL|SR_IO)) { - done = 0; - dprintk(NDEBUG_INTR, "scsi%d: SEL interrupt\n", HOSTNO); - NCR5380_reselect(instance); - (void)NCR5380_read(RESET_PARITY_INTERRUPT_REG); - } else if (basr & BASR_PARITY_ERROR) { - dprintk(NDEBUG_INTR, "scsi%d: PARITY interrupt\n", HOSTNO); - (void)NCR5380_read(RESET_PARITY_INTERRUPT_REG); - } else if ((NCR5380_read(STATUS_REG) & SR_RST) == SR_RST) { - dprintk(NDEBUG_INTR, "scsi%d: RESET interrupt\n", HOSTNO); - (void)NCR5380_read(RESET_PARITY_INTERRUPT_REG); - } else { - /* - * The rest of the interrupt conditions can occur only during a - * DMA transfer - */ + unsigned char mr = NCR5380_read(MODE_REG); + unsigned char sr = NCR5380_read(STATUS_REG); + + dprintk(NDEBUG_INTR, "scsi%d: IRQ %d, BASR 0x%02x, SR 0x%02x, MR 0x%02x\n", + HOSTNO, irq, basr, sr, mr); #if defined(REAL_DMA) - /* - * We should only get PHASE MISMATCH and EOP interrupts if we have - * DMA enabled, so do a sanity check based on the current setting - * of the MODE register. + if ((mr & MR_DMA_MODE) || (mr & MR_MONITOR_BSY)) { + /* Probably End of DMA, Phase Mismatch or Loss of BSY. + * We ack IRQ after clearing Mode Register. Workarounds + * for End of DMA errata need to happen in DMA Mode. */ - if ((NCR5380_read(MODE_REG) & MR_DMA_MODE) && - ((basr & BASR_END_DMA_TRANSFER) || - !(basr & BASR_PHASE_MATCH))) { + dprintk(NDEBUG_INTR, "scsi%d: interrupt in DMA mode\n", HOSTNO); - dprintk(NDEBUG_INTR, "scsi%d: PHASE MISM or EOP interrupt\n", HOSTNO); - NCR5380_dma_complete( instance ); - done = 0; - } else + if (hostdata->connected) { + NCR5380_dma_complete(instance); + queue_work(hostdata->work_q, &hostdata->main_task); + } else { + NCR5380_write(MODE_REG, MR_BASE); + NCR5380_read(RESET_PARITY_INTERRUPT_REG); + } + } else #endif /* REAL_DMA */ - { -/* MS: Ignore unknown phase mismatch interrupts (caused by EOP interrupt) */ - if (basr & BASR_PHASE_MATCH) - dprintk(NDEBUG_INTR, "scsi%d: unknown interrupt, " - "BASR 0x%x, MR 0x%x, SR 0x%x\n", - HOSTNO, basr, NCR5380_read(MODE_REG), - NCR5380_read(STATUS_REG)); - (void)NCR5380_read(RESET_PARITY_INTERRUPT_REG); + if ((NCR5380_read(CURRENT_SCSI_DATA_REG) & hostdata->id_mask) && + (sr & (SR_SEL | SR_IO | SR_BSY | SR_RST)) == (SR_SEL | SR_IO)) { + /* Probably reselected */ + NCR5380_write(SELECT_ENABLE_REG, 0); + NCR5380_read(RESET_PARITY_INTERRUPT_REG); + + dprintk(NDEBUG_INTR, "scsi%d: interrupt with SEL and IO\n", + HOSTNO); + + if (!hostdata->connected) { + NCR5380_reselect(instance); + queue_work(hostdata->work_q, &hostdata->main_task); + } + if (!hostdata->connected) + NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); + } else { + /* Probably Bus Reset */ + NCR5380_read(RESET_PARITY_INTERRUPT_REG); + + dprintk(NDEBUG_INTR, "scsi%d: unknown interrupt\n", HOSTNO); #ifdef SUN3_SCSI_VME - dregs->csr |= CSR_DMA_ENABLE; + dregs->csr |= CSR_DMA_ENABLE; #endif - } - } /* if !(SELECTION || PARITY) */ + } handled = 1; - } /* BASR & IRQ */ else { - printk(KERN_NOTICE "scsi%d: interrupt without IRQ bit set in BASR, " - "BASR 0x%X, MR 0x%X, SR 0x%x\n", HOSTNO, basr, - NCR5380_read(MODE_REG), NCR5380_read(STATUS_REG)); - (void)NCR5380_read(RESET_PARITY_INTERRUPT_REG); + } else { + shost_printk(KERN_NOTICE, instance, "interrupt without IRQ bit\n"); #ifdef SUN3_SCSI_VME dregs->csr |= CSR_DMA_ENABLE; #endif } - if (!done) - queue_work(hostdata->work_q, &hostdata->main_task); - return IRQ_RETVAL(handled); } @@ -1509,9 +1513,10 @@ static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd) if ((NCR5380_read(STATUS_REG) & (SR_SEL | SR_IO)) == (SR_SEL | SR_IO)) { NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); NCR5380_reselect(instance); + if (!hostdata->connected) + NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); printk(KERN_ERR "scsi%d: reselection after won arbitration?\n", HOSTNO); - NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); return -1; } @@ -1871,19 +1876,14 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, /* send start chain */ sun3scsi_dma_start(c, *data); + NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(p)); + NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE | MR_MONITOR_BSY | + MR_ENABLE_EOP_INTR); if (p & SR_IO) { - NCR5380_write(TARGET_COMMAND_REG, 1); - NCR5380_read(RESET_PARITY_INTERRUPT_REG); NCR5380_write(INITIATOR_COMMAND_REG, 0); - NCR5380_write(MODE_REG, - (NCR5380_read(MODE_REG) | MR_DMA_MODE | MR_ENABLE_EOP_INTR)); NCR5380_write(START_DMA_INITIATOR_RECEIVE_REG, 0); } else { - NCR5380_write(TARGET_COMMAND_REG, 0); - NCR5380_read(RESET_PARITY_INTERRUPT_REG); NCR5380_write(INITIATOR_COMMAND_REG, ICR_ASSERT_DATA); - NCR5380_write(MODE_REG, - (NCR5380_read(MODE_REG) | MR_DMA_MODE | MR_ENABLE_EOP_INTR)); NCR5380_write(START_DMA_SEND_REG, 0); } @@ -1912,10 +1912,8 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, c, (p & SR_IO) ? "to" : "from", d); NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(p)); - -#ifdef REAL_DMA - NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE | MR_ENABLE_EOP_INTR | MR_MONITOR_BSY); -#endif /* def REAL_DMA */ + NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE | MR_MONITOR_BSY | + MR_ENABLE_EOP_INTR); if (!(hostdata->flags & FLAG_LATE_DMA_SETUP)) { /* On the Medusa, it is a must to initialize the DMA before @@ -2389,10 +2387,10 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) #endif hostdata->connected = NULL; cmd->result = DID_ERROR << 16; - NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); maybe_release_dma_irq(instance); local_irq_restore(flags); cmd->scsi_done(cmd); + NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); return; } msgout = NOP; diff --git a/drivers/scsi/dtc.c b/drivers/scsi/dtc.c index 60bffb34ecfb..3af4f69c199c 100644 --- a/drivers/scsi/dtc.c +++ b/drivers/scsi/dtc.c @@ -334,8 +334,6 @@ static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst, struct NCR5380_hostdata *hostdata = shost_priv(instance); i = 0; - NCR5380_read(RESET_PARITY_INTERRUPT_REG); - NCR5380_write(MODE_REG, MR_ENABLE_EOP_INTR | MR_DMA_MODE); if (instance->irq == NO_IRQ) NCR5380_write(DTC_CONTROL_REG, CSR_DIR_READ); else @@ -357,9 +355,7 @@ static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst, rtrc(4); while (!(NCR5380_read(DTC_CONTROL_REG) & D_CR_ACCESS)) ++i; - NCR5380_write(MODE_REG, 0); /* Clear the operating mode */ rtrc(0); - NCR5380_read(RESET_PARITY_INTERRUPT_REG); if (i > hostdata->spin_max_r) hostdata->spin_max_r = i; return (0); @@ -383,9 +379,6 @@ static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src, int i; struct NCR5380_hostdata *hostdata = shost_priv(instance); - NCR5380_read(RESET_PARITY_INTERRUPT_REG); - NCR5380_write(MODE_REG, MR_ENABLE_EOP_INTR | MR_DMA_MODE); - /* set direction (write) */ if (instance->irq == NO_IRQ) NCR5380_write(DTC_CONTROL_REG, 0); else @@ -410,7 +403,6 @@ static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src, ++i; rtrc(7); /* Check for parity error here. fixme. */ - NCR5380_write(MODE_REG, 0); /* Clear the operating mode */ rtrc(0); if (i > hostdata->spin_max_w) hostdata->spin_max_w = i; diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c index 258bc2ff0d1c..4124f053d1b3 100644 --- a/drivers/scsi/g_NCR5380.c +++ b/drivers/scsi/g_NCR5380.c @@ -594,8 +594,6 @@ static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst, if (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_END_DMA_TRANSFER)) printk(KERN_ERR "53C400r: no end dma signal\n"); - NCR5380_write(MODE_REG, MR_BASE); - NCR5380_read(RESET_PARITY_INTERRUPT_REG); return 0; } -- cgit From b32ade124494fc16eb19521ac310cbd5cb48dda8 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sun, 3 Jan 2016 16:05:41 +1100 Subject: ncr5380: Introduce NCR5380_poll_politely2 SCSI bus protocol sometimes requires monitoring two related conditions simultaneously. Enhance NCR5380_poll_politely() for this purpose, and put it to use in the arbitration algorithm. It will also find use in pseudo DMA. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Ondrej Zary Tested-by: Michael Schmitz Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.c | 66 +++++++++++++++++++++++++------------------- drivers/scsi/atari_NCR5380.c | 62 ++++++++++++++++++++++++----------------- 2 files changed, 75 insertions(+), 53 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index 8567d69709ce..9c1b69be796c 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -262,11 +262,14 @@ static inline void initialize_SCp(struct scsi_cmnd *cmd) } /** - * NCR5380_poll_politely - wait for chip register value + * NCR5380_poll_politely2 - wait for two chip register values * @instance: controller to poll - * @reg: 5380 register to poll - * @bit: Bitmask to check - * @val: Value required to exit + * @reg1: 5380 register to poll + * @bit1: Bitmask to check + * @val1: Expected value + * @reg2: Second 5380 register to poll + * @bit2: Second bitmask to check + * @val2: Second expected value * @wait: Time-out in jiffies * * Polls the chip in a reasonably efficient manner waiting for an @@ -274,11 +277,12 @@ static inline void initialize_SCp(struct scsi_cmnd *cmd) * (if possible). In irq contexts the time-out is arbitrarily limited. * Callers may hold locks as long as they are held in irq mode. * - * Returns 0 if event occurred otherwise -ETIMEDOUT. + * Returns 0 if either or both event(s) occurred otherwise -ETIMEDOUT. */ -static int NCR5380_poll_politely(struct Scsi_Host *instance, - int reg, int bit, int val, int wait) +static int NCR5380_poll_politely2(struct Scsi_Host *instance, + int reg1, int bit1, int val1, + int reg2, int bit2, int val2, int wait) { struct NCR5380_hostdata *hostdata = shost_priv(instance); unsigned long deadline = jiffies + wait; @@ -287,9 +291,11 @@ static int NCR5380_poll_politely(struct Scsi_Host *instance, /* Busy-wait for up to 10 ms */ n = min(10000U, jiffies_to_usecs(wait)); n *= hostdata->accesses_per_ms; - n /= 1000; + n /= 2000; do { - if ((NCR5380_read(reg) & bit) == val) + if ((NCR5380_read(reg1) & bit1) == val1) + return 0; + if ((NCR5380_read(reg2) & bit2) == val2) return 0; cpu_relax(); } while (n--); @@ -300,13 +306,22 @@ static int NCR5380_poll_politely(struct Scsi_Host *instance, /* Repeatedly sleep for 1 ms until deadline */ while (time_is_after_jiffies(deadline)) { schedule_timeout_uninterruptible(1); - if ((NCR5380_read(reg) & bit) == val) + if ((NCR5380_read(reg1) & bit1) == val1) + return 0; + if ((NCR5380_read(reg2) & bit2) == val2) return 0; } return -ETIMEDOUT; } +static inline int NCR5380_poll_politely(struct Scsi_Host *instance, + int reg, int bit, int val, int wait) +{ + return NCR5380_poll_politely2(instance, reg, bit, val, + reg, bit, val, wait); +} + static struct { unsigned char value; const char *name; @@ -1101,7 +1116,6 @@ static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd) unsigned char *data; int len; int err; - unsigned long timeout; NCR5380_dprint(NDEBUG_ARBITRATION, instance); dprintk(NDEBUG_ARBITRATION, "scsi%d : starting arbitration, id = %d\n", instance->host_no, instance->this_id); @@ -1125,23 +1139,19 @@ static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd) */ spin_unlock_irq(instance->host_lock); - timeout = jiffies + HZ; - while (1) { - if (time_is_before_jiffies(timeout)) { - NCR5380_write(MODE_REG, MR_BASE); - shost_printk(KERN_ERR, instance, - "select: arbitration timeout\n"); - spin_lock_irq(instance->host_lock); - return -1; - } - spin_lock_irq(instance->host_lock); - if (!(NCR5380_read(MODE_REG) & MR_ARBITRATE)) { - /* Reselection interrupt */ - return -1; - } - if (NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_PROGRESS) - break; - spin_unlock_irq(instance->host_lock); + err = NCR5380_poll_politely2(instance, MODE_REG, MR_ARBITRATE, 0, + INITIATOR_COMMAND_REG, ICR_ARBITRATION_PROGRESS, + ICR_ARBITRATION_PROGRESS, HZ); + spin_lock_irq(instance->host_lock); + if (!(NCR5380_read(MODE_REG) & MR_ARBITRATE)) { + /* Reselection interrupt */ + return -1; + } + if (err < 0) { + NCR5380_write(MODE_REG, MR_BASE); + shost_printk(KERN_ERR, instance, + "select: arbitration timeout\n"); + return -1; } /* The SCSI-2 arbitration delay is 2.4 us */ diff --git a/drivers/scsi/atari_NCR5380.c b/drivers/scsi/atari_NCR5380.c index c8c216a9f448..70398c61fffc 100644 --- a/drivers/scsi/atari_NCR5380.c +++ b/drivers/scsi/atari_NCR5380.c @@ -457,11 +457,14 @@ static inline void initialize_SCp(struct scsi_cmnd *cmd) } /** - * NCR5380_poll_politely - wait for chip register value + * NCR5380_poll_politely2 - wait for two chip register values * @instance: controller to poll - * @reg: 5380 register to poll - * @bit: Bitmask to check - * @val: Value required to exit + * @reg1: 5380 register to poll + * @bit1: Bitmask to check + * @val1: Expected value + * @reg2: Second 5380 register to poll + * @bit2: Second bitmask to check + * @val2: Second expected value * @wait: Time-out in jiffies * * Polls the chip in a reasonably efficient manner waiting for an @@ -469,11 +472,12 @@ static inline void initialize_SCp(struct scsi_cmnd *cmd) * (if possible). In irq contexts the time-out is arbitrarily limited. * Callers may hold locks as long as they are held in irq mode. * - * Returns 0 if event occurred otherwise -ETIMEDOUT. + * Returns 0 if either or both event(s) occurred otherwise -ETIMEDOUT. */ -static int NCR5380_poll_politely(struct Scsi_Host *instance, - int reg, int bit, int val, int wait) +static int NCR5380_poll_politely2(struct Scsi_Host *instance, + int reg1, int bit1, int val1, + int reg2, int bit2, int val2, int wait) { struct NCR5380_hostdata *hostdata = shost_priv(instance); unsigned long deadline = jiffies + wait; @@ -482,9 +486,11 @@ static int NCR5380_poll_politely(struct Scsi_Host *instance, /* Busy-wait for up to 10 ms */ n = min(10000U, jiffies_to_usecs(wait)); n *= hostdata->accesses_per_ms; - n /= 1000; + n /= 2000; do { - if ((NCR5380_read(reg) & bit) == val) + if ((NCR5380_read(reg1) & bit1) == val1) + return 0; + if ((NCR5380_read(reg2) & bit2) == val2) return 0; cpu_relax(); } while (n--); @@ -495,13 +501,22 @@ static int NCR5380_poll_politely(struct Scsi_Host *instance, /* Repeatedly sleep for 1 ms until deadline */ while (time_is_after_jiffies(deadline)) { schedule_timeout_uninterruptible(1); - if ((NCR5380_read(reg) & bit) == val) + if ((NCR5380_read(reg1) & bit1) == val1) + return 0; + if ((NCR5380_read(reg2) & bit2) == val2) return 0; } return -ETIMEDOUT; } +static inline int NCR5380_poll_politely(struct Scsi_Host *instance, + int reg, int bit, int val, int wait) +{ + return NCR5380_poll_politely2(instance, reg, bit, val, + reg, bit, val, wait); +} + #include #if NDEBUG @@ -1348,7 +1363,6 @@ static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd) int len; int err; unsigned long flags; - unsigned long timeout; NCR5380_dprint(NDEBUG_ARBITRATION, instance); dprintk(NDEBUG_ARBITRATION, "scsi%d: starting arbitration, id = %d\n", HOSTNO, @@ -1378,20 +1392,18 @@ static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd) */ local_irq_restore(flags); - timeout = jiffies + HZ; - while (1) { - if (time_is_before_jiffies(timeout)) { - NCR5380_write(MODE_REG, MR_BASE); - shost_printk(KERN_ERR, instance, - "select: arbitration timeout\n"); - return -1; - } - if (!(NCR5380_read(MODE_REG) & MR_ARBITRATE)) { - /* Reselection interrupt */ - return -1; - } - if (NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_PROGRESS) - break; + err = NCR5380_poll_politely2(instance, MODE_REG, MR_ARBITRATE, 0, + INITIATOR_COMMAND_REG, ICR_ARBITRATION_PROGRESS, + ICR_ARBITRATION_PROGRESS, HZ); + if (!(NCR5380_read(MODE_REG) & MR_ARBITRATE)) { + /* Reselection interrupt */ + return -1; + } + if (err < 0) { + NCR5380_write(MODE_REG, MR_BASE); + shost_printk(KERN_ERR, instance, + "select: arbitration timeout\n"); + return -1; } /* The SCSI-2 arbitration delay is 2.4 us */ -- cgit From 55181be8ced18697e48f75d53028b9ee36522dba Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sun, 3 Jan 2016 16:05:42 +1100 Subject: ncr5380: Replace redundant flags with FLAG_NO_DMA_FIXUP The flags DMA_WORKS_RIGHT, FLAG_NCR53C400 and FLAG_HAS_LAST_BYTE_SENT all mean the same thing, i.e. the chip is not a 538[01]. (More recent devices such as the 53C80 have a 'Last Byte Sent' bit in the Target Command Register as well as other fixes for End-of-DMA errata.) These flags have no additional meanings since previous cleanup patches eliminated the NCR53C400 macro, moved g_NCR5380-specific code out of the core driver and standardized interrupt handling. Use the FLAG_NO_DMA_FIXUP flag to suppress End-of-DMA errata workarounds, for those cards and drivers that make use of the TCR_LAST_BYTE_SENT bit. Remove the old flags. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Ondrej Zary Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.c | 68 ++++++++++++++++-------------------------------- drivers/scsi/NCR5380.h | 4 +-- drivers/scsi/dtc.c | 4 +-- drivers/scsi/g_NCR5380.c | 2 +- 4 files changed, 25 insertions(+), 53 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index 9c1b69be796c..29cf1ec27ff2 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -541,7 +541,7 @@ static void prepare_info(struct Scsi_Host *instance) instance->base, instance->irq, instance->can_queue, instance->cmd_per_lun, instance->sg_tablesize, instance->this_id, - hostdata->flags & FLAG_NCR53C400 ? "NCR53C400 " : "", + hostdata->flags & FLAG_NO_DMA_FIXUP ? "NO_DMA_FIXUP " : "", hostdata->flags & FLAG_DTC3181E ? "DTC3181E " : "", hostdata->flags & FLAG_NO_PSEUDO_DMA ? "NO_PSEUDO_DMA " : "", hostdata->flags & FLAG_TOSHIBA_DELAY ? "TOSHIBA_DELAY " : "", @@ -702,6 +702,7 @@ static int NCR5380_init(struct Scsi_Host *instance, int flags) hostdata->connected = NULL; hostdata->issue_queue = NULL; hostdata->disconnected_queue = NULL; + hostdata->flags = flags; INIT_WORK(&hostdata->main_task, NCR5380_main); hostdata->work_q = alloc_workqueue("ncr5380_%d", @@ -710,12 +711,6 @@ static int NCR5380_init(struct Scsi_Host *instance, int flags) if (!hostdata->work_q) return -ENOMEM; - /* The CHECK code seems to break the 53C400. Will check it later maybe */ - if (flags & FLAG_NCR53C400) - hostdata->flags = FLAG_HAS_LAST_BYTE_SENT | flags; - else - hostdata->flags = FLAG_CHECK_LAST_BYTE_SENT | flags; - hostdata->host = instance; prepare_info(instance); @@ -1614,7 +1609,7 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, unsigned char *phase * before the setting of DMA mode to after transfer of the last byte. */ - if (hostdata->flags & FLAG_NCR53C400) + if (hostdata->flags & FLAG_NO_DMA_FIXUP) NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE | MR_MONITOR_BSY | MR_ENABLE_EOP_INTR); else @@ -1734,14 +1729,9 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, unsigned char *phase return 0; #else /* defined(REAL_DMA_POLL) */ if (p & SR_IO) { -#ifdef DMA_WORKS_RIGHT - foo = NCR5380_pread(instance, d, c); -#else - int diff = 1; - if (hostdata->flags & FLAG_NCR53C400) { - diff = 0; - } - if (!(foo = NCR5380_pread(instance, d, c - diff))) { + foo = NCR5380_pread(instance, d, + hostdata->flags & FLAG_NO_DMA_FIXUP ? c : c - 1); + if (!foo && !(hostdata->flags & FLAG_NO_DMA_FIXUP)) { /* * We can't disable DMA mode after successfully transferring * what we plan to be the last byte, since that would open up @@ -1764,46 +1754,32 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, unsigned char *phase * byte. */ - if (!(hostdata->flags & FLAG_NCR53C400)) { - while (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_DRQ)); - /* Wait for clean handshake */ - while (NCR5380_read(STATUS_REG) & SR_REQ); - d[c - 1] = NCR5380_read(INPUT_DATA_REG); + if (NCR5380_poll_politely(instance, BUS_AND_STATUS_REG, + BASR_DRQ, BASR_DRQ, HZ) < 0) { + foo = -1; + shost_printk(KERN_ERR, instance, "PDMA read: DRQ timeout\n"); + } + if (NCR5380_poll_politely(instance, STATUS_REG, + SR_REQ, 0, HZ) < 0) { + foo = -1; + shost_printk(KERN_ERR, instance, "PDMA read: !REQ timeout\n"); } + d[c - 1] = NCR5380_read(INPUT_DATA_REG); } -#endif } else { -#ifdef DMA_WORKS_RIGHT foo = NCR5380_pwrite(instance, d, c); -#else - int timeout; - dprintk(NDEBUG_C400_PWRITE, "About to pwrite %d bytes\n", c); - if (!(foo = NCR5380_pwrite(instance, d, c))) { + if (!foo && !(hostdata->flags & FLAG_NO_DMA_FIXUP)) { /* * Wait for the last byte to be sent. If REQ is being asserted for * the byte we're interested, we'll ACK it and it will go false. */ - if (!(hostdata->flags & FLAG_HAS_LAST_BYTE_SENT)) { - timeout = 20000; - while (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_DRQ) && (NCR5380_read(BUS_AND_STATUS_REG) & BASR_PHASE_MATCH)); - - if (!timeout) - dprintk(NDEBUG_LAST_BYTE_SENT, "scsi%d : timed out on last byte\n", instance->host_no); - - if (hostdata->flags & FLAG_CHECK_LAST_BYTE_SENT) { - hostdata->flags &= ~FLAG_CHECK_LAST_BYTE_SENT; - if (NCR5380_read(TARGET_COMMAND_REG) & TCR_LAST_BYTE_SENT) { - hostdata->flags |= FLAG_HAS_LAST_BYTE_SENT; - dprintk(NDEBUG_LAST_BYTE_SENT, "scsi%d : last byte sent works\n", instance->host_no); - } - } - } else { - dprintk(NDEBUG_C400_PWRITE, "Waiting for LASTBYTE\n"); - while (!(NCR5380_read(TARGET_COMMAND_REG) & TCR_LAST_BYTE_SENT)); - dprintk(NDEBUG_C400_PWRITE, "Got LASTBYTE\n"); + if (NCR5380_poll_politely2(instance, + BUS_AND_STATUS_REG, BASR_DRQ, BASR_DRQ, + BUS_AND_STATUS_REG, BASR_PHASE_MATCH, 0, HZ) < 0) { + foo = -1; + shost_printk(KERN_ERR, instance, "PDMA write: DRQ and phase timeout\n"); } } -#endif } NCR5380_write(MODE_REG, MR_BASE); NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); diff --git a/drivers/scsi/NCR5380.h b/drivers/scsi/NCR5380.h index 78af75142342..e8a26eab32dd 100644 --- a/drivers/scsi/NCR5380.h +++ b/drivers/scsi/NCR5380.h @@ -226,9 +226,7 @@ #define NO_IRQ 0 #endif -#define FLAG_HAS_LAST_BYTE_SENT 1 /* NCR53c81 or better */ -#define FLAG_CHECK_LAST_BYTE_SENT 2 /* Only test once */ -#define FLAG_NCR53C400 4 /* NCR53c400 */ +#define FLAG_NO_DMA_FIXUP 1 /* No DMA errata workarounds */ #define FLAG_NO_PSEUDO_DMA 8 /* Inhibit DMA */ #define FLAG_DTC3181E 16 /* DTC3181E */ #define FLAG_LATE_DMA_SETUP 32 /* Setup NCR before DMA H/W */ diff --git a/drivers/scsi/dtc.c b/drivers/scsi/dtc.c index 3af4f69c199c..1beefdbcbea8 100644 --- a/drivers/scsi/dtc.c +++ b/drivers/scsi/dtc.c @@ -1,7 +1,5 @@ #define PSEUDO_DMA #define DONT_USE_INTR -#define DMA_WORKS_RIGHT - /* * DTC 3180/3280 driver, by @@ -233,7 +231,7 @@ found: instance->base = addr; ((struct NCR5380_hostdata *)(instance)->hostdata)->base = base; - if (NCR5380_init(instance, 0)) + if (NCR5380_init(instance, FLAG_NO_DMA_FIXUP)) goto out_unregister; NCR5380_maybe_reset_bus(instance); diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c index 4124f053d1b3..e71c79683925 100644 --- a/drivers/scsi/g_NCR5380.c +++ b/drivers/scsi/g_NCR5380.c @@ -321,7 +321,7 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt) break; case BOARD_NCR53C400: #ifdef PSEUDO_DMA - flags = FLAG_NCR53C400; + flags = FLAG_NO_DMA_FIXUP; #endif break; case BOARD_NCR53C400A: -- cgit From 9db6024e55ee9b53c411d618e2a9476f6a130151 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sun, 3 Jan 2016 16:05:43 +1100 Subject: ncr5380: Replace READ_OVERRUNS macro with FLAG_NO_DMA_FIXUPS The workarounds for chip errata appear twice, in slightly different forms. One is used when defined(REAL_DMA) || defined(REAL_DMA_POLL), the other when defined(PSEUDO_DMA). In the PDMA case, the workarounds have been made conditional on FLAG_NO_DMA_FIXUPS. Do the same for the DMA case, to eliminate the READ_OVERRUNS macro. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Ondrej Zary Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.c | 28 +++++++++++----------------- 1 file changed, 11 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index 29cf1ec27ff2..ffa3719312d1 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -94,11 +94,6 @@ #undef REAL_DMA #endif -#ifdef REAL_DMA_POLL -#undef READ_OVERRUNS -#define READ_OVERRUNS -#endif - #ifdef BOARD_REQUIRES_NO_DELAY #define io_recovery_delay(x) #else @@ -1586,11 +1581,10 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, unsigned char *phase return -1; } #if defined(REAL_DMA) || defined(REAL_DMA_POLL) -#ifdef READ_OVERRUNS if (p & SR_IO) { - c -= 2; + if (!(hostdata->flags & FLAG_NO_DMA_FIXUPS)) + c -= 2; } -#endif dprintk(NDEBUG_DMA, "scsi%d : initializing DMA channel %d for %s, %d bytes %s %0x\n", instance->host_no, instance->dma_channel, (p & SR_IO) ? "reading" : "writing", c, (p & SR_IO) ? "to" : "from", (unsigned) d); hostdata->dma_len = (p & SR_IO) ? NCR5380_dma_read_setup(instance, d, c) : NCR5380_dma_write_setup(instance, d, c); #endif @@ -1676,13 +1670,14 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, unsigned char *phase */ if (p & SR_IO) { -#ifdef READ_OVERRUNS - udelay(10); - if (((NCR5380_read(BUS_AND_STATUS_REG) & (BASR_PHASE_MATCH | BASR_ACK)) == (BASR_PHASE_MATCH | BASR_ACK))) { - saved_data = NCR5380_read(INPUT_DATA_REGISTER); - overrun = 1; + if (!(hostdata->flags & FLAG_NO_DMA_FIXUPS)) { + udelay(10); + if ((NCR5380_read(BUS_AND_STATUS_REG) & (BASR_PHASE_MATCH | BASR_ACK)) == + (BASR_PHASE_MATCH | BASR_ACK)) { + saved_data = NCR5380_read(INPUT_DATA_REGISTER); + overrun = 1; + } } -#endif } else { int limit = 100; while (((tmp = NCR5380_read(BUS_AND_STATUS_REG)) & BASR_ACK) || (NCR5380_read(STATUS_REG) & SR_REQ)) { @@ -1704,8 +1699,8 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, unsigned char *phase *data += c; *phase = NCR5380_read(STATUS_REG) & PHASE_MASK; -#ifdef READ_OVERRUNS - if (*phase == p && (p & SR_IO) && residue == 0) { + if (!(hostdata->flags & FLAG_NO_DMA_FIXUPS) && + *phase == p && (p & SR_IO) && residue == 0) { if (overrun) { dprintk(NDEBUG_DMA, "Got an input overrun, using saved byte\n"); **data = saved_data; @@ -1720,7 +1715,6 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, unsigned char *phase NCR5380_transfer_pio(instance, phase, &cnt, data); *count -= toPIO - cnt; } -#endif dprintk(NDEBUG_DMA, "Return with data ptr = 0x%X, count %d, last 0x%X, next 0x%X\n", *data, *count, *(*data + *count - 1), *(*data + *count)); return 0; -- cgit From 72064a783b0c24dc4325295ffba949c115aff6d2 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sun, 3 Jan 2016 16:05:44 +1100 Subject: ncr5380: Standardize reselection handling Bring the two NCR5380_reselect() implementations into agreement. Replace infinite loops in atari_NCR5380.c with timeouts, as per NCR5380.c. Remove 'abort' flag in NCR5380.c as per atari_NCR5380.c -- if reselection fails, there may be no MESSAGE IN phase so don't attempt data transfer. During selection, don't interfere with the chip registers after a reselection interrupt intervenes. Clean up some trivial issues with code style, comments and printk. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Ondrej Zary Tested-by: Michael Schmitz Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.c | 115 ++++++++++++++++++++++++------------------- drivers/scsi/atari_NCR5380.c | 50 +++++++++++-------- 2 files changed, 93 insertions(+), 72 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index ffa3719312d1..78cf970e13ba 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -1182,6 +1182,10 @@ static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd) else udelay(2); + /* NCR5380_reselect() clears MODE_REG after a reselection interrupt */ + if (!(NCR5380_read(MODE_REG) & MR_ARBITRATE)) + return -1; + dprintk(NDEBUG_ARBITRATION, "scsi%d : won arbitration\n", instance->host_no); /* @@ -1953,12 +1957,14 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { cmd->scsi_done(cmd); } - NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); /* * Restore phase bits to 0 so an interrupted selection, * arbitration can resume. */ NCR5380_write(TARGET_COMMAND_REG, 0); + + /* Enable reselect interrupts */ + NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); return; case MESSAGE_REJECT: /* Accept message by clearing ACK */ @@ -2144,7 +2150,6 @@ static void NCR5380_reselect(struct Scsi_Host *instance) { unsigned char msg[3]; unsigned char *data; struct scsi_cmnd *tmp = NULL, *prev; - int abort = 0; /* * Disable arbitration, etc. since the host adapter obviously @@ -2154,7 +2159,7 @@ static void NCR5380_reselect(struct Scsi_Host *instance) { NCR5380_write(MODE_REG, MR_BASE); target_mask = NCR5380_read(CURRENT_SCSI_DATA_REG) & ~(hostdata->id_mask); - dprintk(NDEBUG_SELECTION, "scsi%d : reselect\n", instance->host_no); + dprintk(NDEBUG_RESELECTION, "scsi%d : reselect\n", instance->host_no); /* * At this point, we have detected that our SCSI ID is on the bus, @@ -2166,77 +2171,85 @@ static void NCR5380_reselect(struct Scsi_Host *instance) { */ NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_BSY); - - /* FIXME: timeout too long, must fail to workqueue */ - if(NCR5380_poll_politely(instance, STATUS_REG, SR_SEL, 0, 2*HZ)<0) - abort = 1; - + if (NCR5380_poll_politely(instance, + STATUS_REG, SR_SEL, 0, 2 * HZ) < 0) { + NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); + return; + } NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); /* * Wait for target to go into MSGIN. - * FIXME: timeout needed and fail to work queeu */ if (NCR5380_poll_politely(instance, - STATUS_REG, SR_REQ, SR_REQ, 2 * HZ) < 0) - abort = 1; + STATUS_REG, SR_REQ, SR_REQ, 2 * HZ) < 0) { + do_abort(instance); + return; + } len = 1; data = msg; phase = PHASE_MSGIN; NCR5380_transfer_pio(instance, &phase, &len, &data); + if (len) { + do_abort(instance); + return; + } + if (!(msg[0] & 0x80)) { - printk(KERN_ERR "scsi%d : expecting IDENTIFY message, got ", instance->host_no); + shost_printk(KERN_ERR, instance, "expecting IDENTIFY message, got "); spi_print_msg(msg); - abort = 1; - } else { - /* Accept message by clearing ACK */ - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - lun = (msg[0] & 0x07); - - /* - * We need to add code for SCSI-II to track which devices have - * I_T_L_Q nexuses established, and which have simple I_T_L - * nexuses so we can chose to do additional data transfer. - */ + printk("\n"); + do_abort(instance); + return; + } + lun = msg[0] & 0x07; - /* - * Find the command corresponding to the I_T_L or I_T_L_Q nexus we - * just reestablished, and remove it from the disconnected queue. - */ + /* + * We need to add code for SCSI-II to track which devices have + * I_T_L_Q nexuses established, and which have simple I_T_L + * nexuses so we can chose to do additional data transfer. + */ + /* + * Find the command corresponding to the I_T_L or I_T_L_Q nexus we + * just reestablished, and remove it from the disconnected queue. + */ - for (tmp = (struct scsi_cmnd *) hostdata->disconnected_queue, prev = NULL; tmp; prev = tmp, tmp = (struct scsi_cmnd *) tmp->host_scribble) - if ((target_mask == (1 << tmp->device->id)) && (lun == (u8)tmp->device->lun) - ) { - if (prev) { - REMOVE(prev, prev->host_scribble, tmp, tmp->host_scribble); - prev->host_scribble = tmp->host_scribble; - } else { - REMOVE(-1, hostdata->disconnected_queue, tmp, tmp->host_scribble); - hostdata->disconnected_queue = (struct scsi_cmnd *) tmp->host_scribble; - } - tmp->host_scribble = NULL; - break; + for (tmp = (struct scsi_cmnd *) hostdata->disconnected_queue, prev = NULL; + tmp; prev = tmp, tmp = (struct scsi_cmnd *) tmp->host_scribble) { + if ((target_mask == (1 << tmp->device->id)) && (lun == (u8)tmp->device->lun)) { + if (prev) { + REMOVE(prev, prev->host_scribble, tmp, tmp->host_scribble); + prev->host_scribble = tmp->host_scribble; + } else { + REMOVE(-1, hostdata->disconnected_queue, tmp, tmp->host_scribble); + hostdata->disconnected_queue = + (struct scsi_cmnd *) tmp->host_scribble; } - if (!tmp) { - printk(KERN_ERR "scsi%d : warning : target bitmask %02x lun %d not in disconnect_queue.\n", instance->host_no, target_mask, lun); - /* - * Since we have an established nexus that we can't do anything with, - * we must abort it. - */ - abort = 1; + tmp->host_scribble = NULL; + break; } } - - if (abort) { + if (!tmp) { + shost_printk(KERN_ERR, instance, "target bitmask 0x%02x lun %d not in disconnected queue.\n", + target_mask, lun); + /* + * Since we have an established nexus that we can't do anything with, + * we must abort it. + */ do_abort(instance); - } else { - hostdata->connected = tmp; - dprintk(NDEBUG_RESELECTION, "scsi%d : nexus established, target = %d, lun = %llu, tag = %d\n", instance->host_no, tmp->device->id, tmp->device->lun, tmp->tag); + return; } + + /* Accept message by clearing ACK */ + NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); + + hostdata->connected = tmp; + dprintk(NDEBUG_RESELECTION, "scsi%d : nexus established, target = %d, lun = %llu, tag = %d\n", + instance->host_no, tmp->device->id, tmp->device->lun, tmp->tag); } /* diff --git a/drivers/scsi/atari_NCR5380.c b/drivers/scsi/atari_NCR5380.c index 70398c61fffc..214f43b4baad 100644 --- a/drivers/scsi/atari_NCR5380.c +++ b/drivers/scsi/atari_NCR5380.c @@ -1446,11 +1446,9 @@ static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd) else udelay(2); - if (hostdata->connected) { - NCR5380_write(MODE_REG, MR_BASE); - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); + /* NCR5380_reselect() clears MODE_REG after a reselection interrupt */ + if (!(NCR5380_read(MODE_REG) & MR_ARBITRATE)) return -1; - } dprintk(NDEBUG_ARBITRATION, "scsi%d: won arbitration\n", HOSTNO); @@ -2223,13 +2221,15 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) cmd->scsi_done(cmd); } - NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); /* * Restore phase bits to 0 so an interrupted selection, * arbitration can resume. */ NCR5380_write(TARGET_COMMAND_REG, 0); + /* Enable reselect interrupts */ + NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); + /* ++roman: For Falcon SCSI, release the lock on the * ST-DMA here if no other commands are waiting on the * disconnected queue. @@ -2482,17 +2482,22 @@ static void NCR5380_reselect(struct Scsi_Host *instance) */ NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_BSY); - - while (NCR5380_read(STATUS_REG) & SR_SEL) - ; + if (NCR5380_poll_politely(instance, + STATUS_REG, SR_SEL, 0, 2 * HZ) < 0) { + NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); + return; + } NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); /* * Wait for target to go into MSGIN. */ - while (!(NCR5380_read(STATUS_REG) & SR_REQ)) - ; + if (NCR5380_poll_politely(instance, + STATUS_REG, SR_REQ, SR_REQ, 2 * HZ) < 0) { + do_abort(instance); + return; + } #if defined(CONFIG_SUN3) && defined(REAL_DMA) /* acknowledge toggle to MSGIN */ @@ -2505,15 +2510,21 @@ static void NCR5380_reselect(struct Scsi_Host *instance) data = msg; phase = PHASE_MSGIN; NCR5380_transfer_pio(instance, &phase, &len, &data); + + if (len) { + do_abort(instance); + return; + } #endif if (!(msg[0] & 0x80)) { - printk(KERN_DEBUG "scsi%d: expecting IDENTIFY message, got ", HOSTNO); + shost_printk(KERN_ERR, instance, "expecting IDENTIFY message, got "); spi_print_msg(msg); + printk("\n"); do_abort(instance); return; } - lun = (msg[0] & 0x07); + lun = msg[0] & 0x07; #if defined(SUPPORT_TAGS) && !defined(CONFIG_SUN3) /* If the phase is still MSGIN, the target wants to send some more @@ -2541,7 +2552,7 @@ static void NCR5380_reselect(struct Scsi_Host *instance) for (tmp = (struct scsi_cmnd *) hostdata->disconnected_queue, prev = NULL; tmp; prev = tmp, tmp = NEXT(tmp)) { - if ((target_mask == (1 << tmp->device->id)) && (lun == tmp->device->lun) + if ((target_mask == (1 << tmp->device->id)) && (lun == (u8)tmp->device->lun) #ifdef SUPPORT_TAGS && (tag == tmp->tag) #endif @@ -2559,16 +2570,13 @@ static void NCR5380_reselect(struct Scsi_Host *instance) } if (!tmp) { - printk(KERN_WARNING "scsi%d: warning: target bitmask %02x lun %d " #ifdef SUPPORT_TAGS - "tag %d " -#endif - "not in disconnected_queue.\n", - HOSTNO, target_mask, lun -#ifdef SUPPORT_TAGS - , tag + shost_printk(KERN_ERR, instance, "target bitmask 0x%02x lun %d tag %d not in disconnected queue.\n", + target_mask, lun, tag); +#else + shost_printk(KERN_ERR, instance, "target bitmask 0x%02x lun %d not in disconnected queue.\n", + target_mask, lun); #endif - ); /* * Since we have an established nexus that we can't do anything * with, we must abort it. -- cgit From e0783ed3660aecb83af580cdace583980b22809b Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sun, 3 Jan 2016 16:05:45 +1100 Subject: ncr5380: Fix off-by-one bug in extended_msg[] bounds check Fix the array bounds check when transferring an extended message from the target. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Ondrej Zary Tested-by: Michael Schmitz Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.c | 3 ++- drivers/scsi/atari_NCR5380.c | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index 78cf970e13ba..c6b69ee0021a 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -2039,7 +2039,8 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { dprintk(NDEBUG_EXTENDED, "scsi%d : length=%d, code=0x%02x\n", instance->host_no, (int) extended_msg[1], (int) extended_msg[2]); - if (!len && extended_msg[1] <= (sizeof(extended_msg) - 1)) { + if (!len && extended_msg[1] > 0 && + extended_msg[1] <= sizeof(extended_msg) - 2) { /* Accept third byte by clearing ACK */ NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); len = extended_msg[1] - 1; diff --git a/drivers/scsi/atari_NCR5380.c b/drivers/scsi/atari_NCR5380.c index 214f43b4baad..c14cfb1cc3dd 100644 --- a/drivers/scsi/atari_NCR5380.c +++ b/drivers/scsi/atari_NCR5380.c @@ -2330,8 +2330,8 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) dprintk(NDEBUG_EXTENDED, "scsi%d: length=%d, code=0x%02x\n", HOSTNO, (int)extended_msg[1], (int)extended_msg[2]); - if (!len && extended_msg[1] <= - (sizeof(extended_msg) - 1)) { + if (!len && extended_msg[1] > 0 && + extended_msg[1] <= sizeof(extended_msg) - 2) { /* Accept third byte by clearing ACK */ NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); len = extended_msg[1] - 1; -- cgit From 161c0059a2a80aefe7000d9ab7ce5c36e5463b5f Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sun, 3 Jan 2016 16:05:46 +1100 Subject: ncr5380: Cleanup #include directives Remove unused includes (stat.h, signal.h, proc_fs.h) and move includes needed by the core drivers into the common header (delay.h etc). Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Ondrej Zary Tested-by: Michael Schmitz Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.c | 2 -- drivers/scsi/NCR5380.h | 4 ++++ drivers/scsi/arm/cumana_1.c | 4 ---- drivers/scsi/arm/oak.c | 2 -- drivers/scsi/atari_NCR5380.c | 5 ----- drivers/scsi/atari_scsi.c | 1 - drivers/scsi/dmx3191d.c | 5 ----- drivers/scsi/dtc.c | 4 +--- drivers/scsi/g_NCR5380.c | 6 ++---- drivers/scsi/mac_scsi.c | 1 - drivers/scsi/pas16.c | 4 ---- drivers/scsi/t128.c | 3 --- 12 files changed, 7 insertions(+), 34 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index c6b69ee0021a..9ef26b64255a 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -79,8 +79,6 @@ * 4. Test SCSI-II tagged queueing (I have no devices which support * tagged queueing) */ -#include -#include #if (NDEBUG & NDEBUG_LISTS) #define LIST(x,y) {printk("LINE:%d Adding %p to %p\n", __LINE__, (void*)(x), (void*)(y)); if ((x)==(y)) udelay(5); } diff --git a/drivers/scsi/NCR5380.h b/drivers/scsi/NCR5380.h index e8a26eab32dd..9777602daa3d 100644 --- a/drivers/scsi/NCR5380.h +++ b/drivers/scsi/NCR5380.h @@ -22,8 +22,12 @@ #ifndef NCR5380_H #define NCR5380_H +#include #include +#include +#include #include +#include #define NDEBUG_ARBITRATION 0x1 #define NDEBUG_AUTOSENSE 0x2 diff --git a/drivers/scsi/arm/cumana_1.c b/drivers/scsi/arm/cumana_1.c index f9fb8dabdbbd..921c982886ae 100644 --- a/drivers/scsi/arm/cumana_1.c +++ b/drivers/scsi/arm/cumana_1.c @@ -4,9 +4,7 @@ * Copyright 1995-2002, Russell King */ #include -#include #include -#include #include #include @@ -15,8 +13,6 @@ #include -#include - #define PSEUDO_DMA #define priv(host) ((struct NCR5380_hostdata *)(host)->hostdata) diff --git a/drivers/scsi/arm/oak.c b/drivers/scsi/arm/oak.c index d95a1d4f4e02..719600a373d6 100644 --- a/drivers/scsi/arm/oak.c +++ b/drivers/scsi/arm/oak.c @@ -5,9 +5,7 @@ */ #include -#include #include -#include #include #include diff --git a/drivers/scsi/atari_NCR5380.c b/drivers/scsi/atari_NCR5380.c index c14cfb1cc3dd..8024f1cb9756 100644 --- a/drivers/scsi/atari_NCR5380.c +++ b/drivers/scsi/atari_NCR5380.c @@ -68,9 +68,6 @@ /* Adapted for the sun3 by Sam Creasey. */ -#include -#include - #if (NDEBUG & NDEBUG_LISTS) #define LIST(x, y) \ do { \ @@ -517,8 +514,6 @@ static inline int NCR5380_poll_politely(struct Scsi_Host *instance, reg, bit, val, wait); } -#include - #if NDEBUG static struct { unsigned char mask; diff --git a/drivers/scsi/atari_scsi.c b/drivers/scsi/atari_scsi.c index 1c6c4ca0a82f..2ba075749326 100644 --- a/drivers/scsi/atari_scsi.c +++ b/drivers/scsi/atari_scsi.c @@ -66,7 +66,6 @@ #include #include -#include #include #include #include diff --git a/drivers/scsi/dmx3191d.c b/drivers/scsi/dmx3191d.c index db415359fee8..05402830defe 100644 --- a/drivers/scsi/dmx3191d.c +++ b/drivers/scsi/dmx3191d.c @@ -41,11 +41,6 @@ #define NCR5380_implementation_fields /* none */ -/* - * Includes needed for NCR5380.[ch] (XXX: Move them to NCR5380.h) - */ -#include - #include "NCR5380.h" #include "NCR5380.c" diff --git a/drivers/scsi/dtc.c b/drivers/scsi/dtc.c index 1beefdbcbea8..6c96dad5cf23 100644 --- a/drivers/scsi/dtc.c +++ b/drivers/scsi/dtc.c @@ -46,15 +46,13 @@ #include -#include #include -#include -#include #include #include #include #include #include + #include "dtc.h" #define AUTOPROBE_IRQ #include "NCR5380.h" diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c index e71c79683925..1e8f29f500d5 100644 --- a/drivers/scsi/g_NCR5380.c +++ b/drivers/scsi/g_NCR5380.c @@ -63,16 +63,14 @@ #endif #include -#include #include +#include #include #include "g_NCR5380.h" #include "NCR5380.h" -#include #include #include #include -#include #include static int ncr_irq; @@ -732,7 +730,7 @@ static struct scsi_host_template driver_template = { .cmd_per_lun = CMD_PER_LUN, .use_clustering = DISABLE_CLUSTERING, }; -#include + #include "scsi_module.c" module_param(ncr_irq, int, 0); diff --git a/drivers/scsi/mac_scsi.c b/drivers/scsi/mac_scsi.c index f8ed2acd1456..420c2e204c13 100644 --- a/drivers/scsi/mac_scsi.c +++ b/drivers/scsi/mac_scsi.c @@ -12,7 +12,6 @@ */ #include -#include #include #include #include diff --git a/drivers/scsi/pas16.c b/drivers/scsi/pas16.c index 4570536187d8..6a5896dade20 100644 --- a/drivers/scsi/pas16.c +++ b/drivers/scsi/pas16.c @@ -69,14 +69,10 @@ #include -#include -#include #include #include #include -#include #include -#include #include #include diff --git a/drivers/scsi/t128.c b/drivers/scsi/t128.c index 3dac6d7f5d22..167c0750eba6 100644 --- a/drivers/scsi/t128.c +++ b/drivers/scsi/t128.c @@ -68,14 +68,11 @@ * 15 9-11 */ -#include #include #include #include -#include #include #include -#include #include #include "t128.h" -- cgit From bf1a0c6f8f2c1959082f1b55b907dde100c87501 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sun, 3 Jan 2016 16:05:47 +1100 Subject: ncr5380: Fix NDEBUG_NO_DATAOUT flag NDEBUG_NO_DATAOUT should not disable DATA IN phases too. Fix this. (This bug has long been fixed in atari_NCR5380.c.) Signed-off-by: Finn Thain Tested-by: Ondrej Zary Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index 9ef26b64255a..be40c965fffb 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -1838,7 +1838,6 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { continue; } switch (phase) { - case PHASE_DATAIN: case PHASE_DATAOUT: #if (NDEBUG & NDEBUG_NO_DATAOUT) printk("scsi%d : NDEBUG_NO_DATAOUT set, attempted DATAOUT aborted\n", instance->host_no); @@ -1848,6 +1847,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { cmd->scsi_done(cmd); return; #endif + case PHASE_DATAIN: /* * If there is no room left in the current buffer in the * scatter-gather list, move onto the next one. -- cgit From aa2e2cb1dde0e72e039f94210fb17e73661a6351 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sun, 3 Jan 2016 16:05:48 +1100 Subject: ncr5380: Fix and cleanup scsi_host_template initializers Add missing .module initializer. Use distinct .proc_name values for the g_NCR5380 and g_NCR5380_mmio modules. Remove pointless CAN_QUEUE and CMD_PER_LUN override macros. Cleanup whitespace and code style. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Ondrej Zary Tested-by: Michael Schmitz Signed-off-by: Martin K. Petersen --- drivers/scsi/atari_scsi.c | 2 +- drivers/scsi/dmx3191d.c | 1 + drivers/scsi/dtc.c | 32 ++++++++++++++++---------------- drivers/scsi/dtc.h | 8 -------- drivers/scsi/g_NCR5380.c | 26 +++++++++++++------------- drivers/scsi/g_NCR5380.h | 10 ++-------- drivers/scsi/mac_scsi.c | 28 ++++++++++++++-------------- drivers/scsi/pas16.c | 32 ++++++++++++++++---------------- drivers/scsi/pas16.h | 8 -------- drivers/scsi/sun3_scsi.c | 6 +++--- drivers/scsi/t128.c | 32 ++++++++++++++++---------------- drivers/scsi/t128.h | 8 -------- 12 files changed, 82 insertions(+), 111 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/atari_scsi.c b/drivers/scsi/atari_scsi.c index 2ba075749326..e263aa30282b 100644 --- a/drivers/scsi/atari_scsi.c +++ b/drivers/scsi/atari_scsi.c @@ -781,7 +781,7 @@ static struct scsi_host_template atari_scsi_template = { .eh_abort_handler = atari_scsi_abort, .eh_bus_reset_handler = atari_scsi_bus_reset, .this_id = 7, - .use_clustering = DISABLE_CLUSTERING + .use_clustering = DISABLE_CLUSTERING, }; static int __init atari_scsi_probe(struct platform_device *pdev) diff --git a/drivers/scsi/dmx3191d.c b/drivers/scsi/dmx3191d.c index 05402830defe..7f66c9e76c3b 100644 --- a/drivers/scsi/dmx3191d.c +++ b/drivers/scsi/dmx3191d.c @@ -49,6 +49,7 @@ static struct scsi_host_template dmx3191d_driver_template = { + .module = THIS_MODULE, .proc_name = DMX3191D_DRIVER_NAME, .name = "Domex DMX3191D", .info = NCR5380_info, diff --git a/drivers/scsi/dtc.c b/drivers/scsi/dtc.c index 6c96dad5cf23..d74661458f15 100644 --- a/drivers/scsi/dtc.c +++ b/drivers/scsi/dtc.c @@ -436,21 +436,21 @@ static int dtc_release(struct Scsi_Host *shost) } static struct scsi_host_template driver_template = { - .name = "DTC 3180/3280 ", - .detect = dtc_detect, - .release = dtc_release, - .proc_name = "dtc3x80", - .show_info = dtc_show_info, - .write_info = dtc_write_info, - .info = dtc_info, - .queuecommand = dtc_queue_command, - .eh_abort_handler = dtc_abort, - .eh_bus_reset_handler = dtc_bus_reset, - .bios_param = dtc_biosparam, - .can_queue = CAN_QUEUE, - .this_id = 7, - .sg_tablesize = SG_ALL, - .cmd_per_lun = CMD_PER_LUN, - .use_clustering = DISABLE_CLUSTERING, + .name = "DTC 3180/3280", + .detect = dtc_detect, + .release = dtc_release, + .proc_name = "dtc3x80", + .show_info = dtc_show_info, + .write_info = dtc_write_info, + .info = dtc_info, + .queuecommand = dtc_queue_command, + .eh_abort_handler = dtc_abort, + .eh_bus_reset_handler = dtc_bus_reset, + .bios_param = dtc_biosparam, + .can_queue = 32, + .this_id = 7, + .sg_tablesize = SG_ALL, + .cmd_per_lun = 2, + .use_clustering = DISABLE_CLUSTERING, }; #include "scsi_module.c" diff --git a/drivers/scsi/dtc.h b/drivers/scsi/dtc.h index e6c09a9174ce..56732cba8aba 100644 --- a/drivers/scsi/dtc.h +++ b/drivers/scsi/dtc.h @@ -10,14 +10,6 @@ #ifndef DTC3280_H #define DTC3280_H -#ifndef CMD_PER_LUN -#define CMD_PER_LUN 2 -#endif - -#ifndef CAN_QUEUE -#define CAN_QUEUE 32 -#endif - #define NCR5380_implementation_fields \ void __iomem *base diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c index 1e8f29f500d5..ea9d0de2fc85 100644 --- a/drivers/scsi/g_NCR5380.c +++ b/drivers/scsi/g_NCR5380.c @@ -305,7 +305,6 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt) } } #endif - tpnt->proc_name = "g_NCR5380"; for (count = 0; current_override < NO_OVERRIDES; ++current_override) { if (!(overrides[current_override].NCR5380_map_name)) @@ -715,20 +714,21 @@ static int generic_NCR5380_dma_xfer_len(struct scsi_cmnd *cmd) #include "NCR5380.c" static struct scsi_host_template driver_template = { - .show_info = generic_NCR5380_show_info, - .name = "Generic NCR5380/NCR53C400 SCSI", - .detect = generic_NCR5380_detect, - .release = generic_NCR5380_release_resources, - .info = generic_NCR5380_info, - .queuecommand = generic_NCR5380_queue_command, + .proc_name = DRV_MODULE_NAME, + .show_info = generic_NCR5380_show_info, + .name = "Generic NCR5380/NCR53C400 SCSI", + .detect = generic_NCR5380_detect, + .release = generic_NCR5380_release_resources, + .info = generic_NCR5380_info, + .queuecommand = generic_NCR5380_queue_command, .eh_abort_handler = generic_NCR5380_abort, .eh_bus_reset_handler = generic_NCR5380_bus_reset, - .bios_param = NCR5380_BIOSPARAM, - .can_queue = CAN_QUEUE, - .this_id = 7, - .sg_tablesize = SG_ALL, - .cmd_per_lun = CMD_PER_LUN, - .use_clustering = DISABLE_CLUSTERING, + .bios_param = NCR5380_BIOSPARAM, + .can_queue = 16, + .this_id = 7, + .sg_tablesize = SG_ALL, + .cmd_per_lun = 2, + .use_clustering = DISABLE_CLUSTERING, }; #include "scsi_module.c" diff --git a/drivers/scsi/g_NCR5380.h b/drivers/scsi/g_NCR5380.h index 0056790a9cbe..fd201e94f66b 100644 --- a/drivers/scsi/g_NCR5380.h +++ b/drivers/scsi/g_NCR5380.h @@ -21,18 +21,11 @@ #define NCR5380_BIOSPARAM NULL #endif -#ifndef CMD_PER_LUN -#define CMD_PER_LUN 2 -#endif - -#ifndef CAN_QUEUE -#define CAN_QUEUE 16 -#endif - #define __STRVAL(x) #x #define STRVAL(x) __STRVAL(x) #ifndef SCSI_G_NCR5380_MEM +#define DRV_MODULE_NAME "g_NCR5380" #define NCR5380_map_type int #define NCR5380_map_name port @@ -53,6 +46,7 @@ #else /* therefore SCSI_G_NCR5380_MEM */ +#define DRV_MODULE_NAME "g_NCR5380_mmio" #define NCR5380_map_type unsigned long #define NCR5380_map_name base diff --git a/drivers/scsi/mac_scsi.c b/drivers/scsi/mac_scsi.c index 420c2e204c13..e75bed25dd15 100644 --- a/drivers/scsi/mac_scsi.c +++ b/drivers/scsi/mac_scsi.c @@ -309,20 +309,20 @@ static int macscsi_pwrite(struct Scsi_Host *instance, #define PFX DRV_MODULE_NAME ": " static struct scsi_host_template mac_scsi_template = { - .module = THIS_MODULE, - .proc_name = DRV_MODULE_NAME, - .show_info = macscsi_show_info, - .write_info = macscsi_write_info, - .name = "Macintosh NCR5380 SCSI", - .info = macscsi_info, - .queuecommand = macscsi_queue_command, - .eh_abort_handler = macscsi_abort, - .eh_bus_reset_handler = macscsi_bus_reset, - .can_queue = 16, - .this_id = 7, - .sg_tablesize = SG_ALL, - .cmd_per_lun = 2, - .use_clustering = DISABLE_CLUSTERING + .module = THIS_MODULE, + .proc_name = DRV_MODULE_NAME, + .show_info = macscsi_show_info, + .write_info = macscsi_write_info, + .name = "Macintosh NCR5380 SCSI", + .info = macscsi_info, + .queuecommand = macscsi_queue_command, + .eh_abort_handler = macscsi_abort, + .eh_bus_reset_handler = macscsi_bus_reset, + .can_queue = 16, + .this_id = 7, + .sg_tablesize = SG_ALL, + .cmd_per_lun = 2, + .use_clustering = DISABLE_CLUSTERING, }; static int __init mac_scsi_probe(struct platform_device *pdev) diff --git a/drivers/scsi/pas16.c b/drivers/scsi/pas16.c index 6a5896dade20..5f8a8295a5c1 100644 --- a/drivers/scsi/pas16.c +++ b/drivers/scsi/pas16.c @@ -546,22 +546,22 @@ static int pas16_release(struct Scsi_Host *shost) } static struct scsi_host_template driver_template = { - .name = "Pro Audio Spectrum-16 SCSI", - .detect = pas16_detect, - .release = pas16_release, - .proc_name = "pas16", - .show_info = pas16_show_info, - .write_info = pas16_write_info, - .info = pas16_info, - .queuecommand = pas16_queue_command, - .eh_abort_handler = pas16_abort, - .eh_bus_reset_handler = pas16_bus_reset, - .bios_param = pas16_biosparam, - .can_queue = CAN_QUEUE, - .this_id = 7, - .sg_tablesize = SG_ALL, - .cmd_per_lun = CMD_PER_LUN, - .use_clustering = DISABLE_CLUSTERING, + .name = "Pro Audio Spectrum-16 SCSI", + .detect = pas16_detect, + .release = pas16_release, + .proc_name = "pas16", + .show_info = pas16_show_info, + .write_info = pas16_write_info, + .info = pas16_info, + .queuecommand = pas16_queue_command, + .eh_abort_handler = pas16_abort, + .eh_bus_reset_handler = pas16_bus_reset, + .bios_param = pas16_biosparam, + .can_queue = 32, + .this_id = 7, + .sg_tablesize = SG_ALL, + .cmd_per_lun = 2, + .use_clustering = DISABLE_CLUSTERING, }; #include "scsi_module.c" diff --git a/drivers/scsi/pas16.h b/drivers/scsi/pas16.h index a827a7c1c133..d37527717225 100644 --- a/drivers/scsi/pas16.h +++ b/drivers/scsi/pas16.h @@ -95,14 +95,6 @@ #define OPERATION_MODE_1 0xec03 #define IO_CONFIG_3 0xf002 -#ifndef CMD_PER_LUN -#define CMD_PER_LUN 2 -#endif - -#ifndef CAN_QUEUE -#define CAN_QUEUE 32 -#endif - #define NCR5380_implementation_fields /* none */ #define PAS16_io_port(reg) (instance->io_port + pas16_offset[(reg)]) diff --git a/drivers/scsi/sun3_scsi.c b/drivers/scsi/sun3_scsi.c index c4fcf2fa74fc..082c91a4c1c4 100644 --- a/drivers/scsi/sun3_scsi.c +++ b/drivers/scsi/sun3_scsi.c @@ -463,13 +463,13 @@ static struct scsi_host_template sun3_scsi_template = { .name = SUN3_SCSI_NAME, .info = sun3scsi_info, .queuecommand = sun3scsi_queue_command, - .eh_abort_handler = sun3scsi_abort, - .eh_bus_reset_handler = sun3scsi_bus_reset, + .eh_abort_handler = sun3scsi_abort, + .eh_bus_reset_handler = sun3scsi_bus_reset, .can_queue = 16, .this_id = 7, .sg_tablesize = SG_NONE, .cmd_per_lun = 2, - .use_clustering = DISABLE_CLUSTERING + .use_clustering = DISABLE_CLUSTERING, }; static int __init sun3_scsi_probe(struct platform_device *pdev) diff --git a/drivers/scsi/t128.c b/drivers/scsi/t128.c index 167c0750eba6..d1ed1f532a24 100644 --- a/drivers/scsi/t128.c +++ b/drivers/scsi/t128.c @@ -390,21 +390,21 @@ MODULE_LICENSE("GPL"); #include "NCR5380.c" static struct scsi_host_template driver_template = { - .name = "Trantor T128/T128F/T228", - .detect = t128_detect, - .release = t128_release, - .proc_name = "t128", - .show_info = t128_show_info, - .write_info = t128_write_info, - .info = t128_info, - .queuecommand = t128_queue_command, - .eh_abort_handler = t128_abort, - .eh_bus_reset_handler = t128_bus_reset, - .bios_param = t128_biosparam, - .can_queue = CAN_QUEUE, - .this_id = 7, - .sg_tablesize = SG_ALL, - .cmd_per_lun = CMD_PER_LUN, - .use_clustering = DISABLE_CLUSTERING, + .name = "Trantor T128/T128F/T228", + .detect = t128_detect, + .release = t128_release, + .proc_name = "t128", + .show_info = t128_show_info, + .write_info = t128_write_info, + .info = t128_info, + .queuecommand = t128_queue_command, + .eh_abort_handler = t128_abort, + .eh_bus_reset_handler = t128_bus_reset, + .bios_param = t128_biosparam, + .can_queue = 32, + .this_id = 7, + .sg_tablesize = SG_ALL, + .cmd_per_lun = 2, + .use_clustering = DISABLE_CLUSTERING, }; #include "scsi_module.c" diff --git a/drivers/scsi/t128.h b/drivers/scsi/t128.h index 16691d5fb81b..dd16d85497e1 100644 --- a/drivers/scsi/t128.h +++ b/drivers/scsi/t128.h @@ -67,14 +67,6 @@ #define T_DATA_REG_OFFSET 0x1e00 /* rw 512 bytes long */ -#ifndef CMD_PER_LUN -#define CMD_PER_LUN 2 -#endif - -#ifndef CAN_QUEUE -#define CAN_QUEUE 32 -#endif - #define NCR5380_implementation_fields \ void __iomem *base -- cgit From e42d01518d006c4557e202bc9e8fdc41972fb49f Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sun, 3 Jan 2016 16:05:49 +1100 Subject: atari_NCR5380: Fix queue_size limit When a target reports a QUEUE_FULL condition it causes the driver to update the 'queue_size' limit with the number of currently allocated tags. At least, that's what's supposed to happen, according to the comments. Unfortunately the terms in the assignment are swapped. Fix this and cleanup some obsolete comments. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Michael Schmitz Signed-off-by: Martin K. Petersen --- drivers/scsi/atari_NCR5380.c | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/atari_NCR5380.c b/drivers/scsi/atari_NCR5380.c index 8024f1cb9756..06245c07ebd2 100644 --- a/drivers/scsi/atari_NCR5380.c +++ b/drivers/scsi/atari_NCR5380.c @@ -229,9 +229,7 @@ static void do_reset(struct Scsi_Host *); * cannot know it in advance :-( We just see a QUEUE_FULL status being * returned. So, in this case, the driver internal queue size assumption is * reduced to the number of active tags if QUEUE_FULL is returned by the - * target. The command is returned to the mid-level, but with status changed - * to BUSY, since --as I've seen-- the mid-level can't handle QUEUE_FULL - * correctly. + * target. * * We're also not allowed running tagged commands as long as an untagged * command is active. And REQUEST SENSE commands after a contingent allegiance @@ -2152,21 +2150,13 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) #ifdef SUPPORT_TAGS cmd_free_tag(cmd); if (status_byte(cmd->SCp.Status) == QUEUE_FULL) { - /* Turn a QUEUE FULL status into BUSY, I think the - * mid level cannot handle QUEUE FULL :-( (The - * command is retried after BUSY). Also update our - * queue size to the number of currently issued - * commands now. - */ - /* ++Andreas: the mid level code knows about - QUEUE_FULL now. */ struct tag_alloc *ta = &hostdata->TagAlloc[scmd_id(cmd)][cmd->device->lun]; dprintk(NDEBUG_TAGS, "scsi%d: target %d lun %llu returned " "QUEUE_FULL after %d commands\n", HOSTNO, cmd->device->id, cmd->device->lun, ta->nr_allocated); if (ta->queue_size > ta->nr_allocated) - ta->nr_allocated = ta->queue_size; + ta->queue_size = ta->nr_allocated; } #else hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun); -- cgit From be3f4121aa352d8fef77a57df4b5e106d7f9a917 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sun, 3 Jan 2016 16:05:50 +1100 Subject: ncr5380: Remove redundant ICR_ARBITRATION_LOST test and eliminate FLAG_DTC3181E Remove FLAG_DTC3181E. It was used to suppress a final Arbitration Lost (SEL asserted) test that isn't actually needed. The test was suppressed because it causes problems for DTC436 and DTC536 chips. It takes place after the host wins arbitration, so SEL has been asserted. These chips can't seem to tell whether it was the host or another bus device that did so. This questionable final test appears in a flow chart in an early NCR5380 datasheet. It was removed from later documents like the DP5380 datasheet. By the time this final test takes place, the driver has already tested the Arbitration Lost bit several times. The first test happens 3 us after BUS FREE (or longer due to register access delays). The protocol requires that a device stop signalling within 1.8 us after BUS FREE unless it won arbitration, in which case it must assert SEL, which is detected 1.2 us later by the first Arbitration Lost test. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Ondrej Zary Tested-by: Michael Schmitz Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.c | 14 +------------- drivers/scsi/NCR5380.h | 1 - drivers/scsi/atari_NCR5380.c | 9 --------- drivers/scsi/dmx3191d.c | 2 +- drivers/scsi/g_NCR5380.c | 2 +- 5 files changed, 3 insertions(+), 25 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index be40c965fffb..a4defd1977c9 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -528,14 +528,13 @@ static void prepare_info(struct Scsi_Host *instance) "base 0x%lx, irq %d, " "can_queue %d, cmd_per_lun %d, " "sg_tablesize %d, this_id %d, " - "flags { %s%s%s%s}, " + "flags { %s%s%s}, " "options { %s} ", instance->hostt->name, instance->io_port, instance->n_io_port, instance->base, instance->irq, instance->can_queue, instance->cmd_per_lun, instance->sg_tablesize, instance->this_id, hostdata->flags & FLAG_NO_DMA_FIXUP ? "NO_DMA_FIXUP " : "", - hostdata->flags & FLAG_DTC3181E ? "DTC3181E " : "", hostdata->flags & FLAG_NO_PSEUDO_DMA ? "NO_PSEUDO_DMA " : "", hostdata->flags & FLAG_TOSHIBA_DELAY ? "TOSHIBA_DELAY " : "", #ifdef AUTOPROBE_IRQ @@ -1159,17 +1158,6 @@ static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd) NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_SEL | ICR_ASSERT_BSY); - if (!(hostdata->flags & FLAG_DTC3181E) && - /* RvC: DTC3181E has some trouble with this - * so we simply removed it. Seems to work with - * only Mustek scanner attached - */ - (NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_LOST)) { - NCR5380_write(MODE_REG, MR_BASE); - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - dprintk(NDEBUG_ARBITRATION, "scsi%d : lost arbitration, deasserting ICR_ASSERT_SEL\n", instance->host_no); - return -1; - } /* * Again, bus clear + bus settle time is 1.2us, however, this is * a minimum so we'll udelay ceil(1.2) diff --git a/drivers/scsi/NCR5380.h b/drivers/scsi/NCR5380.h index 9777602daa3d..96fced9e6064 100644 --- a/drivers/scsi/NCR5380.h +++ b/drivers/scsi/NCR5380.h @@ -232,7 +232,6 @@ #define FLAG_NO_DMA_FIXUP 1 /* No DMA errata workarounds */ #define FLAG_NO_PSEUDO_DMA 8 /* Inhibit DMA */ -#define FLAG_DTC3181E 16 /* DTC3181E */ #define FLAG_LATE_DMA_SETUP 32 /* Setup NCR before DMA H/W */ #define FLAG_TAGGED_QUEUING 64 /* as X3T9.2 spelled it */ #define FLAG_TOSHIBA_DELAY 128 /* Allow for borken CD-ROMs */ diff --git a/drivers/scsi/atari_NCR5380.c b/drivers/scsi/atari_NCR5380.c index 06245c07ebd2..08e8ace2681b 100644 --- a/drivers/scsi/atari_NCR5380.c +++ b/drivers/scsi/atari_NCR5380.c @@ -1420,15 +1420,6 @@ static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd) NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_SEL | ICR_ASSERT_BSY); - if ((NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_LOST) || - hostdata->connected) { - NCR5380_write(MODE_REG, MR_BASE); - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - dprintk(NDEBUG_ARBITRATION, "scsi%d: lost arbitration, deasserting ICR_ASSERT_SEL\n", - HOSTNO); - return -1; - } - /* * Again, bus clear + bus settle time is 1.2us, however, this is * a minimum so we'll udelay ceil(1.2) diff --git a/drivers/scsi/dmx3191d.c b/drivers/scsi/dmx3191d.c index 7f66c9e76c3b..51e63fe957c5 100644 --- a/drivers/scsi/dmx3191d.c +++ b/drivers/scsi/dmx3191d.c @@ -91,7 +91,7 @@ static int dmx3191d_probe_one(struct pci_dev *pdev, */ shost->irq = NO_IRQ; - error = NCR5380_init(shost, FLAG_NO_PSEUDO_DMA | FLAG_DTC3181E); + error = NCR5380_init(shost, FLAG_NO_PSEUDO_DMA); if (error) goto out_host_put; diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c index ea9d0de2fc85..0e59df6b4f5f 100644 --- a/drivers/scsi/g_NCR5380.c +++ b/drivers/scsi/g_NCR5380.c @@ -326,7 +326,7 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt) ports = ncr_53c400a_ports; break; case BOARD_DTC3181E: - flags = FLAG_NO_PSEUDO_DMA | FLAG_DTC3181E; + flags = FLAG_NO_PSEUDO_DMA; ports = dtc_3181e_ports; break; } -- cgit From 11d2f63b9cf5665ce9dc425236b326dd327c4aa3 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sun, 3 Jan 2016 16:05:51 +1100 Subject: ncr5380: Change instance->host_lock to hostdata->lock NCR5380.c presently uses the instance->host_lock spin lock. Convert this to a new spin lock that protects the NCR5380_hostdata struct. atari_NCR5380.c previously used local_irq_save/restore() rather than a spin lock. Convert this to hostdata->lock in irq mode. For SMP platforms, the interrupt handler now also acquires the spin lock. This brings all locking in the two core drivers into agreement. Adding this locking also means that a bunch of volatile qualifiers can be removed from the members of the NCR5380_hostdata struct. This is done in a subsequent patch. Proper locking will allow the abort handler to locate a command being aborted. This is presently impossible if the abort handler is invoked when the command has been moved from a queue to a pointer on the stack. (If eh_abort_handler can't determine whether a command has been completed or is still being processed then it can't decide whether to return success or failure.) The hostdata spin lock is now held when calling NCR5380_select() and NCR5380_information_transfer(). Where possible, the lock is dropped for polling and PIO transfers. Clean up the now-redundant SELECT_ENABLE_REG writes, that used to provide limited mutual exclusion between information_transfer() and reselect(). Accessing hostdata->connected without data races means taking the lock; cleanup these accesses. The new spin lock falls away for m68k and other UP builds, so this should have little impact there. In the SMP case the new lock should be uncontested even when the SCSI bus is contested. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Ondrej Zary Tested-by: Michael Schmitz Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.c | 82 ++++++++++++++++---------- drivers/scsi/NCR5380.h | 1 + drivers/scsi/atari_NCR5380.c | 135 ++++++++++++++++++------------------------- 3 files changed, 109 insertions(+), 109 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index a4defd1977c9..5209f346ae80 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -612,6 +612,7 @@ static int __maybe_unused NCR5380_show_info(struct seq_file *m, { struct NCR5380_hostdata *hostdata; struct scsi_cmnd *ptr; + unsigned long flags; hostdata = (struct NCR5380_hostdata *) instance->hostdata; @@ -619,7 +620,7 @@ static int __maybe_unused NCR5380_show_info(struct seq_file *m, seq_printf(m, "Highwater I/O busy spin counts: write %d, read %d\n", hostdata->spin_max_w, hostdata->spin_max_r); #endif - spin_lock_irq(instance->host_lock); + spin_lock_irqsave(&hostdata->lock, flags); if (!hostdata->connected) seq_printf(m, "scsi%d: no currently connected command\n", instance->host_no); else @@ -631,7 +632,7 @@ static int __maybe_unused NCR5380_show_info(struct seq_file *m, seq_printf(m, "scsi%d: disconnected_queue\n", instance->host_no); for (ptr = (struct scsi_cmnd *) hostdata->disconnected_queue; ptr; ptr = (struct scsi_cmnd *) ptr->host_scribble) lprint_Scsi_Cmnd(ptr, m); - spin_unlock_irq(instance->host_lock); + spin_unlock_irqrestore(&hostdata->lock, flags); return 0; } @@ -691,6 +692,7 @@ static int NCR5380_init(struct Scsi_Host *instance, int flags) #ifdef REAL_DMA hostdata->dmalen = 0; #endif + spin_lock_init(&hostdata->lock); hostdata->connected = NULL; hostdata->issue_queue = NULL; hostdata->disconnected_queue = NULL; @@ -830,7 +832,7 @@ static int NCR5380_queue_command(struct Scsi_Host *instance, cmd->host_scribble = NULL; cmd->result = 0; - spin_lock_irqsave(instance->host_lock, flags); + spin_lock_irqsave(&hostdata->lock, flags); /* * Insert the cmd into the issue queue. Note that REQUEST SENSE @@ -848,7 +850,7 @@ static int NCR5380_queue_command(struct Scsi_Host *instance, LIST(cmd, tmp); tmp->host_scribble = (unsigned char *) cmd; } - spin_unlock_irqrestore(instance->host_lock, flags); + spin_unlock_irqrestore(&hostdata->lock, flags); dprintk(NDEBUG_QUEUES, "scsi%d : command added to %s of queue\n", instance->host_no, (cmd->cmnd[0] == REQUEST_SENSE) ? "head" : "tail"); @@ -877,10 +879,10 @@ static void NCR5380_main(struct work_struct *work) struct scsi_cmnd *tmp, *prev; int done; - spin_lock_irq(instance->host_lock); + spin_lock_irq(&hostdata->lock); do { - /* Lock held here */ done = 1; + if (!hostdata->connected) { dprintk(NDEBUG_MAIN, "scsi%d : not connected\n", instance->host_no); /* @@ -930,11 +932,10 @@ static void NCR5380_main(struct work_struct *work) } if (hostdata->connected) break; - /* lock held here still */ } /* if target/lun is not busy */ } /* for */ - /* exited locked */ } /* if (!hostdata->connected) */ + if (hostdata->connected #ifdef REAL_DMA && !hostdata->dmalen @@ -946,8 +947,7 @@ static void NCR5380_main(struct work_struct *work) done = 0; } } while (!done); - - spin_unlock_irq(instance->host_lock); + spin_unlock_irq(&hostdata->lock); } #ifndef DONT_USE_INTR @@ -994,7 +994,7 @@ static irqreturn_t NCR5380_intr(int irq, void *dev_id) unsigned char basr; unsigned long flags; - spin_lock_irqsave(instance->host_lock, flags); + spin_lock_irqsave(&hostdata->lock, flags); basr = NCR5380_read(BUS_AND_STATUS_REG); if (basr & BASR_IRQ) { @@ -1058,7 +1058,7 @@ static irqreturn_t NCR5380_intr(int irq, void *dev_id) shost_printk(KERN_NOTICE, instance, "interrupt without IRQ bit\n"); } - spin_unlock_irqrestore(instance->host_lock, flags); + spin_unlock_irqrestore(&hostdata->lock, flags); return IRQ_RETVAL(handled); } @@ -1125,11 +1125,11 @@ static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd) * Bus Free Delay, arbitration will begin. */ - spin_unlock_irq(instance->host_lock); + spin_unlock_irq(&hostdata->lock); err = NCR5380_poll_politely2(instance, MODE_REG, MR_ARBITRATE, 0, INITIATOR_COMMAND_REG, ICR_ARBITRATION_PROGRESS, ICR_ARBITRATION_PROGRESS, HZ); - spin_lock_irq(instance->host_lock); + spin_lock_irq(&hostdata->lock); if (!(NCR5380_read(MODE_REG) & MR_ARBITRATE)) { /* Reselection interrupt */ return -1; @@ -1140,6 +1140,7 @@ static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd) "select: arbitration timeout\n"); return -1; } + spin_unlock_irq(&hostdata->lock); /* The SCSI-2 arbitration delay is 2.4 us */ udelay(3); @@ -1148,6 +1149,7 @@ static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd) if ((NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_LOST) || (NCR5380_read(CURRENT_SCSI_DATA_REG) & hostdata->id_higher_mask) || (NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_LOST)) { NCR5380_write(MODE_REG, MR_BASE); dprintk(NDEBUG_ARBITRATION, "scsi%d : lost arbitration, deasserting MR_ARBITRATE\n", instance->host_no); + spin_lock_irq(&hostdata->lock); return -1; } @@ -1168,6 +1170,8 @@ static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd) else udelay(2); + spin_lock_irq(&hostdata->lock); + /* NCR5380_reselect() clears MODE_REG after a reselection interrupt */ if (!(NCR5380_read(MODE_REG) & MR_ARBITRATE)) return -1; @@ -1196,6 +1200,8 @@ static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd) */ NCR5380_write(SELECT_ENABLE_REG, 0); + spin_unlock_irq(&hostdata->lock); + /* * The initiator shall then wait at least two deskew delays and release * the BSY signal. @@ -1235,6 +1241,7 @@ static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd) msecs_to_jiffies(250)); if ((NCR5380_read(STATUS_REG) & (SR_SEL | SR_IO)) == (SR_SEL | SR_IO)) { + spin_lock_irq(&hostdata->lock); NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); NCR5380_reselect(instance); if (!hostdata->connected) @@ -1244,6 +1251,7 @@ static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd) } if (err < 0) { + spin_lock_irq(&hostdata->lock); NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); cmd->result = DID_BAD_TARGET << 16; cmd->scsi_done(cmd); @@ -1280,9 +1288,8 @@ static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd) /* Wait for start of REQ/ACK handshake */ - spin_unlock_irq(instance->host_lock); err = NCR5380_poll_politely(instance, STATUS_REG, SR_REQ, SR_REQ, HZ); - spin_lock_irq(instance->host_lock); + spin_lock_irq(&hostdata->lock); if (err < 0) { shost_printk(KERN_ERR, instance, "select: REQ timeout\n"); NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); @@ -1302,6 +1309,7 @@ static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd) NCR5380_transfer_pio(instance, &phase, &len, &data); dprintk(NDEBUG_SELECTION, "scsi%d : nexus established.\n", instance->host_no); /* XXX need to handle errors here */ + hostdata->connected = cmd; hostdata->busy[cmd->device->id] |= (1 << (cmd->device->lun & 0xFF)); @@ -1805,9 +1813,9 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { #endif unsigned char *data; unsigned char phase, tmp, extended_msg[10], old_phase = 0xff; - struct scsi_cmnd *cmd = (struct scsi_cmnd *) hostdata->connected; + struct scsi_cmnd *cmd; - while (1) { + while ((cmd = hostdata->connected)) { tmp = NCR5380_read(STATUS_REG); /* We only have a valid SCSI phase when REQ is asserted */ if (tmp & SR_REQ) { @@ -1883,8 +1891,12 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { cmd->SCp.this_residual -= transfersize - len; } else #endif /* defined(PSEUDO_DMA) || defined(REAL_DMA_POLL) */ + { + spin_unlock_irq(&hostdata->lock); NCR5380_transfer_pio(instance, &phase, (int *) &cmd->SCp.this_residual, (unsigned char **) &cmd->SCp.ptr); + spin_lock_irq(&hostdata->lock); + } break; case PHASE_MSGIN: len = 1; @@ -2016,6 +2028,9 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { extended_msg[0] = EXTENDED_MESSAGE; /* Accept first byte by clearing ACK */ NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); + + spin_unlock_irq(&hostdata->lock); + dprintk(NDEBUG_EXTENDED, "scsi%d : receiving extended message\n", instance->host_no); len = 2; @@ -2050,6 +2065,11 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { printk("scsi%d: extended message code %02x length %d is too long\n", instance->host_no, extended_msg[2], extended_msg[1]); tmp = 0; } + + spin_lock_irq(&hostdata->lock); + if (!hostdata->connected) + return; + /* Fall through to reject message */ /* @@ -2109,11 +2129,11 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { NCR5380_dprint(NDEBUG_ANY, instance); } /* switch(phase) */ } else { - spin_unlock_irq(instance->host_lock); + spin_unlock_irq(&hostdata->lock); NCR5380_poll_politely(instance, STATUS_REG, SR_REQ, SR_REQ, HZ); - spin_lock_irq(instance->host_lock); + spin_lock_irq(&hostdata->lock); } - } /* while (1) */ + } } /* @@ -2309,10 +2329,12 @@ static int NCR5380_abort(struct scsi_cmnd *cmd) struct Scsi_Host *instance = cmd->device->host; struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) instance->hostdata; struct scsi_cmnd *tmp, **prev; + unsigned long flags; scmd_printk(KERN_WARNING, cmd, "aborting command\n"); - spin_lock_irq(instance->host_lock); + spin_lock_irqsave(&hostdata->lock, flags); + NCR5380_print_status(instance); dprintk(NDEBUG_ABORT, "scsi%d : abort called\n", instance->host_no); @@ -2359,7 +2381,7 @@ static int NCR5380_abort(struct scsi_cmnd *cmd) REMOVE(5, *prev, tmp, tmp->host_scribble); (*prev) = (struct scsi_cmnd *) tmp->host_scribble; tmp->host_scribble = NULL; - spin_unlock_irq(instance->host_lock); + spin_unlock_irqrestore(&hostdata->lock, flags); tmp->result = DID_ABORT << 16; dprintk(NDEBUG_ABORT, "scsi%d : abort removed command from issue queue.\n", instance->host_no); tmp->scsi_done(tmp); @@ -2383,7 +2405,7 @@ static int NCR5380_abort(struct scsi_cmnd *cmd) */ if (hostdata->connected) { - spin_unlock_irq(instance->host_lock); + spin_unlock_irqrestore(&hostdata->lock, flags); dprintk(NDEBUG_ABORT, "scsi%d : abort failed, command connected.\n", instance->host_no); return FAILED; } @@ -2417,7 +2439,7 @@ static int NCR5380_abort(struct scsi_cmnd *cmd) dprintk(NDEBUG_ABORT, "scsi%d : aborting disconnected command.\n", instance->host_no); if (NCR5380_select(instance, cmd)) { - spin_unlock_irq(instance->host_lock); + spin_unlock_irq(&hostdata->lock); return FAILED; } dprintk(NDEBUG_ABORT, "scsi%d : nexus reestablished.\n", instance->host_no); @@ -2429,7 +2451,7 @@ static int NCR5380_abort(struct scsi_cmnd *cmd) REMOVE(5, *prev, tmp, tmp->host_scribble); *prev = (struct scsi_cmnd *) tmp->host_scribble; tmp->host_scribble = NULL; - spin_unlock_irq(instance->host_lock); + spin_unlock_irqrestore(&hostdata->lock, flags); tmp->result = DID_ABORT << 16; tmp->scsi_done(tmp); return SUCCESS; @@ -2444,7 +2466,7 @@ static int NCR5380_abort(struct scsi_cmnd *cmd) * so we won't panic, but we will notify the user in case something really * broke. */ - spin_unlock_irq(instance->host_lock); + spin_unlock_irqrestore(&hostdata->lock, flags); printk(KERN_WARNING "scsi%d : warning : SCSI command probably completed successfully\n" " before abortion\n", instance->host_no); return FAILED; @@ -2461,8 +2483,10 @@ static int NCR5380_abort(struct scsi_cmnd *cmd) static int NCR5380_bus_reset(struct scsi_cmnd *cmd) { struct Scsi_Host *instance = cmd->device->host; + struct NCR5380_hostdata *hostdata = shost_priv(instance); + unsigned long flags; - spin_lock_irq(instance->host_lock); + spin_lock_irqsave(&hostdata->lock, flags); #if (NDEBUG & NDEBUG_ANY) scmd_printk(KERN_INFO, cmd, "performing bus reset\n"); @@ -2471,7 +2495,7 @@ static int NCR5380_bus_reset(struct scsi_cmnd *cmd) do_reset(instance); - spin_unlock_irq(instance->host_lock); + spin_unlock_irqrestore(&hostdata->lock, flags); return SUCCESS; } diff --git a/drivers/scsi/NCR5380.h b/drivers/scsi/NCR5380.h index 96fced9e6064..aab360810c43 100644 --- a/drivers/scsi/NCR5380.h +++ b/drivers/scsi/NCR5380.h @@ -256,6 +256,7 @@ struct NCR5380_hostdata { volatile struct scsi_cmnd *connected; /* currently connected command */ volatile struct scsi_cmnd *issue_queue; /* waiting to be issued */ volatile struct scsi_cmnd *disconnected_queue; /* waiting for reconnect */ + spinlock_t lock; /* protects this struct */ int flags; struct scsi_eh_save ses; char info[256]; diff --git a/drivers/scsi/atari_NCR5380.c b/drivers/scsi/atari_NCR5380.c index 08e8ace2681b..2dd65cdb0930 100644 --- a/drivers/scsi/atari_NCR5380.c +++ b/drivers/scsi/atari_NCR5380.c @@ -546,15 +546,13 @@ static struct { static void NCR5380_print(struct Scsi_Host *instance) { unsigned char status, data, basr, mr, icr, i; - unsigned long flags; - local_irq_save(flags); data = NCR5380_read(CURRENT_SCSI_DATA_REG); status = NCR5380_read(STATUS_REG); mr = NCR5380_read(MODE_REG); icr = NCR5380_read(INITIATOR_COMMAND_REG); basr = NCR5380_read(BUS_AND_STATUS_REG); - local_irq_restore(flags); + printk("STATUS_REG: %02x ", status); for (i = 0; signals[i].mask; ++i) if (status & signals[i].mask) @@ -684,14 +682,12 @@ static void __maybe_unused NCR5380_print_status(struct Scsi_Host *instance) { struct NCR5380_hostdata *hostdata; struct scsi_cmnd *ptr; - unsigned long flags; NCR5380_dprint(NDEBUG_ANY, instance); NCR5380_dprint_phase(NDEBUG_ANY, instance); hostdata = (struct NCR5380_hostdata *)instance->hostdata; - local_irq_save(flags); if (!hostdata->connected) printk("scsi%d: no currently connected command\n", HOSTNO); else @@ -704,8 +700,6 @@ static void __maybe_unused NCR5380_print_status(struct Scsi_Host *instance) for (ptr = (struct scsi_cmnd *) hostdata->disconnected_queue; ptr; ptr = NEXT(ptr)) lprint_Scsi_Cmnd(ptr); - - local_irq_restore(flags); printk("\n"); } @@ -732,7 +726,7 @@ static int __maybe_unused NCR5380_show_info(struct seq_file *m, hostdata = (struct NCR5380_hostdata *)instance->hostdata; - local_irq_save(flags); + spin_lock_irqsave(&hostdata->lock, flags); if (!hostdata->connected) seq_printf(m, "scsi%d: no currently connected command\n", HOSTNO); else @@ -746,7 +740,7 @@ static int __maybe_unused NCR5380_show_info(struct seq_file *m, ptr = NEXT(ptr)) show_Scsi_Cmnd(ptr, m); - local_irq_restore(flags); + spin_unlock_irqrestore(&hostdata->lock, flags); return 0; } @@ -784,6 +778,7 @@ static int __init NCR5380_init(struct Scsi_Host *instance, int flags) #if defined (REAL_DMA) hostdata->dma_len = 0; #endif + spin_lock_init(&hostdata->lock); hostdata->connected = NULL; hostdata->issue_queue = NULL; hostdata->disconnected_queue = NULL; @@ -946,7 +941,7 @@ static int NCR5380_queue_command(struct Scsi_Host *instance, if (!NCR5380_acquire_dma_irq(instance)) return SCSI_MLQUEUE_HOST_BUSY; - local_irq_save(flags); + spin_lock_irqsave(&hostdata->lock, flags); /* * Insert the cmd into the issue queue. Note that REQUEST SENSE @@ -966,7 +961,7 @@ static int NCR5380_queue_command(struct Scsi_Host *instance, LIST(cmd, tmp); SET_NEXT(tmp, cmd); } - local_irq_restore(flags); + spin_unlock_irqrestore(&hostdata->lock, flags); dprintk(NDEBUG_QUEUES, "scsi%d: command added to %s of queue\n", H_NO(cmd), (cmd->cmnd[0] == REQUEST_SENSE) ? "head" : "tail"); @@ -1006,7 +1001,6 @@ static void NCR5380_main(struct work_struct *work) struct Scsi_Host *instance = hostdata->host; struct scsi_cmnd *tmp, *prev; int done; - unsigned long flags; /* * ++roman: Just disabling the NCR interrupt isn't sufficient here, @@ -1014,9 +1008,8 @@ static void NCR5380_main(struct work_struct *work) * alter queues and touch the Falcon lock. */ - local_save_flags(flags); + spin_lock_irq(&hostdata->lock); do { - local_irq_disable(); /* Freeze request queues */ done = 1; if (!hostdata->connected) { @@ -1043,7 +1036,6 @@ static void NCR5380_main(struct work_struct *work) tmp, scmd_id(tmp), hostdata->busy[scmd_id(tmp)], lun); /* When we find one, remove it from the issue queue. */ - /* ++guenther: possible race with Falcon locking */ if ( #ifdef SUPPORT_TAGS !is_lun_busy( tmp, tmp->cmnd[0] != REQUEST_SENSE) @@ -1051,8 +1043,6 @@ static void NCR5380_main(struct work_struct *work) !(hostdata->busy[tmp->device->id] & (1 << lun)) #endif ) { - /* ++guenther: just to be sure, this must be atomic */ - local_irq_disable(); if (prev) { REMOVE(prev, NEXT(prev), tmp, NEXT(tmp)); SET_NEXT(prev, NEXT(tmp)); @@ -1063,9 +1053,6 @@ static void NCR5380_main(struct work_struct *work) SET_NEXT(tmp, NULL); hostdata->retain_dma_intr++; - /* reenable interrupts after finding one */ - local_irq_restore(flags); - /* * Attempt to establish an I_T_L nexus here. * On success, instance->hostdata->connected is set. @@ -1090,13 +1077,10 @@ static void NCR5380_main(struct work_struct *work) #endif if (!NCR5380_select(instance, tmp)) { /* OK or bad target */ - local_irq_disable(); hostdata->retain_dma_intr--; maybe_release_dma_irq(instance); - local_irq_restore(flags); } else { /* Need to retry */ - local_irq_disable(); LIST(tmp, hostdata->issue_queue); SET_NEXT(tmp, hostdata->issue_queue); hostdata->issue_queue = tmp; @@ -1104,7 +1088,6 @@ static void NCR5380_main(struct work_struct *work) cmd_free_tag(tmp); #endif hostdata->retain_dma_intr--; - local_irq_restore(flags); done = 0; dprintk(NDEBUG_MAIN, "scsi%d: main(): select() failed, " "returned to issue_queue\n", HOSTNO); @@ -1120,7 +1103,6 @@ static void NCR5380_main(struct work_struct *work) && !hostdata->dma_len #endif ) { - local_irq_restore(flags); dprintk(NDEBUG_MAIN, "scsi%d: main: performing information transfer\n", HOSTNO); NCR5380_information_transfer(instance); @@ -1128,7 +1110,7 @@ static void NCR5380_main(struct work_struct *work) done = 0; } } while (!done); - local_irq_restore(flags); + spin_unlock_irq(&hostdata->lock); } @@ -1257,6 +1239,9 @@ static irqreturn_t NCR5380_intr(int irq, void *dev_id) struct NCR5380_hostdata *hostdata = shost_priv(instance); int handled = 0; unsigned char basr; + unsigned long flags; + + spin_lock_irqsave(&hostdata->lock, flags); basr = NCR5380_read(BUS_AND_STATUS_REG); if (basr & BASR_IRQ) { @@ -1316,6 +1301,8 @@ static irqreturn_t NCR5380_intr(int irq, void *dev_id) #endif } + spin_unlock_irqrestore(&hostdata->lock, flags); + return IRQ_RETVAL(handled); } @@ -1355,7 +1342,6 @@ static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd) unsigned char *data; int len; int err; - unsigned long flags; NCR5380_dprint(NDEBUG_ARBITRATION, instance); dprintk(NDEBUG_ARBITRATION, "scsi%d: starting arbitration, id = %d\n", HOSTNO, @@ -1366,11 +1352,6 @@ static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd) * data bus during SELECTION. */ - local_irq_save(flags); - if (hostdata->connected) { - local_irq_restore(flags); - return -1; - } NCR5380_write(TARGET_COMMAND_REG, 0); /* @@ -1384,10 +1365,11 @@ static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd) * Bus Free Delay, arbitration will begin. */ - local_irq_restore(flags); + spin_unlock_irq(&hostdata->lock); err = NCR5380_poll_politely2(instance, MODE_REG, MR_ARBITRATE, 0, INITIATOR_COMMAND_REG, ICR_ARBITRATION_PROGRESS, ICR_ARBITRATION_PROGRESS, HZ); + spin_lock_irq(&hostdata->lock); if (!(NCR5380_read(MODE_REG) & MR_ARBITRATE)) { /* Reselection interrupt */ return -1; @@ -1398,6 +1380,7 @@ static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd) "select: arbitration timeout\n"); return -1; } + spin_unlock_irq(&hostdata->lock); /* The SCSI-2 arbitration delay is 2.4 us */ udelay(3); @@ -1405,11 +1388,11 @@ static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd) /* Check for lost arbitration */ if ((NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_LOST) || (NCR5380_read(CURRENT_SCSI_DATA_REG) & hostdata->id_higher_mask) || - (NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_LOST) || - hostdata->connected) { + (NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_LOST)) { NCR5380_write(MODE_REG, MR_BASE); dprintk(NDEBUG_ARBITRATION, "scsi%d: lost arbitration, deasserting MR_ARBITRATE\n", HOSTNO); + spin_lock_irq(&hostdata->lock); return -1; } @@ -1430,6 +1413,8 @@ static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd) else udelay(2); + spin_lock_irq(&hostdata->lock); + /* NCR5380_reselect() clears MODE_REG after a reselection interrupt */ if (!(NCR5380_read(MODE_REG) & MR_ARBITRATE)) return -1; @@ -1457,14 +1442,10 @@ static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd) * Reselect interrupts must be turned off prior to the dropping of BSY, * otherwise we will trigger an interrupt. */ - - if (hostdata->connected) { - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - return -1; - } - NCR5380_write(SELECT_ENABLE_REG, 0); + spin_unlock_irq(&hostdata->lock); + /* * The initiator shall then wait at least two deskew delays and release * the BSY signal. @@ -1505,6 +1486,7 @@ static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd) msecs_to_jiffies(250)); if ((NCR5380_read(STATUS_REG) & (SR_SEL | SR_IO)) == (SR_SEL | SR_IO)) { + spin_lock_irq(&hostdata->lock); NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); NCR5380_reselect(instance); if (!hostdata->connected) @@ -1515,6 +1497,7 @@ static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd) } if (err < 0) { + spin_lock_irq(&hostdata->lock); NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); cmd->result = DID_BAD_TARGET << 16; #ifdef SUPPORT_TAGS @@ -1554,6 +1537,7 @@ static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd) /* Wait for start of REQ/ACK handshake */ err = NCR5380_poll_politely(instance, STATUS_REG, SR_REQ, SR_REQ, HZ); + spin_lock_irq(&hostdata->lock); if (err < 0) { shost_printk(KERN_ERR, instance, "select: REQ timeout\n"); NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); @@ -1583,6 +1567,7 @@ static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd) NCR5380_transfer_pio(instance, &phase, &len, &data); dprintk(NDEBUG_SELECTION, "scsi%d: nexus established.\n", HOSTNO); /* XXX need to handle errors here */ + hostdata->connected = cmd; #ifndef SUPPORT_TAGS hostdata->busy[cmd->device->id] |= (1 << cmd->device->lun); @@ -1849,7 +1834,6 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, SETUP_HOSTDATA(instance); register int c = *count; register unsigned char p = *phase; - unsigned long flags; #if defined(CONFIG_SUN3) /* sanity check */ @@ -1865,7 +1849,6 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, c, (p & SR_IO) ? "to" : "from", *data); /* netbsd turns off ints here, why not be safe and do it too */ - local_irq_save(flags); /* send start chain */ sun3scsi_dma_start(c, *data); @@ -1885,8 +1868,6 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, dregs->csr |= CSR_DMA_ENABLE; #endif - local_irq_restore(flags); - sun3_dma_active = 1; #else /* !defined(CONFIG_SUN3) */ @@ -1913,11 +1894,9 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, /* On the Medusa, it is a must to initialize the DMA before * starting the NCR. This is also the cleaner way for the TT. */ - local_irq_save(flags); hostdata->dma_len = (p & SR_IO) ? NCR5380_dma_read_setup(instance, d, c) : NCR5380_dma_write_setup(instance, d, c); - local_irq_restore(flags); } if (p & SR_IO) @@ -1931,11 +1910,9 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, /* On the Falcon, the DMA setup must be done after the last */ /* NCR access, else the DMA setup gets trashed! */ - local_irq_save(flags); hostdata->dma_len = (p & SR_IO) ? NCR5380_dma_read_setup(instance, d, c) : NCR5380_dma_write_setup(instance, d, c); - local_irq_restore(flags); } #endif /* !defined(CONFIG_SUN3) */ @@ -1963,7 +1940,6 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, static void NCR5380_information_transfer(struct Scsi_Host *instance) { SETUP_HOSTDATA(instance); - unsigned long flags; unsigned char msgout = NOP; int sink = 0; int len; @@ -1972,13 +1948,13 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) #endif unsigned char *data; unsigned char phase, tmp, extended_msg[10], old_phase = 0xff; - struct scsi_cmnd *cmd = (struct scsi_cmnd *) hostdata->connected; + struct scsi_cmnd *cmd; #ifdef SUN3_SCSI_VME dregs->csr |= CSR_INTR; #endif - while (1) { + while ((cmd = hostdata->connected)) { tmp = NCR5380_read(STATUS_REG); /* We only have a valid SCSI phase when REQ is asserted */ if (tmp & SR_REQ) { @@ -2112,9 +2088,13 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) } } else #endif /* defined(REAL_DMA) */ + { + spin_unlock_irq(&hostdata->lock); NCR5380_transfer_pio(instance, &phase, (int *)&cmd->SCp.this_residual, (unsigned char **)&cmd->SCp.ptr); + spin_lock_irq(&hostdata->lock); + } #if defined(CONFIG_SUN3) && defined(REAL_DMA) /* if we had intended to dma that command clear it */ if (sun3_dma_setup_done == cmd) @@ -2124,7 +2104,6 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) case PHASE_MSGIN: len = 1; data = &tmp; - NCR5380_write(SELECT_ENABLE_REG, 0); /* disable reselects */ NCR5380_transfer_pio(instance, &phase, &len, &data); cmd->SCp.Message = tmp; @@ -2136,7 +2115,6 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) dprintk(NDEBUG_QUEUES, "scsi%d: command for target %d, lun %llu " "completed\n", HOSTNO, cmd->device->id, cmd->device->lun); - local_irq_save(flags); hostdata->connected = NULL; #ifdef SUPPORT_TAGS cmd_free_tag(cmd); @@ -2152,8 +2130,6 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) #else hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun); #endif - /* Enable reselect interrupts */ - NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); /* * I'm not sure what the correct thing to do here is : @@ -2211,13 +2187,10 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) * disconnected queue. */ maybe_release_dma_irq(instance); - local_irq_restore(flags); return; case MESSAGE_REJECT: /* Accept message by clearing ACK */ NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - /* Enable reselect interrupts */ - NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); switch (hostdata->last_message) { case HEAD_OF_QUEUE_TAG: case ORDERED_QUEUE_TAG: @@ -2241,12 +2214,10 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) case DISCONNECT: /* Accept message by clearing ACK */ NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - local_irq_save(flags); LIST(cmd,hostdata->disconnected_queue); SET_NEXT(cmd, hostdata->disconnected_queue); hostdata->connected = NULL; hostdata->disconnected_queue = cmd; - local_irq_restore(flags); dprintk(NDEBUG_QUEUES, "scsi%d: command for target %d lun %llu was " "moved from connected to the " "disconnected_queue\n", HOSTNO, @@ -2277,8 +2248,6 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) case RESTORE_POINTERS: /* Accept message by clearing ACK */ NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - /* Enable reselect interrupts */ - NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); break; case EXTENDED_MESSAGE: /* @@ -2297,6 +2266,8 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) /* Accept first byte by clearing ACK */ NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); + spin_unlock_irq(&hostdata->lock); + dprintk(NDEBUG_EXTENDED, "scsi%d: receiving extended message\n", HOSTNO); len = 2; @@ -2335,6 +2306,11 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) HOSTNO, extended_msg[2], extended_msg[1]); tmp = 0; } + + spin_lock_irq(&hostdata->lock); + if (!hostdata->connected) + return; + /* Fall through to reject message */ /* @@ -2367,7 +2343,6 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) hostdata->last_message = msgout; NCR5380_transfer_pio(instance, &phase, &len, &data); if (msgout == ABORT) { - local_irq_save(flags); #ifdef SUPPORT_TAGS cmd_free_tag(cmd); #else @@ -2376,7 +2351,6 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) hostdata->connected = NULL; cmd->result = DID_ERROR << 16; maybe_release_dma_irq(instance); - local_irq_restore(flags); cmd->scsi_done(cmd); NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); return; @@ -2404,9 +2378,11 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) NCR5380_dprint(NDEBUG_ANY, instance); } /* switch(phase) */ } else { + spin_unlock_irq(&hostdata->lock); NCR5380_poll_politely(instance, STATUS_REG, SR_REQ, SR_REQ, HZ); + spin_lock_irq(&hostdata->lock); } - } /* while (1) */ + } } /* @@ -2639,9 +2615,9 @@ int NCR5380_abort(struct scsi_cmnd *cmd) scmd_printk(KERN_NOTICE, cmd, "aborting command\n"); - NCR5380_print_status(instance); + spin_lock_irqsave(&hostdata->lock, flags); - local_irq_save(flags); + NCR5380_print_status(instance); dprintk(NDEBUG_ABORT, "scsi%d: abort called basr 0x%02x, sr 0x%02x\n", HOSTNO, NCR5380_read(BUS_AND_STATUS_REG), @@ -2683,11 +2659,11 @@ int NCR5380_abort(struct scsi_cmnd *cmd) hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun); #endif maybe_release_dma_irq(instance); - local_irq_restore(flags); + spin_unlock_irqrestore(&hostdata->lock, flags); cmd->scsi_done(cmd); return SUCCESS; } else { - local_irq_restore(flags); + spin_unlock_irqrestore(&hostdata->lock, flags); printk("scsi%d: abort of connected command failed!\n", HOSTNO); return FAILED; } @@ -2707,7 +2683,7 @@ int NCR5380_abort(struct scsi_cmnd *cmd) SET_NEXT(tmp, NULL); tmp->result = DID_ABORT << 16; maybe_release_dma_irq(instance); - local_irq_restore(flags); + spin_unlock_irqrestore(&hostdata->lock, flags); dprintk(NDEBUG_ABORT, "scsi%d: abort removed command from issue queue.\n", HOSTNO); /* Tagged queuing note: no tag to free here, hasn't been assigned @@ -2729,7 +2705,7 @@ int NCR5380_abort(struct scsi_cmnd *cmd) */ if (hostdata->connected) { - local_irq_restore(flags); + spin_unlock_irqrestore(&hostdata->lock, flags); dprintk(NDEBUG_ABORT, "scsi%d: abort failed, command connected.\n", HOSTNO); return FAILED; } @@ -2762,17 +2738,16 @@ int NCR5380_abort(struct scsi_cmnd *cmd) for (tmp = (struct scsi_cmnd *) hostdata->disconnected_queue; tmp; tmp = NEXT(tmp)) { if (cmd == tmp) { - local_irq_restore(flags); dprintk(NDEBUG_ABORT, "scsi%d: aborting disconnected command.\n", HOSTNO); - if (NCR5380_select(instance, cmd)) + if (NCR5380_select(instance, cmd)) { + spin_unlock_irq(&hostdata->lock); return FAILED; - + } dprintk(NDEBUG_ABORT, "scsi%d: nexus reestablished.\n", HOSTNO); do_abort(instance); - local_irq_save(flags); for (prev = (struct scsi_cmnd **)&(hostdata->disconnected_queue), tmp = (struct scsi_cmnd *)hostdata->disconnected_queue; tmp; prev = NEXTADDR(tmp), tmp = NEXT(tmp)) { @@ -2791,7 +2766,7 @@ int NCR5380_abort(struct scsi_cmnd *cmd) hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun); #endif maybe_release_dma_irq(instance); - local_irq_restore(flags); + spin_unlock_irqrestore(&hostdata->lock, flags); tmp->scsi_done(tmp); return SUCCESS; } @@ -2804,7 +2779,7 @@ int NCR5380_abort(struct scsi_cmnd *cmd) * released after the abort, in case it is kept due to some bug. */ maybe_release_dma_irq(instance); - local_irq_restore(flags); + spin_unlock_irqrestore(&hostdata->lock, flags); /* * Case 5 : If we reached this point, the command was not found in any of @@ -2836,7 +2811,7 @@ static int NCR5380_bus_reset(struct scsi_cmnd *cmd) int i; unsigned long flags; - local_irq_save(flags); + spin_lock_irqsave(&hostdata->lock, flags); #if (NDEBUG & NDEBUG_ANY) scmd_printk(KERN_INFO, cmd, "performing bus reset\n"); @@ -2876,7 +2851,7 @@ static int NCR5380_bus_reset(struct scsi_cmnd *cmd) #endif maybe_release_dma_irq(instance); - local_irq_restore(flags); + spin_unlock_irqrestore(&hostdata->lock, flags); return SUCCESS; } -- cgit From e5c3fddfaa066e440315e713ddf8b60e9ac48cf7 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sun, 3 Jan 2016 16:05:52 +1100 Subject: ncr5380: Remove command list debug code Some NCR5380 hosts offer a .show_info method to access the contents of the various command list data structures from a procfs file. When NDEBUG is set, the same information is sent to the console during EH. The two core drivers, atari_NCR5380.c and NCR5380.c differ here. Because it is just for debugging, the easiest way to fix the discrepancy is simply remove this code. The only remaining users of NCR5380_show_info() and NCR5380_write_info() are drivers that define PSEUDO_DMA. The others have no use for the .show_info method, so don't initialize it. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Ondrej Zary Tested-by: Michael Schmitz Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.c | 70 +++------------------------------ drivers/scsi/arm/oak.c | 2 - drivers/scsi/atari_NCR5380.c | 94 ++------------------------------------------ drivers/scsi/atari_scsi.c | 2 - drivers/scsi/g_NCR5380.c | 1 - drivers/scsi/sun3_scsi.c | 2 - 6 files changed, 9 insertions(+), 162 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index 5209f346ae80..2ac01d86d330 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -558,22 +558,6 @@ static void prepare_info(struct Scsi_Host *instance) ""); } -/** - * NCR5380_print_status - dump controller info - * @instance: controller to dump - * - * Print commands in the various queues, called from NCR5380_abort - * and NCR5380_debug to aid debugging. - * - * Locks: called functions disable irqs - */ - -static void __maybe_unused NCR5380_print_status(struct Scsi_Host *instance) -{ - NCR5380_dprint(NDEBUG_ANY, instance); - NCR5380_dprint_phase(NDEBUG_ANY, instance); -} - #ifdef PSEUDO_DMA /******************************************/ /* @@ -598,65 +582,19 @@ static int __maybe_unused NCR5380_write_info(struct Scsi_Host *instance, hostdata->spin_max_w = 0; return 0; } -#endif - -static -void lprint_Scsi_Cmnd(struct scsi_cmnd *cmd, struct seq_file *m); -static -void lprint_command(unsigned char *cmd, struct seq_file *m); -static -void lprint_opcode(int opcode, struct seq_file *m); static int __maybe_unused NCR5380_show_info(struct seq_file *m, struct Scsi_Host *instance) { struct NCR5380_hostdata *hostdata; - struct scsi_cmnd *ptr; - unsigned long flags; hostdata = (struct NCR5380_hostdata *) instance->hostdata; -#ifdef PSEUDO_DMA seq_printf(m, "Highwater I/O busy spin counts: write %d, read %d\n", hostdata->spin_max_w, hostdata->spin_max_r); -#endif - spin_lock_irqsave(&hostdata->lock, flags); - if (!hostdata->connected) - seq_printf(m, "scsi%d: no currently connected command\n", instance->host_no); - else - lprint_Scsi_Cmnd((struct scsi_cmnd *) hostdata->connected, m); - seq_printf(m, "scsi%d: issue_queue\n", instance->host_no); - for (ptr = (struct scsi_cmnd *) hostdata->issue_queue; ptr; ptr = (struct scsi_cmnd *) ptr->host_scribble) - lprint_Scsi_Cmnd(ptr, m); - - seq_printf(m, "scsi%d: disconnected_queue\n", instance->host_no); - for (ptr = (struct scsi_cmnd *) hostdata->disconnected_queue; ptr; ptr = (struct scsi_cmnd *) ptr->host_scribble) - lprint_Scsi_Cmnd(ptr, m); - spin_unlock_irqrestore(&hostdata->lock, flags); return 0; } - -static void lprint_Scsi_Cmnd(struct scsi_cmnd *cmd, struct seq_file *m) -{ - seq_printf(m, "scsi%d : destination target %d, lun %llu\n", cmd->device->host->host_no, cmd->device->id, cmd->device->lun); - seq_puts(m, " command = "); - lprint_command(cmd->cmnd, m); -} - -static void lprint_command(unsigned char *command, struct seq_file *m) -{ - int i, s; - lprint_opcode(command[0], m); - for (i = 1, s = COMMAND_SIZE(command[0]); i < s; ++i) - seq_printf(m, "%02x ", command[i]); - seq_putc(m, '\n'); -} - -static void lprint_opcode(int opcode, struct seq_file *m) -{ - seq_printf(m, "%2d (0x%02x)", opcode, opcode); -} - +#endif /** * NCR5380_init - initialise an NCR5380 @@ -2335,7 +2273,8 @@ static int NCR5380_abort(struct scsi_cmnd *cmd) spin_lock_irqsave(&hostdata->lock, flags); - NCR5380_print_status(instance); + NCR5380_dprint(NDEBUG_ANY, instance); + NCR5380_dprint_phase(NDEBUG_ANY, instance); dprintk(NDEBUG_ABORT, "scsi%d : abort called\n", instance->host_no); dprintk(NDEBUG_ABORT, " basr 0x%X, sr 0x%X\n", NCR5380_read(BUS_AND_STATUS_REG), NCR5380_read(STATUS_REG)); @@ -2490,8 +2429,9 @@ static int NCR5380_bus_reset(struct scsi_cmnd *cmd) #if (NDEBUG & NDEBUG_ANY) scmd_printk(KERN_INFO, cmd, "performing bus reset\n"); - NCR5380_print_status(instance); #endif + NCR5380_dprint(NDEBUG_ANY, instance); + NCR5380_dprint_phase(NDEBUG_ANY, instance); do_reset(instance); diff --git a/drivers/scsi/arm/oak.c b/drivers/scsi/arm/oak.c index 719600a373d6..4eef3cdd9aa0 100644 --- a/drivers/scsi/arm/oak.c +++ b/drivers/scsi/arm/oak.c @@ -28,7 +28,6 @@ #define NCR5380_queue_command oakscsi_queue_command #define NCR5380_info oakscsi_info -#define NCR5380_show_info oakscsi_show_info #define NCR5380_implementation_fields \ void __iomem *base @@ -104,7 +103,6 @@ printk("reading %p len %d\n", addr, len); static struct scsi_host_template oakscsi_template = { .module = THIS_MODULE, - .show_info = oakscsi_show_info, .name = "Oak 16-bit SCSI", .info = oakscsi_info, .queuecommand = oakscsi_queue_command, diff --git a/drivers/scsi/atari_NCR5380.c b/drivers/scsi/atari_NCR5380.c index 2dd65cdb0930..f31a4d544e2e 100644 --- a/drivers/scsi/atari_NCR5380.c +++ b/drivers/scsi/atari_NCR5380.c @@ -656,94 +656,6 @@ static void prepare_info(struct Scsi_Host *instance) ""); } -/** - * NCR5380_print_status - dump controller info - * @instance: controller to dump - * - * Print commands in the various queues, called from NCR5380_abort - * to aid debugging. - */ - -static void lprint_Scsi_Cmnd(struct scsi_cmnd *cmd) -{ - int i, s; - unsigned char *command; - printk("scsi%d: destination target %d, lun %llu\n", - H_NO(cmd), cmd->device->id, cmd->device->lun); - printk(KERN_CONT " command = "); - command = cmd->cmnd; - printk(KERN_CONT "%2d (0x%02x)", command[0], command[0]); - for (i = 1, s = COMMAND_SIZE(command[0]); i < s; ++i) - printk(KERN_CONT " %02x", command[i]); - printk("\n"); -} - -static void __maybe_unused NCR5380_print_status(struct Scsi_Host *instance) -{ - struct NCR5380_hostdata *hostdata; - struct scsi_cmnd *ptr; - - NCR5380_dprint(NDEBUG_ANY, instance); - NCR5380_dprint_phase(NDEBUG_ANY, instance); - - hostdata = (struct NCR5380_hostdata *)instance->hostdata; - - if (!hostdata->connected) - printk("scsi%d: no currently connected command\n", HOSTNO); - else - lprint_Scsi_Cmnd((struct scsi_cmnd *) hostdata->connected); - printk("scsi%d: issue_queue\n", HOSTNO); - for (ptr = (struct scsi_cmnd *)hostdata->issue_queue; ptr; ptr = NEXT(ptr)) - lprint_Scsi_Cmnd(ptr); - - printk("scsi%d: disconnected_queue\n", HOSTNO); - for (ptr = (struct scsi_cmnd *) hostdata->disconnected_queue; ptr; - ptr = NEXT(ptr)) - lprint_Scsi_Cmnd(ptr); - printk("\n"); -} - -static void show_Scsi_Cmnd(struct scsi_cmnd *cmd, struct seq_file *m) -{ - int i, s; - unsigned char *command; - seq_printf(m, "scsi%d: destination target %d, lun %llu\n", - H_NO(cmd), cmd->device->id, cmd->device->lun); - seq_puts(m, " command = "); - command = cmd->cmnd; - seq_printf(m, "%2d (0x%02x)", command[0], command[0]); - for (i = 1, s = COMMAND_SIZE(command[0]); i < s; ++i) - seq_printf(m, " %02x", command[i]); - seq_putc(m, '\n'); -} - -static int __maybe_unused NCR5380_show_info(struct seq_file *m, - struct Scsi_Host *instance) -{ - struct NCR5380_hostdata *hostdata; - struct scsi_cmnd *ptr; - unsigned long flags; - - hostdata = (struct NCR5380_hostdata *)instance->hostdata; - - spin_lock_irqsave(&hostdata->lock, flags); - if (!hostdata->connected) - seq_printf(m, "scsi%d: no currently connected command\n", HOSTNO); - else - show_Scsi_Cmnd((struct scsi_cmnd *) hostdata->connected, m); - seq_printf(m, "scsi%d: issue_queue\n", HOSTNO); - for (ptr = (struct scsi_cmnd *)hostdata->issue_queue; ptr; ptr = NEXT(ptr)) - show_Scsi_Cmnd(ptr, m); - - seq_printf(m, "scsi%d: disconnected_queue\n", HOSTNO); - for (ptr = (struct scsi_cmnd *) hostdata->disconnected_queue; ptr; - ptr = NEXT(ptr)) - show_Scsi_Cmnd(ptr, m); - - spin_unlock_irqrestore(&hostdata->lock, flags); - return 0; -} - /** * NCR5380_init - initialise an NCR5380 * @instance: adapter to configure @@ -2617,7 +2529,8 @@ int NCR5380_abort(struct scsi_cmnd *cmd) spin_lock_irqsave(&hostdata->lock, flags); - NCR5380_print_status(instance); + NCR5380_dprint(NDEBUG_ANY, instance); + NCR5380_dprint_phase(NDEBUG_ANY, instance); dprintk(NDEBUG_ABORT, "scsi%d: abort called basr 0x%02x, sr 0x%02x\n", HOSTNO, NCR5380_read(BUS_AND_STATUS_REG), @@ -2815,8 +2728,9 @@ static int NCR5380_bus_reset(struct scsi_cmnd *cmd) #if (NDEBUG & NDEBUG_ANY) scmd_printk(KERN_INFO, cmd, "performing bus reset\n"); - NCR5380_print_status(instance); #endif + NCR5380_dprint(NDEBUG_ANY, instance); + NCR5380_dprint_phase(NDEBUG_ANY, instance); do_reset(instance); diff --git a/drivers/scsi/atari_scsi.c b/drivers/scsi/atari_scsi.c index e263aa30282b..e271b08ccbb2 100644 --- a/drivers/scsi/atari_scsi.c +++ b/drivers/scsi/atari_scsi.c @@ -97,7 +97,6 @@ #define NCR5380_queue_command atari_scsi_queue_command #define NCR5380_abort atari_scsi_abort -#define NCR5380_show_info atari_scsi_show_info #define NCR5380_info atari_scsi_info #define NCR5380_dma_read_setup(instance, data, count) \ @@ -774,7 +773,6 @@ static int atari_scsi_bus_reset(struct scsi_cmnd *cmd) static struct scsi_host_template atari_scsi_template = { .module = THIS_MODULE, .proc_name = DRV_MODULE_NAME, - .show_info = atari_scsi_show_info, .name = "Atari native SCSI", .info = atari_scsi_info, .queuecommand = atari_scsi_queue_command, diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c index 0e59df6b4f5f..0f2b3d9a6ae8 100644 --- a/drivers/scsi/g_NCR5380.c +++ b/drivers/scsi/g_NCR5380.c @@ -715,7 +715,6 @@ static int generic_NCR5380_dma_xfer_len(struct scsi_cmnd *cmd) static struct scsi_host_template driver_template = { .proc_name = DRV_MODULE_NAME, - .show_info = generic_NCR5380_show_info, .name = "Generic NCR5380/NCR53C400 SCSI", .detect = generic_NCR5380_detect, .release = generic_NCR5380_release_resources, diff --git a/drivers/scsi/sun3_scsi.c b/drivers/scsi/sun3_scsi.c index 082c91a4c1c4..14835540fecb 100644 --- a/drivers/scsi/sun3_scsi.c +++ b/drivers/scsi/sun3_scsi.c @@ -53,7 +53,6 @@ #define NCR5380_queue_command sun3scsi_queue_command #define NCR5380_bus_reset sun3scsi_bus_reset #define NCR5380_abort sun3scsi_abort -#define NCR5380_show_info sun3scsi_show_info #define NCR5380_info sun3scsi_info #define NCR5380_dma_read_setup(instance, data, count) \ @@ -459,7 +458,6 @@ static int sun3scsi_dma_finish(int write_flag) static struct scsi_host_template sun3_scsi_template = { .module = THIS_MODULE, .proc_name = DRV_MODULE_NAME, - .show_info = sun3scsi_show_info, .name = SUN3_SCSI_NAME, .info = sun3scsi_info, .queuecommand = sun3scsi_queue_command, -- cgit From dbb6b350695186b340e621f5edf4c31420f9ab23 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sun, 3 Jan 2016 16:05:53 +1100 Subject: ncr5380: Remove H_NO macro and introduce dsprintk Replace all H_NO and some HOSTNO macros (both peculiar to atari_NCR5380.c) with a new dsprintk macro that's more useful and more consistent. The new macro avoids a lot of boilerplate in new code in subsequent patches. Keep NCR5380.c in sync. Remaining HOSTNO macros are removed as side-effects of subsequent patches. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Ondrej Zary Tested-by: Michael Schmitz Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.c | 9 +++++--- drivers/scsi/NCR5380.h | 5 ++++ drivers/scsi/atari_NCR5380.c | 54 ++++++++++++++++++++++---------------------- 3 files changed, 38 insertions(+), 30 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index 2ac01d86d330..54939836ca53 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -755,7 +755,7 @@ static int NCR5380_queue_command(struct Scsi_Host *instance, switch (cmd->cmnd[0]) { case WRITE_6: case WRITE_10: - printk("scsi%d : WRITE attempted with NO_WRITE debugging flag set\n", instance->host_no); + shost_printk(KERN_DEBUG, instance, "WRITE attempted with NDEBUG_NO_WRITE set\n"); cmd->result = (DID_ERROR << 16); cmd->scsi_done(cmd); return 0; @@ -790,7 +790,8 @@ static int NCR5380_queue_command(struct Scsi_Host *instance, } spin_unlock_irqrestore(&hostdata->lock, flags); - dprintk(NDEBUG_QUEUES, "scsi%d : command added to %s of queue\n", instance->host_no, (cmd->cmnd[0] == REQUEST_SENSE) ? "head" : "tail"); + dsprintk(NDEBUG_QUEUES, instance, "command %p added to %s of queue\n", + cmd, (cmd->cmnd[0] == REQUEST_SENSE) ? "head" : "tail"); /* Kick off command processing */ queue_work(hostdata->work_q, &hostdata->main_task); @@ -1888,7 +1889,9 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { cmd->host_scribble = (unsigned char *) hostdata->issue_queue; hostdata->issue_queue = (struct scsi_cmnd *) cmd; - dprintk(NDEBUG_QUEUES, "scsi%d : REQUEST SENSE added to head of issue queue\n", instance->host_no); + dsprintk(NDEBUG_QUEUES, instance, + "REQUEST SENSE cmd %p added to head of issue queue\n", + cmd); } else { cmd->scsi_done(cmd); } diff --git a/drivers/scsi/NCR5380.h b/drivers/scsi/NCR5380.h index aab360810c43..3cfbd3dd9436 100644 --- a/drivers/scsi/NCR5380.h +++ b/drivers/scsi/NCR5380.h @@ -285,6 +285,11 @@ struct NCR5380_hostdata { do { if ((NDEBUG) & (flg)) \ printk(KERN_DEBUG fmt, ## __VA_ARGS__); } while (0) +#define dsprintk(flg, host, fmt, ...) \ + do { if ((NDEBUG) & (flg)) \ + shost_printk(KERN_DEBUG, host, fmt, ## __VA_ARGS__); \ + } while (0) + #if NDEBUG #define NCR5380_dprint(flg, arg) \ do { if ((NDEBUG) & (flg)) NCR5380_print(arg); } while (0) diff --git a/drivers/scsi/atari_NCR5380.c b/drivers/scsi/atari_NCR5380.c index f31a4d544e2e..029f6522e19c 100644 --- a/drivers/scsi/atari_NCR5380.c +++ b/drivers/scsi/atari_NCR5380.c @@ -207,7 +207,6 @@ #define NEXTADDR(cmd) ((struct scsi_cmnd **)&(cmd)->host_scribble) #define HOSTNO instance->host_no -#define H_NO(cmd) (cmd)->device->host->host_no static int do_abort(struct Scsi_Host *); static void do_reset(struct Scsi_Host *); @@ -280,7 +279,8 @@ static void __init init_tags(struct NCR5380_hostdata *hostdata) static int is_lun_busy(struct scsi_cmnd *cmd, int should_be_tagged) { u8 lun = cmd->device->lun; - SETUP_HOSTDATA(cmd->device->host); + struct Scsi_Host *instance = cmd->device->host; + struct NCR5380_hostdata *hostdata = shost_priv(instance); if (hostdata->busy[cmd->device->id] & (1 << lun)) return 1; @@ -290,8 +290,8 @@ static int is_lun_busy(struct scsi_cmnd *cmd, int should_be_tagged) return 0; if (hostdata->TagAlloc[scmd_id(cmd)][lun].nr_allocated >= hostdata->TagAlloc[scmd_id(cmd)][lun].queue_size) { - dprintk(NDEBUG_TAGS, "scsi%d: target %d lun %d: no free tags\n", - H_NO(cmd), cmd->device->id, lun); + dsprintk(NDEBUG_TAGS, instance, "target %d lun %d: no free tags\n", + scmd_id(cmd), lun); return 1; } return 0; @@ -306,7 +306,8 @@ static int is_lun_busy(struct scsi_cmnd *cmd, int should_be_tagged) static void cmd_get_tag(struct scsi_cmnd *cmd, int should_be_tagged) { u8 lun = cmd->device->lun; - SETUP_HOSTDATA(cmd->device->host); + struct Scsi_Host *instance = cmd->device->host; + struct NCR5380_hostdata *hostdata = shost_priv(instance); /* If we or the target don't support tagged queuing, allocate the LUN for * an untagged command. @@ -316,18 +317,16 @@ static void cmd_get_tag(struct scsi_cmnd *cmd, int should_be_tagged) !cmd->device->tagged_supported) { cmd->tag = TAG_NONE; hostdata->busy[cmd->device->id] |= (1 << lun); - dprintk(NDEBUG_TAGS, "scsi%d: target %d lun %d now allocated by untagged " - "command\n", H_NO(cmd), cmd->device->id, lun); + dsprintk(NDEBUG_TAGS, instance, "target %d lun %d now allocated by untagged command\n", + scmd_id(cmd), lun); } else { struct tag_alloc *ta = &hostdata->TagAlloc[scmd_id(cmd)][lun]; cmd->tag = find_first_zero_bit(ta->allocated, MAX_TAGS); set_bit(cmd->tag, ta->allocated); ta->nr_allocated++; - dprintk(NDEBUG_TAGS, "scsi%d: using tag %d for target %d lun %d " - "(now %d tags in use)\n", - H_NO(cmd), cmd->tag, cmd->device->id, - lun, ta->nr_allocated); + dsprintk(NDEBUG_TAGS, instance, "using tag %d for target %d lun %d (%d tags allocated)\n", + cmd->tag, scmd_id(cmd), lun, ta->nr_allocated); } } @@ -339,21 +338,22 @@ static void cmd_get_tag(struct scsi_cmnd *cmd, int should_be_tagged) static void cmd_free_tag(struct scsi_cmnd *cmd) { u8 lun = cmd->device->lun; - SETUP_HOSTDATA(cmd->device->host); + struct Scsi_Host *instance = cmd->device->host; + struct NCR5380_hostdata *hostdata = shost_priv(instance); if (cmd->tag == TAG_NONE) { hostdata->busy[cmd->device->id] &= ~(1 << lun); - dprintk(NDEBUG_TAGS, "scsi%d: target %d lun %d untagged cmd finished\n", - H_NO(cmd), cmd->device->id, lun); + dsprintk(NDEBUG_TAGS, instance, "target %d lun %d untagged cmd freed\n", + scmd_id(cmd), lun); } else if (cmd->tag >= MAX_TAGS) { - printk(KERN_NOTICE "scsi%d: trying to free bad tag %d!\n", - H_NO(cmd), cmd->tag); + shost_printk(KERN_NOTICE, instance, + "trying to free bad tag %d!\n", cmd->tag); } else { struct tag_alloc *ta = &hostdata->TagAlloc[scmd_id(cmd)][lun]; clear_bit(cmd->tag, ta->allocated); ta->nr_allocated--; - dprintk(NDEBUG_TAGS, "scsi%d: freed tag %d for target %d lun %d\n", - H_NO(cmd), cmd->tag, cmd->device->id, lun); + dsprintk(NDEBUG_TAGS, instance, "freed tag %d for target %d lun %d\n", + cmd->tag, scmd_id(cmd), lun); } } @@ -815,8 +815,7 @@ static int NCR5380_queue_command(struct Scsi_Host *instance, switch (cmd->cmnd[0]) { case WRITE_6: case WRITE_10: - printk(KERN_NOTICE "scsi%d: WRITE attempted with NO_WRITE debugging flag set\n", - H_NO(cmd)); + shost_printk(KERN_DEBUG, instance, "WRITE attempted with NDEBUG_NO_WRITE set\n"); cmd->result = (DID_ERROR << 16); cmd->scsi_done(cmd); return 0; @@ -875,8 +874,8 @@ static int NCR5380_queue_command(struct Scsi_Host *instance, } spin_unlock_irqrestore(&hostdata->lock, flags); - dprintk(NDEBUG_QUEUES, "scsi%d: command added to %s of queue\n", H_NO(cmd), - (cmd->cmnd[0] == REQUEST_SENSE) ? "head" : "tail"); + dsprintk(NDEBUG_QUEUES, instance, "command %p added to %s of queue\n", + cmd, (cmd->cmnd[0] == REQUEST_SENSE) ? "head" : "tail"); /* Kick off command processing */ queue_work(hostdata->work_q, &hostdata->main_task); @@ -2079,8 +2078,9 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) LIST(cmd,hostdata->issue_queue); SET_NEXT(cmd, hostdata->issue_queue); hostdata->issue_queue = (struct scsi_cmnd *) cmd; - dprintk(NDEBUG_QUEUES, "scsi%d: REQUEST SENSE added to head of " - "issue queue\n", H_NO(cmd)); + dsprintk(NDEBUG_QUEUES, instance, + "REQUEST SENSE cmd %p added to head of issue queue\n", + cmd); } else { cmd->scsi_done(cmd); } @@ -2746,11 +2746,11 @@ static int NCR5380_bus_reset(struct scsi_cmnd *cmd) */ if (hostdata->issue_queue) - dprintk(NDEBUG_ABORT, "scsi%d: reset aborted issued command(s)\n", H_NO(cmd)); + dsprintk(NDEBUG_ABORT, instance, "reset aborted issued command(s)\n"); if (hostdata->connected) - dprintk(NDEBUG_ABORT, "scsi%d: reset aborted a connected command\n", H_NO(cmd)); + dsprintk(NDEBUG_ABORT, instance, "reset aborted a connected command\n"); if (hostdata->disconnected_queue) - dprintk(NDEBUG_ABORT, "scsi%d: reset aborted disconnected command(s)\n", H_NO(cmd)); + dsprintk(NDEBUG_ABORT, instance, "reset aborted disconnected command(s)\n"); hostdata->issue_queue = NULL; hostdata->connected = NULL; -- cgit From e8a601444297e336a7c4355f07b4bb386962894c Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sun, 3 Jan 2016 16:05:54 +1100 Subject: ncr5380: Use shost_priv helper Make use of the shost_priv() helper. Remove HOSTDATA and SETUP_HOSTDATA macros because they harm readability. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Ondrej Zary Tested-by: Michael Schmitz Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.c | 23 ++++++++++------------- drivers/scsi/atari_NCR5380.c | 20 +++++++------------- 2 files changed, 17 insertions(+), 26 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index 54939836ca53..3774adb3e75a 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -464,7 +464,7 @@ static irqreturn_t __init probe_intr(int irq, void *dev_id) static int __init __maybe_unused NCR5380_probe_irq(struct Scsi_Host *instance, int possible) { - struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) instance->hostdata; + struct NCR5380_hostdata *hostdata = shost_priv(instance); unsigned long timeout; int trying_irqs, i, mask; @@ -586,9 +586,7 @@ static int __maybe_unused NCR5380_write_info(struct Scsi_Host *instance, static int __maybe_unused NCR5380_show_info(struct seq_file *m, struct Scsi_Host *instance) { - struct NCR5380_hostdata *hostdata; - - hostdata = (struct NCR5380_hostdata *) instance->hostdata; + struct NCR5380_hostdata *hostdata = shost_priv(instance); seq_printf(m, "Highwater I/O busy spin counts: write %d, read %d\n", hostdata->spin_max_w, hostdata->spin_max_r); @@ -614,8 +612,8 @@ static int __maybe_unused NCR5380_show_info(struct seq_file *m, static int NCR5380_init(struct Scsi_Host *instance, int flags) { + struct NCR5380_hostdata *hostdata = shost_priv(instance); int i; - struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) instance->hostdata; unsigned long deadline; if(in_interrupt()) @@ -728,7 +726,7 @@ static int NCR5380_maybe_reset_bus(struct Scsi_Host *instance) static void NCR5380_exit(struct Scsi_Host *instance) { - struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) instance->hostdata; + struct NCR5380_hostdata *hostdata = shost_priv(instance); cancel_work_sync(&hostdata->main_task); destroy_workqueue(hostdata->work_q); @@ -1037,7 +1035,7 @@ static irqreturn_t NCR5380_intr(int irq, void *dev_id) static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd) { - struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) instance->hostdata; + struct NCR5380_hostdata *hostdata = shost_priv(instance); unsigned char tmp[3], phase; unsigned char *data; int len; @@ -1511,7 +1509,7 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, unsigned char *phase unsigned char saved_data = 0, overrun = 0, residue; #endif - struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) instance->hostdata; + struct NCR5380_hostdata *hostdata = shost_priv(instance); if ((tmp = (NCR5380_read(STATUS_REG) & PHASE_MASK)) != p) { *phase = tmp; @@ -1743,7 +1741,7 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, unsigned char *phase */ static void NCR5380_information_transfer(struct Scsi_Host *instance) { - struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *)instance->hostdata; + struct NCR5380_hostdata *hostdata = shost_priv(instance); unsigned char msgout = NOP; int sink = 0; int len; @@ -2090,8 +2088,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { */ static void NCR5380_reselect(struct Scsi_Host *instance) { - struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) - instance->hostdata; + struct NCR5380_hostdata *hostdata = shost_priv(instance); unsigned char target_mask; unsigned char lun, phase; int len; @@ -2214,7 +2211,7 @@ static void NCR5380_reselect(struct Scsi_Host *instance) { #ifdef REAL_DMA static void NCR5380_dma_complete(NCR5380_instance * instance) { - struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) instance->hostdata; + struct NCR5380_hostdata *hostdata = shost_priv(instance); int transferred; /* @@ -2268,7 +2265,7 @@ static void NCR5380_dma_complete(NCR5380_instance * instance) { static int NCR5380_abort(struct scsi_cmnd *cmd) { struct Scsi_Host *instance = cmd->device->host; - struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) instance->hostdata; + struct NCR5380_hostdata *hostdata = shost_priv(instance); struct scsi_cmnd *tmp, **prev; unsigned long flags; diff --git a/drivers/scsi/atari_NCR5380.c b/drivers/scsi/atari_NCR5380.c index 029f6522e19c..fcf2a453aa3e 100644 --- a/drivers/scsi/atari_NCR5380.c +++ b/drivers/scsi/atari_NCR5380.c @@ -196,12 +196,6 @@ * possible) function may be used. */ -/* Macros ease life... :-) */ -#define SETUP_HOSTDATA(in) \ - struct NCR5380_hostdata *hostdata = \ - (struct NCR5380_hostdata *)(in)->hostdata -#define HOSTDATA(in) ((struct NCR5380_hostdata *)(in)->hostdata) - #define NEXT(cmd) ((struct scsi_cmnd *)(cmd)->host_scribble) #define SET_NEXT(cmd,next) ((cmd)->host_scribble = (void *)(next)) #define NEXTADDR(cmd) ((struct scsi_cmnd **)&(cmd)->host_scribble) @@ -672,8 +666,8 @@ static void prepare_info(struct Scsi_Host *instance) static int __init NCR5380_init(struct Scsi_Host *instance, int flags) { + struct NCR5380_hostdata *hostdata = shost_priv(instance); int i; - SETUP_HOSTDATA(instance); unsigned long deadline; hostdata->host = instance; @@ -1038,7 +1032,7 @@ static void NCR5380_main(struct work_struct *work) static void NCR5380_dma_complete(struct Scsi_Host *instance) { - SETUP_HOSTDATA(instance); + struct NCR5380_hostdata *hostdata = shost_priv(instance); int transferred; unsigned char **data; volatile int *count; @@ -1248,7 +1242,7 @@ static irqreturn_t NCR5380_intr(int irq, void *dev_id) static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd) { - SETUP_HOSTDATA(instance); + struct NCR5380_hostdata *hostdata = shost_priv(instance); unsigned char tmp[3], phase; unsigned char *data; int len; @@ -1742,7 +1736,7 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, unsigned char *phase, int *count, unsigned char **data) { - SETUP_HOSTDATA(instance); + struct NCR5380_hostdata *hostdata = shost_priv(instance); register int c = *count; register unsigned char p = *phase; @@ -1850,7 +1844,7 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, static void NCR5380_information_transfer(struct Scsi_Host *instance) { - SETUP_HOSTDATA(instance); + struct NCR5380_hostdata *hostdata = shost_priv(instance); unsigned char msgout = NOP; int sink = 0; int len; @@ -2314,7 +2308,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) static void NCR5380_reselect(struct Scsi_Host *instance) { - SETUP_HOSTDATA(instance); + struct NCR5380_hostdata *hostdata = shost_priv(instance); unsigned char target_mask; unsigned char lun; #ifdef SUPPORT_TAGS @@ -2521,7 +2515,7 @@ static int NCR5380_abort(struct scsi_cmnd *cmd) { struct Scsi_Host *instance = cmd->device->host; - SETUP_HOSTDATA(instance); + struct NCR5380_hostdata *hostdata = shost_priv(instance); struct scsi_cmnd *tmp, **prev; unsigned long flags; -- cgit From 0d3d9a423cd9a4007908a7ec36bf1261e4e5b773 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sun, 3 Jan 2016 16:05:55 +1100 Subject: ncr5380: Use dsprintk() for queue debugging Print the command pointers in the log messages for debugging queue data structures. The LIST and REMOVE macros can then be removed. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Ondrej Zary Tested-by: Michael Schmitz Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.c | 36 ++++++++++++++++++++++++------------ drivers/scsi/atari_NCR5380.c | 43 +++++++++++++++++++++++-------------------- 2 files changed, 47 insertions(+), 32 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index 3774adb3e75a..41bd2e9055f5 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -828,8 +828,9 @@ static void NCR5380_main(struct work_struct *work) */ for (tmp = (struct scsi_cmnd *) hostdata->issue_queue, prev = NULL; tmp; prev = tmp, tmp = (struct scsi_cmnd *) tmp->host_scribble) { - if (prev != tmp) - dprintk(NDEBUG_LISTS, "MAIN tmp=%p target=%d busy=%d lun=%llu\n", tmp, tmp->device->id, hostdata->busy[tmp->device->id], tmp->device->lun); + dsprintk(NDEBUG_QUEUES, instance, "main: tmp=%p target=%d busy=%d lun=%llu\n", + tmp, scmd_id(tmp), hostdata->busy[scmd_id(tmp)], + tmp->device->lun); /* When we find one, remove it from the issue queue. */ if (!(hostdata->busy[tmp->device->id] & (1 << (u8)(tmp->device->lun & 0xff)))) { @@ -841,6 +842,9 @@ static void NCR5380_main(struct work_struct *work) hostdata->issue_queue = (struct scsi_cmnd *) tmp->host_scribble; } tmp->host_scribble = NULL; + dsprintk(NDEBUG_MAIN | NDEBUG_QUEUES, + instance, "main: removed %p from issue queue %p\n", + tmp, prev); /* * Attempt to establish an I_T_L nexus here. @@ -848,8 +852,6 @@ static void NCR5380_main(struct work_struct *work) * On failure, we must add the command back to the * issue queue so we can keep trying. */ - dprintk(NDEBUG_MAIN|NDEBUG_QUEUES, "scsi%d : main() : command for target %d lun %llu removed from issue_queue\n", instance->host_no, tmp->device->id, tmp->device->lun); - /* * REQUEST SENSE commands are issued without tagged * queueing, even on SCSI-II devices because the @@ -864,8 +866,10 @@ static void NCR5380_main(struct work_struct *work) LIST(tmp, hostdata->issue_queue); tmp->host_scribble = (unsigned char *) hostdata->issue_queue; hostdata->issue_queue = tmp; + dsprintk(NDEBUG_MAIN | NDEBUG_QUEUES, + instance, "main: select() failed, %p returned to issue queue\n", + tmp); done = 0; - dprintk(NDEBUG_MAIN|NDEBUG_QUEUES, "scsi%d : main(): select() failed, returned to issue_queue\n", instance->host_no); } if (hostdata->connected) break; @@ -1847,8 +1851,11 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { /* Accept message by clearing ACK */ sink = 1; NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); + dsprintk(NDEBUG_QUEUES, instance, + "COMMAND COMPLETE %p target %d lun %llu\n", + cmd, scmd_id(cmd), cmd->device->lun); + hostdata->connected = NULL; - dprintk(NDEBUG_QUEUES, "scsi%d : command for target %d, lun %llu completed\n", instance->host_no, cmd->device->id, cmd->device->lun); hostdata->busy[cmd->device->id] &= ~(1 << (cmd->device->lun & 0xFF)); /* @@ -1881,14 +1888,12 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { if ((cmd->cmnd[0] != REQUEST_SENSE) && (status_byte(cmd->SCp.Status) == CHECK_CONDITION)) { scsi_eh_prep_cmnd(cmd, &hostdata->ses, NULL, 0, ~0); - dprintk(NDEBUG_AUTOSENSE, "scsi%d : performing request sense\n", instance->host_no); - LIST(cmd, hostdata->issue_queue); cmd->host_scribble = (unsigned char *) hostdata->issue_queue; hostdata->issue_queue = (struct scsi_cmnd *) cmd; - dsprintk(NDEBUG_QUEUES, instance, - "REQUEST SENSE cmd %p added to head of issue queue\n", + dsprintk(NDEBUG_AUTOSENSE | NDEBUG_QUEUES, + instance, "REQUEST SENSE cmd %p added to head of issue queue\n", cmd); } else { cmd->scsi_done(cmd); @@ -1925,7 +1930,10 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { hostdata->disconnected_queue; hostdata->connected = NULL; hostdata->disconnected_queue = cmd; - dprintk(NDEBUG_QUEUES, "scsi%d : command for target %d lun %llu was moved from connected to" " the disconnected_queue\n", instance->host_no, cmd->device->id, cmd->device->lun); + dsprintk(NDEBUG_INFORMATION | NDEBUG_QUEUES, + instance, "connected command %p for target %d lun %llu moved to disconnected queue\n", + cmd, scmd_id(cmd), cmd->device->lun); + /* * Restore phase bits to 0 so an interrupted selection, * arbitration can resume. @@ -2178,7 +2186,11 @@ static void NCR5380_reselect(struct Scsi_Host *instance) { break; } } - if (!tmp) { + + if (tmp) { + dsprintk(NDEBUG_RESELECTION | NDEBUG_QUEUES, instance, + "reselect: removed %p from disconnected queue\n", tmp); + } else { shost_printk(KERN_ERR, instance, "target bitmask 0x%02x lun %d not in disconnected queue.\n", target_mask, lun); /* diff --git a/drivers/scsi/atari_NCR5380.c b/drivers/scsi/atari_NCR5380.c index fcf2a453aa3e..9f0d52b248b1 100644 --- a/drivers/scsi/atari_NCR5380.c +++ b/drivers/scsi/atari_NCR5380.c @@ -936,10 +936,8 @@ static void NCR5380_main(struct work_struct *work) prev = NULL; tmp; prev = tmp, tmp = NEXT(tmp)) { u8 lun = tmp->device->lun; - dprintk(NDEBUG_LISTS, - "MAIN tmp=%p target=%d busy=%d lun=%d\n", - tmp, scmd_id(tmp), hostdata->busy[scmd_id(tmp)], - lun); + dsprintk(NDEBUG_QUEUES, instance, "main: tmp=%p target=%d busy=%d lun=%d\n", + tmp, scmd_id(tmp), hostdata->busy[scmd_id(tmp)], lun); /* When we find one, remove it from the issue queue. */ if ( #ifdef SUPPORT_TAGS @@ -956,6 +954,10 @@ static void NCR5380_main(struct work_struct *work) hostdata->issue_queue = NEXT(tmp); } SET_NEXT(tmp, NULL); + dsprintk(NDEBUG_MAIN | NDEBUG_QUEUES, + instance, "main: removed %p from issue queue %p\n", + tmp, prev); + hostdata->retain_dma_intr++; /* @@ -964,9 +966,6 @@ static void NCR5380_main(struct work_struct *work) * On failure, we must add the command back to the * issue queue so we can keep trying. */ - dprintk(NDEBUG_MAIN, "scsi%d: main(): command for target %d " - "lun %d removed from issue_queue\n", - HOSTNO, tmp->device->id, lun); /* * REQUEST SENSE commands are issued without tagged * queueing, even on SCSI-II devices because the @@ -989,13 +988,14 @@ static void NCR5380_main(struct work_struct *work) LIST(tmp, hostdata->issue_queue); SET_NEXT(tmp, hostdata->issue_queue); hostdata->issue_queue = tmp; + dsprintk(NDEBUG_MAIN | NDEBUG_QUEUES, + instance, "main: select() failed, %p returned to issue queue\n", + tmp); #ifdef SUPPORT_TAGS cmd_free_tag(tmp); #endif hostdata->retain_dma_intr--; done = 0; - dprintk(NDEBUG_MAIN, "scsi%d: main(): select() failed, " - "returned to issue_queue\n", HOSTNO); } if (hostdata->connected) break; @@ -2017,8 +2017,9 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) case COMMAND_COMPLETE: /* Accept message by clearing ACK */ NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - dprintk(NDEBUG_QUEUES, "scsi%d: command for target %d, lun %llu " - "completed\n", HOSTNO, cmd->device->id, cmd->device->lun); + dsprintk(NDEBUG_QUEUES, instance, + "COMMAND COMPLETE %p target %d lun %llu\n", + cmd, scmd_id(cmd), cmd->device->lun); hostdata->connected = NULL; #ifdef SUPPORT_TAGS @@ -2067,13 +2068,11 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) (status_byte(cmd->SCp.Status) == CHECK_CONDITION)) { scsi_eh_prep_cmnd(cmd, &hostdata->ses, NULL, 0, ~0); - dprintk(NDEBUG_AUTOSENSE, "scsi%d: performing request sense\n", HOSTNO); - LIST(cmd,hostdata->issue_queue); SET_NEXT(cmd, hostdata->issue_queue); hostdata->issue_queue = (struct scsi_cmnd *) cmd; - dsprintk(NDEBUG_QUEUES, instance, - "REQUEST SENSE cmd %p added to head of issue queue\n", + dsprintk(NDEBUG_AUTOSENSE | NDEBUG_QUEUES, + instance, "REQUEST SENSE cmd %p added to head of issue queue\n", cmd); } else { cmd->scsi_done(cmd); @@ -2124,10 +2123,10 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) SET_NEXT(cmd, hostdata->disconnected_queue); hostdata->connected = NULL; hostdata->disconnected_queue = cmd; - dprintk(NDEBUG_QUEUES, "scsi%d: command for target %d lun %llu was " - "moved from connected to the " - "disconnected_queue\n", HOSTNO, - cmd->device->id, cmd->device->lun); + dsprintk(NDEBUG_INFORMATION | NDEBUG_QUEUES, + instance, "connected command %p for target %d lun %llu moved to disconnected queue\n", + cmd, scmd_id(cmd), cmd->device->lun); + /* * Restore phase bits to 0 so an interrupted selection, * arbitration can resume. @@ -2427,7 +2426,11 @@ static void NCR5380_reselect(struct Scsi_Host *instance) } } - if (!tmp) { + if (tmp) { + dsprintk(NDEBUG_RESELECTION | NDEBUG_QUEUES, instance, + "reselect: removed %p from disconnected queue\n", tmp); + } else { + #ifdef SUPPORT_TAGS shost_printk(KERN_ERR, instance, "target bitmask 0x%02x lun %d tag %d not in disconnected queue.\n", target_mask, lun, tag); -- cgit From 9903fa914aece320599e74b39ae6cf1bebe1a796 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sun, 3 Jan 2016 16:05:56 +1100 Subject: ncr5380: Remove LIST and REMOVE macros Printing command pointers can be useful when debugging queues. Other than that, the LIST and REMOVE macros are just clutter. These macros are redundant now that NDEBUG_QUEUES causes pointers to be printed, so remove them. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Ondrej Zary Tested-by: Michael Schmitz Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.c | 19 ------------------- drivers/scsi/atari_NCR5380.c | 32 -------------------------------- 2 files changed, 51 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index 41bd2e9055f5..9e8636300c8a 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -80,14 +80,6 @@ * tagged queueing) */ -#if (NDEBUG & NDEBUG_LISTS) -#define LIST(x,y) {printk("LINE:%d Adding %p to %p\n", __LINE__, (void*)(x), (void*)(y)); if ((x)==(y)) udelay(5); } -#define REMOVE(w,x,y,z) {printk("LINE:%d Removing: %p->%p %p->%p \n", __LINE__, (void*)(w), (void*)(x), (void*)(y), (void*)(z)); if ((x)==(y)) udelay(5); } -#else -#define LIST(x,y) -#define REMOVE(w,x,y,z) -#endif - #ifndef notyet #undef REAL_DMA #endif @@ -778,12 +770,10 @@ static int NCR5380_queue_command(struct Scsi_Host *instance, */ if (!(hostdata->issue_queue) || (cmd->cmnd[0] == REQUEST_SENSE)) { - LIST(cmd, hostdata->issue_queue); cmd->host_scribble = (unsigned char *) hostdata->issue_queue; hostdata->issue_queue = cmd; } else { for (tmp = (struct scsi_cmnd *) hostdata->issue_queue; tmp->host_scribble; tmp = (struct scsi_cmnd *) tmp->host_scribble); - LIST(cmd, tmp); tmp->host_scribble = (unsigned char *) cmd; } spin_unlock_irqrestore(&hostdata->lock, flags); @@ -835,10 +825,8 @@ static void NCR5380_main(struct work_struct *work) if (!(hostdata->busy[tmp->device->id] & (1 << (u8)(tmp->device->lun & 0xff)))) { if (prev) { - REMOVE(prev, prev->host_scribble, tmp, tmp->host_scribble); prev->host_scribble = tmp->host_scribble; } else { - REMOVE(-1, hostdata->issue_queue, tmp, tmp->host_scribble); hostdata->issue_queue = (struct scsi_cmnd *) tmp->host_scribble; } tmp->host_scribble = NULL; @@ -863,7 +851,6 @@ static void NCR5380_main(struct work_struct *work) /* OK or bad target */ } else { /* Need to retry */ - LIST(tmp, hostdata->issue_queue); tmp->host_scribble = (unsigned char *) hostdata->issue_queue; hostdata->issue_queue = tmp; dsprintk(NDEBUG_MAIN | NDEBUG_QUEUES, @@ -1888,7 +1875,6 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { if ((cmd->cmnd[0] != REQUEST_SENSE) && (status_byte(cmd->SCp.Status) == CHECK_CONDITION)) { scsi_eh_prep_cmnd(cmd, &hostdata->ses, NULL, 0, ~0); - LIST(cmd, hostdata->issue_queue); cmd->host_scribble = (unsigned char *) hostdata->issue_queue; hostdata->issue_queue = (struct scsi_cmnd *) cmd; @@ -1925,7 +1911,6 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { case DISCONNECT:{ /* Accept message by clearing ACK */ NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - LIST(cmd, hostdata->disconnected_queue); cmd->host_scribble = (unsigned char *) hostdata->disconnected_queue; hostdata->connected = NULL; @@ -2175,10 +2160,8 @@ static void NCR5380_reselect(struct Scsi_Host *instance) { tmp; prev = tmp, tmp = (struct scsi_cmnd *) tmp->host_scribble) { if ((target_mask == (1 << tmp->device->id)) && (lun == (u8)tmp->device->lun)) { if (prev) { - REMOVE(prev, prev->host_scribble, tmp, tmp->host_scribble); prev->host_scribble = tmp->host_scribble; } else { - REMOVE(-1, hostdata->disconnected_queue, tmp, tmp->host_scribble); hostdata->disconnected_queue = (struct scsi_cmnd *) tmp->host_scribble; } @@ -2329,7 +2312,6 @@ static int NCR5380_abort(struct scsi_cmnd *cmd) dprintk(NDEBUG_ABORT, "scsi%d : abort going into loop.\n", instance->host_no); for (prev = (struct scsi_cmnd **) &(hostdata->issue_queue), tmp = (struct scsi_cmnd *) hostdata->issue_queue; tmp; prev = (struct scsi_cmnd **) &(tmp->host_scribble), tmp = (struct scsi_cmnd *) tmp->host_scribble) if (cmd == tmp) { - REMOVE(5, *prev, tmp, tmp->host_scribble); (*prev) = (struct scsi_cmnd *) tmp->host_scribble; tmp->host_scribble = NULL; spin_unlock_irqrestore(&hostdata->lock, flags); @@ -2399,7 +2381,6 @@ static int NCR5380_abort(struct scsi_cmnd *cmd) for (prev = (struct scsi_cmnd **) &(hostdata->disconnected_queue), tmp = (struct scsi_cmnd *) hostdata->disconnected_queue; tmp; prev = (struct scsi_cmnd **) &(tmp->host_scribble), tmp = (struct scsi_cmnd *) tmp->host_scribble) if (cmd == tmp) { - REMOVE(5, *prev, tmp, tmp->host_scribble); *prev = (struct scsi_cmnd *) tmp->host_scribble; tmp->host_scribble = NULL; spin_unlock_irqrestore(&hostdata->lock, flags); diff --git a/drivers/scsi/atari_NCR5380.c b/drivers/scsi/atari_NCR5380.c index 9f0d52b248b1..0347c87c7b53 100644 --- a/drivers/scsi/atari_NCR5380.c +++ b/drivers/scsi/atari_NCR5380.c @@ -68,27 +68,6 @@ /* Adapted for the sun3 by Sam Creasey. */ -#if (NDEBUG & NDEBUG_LISTS) -#define LIST(x, y) \ - do { \ - printk("LINE:%d Adding %p to %p\n", \ - __LINE__, (void*)(x), (void*)(y)); \ - if ((x) == (y)) \ - udelay(5); \ - } while (0) -#define REMOVE(w, x, y, z) \ - do { \ - printk("LINE:%d Removing: %p->%p %p->%p \n", \ - __LINE__, (void*)(w), (void*)(x), \ - (void*)(y), (void*)(z)); \ - if ((x) == (y)) \ - udelay(5); \ - } while (0) -#else -#define LIST(x,y) -#define REMOVE(w,x,y,z) -#endif - /* * Design * @@ -856,14 +835,12 @@ static int NCR5380_queue_command(struct Scsi_Host *instance, */ if (!(hostdata->issue_queue) || (cmd->cmnd[0] == REQUEST_SENSE)) { - LIST(cmd, hostdata->issue_queue); SET_NEXT(cmd, hostdata->issue_queue); hostdata->issue_queue = cmd; } else { for (tmp = (struct scsi_cmnd *)hostdata->issue_queue; NEXT(tmp); tmp = NEXT(tmp)) ; - LIST(cmd, tmp); SET_NEXT(tmp, cmd); } spin_unlock_irqrestore(&hostdata->lock, flags); @@ -947,10 +924,8 @@ static void NCR5380_main(struct work_struct *work) #endif ) { if (prev) { - REMOVE(prev, NEXT(prev), tmp, NEXT(tmp)); SET_NEXT(prev, NEXT(tmp)); } else { - REMOVE(-1, hostdata->issue_queue, tmp, NEXT(tmp)); hostdata->issue_queue = NEXT(tmp); } SET_NEXT(tmp, NULL); @@ -985,7 +960,6 @@ static void NCR5380_main(struct work_struct *work) maybe_release_dma_irq(instance); } else { /* Need to retry */ - LIST(tmp, hostdata->issue_queue); SET_NEXT(tmp, hostdata->issue_queue); hostdata->issue_queue = tmp; dsprintk(NDEBUG_MAIN | NDEBUG_QUEUES, @@ -2068,7 +2042,6 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) (status_byte(cmd->SCp.Status) == CHECK_CONDITION)) { scsi_eh_prep_cmnd(cmd, &hostdata->ses, NULL, 0, ~0); - LIST(cmd,hostdata->issue_queue); SET_NEXT(cmd, hostdata->issue_queue); hostdata->issue_queue = (struct scsi_cmnd *) cmd; dsprintk(NDEBUG_AUTOSENSE | NDEBUG_QUEUES, @@ -2119,7 +2092,6 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) case DISCONNECT: /* Accept message by clearing ACK */ NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - LIST(cmd,hostdata->disconnected_queue); SET_NEXT(cmd, hostdata->disconnected_queue); hostdata->connected = NULL; hostdata->disconnected_queue = cmd; @@ -2415,10 +2387,8 @@ static void NCR5380_reselect(struct Scsi_Host *instance) #endif ) { if (prev) { - REMOVE(prev, NEXT(prev), tmp, NEXT(tmp)); SET_NEXT(prev, NEXT(tmp)); } else { - REMOVE(-1, hostdata->disconnected_queue, tmp, NEXT(tmp)); hostdata->disconnected_queue = NEXT(tmp); } SET_NEXT(tmp, NULL); @@ -2588,7 +2558,6 @@ int NCR5380_abort(struct scsi_cmnd *cmd) tmp = (struct scsi_cmnd *)hostdata->issue_queue; tmp; prev = NEXTADDR(tmp), tmp = NEXT(tmp)) { if (cmd == tmp) { - REMOVE(5, *prev, tmp, NEXT(tmp)); (*prev) = NEXT(tmp); SET_NEXT(tmp, NULL); tmp->result = DID_ABORT << 16; @@ -2662,7 +2631,6 @@ int NCR5380_abort(struct scsi_cmnd *cmd) tmp = (struct scsi_cmnd *)hostdata->disconnected_queue; tmp; prev = NEXTADDR(tmp), tmp = NEXT(tmp)) { if (cmd == tmp) { - REMOVE(5, *prev, tmp, NEXT(tmp)); *prev = NEXT(tmp); SET_NEXT(tmp, NULL); tmp->result = DID_ABORT << 16; -- cgit From 5299b3caf525c5a6cdebbe162733c8ff1692c4d0 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sun, 3 Jan 2016 16:05:57 +1100 Subject: ncr5380: Remove redundant volatile qualifiers The hostdata struct is now protected by a spin lock so the volatile qualifiers are redundant. Remove them. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Ondrej Zary Tested-by: Michael Schmitz Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.h | 12 ++++++------ drivers/scsi/atari_NCR5380.c | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/NCR5380.h b/drivers/scsi/NCR5380.h index 3cfbd3dd9436..87c2f2104e68 100644 --- a/drivers/scsi/NCR5380.h +++ b/drivers/scsi/NCR5380.h @@ -248,14 +248,14 @@ struct NCR5380_hostdata { NCR5380_implementation_fields; /* implementation specific */ struct Scsi_Host *host; /* Host backpointer */ unsigned char id_mask, id_higher_mask; /* 1 << id, all bits greater */ - volatile unsigned char busy[8]; /* index = target, bit = lun */ + unsigned char busy[8]; /* index = target, bit = lun */ #if defined(REAL_DMA) || defined(REAL_DMA_POLL) - volatile int dma_len; /* requested length of DMA */ + int dma_len; /* requested length of DMA */ #endif - volatile unsigned char last_message; /* last message OUT */ - volatile struct scsi_cmnd *connected; /* currently connected command */ - volatile struct scsi_cmnd *issue_queue; /* waiting to be issued */ - volatile struct scsi_cmnd *disconnected_queue; /* waiting for reconnect */ + unsigned char last_message; /* last message OUT */ + struct scsi_cmnd *connected; /* currently connected cmnd */ + struct scsi_cmnd *issue_queue; /* waiting to be issued */ + struct scsi_cmnd *disconnected_queue; /* waiting for reconnect */ spinlock_t lock; /* protects this struct */ int flags; struct scsi_eh_save ses; diff --git a/drivers/scsi/atari_NCR5380.c b/drivers/scsi/atari_NCR5380.c index 0347c87c7b53..809ef25b7049 100644 --- a/drivers/scsi/atari_NCR5380.c +++ b/drivers/scsi/atari_NCR5380.c @@ -1009,7 +1009,7 @@ static void NCR5380_dma_complete(struct Scsi_Host *instance) struct NCR5380_hostdata *hostdata = shost_priv(instance); int transferred; unsigned char **data; - volatile int *count; + int *count; int saved_data = 0, overrun = 0; unsigned char p; -- cgit From 32b26a104237c1ba3575a6c8d47e46060cc416fb Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sun, 3 Jan 2016 16:05:58 +1100 Subject: ncr5380: Use standard list data structure The NCR5380 drivers have a home-spun linked list implementation for scsi_cmnd structs that uses cmd->host_scribble as a 'next' pointer. Adopt the standard list_head data structure and list operations instead. Remove the eh_abort_handler rather than convert it. Doing the conversion would only be churn because the existing EH handlers don't work and get replaced in a subsequent patch. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Ondrej Zary Tested-by: Michael Schmitz Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.c | 214 ++++++-------------------------- drivers/scsi/NCR5380.h | 16 ++- drivers/scsi/arm/cumana_1.c | 1 + drivers/scsi/arm/oak.c | 1 + drivers/scsi/atari_NCR5380.c | 287 +++++++------------------------------------ drivers/scsi/atari_scsi.c | 1 + drivers/scsi/dmx3191d.c | 1 + drivers/scsi/dtc.c | 1 + drivers/scsi/g_NCR5380.c | 1 + drivers/scsi/mac_scsi.c | 1 + drivers/scsi/pas16.c | 1 + drivers/scsi/sun3_scsi.c | 1 + drivers/scsi/t128.c | 1 + 13 files changed, 106 insertions(+), 421 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index 9e8636300c8a..6b861fd3fbb1 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -622,8 +622,9 @@ static int NCR5380_init(struct Scsi_Host *instance, int flags) #endif spin_lock_init(&hostdata->lock); hostdata->connected = NULL; - hostdata->issue_queue = NULL; - hostdata->disconnected_queue = NULL; + INIT_LIST_HEAD(&hostdata->unissued); + INIT_LIST_HEAD(&hostdata->disconnected); + hostdata->flags = flags; INIT_WORK(&hostdata->main_task, NCR5380_main); @@ -738,7 +739,7 @@ static int NCR5380_queue_command(struct Scsi_Host *instance, struct scsi_cmnd *cmd) { struct NCR5380_hostdata *hostdata = shost_priv(instance); - struct scsi_cmnd *tmp; + struct NCR5380_cmd *ncmd = scsi_cmd_priv(cmd); unsigned long flags; #if (NDEBUG & NDEBUG_NO_WRITE) @@ -752,12 +753,6 @@ static int NCR5380_queue_command(struct Scsi_Host *instance, } #endif /* (NDEBUG & NDEBUG_NO_WRITE) */ - /* - * We use the host_scribble field as a pointer to the next command - * in a queue - */ - - cmd->host_scribble = NULL; cmd->result = 0; spin_lock_irqsave(&hostdata->lock, flags); @@ -769,13 +764,11 @@ static int NCR5380_queue_command(struct Scsi_Host *instance, * sense data is only guaranteed to be valid while the condition exists. */ - if (!(hostdata->issue_queue) || (cmd->cmnd[0] == REQUEST_SENSE)) { - cmd->host_scribble = (unsigned char *) hostdata->issue_queue; - hostdata->issue_queue = cmd; - } else { - for (tmp = (struct scsi_cmnd *) hostdata->issue_queue; tmp->host_scribble; tmp = (struct scsi_cmnd *) tmp->host_scribble); - tmp->host_scribble = (unsigned char *) cmd; - } + if (cmd->cmnd[0] == REQUEST_SENSE) + list_add(&ncmd->list, &hostdata->unissued); + else + list_add_tail(&ncmd->list, &hostdata->unissued); + spin_unlock_irqrestore(&hostdata->lock, flags); dsprintk(NDEBUG_QUEUES, instance, "command %p added to %s of queue\n", @@ -803,7 +796,7 @@ static void NCR5380_main(struct work_struct *work) struct NCR5380_hostdata *hostdata = container_of(work, struct NCR5380_hostdata, main_task); struct Scsi_Host *instance = hostdata->host; - struct scsi_cmnd *tmp, *prev; + struct NCR5380_cmd *ncmd, *n; int done; spin_lock_irq(&hostdata->lock); @@ -816,23 +809,20 @@ static void NCR5380_main(struct work_struct *work) * Search through the issue_queue for a command destined * for a target that's not busy. */ - for (tmp = (struct scsi_cmnd *) hostdata->issue_queue, prev = NULL; tmp; prev = tmp, tmp = (struct scsi_cmnd *) tmp->host_scribble) - { + list_for_each_entry_safe(ncmd, n, &hostdata->unissued, + list) { + struct scsi_cmnd *tmp = NCR5380_to_scmd(ncmd); + dsprintk(NDEBUG_QUEUES, instance, "main: tmp=%p target=%d busy=%d lun=%llu\n", tmp, scmd_id(tmp), hostdata->busy[scmd_id(tmp)], tmp->device->lun); /* When we find one, remove it from the issue queue. */ if (!(hostdata->busy[tmp->device->id] & (1 << (u8)(tmp->device->lun & 0xff)))) { - if (prev) { - prev->host_scribble = tmp->host_scribble; - } else { - hostdata->issue_queue = (struct scsi_cmnd *) tmp->host_scribble; - } - tmp->host_scribble = NULL; + list_del(&ncmd->list); dsprintk(NDEBUG_MAIN | NDEBUG_QUEUES, - instance, "main: removed %p from issue queue %p\n", - tmp, prev); + instance, "main: removed %p from issue queue\n", + tmp); /* * Attempt to establish an I_T_L nexus here. @@ -851,8 +841,7 @@ static void NCR5380_main(struct work_struct *work) /* OK or bad target */ } else { /* Need to retry */ - tmp->host_scribble = (unsigned char *) hostdata->issue_queue; - hostdata->issue_queue = tmp; + list_add(&ncmd->list, &hostdata->unissued); dsprintk(NDEBUG_MAIN | NDEBUG_QUEUES, instance, "main: select() failed, %p returned to issue queue\n", tmp); @@ -1744,6 +1733,8 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { struct scsi_cmnd *cmd; while ((cmd = hostdata->connected)) { + struct NCR5380_cmd *ncmd = scsi_cmd_priv(cmd); + tmp = NCR5380_read(STATUS_REG); /* We only have a valid SCSI phase when REQ is asserted */ if (tmp & SR_REQ) { @@ -1875,9 +1866,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { if ((cmd->cmnd[0] != REQUEST_SENSE) && (status_byte(cmd->SCp.Status) == CHECK_CONDITION)) { scsi_eh_prep_cmnd(cmd, &hostdata->ses, NULL, 0, ~0); - cmd->host_scribble = (unsigned char *) - hostdata->issue_queue; - hostdata->issue_queue = (struct scsi_cmnd *) cmd; + list_add(&ncmd->list, &hostdata->unissued); dsprintk(NDEBUG_AUTOSENSE | NDEBUG_QUEUES, instance, "REQUEST SENSE cmd %p added to head of issue queue\n", cmd); @@ -1911,10 +1900,8 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { case DISCONNECT:{ /* Accept message by clearing ACK */ NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - cmd->host_scribble = (unsigned char *) - hostdata->disconnected_queue; hostdata->connected = NULL; - hostdata->disconnected_queue = cmd; + list_add(&ncmd->list, &hostdata->disconnected); dsprintk(NDEBUG_INFORMATION | NDEBUG_QUEUES, instance, "connected command %p for target %d lun %llu moved to disconnected queue\n", cmd, scmd_id(cmd), cmd->device->lun); @@ -2087,7 +2074,8 @@ static void NCR5380_reselect(struct Scsi_Host *instance) { int len; unsigned char msg[3]; unsigned char *data; - struct scsi_cmnd *tmp = NULL, *prev; + struct NCR5380_cmd *ncmd; + struct scsi_cmnd *tmp; /* * Disable arbitration, etc. since the host adapter obviously @@ -2156,16 +2144,14 @@ static void NCR5380_reselect(struct Scsi_Host *instance) { * just reestablished, and remove it from the disconnected queue. */ - for (tmp = (struct scsi_cmnd *) hostdata->disconnected_queue, prev = NULL; - tmp; prev = tmp, tmp = (struct scsi_cmnd *) tmp->host_scribble) { - if ((target_mask == (1 << tmp->device->id)) && (lun == (u8)tmp->device->lun)) { - if (prev) { - prev->host_scribble = tmp->host_scribble; - } else { - hostdata->disconnected_queue = - (struct scsi_cmnd *) tmp->host_scribble; - } - tmp->host_scribble = NULL; + tmp = NULL; + list_for_each_entry(ncmd, &hostdata->disconnected, list) { + struct scsi_cmnd *cmd = NCR5380_to_scmd(ncmd); + + if (target_mask == (1 << scmd_id(cmd)) && + lun == (u8)cmd->device->lun) { + list_del(&ncmd->list); + tmp = cmd; break; } } @@ -2261,146 +2247,18 @@ static int NCR5380_abort(struct scsi_cmnd *cmd) { struct Scsi_Host *instance = cmd->device->host; struct NCR5380_hostdata *hostdata = shost_priv(instance); - struct scsi_cmnd *tmp, **prev; unsigned long flags; - scmd_printk(KERN_WARNING, cmd, "aborting command\n"); - spin_lock_irqsave(&hostdata->lock, flags); +#if (NDEBUG & NDEBUG_ANY) + scmd_printk(KERN_INFO, cmd, "aborting command\n"); +#endif NCR5380_dprint(NDEBUG_ANY, instance); NCR5380_dprint_phase(NDEBUG_ANY, instance); - dprintk(NDEBUG_ABORT, "scsi%d : abort called\n", instance->host_no); - dprintk(NDEBUG_ABORT, " basr 0x%X, sr 0x%X\n", NCR5380_read(BUS_AND_STATUS_REG), NCR5380_read(STATUS_REG)); - -#if 0 -/* - * Case 1 : If the command is the currently executing command, - * we'll set the aborted flag and return control so that - * information transfer routine can exit cleanly. - */ - - if (hostdata->connected == cmd) { - dprintk(NDEBUG_ABORT, "scsi%d : aborting connected command\n", instance->host_no); -/* - * We should perform BSY checking, and make sure we haven't slipped - * into BUS FREE. - */ - - NCR5380_write(INITIATOR_COMMAND_REG, ICR_ASSERT_ATN); -/* - * Since we can't change phases until we've completed the current - * handshake, we have to source or sink a byte of data if the current - * phase is not MSGOUT. - */ - -/* - * Return control to the executing NCR drive so we can clear the - * aborted flag and get back into our main loop. - */ - - return SUCCESS; - } -#endif - -/* - * Case 2 : If the command hasn't been issued yet, we simply remove it - * from the issue queue. - */ - - dprintk(NDEBUG_ABORT, "scsi%d : abort going into loop.\n", instance->host_no); - for (prev = (struct scsi_cmnd **) &(hostdata->issue_queue), tmp = (struct scsi_cmnd *) hostdata->issue_queue; tmp; prev = (struct scsi_cmnd **) &(tmp->host_scribble), tmp = (struct scsi_cmnd *) tmp->host_scribble) - if (cmd == tmp) { - (*prev) = (struct scsi_cmnd *) tmp->host_scribble; - tmp->host_scribble = NULL; - spin_unlock_irqrestore(&hostdata->lock, flags); - tmp->result = DID_ABORT << 16; - dprintk(NDEBUG_ABORT, "scsi%d : abort removed command from issue queue.\n", instance->host_no); - tmp->scsi_done(tmp); - return SUCCESS; - } -#if (NDEBUG & NDEBUG_ABORT) - /* KLL */ - else if (prev == tmp) - printk(KERN_ERR "scsi%d : LOOP\n", instance->host_no); -#endif - -/* - * Case 3 : If any commands are connected, we're going to fail the abort - * and let the high level SCSI driver retry at a later time or - * issue a reset. - * - * Timeouts, and therefore aborted commands, will be highly unlikely - * and handling them cleanly in this situation would make the common - * case of noresets less efficient, and would pollute our code. So, - * we fail. - */ - - if (hostdata->connected) { - spin_unlock_irqrestore(&hostdata->lock, flags); - dprintk(NDEBUG_ABORT, "scsi%d : abort failed, command connected.\n", instance->host_no); - return FAILED; - } -/* - * Case 4: If the command is currently disconnected from the bus, and - * there are no connected commands, we reconnect the I_T_L or - * I_T_L_Q nexus associated with it, go into message out, and send - * an abort message. - * - * This case is especially ugly. In order to reestablish the nexus, we - * need to call NCR5380_select(). The easiest way to implement this - * function was to abort if the bus was busy, and let the interrupt - * handler triggered on the SEL for reselect take care of lost arbitrations - * where necessary, meaning interrupts need to be enabled. - * - * When interrupts are enabled, the queues may change - so we - * can't remove it from the disconnected queue before selecting it - * because that could cause a failure in hashing the nexus if that - * device reselected. - * - * Since the queues may change, we can't use the pointers from when we - * first locate it. - * - * So, we must first locate the command, and if NCR5380_select() - * succeeds, then issue the abort, relocate the command and remove - * it from the disconnected queue. - */ - - for (tmp = (struct scsi_cmnd *) hostdata->disconnected_queue; tmp; tmp = (struct scsi_cmnd *) tmp->host_scribble) - if (cmd == tmp) { - dprintk(NDEBUG_ABORT, "scsi%d : aborting disconnected command.\n", instance->host_no); - - if (NCR5380_select(instance, cmd)) { - spin_unlock_irq(&hostdata->lock); - return FAILED; - } - dprintk(NDEBUG_ABORT, "scsi%d : nexus reestablished.\n", instance->host_no); - - do_abort(instance); - - for (prev = (struct scsi_cmnd **) &(hostdata->disconnected_queue), tmp = (struct scsi_cmnd *) hostdata->disconnected_queue; tmp; prev = (struct scsi_cmnd **) &(tmp->host_scribble), tmp = (struct scsi_cmnd *) tmp->host_scribble) - if (cmd == tmp) { - *prev = (struct scsi_cmnd *) tmp->host_scribble; - tmp->host_scribble = NULL; - spin_unlock_irqrestore(&hostdata->lock, flags); - tmp->result = DID_ABORT << 16; - tmp->scsi_done(tmp); - return SUCCESS; - } - } -/* - * Case 5 : If we reached this point, the command was not found in any of - * the queues. - * - * We probably reached this point because of an unlikely race condition - * between the command completing successfully and the abortion code, - * so we won't panic, but we will notify the user in case something really - * broke. - */ spin_unlock_irqrestore(&hostdata->lock, flags); - printk(KERN_WARNING "scsi%d : warning : SCSI command probably completed successfully\n" - " before abortion\n", instance->host_no); + return FAILED; } diff --git a/drivers/scsi/NCR5380.h b/drivers/scsi/NCR5380.h index 87c2f2104e68..56252a5516d7 100644 --- a/drivers/scsi/NCR5380.h +++ b/drivers/scsi/NCR5380.h @@ -24,6 +24,7 @@ #include #include +#include #include #include #include @@ -254,8 +255,8 @@ struct NCR5380_hostdata { #endif unsigned char last_message; /* last message OUT */ struct scsi_cmnd *connected; /* currently connected cmnd */ - struct scsi_cmnd *issue_queue; /* waiting to be issued */ - struct scsi_cmnd *disconnected_queue; /* waiting for reconnect */ + struct list_head unissued; /* waiting to be issued */ + struct list_head disconnected; /* waiting for reconnect */ spinlock_t lock; /* protects this struct */ int flags; struct scsi_eh_save ses; @@ -277,6 +278,17 @@ struct NCR5380_hostdata { #ifdef __KERNEL__ +struct NCR5380_cmd { + struct list_head list; +}; + +#define NCR5380_CMD_SIZE (sizeof(struct NCR5380_cmd)) + +static inline struct scsi_cmnd *NCR5380_to_scmd(struct NCR5380_cmd *ncmd_ptr) +{ + return ((struct scsi_cmnd *)ncmd_ptr) - 1; +} + #ifndef NDEBUG #define NDEBUG (0) #endif diff --git a/drivers/scsi/arm/cumana_1.c b/drivers/scsi/arm/cumana_1.c index 921c982886ae..b526ba579ba3 100644 --- a/drivers/scsi/arm/cumana_1.c +++ b/drivers/scsi/arm/cumana_1.c @@ -208,6 +208,7 @@ static struct scsi_host_template cumanascsi_template = { .cmd_per_lun = 2, .use_clustering = DISABLE_CLUSTERING, .proc_name = "CumanaSCSI-1", + .cmd_size = NCR5380_CMD_SIZE, }; static int cumanascsi1_probe(struct expansion_card *ec, diff --git a/drivers/scsi/arm/oak.c b/drivers/scsi/arm/oak.c index 4eef3cdd9aa0..70e648513275 100644 --- a/drivers/scsi/arm/oak.c +++ b/drivers/scsi/arm/oak.c @@ -114,6 +114,7 @@ static struct scsi_host_template oakscsi_template = { .cmd_per_lun = 2, .use_clustering = DISABLE_CLUSTERING, .proc_name = "oakscsi", + .cmd_size = NCR5380_CMD_SIZE, }; static int oakscsi_probe(struct expansion_card *ec, const struct ecard_id *id) diff --git a/drivers/scsi/atari_NCR5380.c b/drivers/scsi/atari_NCR5380.c index 809ef25b7049..12b98cbe7b44 100644 --- a/drivers/scsi/atari_NCR5380.c +++ b/drivers/scsi/atari_NCR5380.c @@ -175,10 +175,6 @@ * possible) function may be used. */ -#define NEXT(cmd) ((struct scsi_cmnd *)(cmd)->host_scribble) -#define SET_NEXT(cmd,next) ((cmd)->host_scribble = (void *)(next)) -#define NEXTADDR(cmd) ((struct scsi_cmnd **)&(cmd)->host_scribble) - #define HOSTNO instance->host_no static int do_abort(struct Scsi_Host *); @@ -665,8 +661,9 @@ static int __init NCR5380_init(struct Scsi_Host *instance, int flags) #endif spin_lock_init(&hostdata->lock); hostdata->connected = NULL; - hostdata->issue_queue = NULL; - hostdata->disconnected_queue = NULL; + INIT_LIST_HEAD(&hostdata->unissued); + INIT_LIST_HEAD(&hostdata->disconnected); + hostdata->flags = flags; INIT_WORK(&hostdata->main_task, NCR5380_main); @@ -781,7 +778,7 @@ static int NCR5380_queue_command(struct Scsi_Host *instance, struct scsi_cmnd *cmd) { struct NCR5380_hostdata *hostdata = shost_priv(instance); - struct scsi_cmnd *tmp; + struct NCR5380_cmd *ncmd = scsi_cmd_priv(cmd); unsigned long flags; #if (NDEBUG & NDEBUG_NO_WRITE) @@ -795,12 +792,6 @@ static int NCR5380_queue_command(struct Scsi_Host *instance, } #endif /* (NDEBUG & NDEBUG_NO_WRITE) */ - /* - * We use the host_scribble field as a pointer to the next command - * in a queue - */ - - SET_NEXT(cmd, NULL); cmd->result = 0; /* @@ -834,15 +825,11 @@ static int NCR5380_queue_command(struct Scsi_Host *instance, * sense data is only guaranteed to be valid while the condition exists. */ - if (!(hostdata->issue_queue) || (cmd->cmnd[0] == REQUEST_SENSE)) { - SET_NEXT(cmd, hostdata->issue_queue); - hostdata->issue_queue = cmd; - } else { - for (tmp = (struct scsi_cmnd *)hostdata->issue_queue; - NEXT(tmp); tmp = NEXT(tmp)) - ; - SET_NEXT(tmp, cmd); - } + if (cmd->cmnd[0] == REQUEST_SENSE) + list_add(&ncmd->list, &hostdata->unissued); + else + list_add_tail(&ncmd->list, &hostdata->unissued); + spin_unlock_irqrestore(&hostdata->lock, flags); dsprintk(NDEBUG_QUEUES, instance, "command %p added to %s of queue\n", @@ -858,8 +845,8 @@ static inline void maybe_release_dma_irq(struct Scsi_Host *instance) struct NCR5380_hostdata *hostdata = shost_priv(instance); /* Caller does the locking needed to set & test these data atomically */ - if (!hostdata->disconnected_queue && - !hostdata->issue_queue && + if (list_empty(&hostdata->disconnected) && + list_empty(&hostdata->unissued) && !hostdata->connected && !hostdata->retain_dma_intr) NCR5380_release_dma_irq(instance); @@ -881,7 +868,7 @@ static void NCR5380_main(struct work_struct *work) struct NCR5380_hostdata *hostdata = container_of(work, struct NCR5380_hostdata, main_task); struct Scsi_Host *instance = hostdata->host; - struct scsi_cmnd *tmp, *prev; + struct NCR5380_cmd *ncmd, *n; int done; /* @@ -900,17 +887,9 @@ static void NCR5380_main(struct work_struct *work) * Search through the issue_queue for a command destined * for a target that's not busy. */ -#if (NDEBUG & NDEBUG_LISTS) - for (tmp = (struct scsi_cmnd *) hostdata->issue_queue, prev = NULL; - tmp && (tmp != prev); prev = tmp, tmp = NEXT(tmp)) - ; - /*printk("%p ", tmp);*/ - if ((tmp == prev) && tmp) - printk(" LOOP\n"); - /* else printk("\n"); */ -#endif - for (tmp = (struct scsi_cmnd *) hostdata->issue_queue, - prev = NULL; tmp; prev = tmp, tmp = NEXT(tmp)) { + list_for_each_entry_safe(ncmd, n, &hostdata->unissued, + list) { + struct scsi_cmnd *tmp = NCR5380_to_scmd(ncmd); u8 lun = tmp->device->lun; dsprintk(NDEBUG_QUEUES, instance, "main: tmp=%p target=%d busy=%d lun=%d\n", @@ -923,15 +902,10 @@ static void NCR5380_main(struct work_struct *work) !(hostdata->busy[tmp->device->id] & (1 << lun)) #endif ) { - if (prev) { - SET_NEXT(prev, NEXT(tmp)); - } else { - hostdata->issue_queue = NEXT(tmp); - } - SET_NEXT(tmp, NULL); + list_del(&ncmd->list); dsprintk(NDEBUG_MAIN | NDEBUG_QUEUES, - instance, "main: removed %p from issue queue %p\n", - tmp, prev); + instance, "main: removed %p from issue queue\n", + tmp); hostdata->retain_dma_intr++; @@ -960,8 +934,7 @@ static void NCR5380_main(struct work_struct *work) maybe_release_dma_irq(instance); } else { /* Need to retry */ - SET_NEXT(tmp, hostdata->issue_queue); - hostdata->issue_queue = tmp; + list_add(&ncmd->list, &hostdata->unissued); dsprintk(NDEBUG_MAIN | NDEBUG_QUEUES, instance, "main: select() failed, %p returned to issue queue\n", tmp); @@ -1834,6 +1807,8 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) #endif while ((cmd = hostdata->connected)) { + struct NCR5380_cmd *ncmd = scsi_cmd_priv(cmd); + tmp = NCR5380_read(STATUS_REG); /* We only have a valid SCSI phase when REQ is asserted */ if (tmp & SR_REQ) { @@ -2042,8 +2017,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) (status_byte(cmd->SCp.Status) == CHECK_CONDITION)) { scsi_eh_prep_cmnd(cmd, &hostdata->ses, NULL, 0, ~0); - SET_NEXT(cmd, hostdata->issue_queue); - hostdata->issue_queue = (struct scsi_cmnd *) cmd; + list_add(&ncmd->list, &hostdata->unissued); dsprintk(NDEBUG_AUTOSENSE | NDEBUG_QUEUES, instance, "REQUEST SENSE cmd %p added to head of issue queue\n", cmd); @@ -2092,9 +2066,8 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) case DISCONNECT: /* Accept message by clearing ACK */ NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - SET_NEXT(cmd, hostdata->disconnected_queue); hostdata->connected = NULL; - hostdata->disconnected_queue = cmd; + list_add(&ncmd->list, &hostdata->disconnected); dsprintk(NDEBUG_INFORMATION | NDEBUG_QUEUES, instance, "connected command %p for target %d lun %llu moved to disconnected queue\n", cmd, scmd_id(cmd), cmd->device->lun); @@ -2288,7 +2261,8 @@ static void NCR5380_reselect(struct Scsi_Host *instance) unsigned char msg[3]; int __maybe_unused len; unsigned char __maybe_unused *data, __maybe_unused phase; - struct scsi_cmnd *tmp = NULL, *prev; + struct NCR5380_cmd *ncmd; + struct scsi_cmnd *tmp; /* * Disable arbitration, etc. since the host adapter obviously @@ -2379,19 +2353,18 @@ static void NCR5380_reselect(struct Scsi_Host *instance) * just reestablished, and remove it from the disconnected queue. */ - for (tmp = (struct scsi_cmnd *) hostdata->disconnected_queue, prev = NULL; - tmp; prev = tmp, tmp = NEXT(tmp)) { - if ((target_mask == (1 << tmp->device->id)) && (lun == (u8)tmp->device->lun) + tmp = NULL; + list_for_each_entry(ncmd, &hostdata->disconnected, list) { + struct scsi_cmnd *cmd = NCR5380_to_scmd(ncmd); + + if (target_mask == (1 << scmd_id(cmd)) && + lun == (u8)cmd->device->lun #ifdef SUPPORT_TAGS - && (tag == tmp->tag) + && (tag == cmd->tag) #endif ) { - if (prev) { - SET_NEXT(prev, NEXT(tmp)); - } else { - hostdata->disconnected_queue = NEXT(tmp); - } - SET_NEXT(tmp, NULL); + list_del(&ncmd->list); + tmp = cmd; break; } } @@ -2489,188 +2462,18 @@ int NCR5380_abort(struct scsi_cmnd *cmd) { struct Scsi_Host *instance = cmd->device->host; struct NCR5380_hostdata *hostdata = shost_priv(instance); - struct scsi_cmnd *tmp, **prev; unsigned long flags; - scmd_printk(KERN_NOTICE, cmd, "aborting command\n"); - spin_lock_irqsave(&hostdata->lock, flags); +#if (NDEBUG & NDEBUG_ANY) + scmd_printk(KERN_INFO, cmd, "aborting command\n"); +#endif NCR5380_dprint(NDEBUG_ANY, instance); NCR5380_dprint_phase(NDEBUG_ANY, instance); - dprintk(NDEBUG_ABORT, "scsi%d: abort called basr 0x%02x, sr 0x%02x\n", HOSTNO, - NCR5380_read(BUS_AND_STATUS_REG), - NCR5380_read(STATUS_REG)); - -#if 1 - /* - * Case 1 : If the command is the currently executing command, - * we'll set the aborted flag and return control so that - * information transfer routine can exit cleanly. - */ - - if (hostdata->connected == cmd) { - - dprintk(NDEBUG_ABORT, "scsi%d: aborting connected command\n", HOSTNO); - /* - * We should perform BSY checking, and make sure we haven't slipped - * into BUS FREE. - */ - - /* NCR5380_write(INITIATOR_COMMAND_REG, ICR_ASSERT_ATN); */ - /* - * Since we can't change phases until we've completed the current - * handshake, we have to source or sink a byte of data if the current - * phase is not MSGOUT. - */ - - /* - * Return control to the executing NCR drive so we can clear the - * aborted flag and get back into our main loop. - */ - - if (do_abort(instance) == 0) { - hostdata->connected = NULL; - cmd->result = DID_ABORT << 16; -#ifdef SUPPORT_TAGS - cmd_free_tag(cmd); -#else - hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun); -#endif - maybe_release_dma_irq(instance); - spin_unlock_irqrestore(&hostdata->lock, flags); - cmd->scsi_done(cmd); - return SUCCESS; - } else { - spin_unlock_irqrestore(&hostdata->lock, flags); - printk("scsi%d: abort of connected command failed!\n", HOSTNO); - return FAILED; - } - } -#endif - - /* - * Case 2 : If the command hasn't been issued yet, we simply remove it - * from the issue queue. - */ - for (prev = (struct scsi_cmnd **)&(hostdata->issue_queue), - tmp = (struct scsi_cmnd *)hostdata->issue_queue; - tmp; prev = NEXTADDR(tmp), tmp = NEXT(tmp)) { - if (cmd == tmp) { - (*prev) = NEXT(tmp); - SET_NEXT(tmp, NULL); - tmp->result = DID_ABORT << 16; - maybe_release_dma_irq(instance); - spin_unlock_irqrestore(&hostdata->lock, flags); - dprintk(NDEBUG_ABORT, "scsi%d: abort removed command from issue queue.\n", - HOSTNO); - /* Tagged queuing note: no tag to free here, hasn't been assigned - * yet... */ - tmp->scsi_done(tmp); - return SUCCESS; - } - } - - /* - * Case 3 : If any commands are connected, we're going to fail the abort - * and let the high level SCSI driver retry at a later time or - * issue a reset. - * - * Timeouts, and therefore aborted commands, will be highly unlikely - * and handling them cleanly in this situation would make the common - * case of noresets less efficient, and would pollute our code. So, - * we fail. - */ - - if (hostdata->connected) { - spin_unlock_irqrestore(&hostdata->lock, flags); - dprintk(NDEBUG_ABORT, "scsi%d: abort failed, command connected.\n", HOSTNO); - return FAILED; - } - - /* - * Case 4: If the command is currently disconnected from the bus, and - * there are no connected commands, we reconnect the I_T_L or - * I_T_L_Q nexus associated with it, go into message out, and send - * an abort message. - * - * This case is especially ugly. In order to reestablish the nexus, we - * need to call NCR5380_select(). The easiest way to implement this - * function was to abort if the bus was busy, and let the interrupt - * handler triggered on the SEL for reselect take care of lost arbitrations - * where necessary, meaning interrupts need to be enabled. - * - * When interrupts are enabled, the queues may change - so we - * can't remove it from the disconnected queue before selecting it - * because that could cause a failure in hashing the nexus if that - * device reselected. - * - * Since the queues may change, we can't use the pointers from when we - * first locate it. - * - * So, we must first locate the command, and if NCR5380_select() - * succeeds, then issue the abort, relocate the command and remove - * it from the disconnected queue. - */ - - for (tmp = (struct scsi_cmnd *) hostdata->disconnected_queue; tmp; - tmp = NEXT(tmp)) { - if (cmd == tmp) { - dprintk(NDEBUG_ABORT, "scsi%d: aborting disconnected command.\n", HOSTNO); - - if (NCR5380_select(instance, cmd)) { - spin_unlock_irq(&hostdata->lock); - return FAILED; - } - dprintk(NDEBUG_ABORT, "scsi%d: nexus reestablished.\n", HOSTNO); - - do_abort(instance); - - for (prev = (struct scsi_cmnd **)&(hostdata->disconnected_queue), - tmp = (struct scsi_cmnd *)hostdata->disconnected_queue; - tmp; prev = NEXTADDR(tmp), tmp = NEXT(tmp)) { - if (cmd == tmp) { - *prev = NEXT(tmp); - SET_NEXT(tmp, NULL); - tmp->result = DID_ABORT << 16; - /* We must unlock the tag/LUN immediately here, since the - * target goes to BUS FREE and doesn't send us another - * message (COMMAND_COMPLETE or the like) - */ -#ifdef SUPPORT_TAGS - cmd_free_tag(tmp); -#else - hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun); -#endif - maybe_release_dma_irq(instance); - spin_unlock_irqrestore(&hostdata->lock, flags); - tmp->scsi_done(tmp); - return SUCCESS; - } - } - } - } - - /* Maybe it is sufficient just to release the ST-DMA lock... (if - * possible at all) At least, we should check if the lock could be - * released after the abort, in case it is kept due to some bug. - */ - maybe_release_dma_irq(instance); spin_unlock_irqrestore(&hostdata->lock, flags); - /* - * Case 5 : If we reached this point, the command was not found in any of - * the queues. - * - * We probably reached this point because of an unlikely race condition - * between the command completing successfully and the abortion code, - * so we won't panic, but we will notify the user in case something really - * broke. - */ - - printk(KERN_INFO "scsi%d: warning : SCSI command probably completed successfully before abortion\n", HOSTNO); - return FAILED; } @@ -2710,16 +2513,18 @@ static int NCR5380_bus_reset(struct scsi_cmnd *cmd) * commands! */ - if (hostdata->issue_queue) - dsprintk(NDEBUG_ABORT, instance, "reset aborted issued command(s)\n"); if (hostdata->connected) dsprintk(NDEBUG_ABORT, instance, "reset aborted a connected command\n"); - if (hostdata->disconnected_queue) - dsprintk(NDEBUG_ABORT, instance, "reset aborted disconnected command(s)\n"); - - hostdata->issue_queue = NULL; hostdata->connected = NULL; - hostdata->disconnected_queue = NULL; + + if (!list_empty(&hostdata->unissued)) + dsprintk(NDEBUG_ABORT, instance, "reset aborted unissued list\n"); + INIT_LIST_HEAD(&hostdata->unissued); + + if (!list_empty(&hostdata->disconnected)) + dsprintk(NDEBUG_ABORT, instance, "reset aborted disconnected list\n"); + INIT_LIST_HEAD(&hostdata->disconnected); + #ifdef SUPPORT_TAGS free_all_tags(hostdata); #endif diff --git a/drivers/scsi/atari_scsi.c b/drivers/scsi/atari_scsi.c index e271b08ccbb2..263cf06a8f30 100644 --- a/drivers/scsi/atari_scsi.c +++ b/drivers/scsi/atari_scsi.c @@ -780,6 +780,7 @@ static struct scsi_host_template atari_scsi_template = { .eh_bus_reset_handler = atari_scsi_bus_reset, .this_id = 7, .use_clustering = DISABLE_CLUSTERING, + .cmd_size = NCR5380_CMD_SIZE, }; static int __init atari_scsi_probe(struct platform_device *pdev) diff --git a/drivers/scsi/dmx3191d.c b/drivers/scsi/dmx3191d.c index 51e63fe957c5..ddb4e616bfed 100644 --- a/drivers/scsi/dmx3191d.c +++ b/drivers/scsi/dmx3191d.c @@ -61,6 +61,7 @@ static struct scsi_host_template dmx3191d_driver_template = { .sg_tablesize = SG_ALL, .cmd_per_lun = 2, .use_clustering = DISABLE_CLUSTERING, + .cmd_size = NCR5380_CMD_SIZE, }; static int dmx3191d_probe_one(struct pci_dev *pdev, diff --git a/drivers/scsi/dtc.c b/drivers/scsi/dtc.c index d74661458f15..f6166e34e3b0 100644 --- a/drivers/scsi/dtc.c +++ b/drivers/scsi/dtc.c @@ -452,5 +452,6 @@ static struct scsi_host_template driver_template = { .sg_tablesize = SG_ALL, .cmd_per_lun = 2, .use_clustering = DISABLE_CLUSTERING, + .cmd_size = NCR5380_CMD_SIZE, }; #include "scsi_module.c" diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c index 0f2b3d9a6ae8..30472064170e 100644 --- a/drivers/scsi/g_NCR5380.c +++ b/drivers/scsi/g_NCR5380.c @@ -728,6 +728,7 @@ static struct scsi_host_template driver_template = { .sg_tablesize = SG_ALL, .cmd_per_lun = 2, .use_clustering = DISABLE_CLUSTERING, + .cmd_size = NCR5380_CMD_SIZE, }; #include "scsi_module.c" diff --git a/drivers/scsi/mac_scsi.c b/drivers/scsi/mac_scsi.c index e75bed25dd15..18f74b4a0b95 100644 --- a/drivers/scsi/mac_scsi.c +++ b/drivers/scsi/mac_scsi.c @@ -323,6 +323,7 @@ static struct scsi_host_template mac_scsi_template = { .sg_tablesize = SG_ALL, .cmd_per_lun = 2, .use_clustering = DISABLE_CLUSTERING, + .cmd_size = NCR5380_CMD_SIZE, }; static int __init mac_scsi_probe(struct platform_device *pdev) diff --git a/drivers/scsi/pas16.c b/drivers/scsi/pas16.c index 5f8a8295a5c1..77789405f4a9 100644 --- a/drivers/scsi/pas16.c +++ b/drivers/scsi/pas16.c @@ -562,6 +562,7 @@ static struct scsi_host_template driver_template = { .sg_tablesize = SG_ALL, .cmd_per_lun = 2, .use_clustering = DISABLE_CLUSTERING, + .cmd_size = NCR5380_CMD_SIZE, }; #include "scsi_module.c" diff --git a/drivers/scsi/sun3_scsi.c b/drivers/scsi/sun3_scsi.c index 14835540fecb..c10782b4843e 100644 --- a/drivers/scsi/sun3_scsi.c +++ b/drivers/scsi/sun3_scsi.c @@ -468,6 +468,7 @@ static struct scsi_host_template sun3_scsi_template = { .sg_tablesize = SG_NONE, .cmd_per_lun = 2, .use_clustering = DISABLE_CLUSTERING, + .cmd_size = NCR5380_CMD_SIZE, }; static int __init sun3_scsi_probe(struct platform_device *pdev) diff --git a/drivers/scsi/t128.c b/drivers/scsi/t128.c index d1ed1f532a24..e50881ab9eb4 100644 --- a/drivers/scsi/t128.c +++ b/drivers/scsi/t128.c @@ -406,5 +406,6 @@ static struct scsi_host_template driver_template = { .sg_tablesize = SG_ALL, .cmd_per_lun = 2, .use_clustering = DISABLE_CLUSTERING, + .cmd_size = NCR5380_CMD_SIZE, }; #include "scsi_module.c" -- cgit From 677e01947e4a34ad97e9867af20435b8281c38e0 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sun, 3 Jan 2016 16:05:59 +1100 Subject: ncr5380: Refactor command completion Implement a 'complete_cmd' function to complete commands. This is needed by the following patch; the new function provides a site for the logic needed to correctly handle REQUEST SENSE commands. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Ondrej Zary Tested-by: Michael Schmitz Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.c | 31 ++++++++++++++++++++++------- drivers/scsi/atari_NCR5380.c | 46 +++++++++++++++++++++++++++++--------------- 2 files changed, 55 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index 6b861fd3fbb1..08319164f012 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -725,6 +725,24 @@ static void NCR5380_exit(struct Scsi_Host *instance) destroy_workqueue(hostdata->work_q); } +/** + * complete_cmd - finish processing a command and return it to the SCSI ML + * @instance: the host instance + * @cmd: command to complete + */ + +static void complete_cmd(struct Scsi_Host *instance, + struct scsi_cmnd *cmd) +{ + struct NCR5380_hostdata *hostdata = shost_priv(instance); + + dsprintk(NDEBUG_QUEUES, instance, "complete_cmd: cmd %p\n", cmd); + + hostdata->busy[scmd_id(cmd)] &= ~(1 << cmd->device->lun); + + cmd->scsi_done(cmd); +} + /** * NCR5380_queue_command - queue a command * @instance: the relevant SCSI adapter @@ -1171,7 +1189,7 @@ static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd) spin_lock_irq(&hostdata->lock); NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); cmd->result = DID_BAD_TARGET << 16; - cmd->scsi_done(cmd); + complete_cmd(instance, cmd); NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); dprintk(NDEBUG_SELECTION, "scsi%d : target did not respond within 250ms\n", instance->host_no); @@ -1759,7 +1777,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { sink = 1; do_abort(instance); cmd->result = DID_ERROR << 16; - cmd->scsi_done(cmd); + complete_cmd(instance, cmd); return; #endif case PHASE_DATAIN: @@ -1804,7 +1822,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { sink = 1; do_abort(instance); cmd->result = DID_ERROR << 16; - cmd->scsi_done(cmd); + complete_cmd(instance, cmd); /* XXX - need to source or sink data here, as appropriate */ } else cmd->SCp.this_residual -= transfersize - len; @@ -1834,7 +1852,6 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { cmd, scmd_id(cmd), cmd->device->lun); hostdata->connected = NULL; - hostdata->busy[cmd->device->id] &= ~(1 << (cmd->device->lun & 0xFF)); /* * I'm not sure what the correct thing to do here is : @@ -1870,8 +1887,9 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { dsprintk(NDEBUG_AUTOSENSE | NDEBUG_QUEUES, instance, "REQUEST SENSE cmd %p added to head of issue queue\n", cmd); + hostdata->busy[cmd->device->id] &= ~(1 << (cmd->device->lun & 0xFF)); } else { - cmd->scsi_done(cmd); + complete_cmd(instance, cmd); } /* @@ -2018,10 +2036,9 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { hostdata->last_message = msgout; NCR5380_transfer_pio(instance, &phase, &len, &data); if (msgout == ABORT) { - hostdata->busy[cmd->device->id] &= ~(1 << (cmd->device->lun & 0xFF)); hostdata->connected = NULL; cmd->result = DID_ERROR << 16; - cmd->scsi_done(cmd); + complete_cmd(instance, cmd); NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); return; } diff --git a/drivers/scsi/atari_NCR5380.c b/drivers/scsi/atari_NCR5380.c index 12b98cbe7b44..a1f9f390d763 100644 --- a/drivers/scsi/atari_NCR5380.c +++ b/drivers/scsi/atari_NCR5380.c @@ -764,6 +764,27 @@ static void NCR5380_exit(struct Scsi_Host *instance) destroy_workqueue(hostdata->work_q); } +/** + * complete_cmd - finish processing a command and return it to the SCSI ML + * @instance: the host instance + * @cmd: command to complete + */ + +static void complete_cmd(struct Scsi_Host *instance, + struct scsi_cmnd *cmd) +{ + struct NCR5380_hostdata *hostdata = shost_priv(instance); + + dsprintk(NDEBUG_QUEUES, instance, "complete_cmd: cmd %p\n", cmd); + +#ifdef SUPPORT_TAGS + cmd_free_tag(cmd); +#else + hostdata->busy[scmd_id(cmd)] &= ~(1 << cmd->device->lun); +#endif + cmd->scsi_done(cmd); +} + /** * NCR5380_queue_command - queue a command * @instance: the relevant SCSI adapter @@ -1352,10 +1373,7 @@ static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd) spin_lock_irq(&hostdata->lock); NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); cmd->result = DID_BAD_TARGET << 16; -#ifdef SUPPORT_TAGS - cmd_free_tag(cmd); -#endif - cmd->scsi_done(cmd); + complete_cmd(instance, cmd); NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); dprintk(NDEBUG_SELECTION, "scsi%d: target did not respond within 250ms\n", HOSTNO); return 0; @@ -1866,7 +1884,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) sink = 1; do_abort(instance); cmd->result = DID_ERROR << 16; - cmd->scsi_done(cmd); + complete_cmd(instance, cmd); return; #endif case PHASE_DATAIN: @@ -1926,7 +1944,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) sink = 1; do_abort(instance); cmd->result = DID_ERROR << 16; - cmd->scsi_done(cmd); + complete_cmd(instance, cmd); /* XXX - need to source or sink data here, as appropriate */ } else { #ifdef REAL_DMA @@ -1982,8 +2000,6 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) if (ta->queue_size > ta->nr_allocated) ta->queue_size = ta->nr_allocated; } -#else - hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun); #endif /* @@ -2021,8 +2037,13 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) dsprintk(NDEBUG_AUTOSENSE | NDEBUG_QUEUES, instance, "REQUEST SENSE cmd %p added to head of issue queue\n", cmd); +#ifdef SUPPORT_TAGS + cmd_free_tag(cmd); +#else + hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun); +#endif } else { - cmd->scsi_done(cmd); + complete_cmd(instance, cmd); } /* @@ -2193,15 +2214,10 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) hostdata->last_message = msgout; NCR5380_transfer_pio(instance, &phase, &len, &data); if (msgout == ABORT) { -#ifdef SUPPORT_TAGS - cmd_free_tag(cmd); -#else - hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun); -#endif hostdata->connected = NULL; cmd->result = DID_ERROR << 16; + complete_cmd(instance, cmd); maybe_release_dma_irq(instance); - cmd->scsi_done(cmd); NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); return; } -- cgit From f27db8eb98a19e0f1b5748f8aad9fb4a98301eb0 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sun, 3 Jan 2016 16:06:00 +1100 Subject: ncr5380: Fix autosense bugs NCR5380_information_transfer() may re-queue a command for autosense, after calling scsi_eh_prep_cmnd(). This creates several possibilities: 1. Reselection may intervene before the re-queued command gets processed. If the reconnected command then undergoes autosense, this causes the scsi_eh_save data from the previous command to be overwritten. 2. After NCR5380_information_transfer() calls scsi_eh_prep_cmnd(), a new REQUEST SENSE command may arrive. This would be queued ahead of any command already undergoing autosense, which means the scsi_eh_save data might be restored to the wrong command. 3. After NCR5380_information_transfer() calls scsi_eh_prep_cmnd(), eh_abort_handler() may abort the command. But the scsi_eh_save data is not discarded, which means the scsi_eh_save data might be incorrectly restored to the next REQUEST SENSE command issued. This patch adds a new autosense list so that commands that are re-queued because of a CHECK CONDITION result can be kept apart from the REQUEST SENSE commands that arrive via queuecommand. This patch also adds a function dedicated to dequeueing and preparing the next command for processing. By refactoring the main loop in this way, scsi_eh_save takes place when an autosense command is dequeued rather than when re-queued. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Ondrej Zary Tested-by: Michael Schmitz Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.c | 194 ++++++++++++++++++++--------------- drivers/scsi/NCR5380.h | 2 + drivers/scsi/atari_NCR5380.c | 239 ++++++++++++++++++++++++------------------- 3 files changed, 249 insertions(+), 186 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index 08319164f012..2c9133f4c386 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -244,6 +244,9 @@ static inline void initialize_SCp(struct scsi_cmnd *cmd) cmd->SCp.ptr = NULL; cmd->SCp.this_residual = 0; } + + cmd->SCp.Status = 0; + cmd->SCp.Message = 0; } /** @@ -622,6 +625,8 @@ static int NCR5380_init(struct Scsi_Host *instance, int flags) #endif spin_lock_init(&hostdata->lock); hostdata->connected = NULL; + hostdata->sensing = NULL; + INIT_LIST_HEAD(&hostdata->autosense); INIT_LIST_HEAD(&hostdata->unissued); INIT_LIST_HEAD(&hostdata->disconnected); @@ -738,6 +743,16 @@ static void complete_cmd(struct Scsi_Host *instance, dsprintk(NDEBUG_QUEUES, instance, "complete_cmd: cmd %p\n", cmd); + if (hostdata->sensing == cmd) { + /* Autosense processing ends here */ + if ((cmd->result & 0xff) != SAM_STAT_GOOD) { + scsi_eh_restore_cmnd(cmd, &hostdata->ses); + set_host_byte(cmd, DID_ERROR); + } else + scsi_eh_restore_cmnd(cmd, &hostdata->ses); + hostdata->sensing = NULL; + } + hostdata->busy[scmd_id(cmd)] &= ~(1 << cmd->device->lun); cmd->scsi_done(cmd); @@ -797,6 +812,64 @@ static int NCR5380_queue_command(struct Scsi_Host *instance, return 0; } +/** + * dequeue_next_cmd - dequeue a command for processing + * @instance: the scsi host instance + * + * Priority is given to commands on the autosense queue. These commands + * need autosense because of a CHECK CONDITION result. + * + * Returns a command pointer if a command is found for a target that is + * not already busy. Otherwise returns NULL. + */ + +static struct scsi_cmnd *dequeue_next_cmd(struct Scsi_Host *instance) +{ + struct NCR5380_hostdata *hostdata = shost_priv(instance); + struct NCR5380_cmd *ncmd; + struct scsi_cmnd *cmd; + + if (list_empty(&hostdata->autosense)) { + list_for_each_entry(ncmd, &hostdata->unissued, list) { + cmd = NCR5380_to_scmd(ncmd); + dsprintk(NDEBUG_QUEUES, instance, "dequeue: cmd=%p target=%d busy=0x%02x lun=%llu\n", + cmd, scmd_id(cmd), hostdata->busy[scmd_id(cmd)], cmd->device->lun); + + if (!(hostdata->busy[scmd_id(cmd)] & (1 << cmd->device->lun))) { + list_del(&ncmd->list); + dsprintk(NDEBUG_QUEUES, instance, + "dequeue: removed %p from issue queue\n", cmd); + return cmd; + } + } + } else { + /* Autosense processing begins here */ + ncmd = list_first_entry(&hostdata->autosense, + struct NCR5380_cmd, list); + list_del(&ncmd->list); + cmd = NCR5380_to_scmd(ncmd); + dsprintk(NDEBUG_QUEUES, instance, + "dequeue: removed %p from autosense queue\n", cmd); + scsi_eh_prep_cmnd(cmd, &hostdata->ses, NULL, 0, ~0); + hostdata->sensing = cmd; + return cmd; + } + return NULL; +} + +static void requeue_cmd(struct Scsi_Host *instance, struct scsi_cmnd *cmd) +{ + struct NCR5380_hostdata *hostdata = shost_priv(instance); + struct NCR5380_cmd *ncmd = scsi_cmd_priv(cmd); + + if (hostdata->sensing) { + scsi_eh_restore_cmnd(cmd, &hostdata->ses); + list_add(&ncmd->list, &hostdata->autosense); + hostdata->sensing = NULL; + } else + list_add(&ncmd->list, &hostdata->unissued); +} + /** * NCR5380_main - NCR state machines * @@ -814,63 +887,40 @@ static void NCR5380_main(struct work_struct *work) struct NCR5380_hostdata *hostdata = container_of(work, struct NCR5380_hostdata, main_task); struct Scsi_Host *instance = hostdata->host; - struct NCR5380_cmd *ncmd, *n; + struct scsi_cmnd *cmd; int done; spin_lock_irq(&hostdata->lock); do { done = 1; - if (!hostdata->connected) { - dprintk(NDEBUG_MAIN, "scsi%d : not connected\n", instance->host_no); - /* - * Search through the issue_queue for a command destined - * for a target that's not busy. - */ - list_for_each_entry_safe(ncmd, n, &hostdata->unissued, - list) { - struct scsi_cmnd *tmp = NCR5380_to_scmd(ncmd); - - dsprintk(NDEBUG_QUEUES, instance, "main: tmp=%p target=%d busy=%d lun=%llu\n", - tmp, scmd_id(tmp), hostdata->busy[scmd_id(tmp)], - tmp->device->lun); - /* When we find one, remove it from the issue queue. */ - if (!(hostdata->busy[tmp->device->id] & - (1 << (u8)(tmp->device->lun & 0xff)))) { - list_del(&ncmd->list); - dsprintk(NDEBUG_MAIN | NDEBUG_QUEUES, - instance, "main: removed %p from issue queue\n", - tmp); + while (!hostdata->connected && + (cmd = dequeue_next_cmd(instance))) { - /* - * Attempt to establish an I_T_L nexus here. - * On success, instance->hostdata->connected is set. - * On failure, we must add the command back to the - * issue queue so we can keep trying. - */ - /* - * REQUEST SENSE commands are issued without tagged - * queueing, even on SCSI-II devices because the - * contingent allegiance condition exists for the - * entire unit. - */ + dsprintk(NDEBUG_MAIN, instance, "main: dequeued %p\n", cmd); - if (!NCR5380_select(instance, tmp)) { - /* OK or bad target */ - } else { - /* Need to retry */ - list_add(&ncmd->list, &hostdata->unissued); - dsprintk(NDEBUG_MAIN | NDEBUG_QUEUES, - instance, "main: select() failed, %p returned to issue queue\n", - tmp); - done = 0; - } - if (hostdata->connected) - break; - } /* if target/lun is not busy */ - } /* for */ - } /* if (!hostdata->connected) */ + /* + * Attempt to establish an I_T_L nexus here. + * On success, instance->hostdata->connected is set. + * On failure, we must add the command back to the + * issue queue so we can keep trying. + */ + /* + * REQUEST SENSE commands are issued without tagged + * queueing, even on SCSI-II devices because the + * contingent allegiance condition exists for the + * entire unit. + */ + if (!NCR5380_select(instance, cmd)) { + dsprintk(NDEBUG_MAIN, instance, "main: selected target %d for command %p\n", + scmd_id(cmd), cmd); + } else { + dsprintk(NDEBUG_MAIN | NDEBUG_QUEUES, instance, + "main: select failed, returning %p to queue\n", cmd); + requeue_cmd(instance, cmd); + } + } if (hostdata->connected #ifdef REAL_DMA && !hostdata->dmalen @@ -1853,43 +1903,21 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { hostdata->connected = NULL; - /* - * I'm not sure what the correct thing to do here is : - * - * If the command that just executed is NOT a request - * sense, the obvious thing to do is to set the result - * code to the values of the stored parameters. - * - * If it was a REQUEST SENSE command, we need some way - * to differentiate between the failure code of the original - * and the failure code of the REQUEST sense - the obvious - * case is success, where we fall through and leave the result - * code unchanged. - * - * The non-obvious place is where the REQUEST SENSE failed - */ - - if (cmd->cmnd[0] != REQUEST_SENSE) - cmd->result = cmd->SCp.Status | (cmd->SCp.Message << 8); - else if (status_byte(cmd->SCp.Status) != GOOD) - cmd->result = (cmd->result & 0x00ffff) | (DID_ERROR << 16); - - if ((cmd->cmnd[0] == REQUEST_SENSE) && - hostdata->ses.cmd_len) { - scsi_eh_restore_cmnd(cmd, &hostdata->ses); - hostdata->ses.cmd_len = 0 ; - } - - if ((cmd->cmnd[0] != REQUEST_SENSE) && (status_byte(cmd->SCp.Status) == CHECK_CONDITION)) { - scsi_eh_prep_cmnd(cmd, &hostdata->ses, NULL, 0, ~0); + cmd->result &= ~0xffff; + cmd->result |= cmd->SCp.Status; + cmd->result |= cmd->SCp.Message << 8; - list_add(&ncmd->list, &hostdata->unissued); - dsprintk(NDEBUG_AUTOSENSE | NDEBUG_QUEUES, - instance, "REQUEST SENSE cmd %p added to head of issue queue\n", - cmd); - hostdata->busy[cmd->device->id] &= ~(1 << (cmd->device->lun & 0xFF)); - } else { + if (cmd->cmnd[0] == REQUEST_SENSE) complete_cmd(instance, cmd); + else { + if (cmd->SCp.Status == SAM_STAT_CHECK_CONDITION || + cmd->SCp.Status == SAM_STAT_COMMAND_TERMINATED) { + dsprintk(NDEBUG_QUEUES, instance, "autosense: adding cmd %p to tail of autosense queue\n", + cmd); + list_add_tail(&ncmd->list, + &hostdata->autosense); + } else + complete_cmd(instance, cmd); } /* diff --git a/drivers/scsi/NCR5380.h b/drivers/scsi/NCR5380.h index 56252a5516d7..81e077afa8db 100644 --- a/drivers/scsi/NCR5380.h +++ b/drivers/scsi/NCR5380.h @@ -256,10 +256,12 @@ struct NCR5380_hostdata { unsigned char last_message; /* last message OUT */ struct scsi_cmnd *connected; /* currently connected cmnd */ struct list_head unissued; /* waiting to be issued */ + struct list_head autosense; /* priority issue queue */ struct list_head disconnected; /* waiting for reconnect */ spinlock_t lock; /* protects this struct */ int flags; struct scsi_eh_save ses; + struct scsi_cmnd *sensing; char info[256]; int read_overruns; /* number of bytes to cut from a * transfer to handle chip overruns */ diff --git a/drivers/scsi/atari_NCR5380.c b/drivers/scsi/atari_NCR5380.c index a1f9f390d763..1fcfbd82474d 100644 --- a/drivers/scsi/atari_NCR5380.c +++ b/drivers/scsi/atari_NCR5380.c @@ -418,6 +418,9 @@ static inline void initialize_SCp(struct scsi_cmnd *cmd) cmd->SCp.ptr = NULL; cmd->SCp.this_residual = 0; } + + cmd->SCp.Status = 0; + cmd->SCp.Message = 0; } /** @@ -661,6 +664,8 @@ static int __init NCR5380_init(struct Scsi_Host *instance, int flags) #endif spin_lock_init(&hostdata->lock); hostdata->connected = NULL; + hostdata->sensing = NULL; + INIT_LIST_HEAD(&hostdata->autosense); INIT_LIST_HEAD(&hostdata->unissued); INIT_LIST_HEAD(&hostdata->disconnected); @@ -777,6 +782,16 @@ static void complete_cmd(struct Scsi_Host *instance, dsprintk(NDEBUG_QUEUES, instance, "complete_cmd: cmd %p\n", cmd); + if (hostdata->sensing == cmd) { + /* Autosense processing ends here */ + if ((cmd->result & 0xff) != SAM_STAT_GOOD) { + scsi_eh_restore_cmnd(cmd, &hostdata->ses); + set_host_byte(cmd, DID_ERROR); + } else + scsi_eh_restore_cmnd(cmd, &hostdata->ses); + hostdata->sensing = NULL; + } + #ifdef SUPPORT_TAGS cmd_free_tag(cmd); #else @@ -868,11 +883,76 @@ static inline void maybe_release_dma_irq(struct Scsi_Host *instance) /* Caller does the locking needed to set & test these data atomically */ if (list_empty(&hostdata->disconnected) && list_empty(&hostdata->unissued) && + list_empty(&hostdata->autosense) && !hostdata->connected && !hostdata->retain_dma_intr) NCR5380_release_dma_irq(instance); } +/** + * dequeue_next_cmd - dequeue a command for processing + * @instance: the scsi host instance + * + * Priority is given to commands on the autosense queue. These commands + * need autosense because of a CHECK CONDITION result. + * + * Returns a command pointer if a command is found for a target that is + * not already busy. Otherwise returns NULL. + */ + +static struct scsi_cmnd *dequeue_next_cmd(struct Scsi_Host *instance) +{ + struct NCR5380_hostdata *hostdata = shost_priv(instance); + struct NCR5380_cmd *ncmd; + struct scsi_cmnd *cmd; + + if (list_empty(&hostdata->autosense)) { + list_for_each_entry(ncmd, &hostdata->unissued, list) { + cmd = NCR5380_to_scmd(ncmd); + dsprintk(NDEBUG_QUEUES, instance, "dequeue: cmd=%p target=%d busy=0x%02x lun=%llu\n", + cmd, scmd_id(cmd), hostdata->busy[scmd_id(cmd)], cmd->device->lun); + + if ( +#ifdef SUPPORT_TAGS + !is_lun_busy(cmd, 1) +#else + !(hostdata->busy[scmd_id(cmd)] & (1 << cmd->device->lun)) +#endif + ) { + list_del(&ncmd->list); + dsprintk(NDEBUG_QUEUES, instance, + "dequeue: removed %p from issue queue\n", cmd); + return cmd; + } + } + } else { + /* Autosense processing begins here */ + ncmd = list_first_entry(&hostdata->autosense, + struct NCR5380_cmd, list); + list_del(&ncmd->list); + cmd = NCR5380_to_scmd(ncmd); + dsprintk(NDEBUG_QUEUES, instance, + "dequeue: removed %p from autosense queue\n", cmd); + scsi_eh_prep_cmnd(cmd, &hostdata->ses, NULL, 0, ~0); + hostdata->sensing = cmd; + return cmd; + } + return NULL; +} + +static void requeue_cmd(struct Scsi_Host *instance, struct scsi_cmnd *cmd) +{ + struct NCR5380_hostdata *hostdata = shost_priv(instance); + struct NCR5380_cmd *ncmd = scsi_cmd_priv(cmd); + + if (hostdata->sensing) { + scsi_eh_restore_cmnd(cmd, &hostdata->ses); + list_add(&ncmd->list, &hostdata->autosense); + hostdata->sensing = NULL; + } else + list_add(&ncmd->list, &hostdata->unissued); +} + /** * NCR5380_main - NCR state machines * @@ -889,7 +969,7 @@ static void NCR5380_main(struct work_struct *work) struct NCR5380_hostdata *hostdata = container_of(work, struct NCR5380_hostdata, main_task); struct Scsi_Host *instance = hostdata->host; - struct NCR5380_cmd *ncmd, *n; + struct scsi_cmnd *cmd; int done; /* @@ -902,75 +982,46 @@ static void NCR5380_main(struct work_struct *work) do { done = 1; - if (!hostdata->connected) { - dprintk(NDEBUG_MAIN, "scsi%d: not connected\n", HOSTNO); - /* - * Search through the issue_queue for a command destined - * for a target that's not busy. - */ - list_for_each_entry_safe(ncmd, n, &hostdata->unissued, - list) { - struct scsi_cmnd *tmp = NCR5380_to_scmd(ncmd); - u8 lun = tmp->device->lun; - - dsprintk(NDEBUG_QUEUES, instance, "main: tmp=%p target=%d busy=%d lun=%d\n", - tmp, scmd_id(tmp), hostdata->busy[scmd_id(tmp)], lun); - /* When we find one, remove it from the issue queue. */ - if ( -#ifdef SUPPORT_TAGS - !is_lun_busy( tmp, tmp->cmnd[0] != REQUEST_SENSE) -#else - !(hostdata->busy[tmp->device->id] & (1 << lun)) -#endif - ) { - list_del(&ncmd->list); - dsprintk(NDEBUG_MAIN | NDEBUG_QUEUES, - instance, "main: removed %p from issue queue\n", - tmp); + while (!hostdata->connected && + (cmd = dequeue_next_cmd(instance))) { - hostdata->retain_dma_intr++; + dsprintk(NDEBUG_MAIN, instance, "main: dequeued %p\n", cmd); - /* - * Attempt to establish an I_T_L nexus here. - * On success, instance->hostdata->connected is set. - * On failure, we must add the command back to the - * issue queue so we can keep trying. - */ - /* - * REQUEST SENSE commands are issued without tagged - * queueing, even on SCSI-II devices because the - * contingent allegiance condition exists for the - * entire unit. - */ - /* ++roman: ...and the standard also requires that - * REQUEST SENSE command are untagged. - */ + /* + * Attempt to establish an I_T_L nexus here. + * On success, instance->hostdata->connected is set. + * On failure, we must add the command back to the + * issue queue so we can keep trying. + */ + /* + * REQUEST SENSE commands are issued without tagged + * queueing, even on SCSI-II devices because the + * contingent allegiance condition exists for the + * entire unit. + */ + /* ++roman: ...and the standard also requires that + * REQUEST SENSE command are untagged. + */ #ifdef SUPPORT_TAGS - cmd_get_tag(tmp, tmp->cmnd[0] != REQUEST_SENSE); + cmd_get_tag(cmd, cmd->cmnd[0] != REQUEST_SENSE); #endif - if (!NCR5380_select(instance, tmp)) { - /* OK or bad target */ - hostdata->retain_dma_intr--; - maybe_release_dma_irq(instance); - } else { - /* Need to retry */ - list_add(&ncmd->list, &hostdata->unissued); - dsprintk(NDEBUG_MAIN | NDEBUG_QUEUES, - instance, "main: select() failed, %p returned to issue queue\n", - tmp); + hostdata->retain_dma_intr++; + if (!NCR5380_select(instance, cmd)) { + dsprintk(NDEBUG_MAIN, instance, "main: selected target %d for command %p\n", + scmd_id(cmd), cmd); + hostdata->retain_dma_intr--; + maybe_release_dma_irq(instance); + } else { + hostdata->retain_dma_intr--; + dsprintk(NDEBUG_MAIN | NDEBUG_QUEUES, instance, + "main: select failed, returning %p to queue\n", cmd); + requeue_cmd(instance, cmd); #ifdef SUPPORT_TAGS - cmd_free_tag(tmp); + cmd_free_tag(cmd); #endif - hostdata->retain_dma_intr--; - done = 0; - } - if (hostdata->connected) - break; - } /* if target/lun/target queue is not busy */ - } /* for issue_queue */ - } /* if (!hostdata->connected) */ - + } + } if (hostdata->connected #ifdef REAL_DMA && !hostdata->dma_len @@ -2002,48 +2053,21 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) } #endif - /* - * I'm not sure what the correct thing to do here is : - * - * If the command that just executed is NOT a request - * sense, the obvious thing to do is to set the result - * code to the values of the stored parameters. - * - * If it was a REQUEST SENSE command, we need some way to - * differentiate between the failure code of the original - * and the failure code of the REQUEST sense - the obvious - * case is success, where we fall through and leave the - * result code unchanged. - * - * The non-obvious place is where the REQUEST SENSE failed - */ - - if (cmd->cmnd[0] != REQUEST_SENSE) - cmd->result = cmd->SCp.Status | (cmd->SCp.Message << 8); - else if (status_byte(cmd->SCp.Status) != GOOD) - cmd->result = (cmd->result & 0x00ffff) | (DID_ERROR << 16); - - if ((cmd->cmnd[0] == REQUEST_SENSE) && - hostdata->ses.cmd_len) { - scsi_eh_restore_cmnd(cmd, &hostdata->ses); - hostdata->ses.cmd_len = 0 ; - } + cmd->result &= ~0xffff; + cmd->result |= cmd->SCp.Status; + cmd->result |= cmd->SCp.Message << 8; - if ((cmd->cmnd[0] != REQUEST_SENSE) && - (status_byte(cmd->SCp.Status) == CHECK_CONDITION)) { - scsi_eh_prep_cmnd(cmd, &hostdata->ses, NULL, 0, ~0); - - list_add(&ncmd->list, &hostdata->unissued); - dsprintk(NDEBUG_AUTOSENSE | NDEBUG_QUEUES, - instance, "REQUEST SENSE cmd %p added to head of issue queue\n", - cmd); -#ifdef SUPPORT_TAGS - cmd_free_tag(cmd); -#else - hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun); -#endif - } else { + if (cmd->cmnd[0] == REQUEST_SENSE) complete_cmd(instance, cmd); + else { + if (cmd->SCp.Status == SAM_STAT_CHECK_CONDITION || + cmd->SCp.Status == SAM_STAT_COMMAND_TERMINATED) { + dsprintk(NDEBUG_QUEUES, instance, "autosense: adding cmd %p to tail of autosense queue\n", + cmd); + list_add_tail(&ncmd->list, + &hostdata->autosense); + } else + complete_cmd(instance, cmd); } /* @@ -2533,6 +2557,15 @@ static int NCR5380_bus_reset(struct scsi_cmnd *cmd) dsprintk(NDEBUG_ABORT, instance, "reset aborted a connected command\n"); hostdata->connected = NULL; + if (hostdata->sensing) { + complete_cmd(instance, hostdata->sensing); + hostdata->sensing = NULL; + } + + if (!list_empty(&hostdata->autosense)) + dsprintk(NDEBUG_ABORT, instance, "reset aborted autosense list\n"); + INIT_LIST_HEAD(&hostdata->autosense); + if (!list_empty(&hostdata->unissued)) dsprintk(NDEBUG_ABORT, instance, "reset aborted unissued list\n"); INIT_LIST_HEAD(&hostdata->unissued); -- cgit From 8b00c3d5d40da0477fceffadcfbc2c09f24104d0 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sun, 3 Jan 2016 16:06:01 +1100 Subject: ncr5380: Implement new eh_abort_handler Introduce a new eh_abort_handler implementation. This one attempts to follow all of the rules relating to EH handlers. There is still a known bug: during selection, a command becomes invisible to the EH handlers because it only appears in a pointer on the stack of a different thread. This bug is addressed in a subsequent patch. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Ondrej Zary Tested-by: Michael Schmitz Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.c | 163 +++++++++++++++++++++++++++++++++++++----- drivers/scsi/atari_NCR5380.c | 165 ++++++++++++++++++++++++++++++++++++++----- 2 files changed, 290 insertions(+), 38 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index 2c9133f4c386..d24852b2a7f3 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -2269,23 +2269,65 @@ static void NCR5380_dma_complete(NCR5380_instance * instance) { } #endif /* def REAL_DMA */ -/* - * Function : int NCR5380_abort (struct scsi_cmnd *cmd) - * - * Purpose : abort a command - * - * Inputs : cmd - the scsi_cmnd to abort, code - code to set the - * host byte of the result field to, if zero DID_ABORTED is - * used. - * - * Returns : SUCCESS - success, FAILED on failure. - * - * XXX - there is no way to abort the command that is currently - * connected, you have to wait for it to complete. If this is - * a problem, we could implement longjmp() / setjmp(), setjmp() - * called where the loop started in NCR5380_main(). - * - * Locks: host lock taken by caller +/** + * list_find_cmd - test for presence of a command in a linked list + * @haystack: list of commands + * @needle: command to search for + */ + +static bool list_find_cmd(struct list_head *haystack, + struct scsi_cmnd *needle) +{ + struct NCR5380_cmd *ncmd; + + list_for_each_entry(ncmd, haystack, list) + if (NCR5380_to_scmd(ncmd) == needle) + return true; + return false; +} + +/** + * list_remove_cmd - remove a command from linked list + * @haystack: list of commands + * @needle: command to remove + */ + +static bool list_del_cmd(struct list_head *haystack, + struct scsi_cmnd *needle) +{ + if (list_find_cmd(haystack, needle)) { + struct NCR5380_cmd *ncmd = scsi_cmd_priv(needle); + + list_del(&ncmd->list); + return true; + } + return false; +} + +/** + * NCR5380_abort - scsi host eh_abort_handler() method + * @cmd: the command to be aborted + * + * Try to abort a given command by removing it from queues and/or sending + * the target an abort message. This may not succeed in causing a target + * to abort the command. Nonetheless, the low-level driver must forget about + * the command because the mid-layer reclaims it and it may be re-issued. + * + * The normal path taken by a command is as follows. For EH we trace this + * same path to locate and abort the command. + * + * unissued -> selecting -> [unissued -> selecting ->]... connected -> + * [disconnected -> connected ->]... + * [autosense -> connected ->] done + * + * If cmd is unissued then just remove it. + * If cmd is disconnected, try to select the target. + * If cmd is connected, try to send an abort message. + * If cmd is waiting for autosense, give it a chance to complete but check + * that it isn't left connected. + * If cmd was not found at all then presumably it has already been completed, + * in which case return SUCCESS to try to avoid further EH measures. + * If the command has not completed yet, we must not fail to find it. */ static int NCR5380_abort(struct scsi_cmnd *cmd) @@ -2293,18 +2335,101 @@ static int NCR5380_abort(struct scsi_cmnd *cmd) struct Scsi_Host *instance = cmd->device->host; struct NCR5380_hostdata *hostdata = shost_priv(instance); unsigned long flags; + int result = SUCCESS; spin_lock_irqsave(&hostdata->lock, flags); #if (NDEBUG & NDEBUG_ANY) - scmd_printk(KERN_INFO, cmd, "aborting command\n"); + scmd_printk(KERN_INFO, cmd, __func__); #endif NCR5380_dprint(NDEBUG_ANY, instance); NCR5380_dprint_phase(NDEBUG_ANY, instance); + if (list_del_cmd(&hostdata->unissued, cmd)) { + dsprintk(NDEBUG_ABORT, instance, + "abort: removed %p from issue queue\n", cmd); + cmd->result = DID_ABORT << 16; + cmd->scsi_done(cmd); /* No tag or busy flag to worry about */ + } + + if (list_del_cmd(&hostdata->disconnected, cmd)) { + dsprintk(NDEBUG_ABORT, instance, + "abort: removed %p from disconnected list\n", cmd); + cmd->result = DID_ERROR << 16; + if (!hostdata->connected) + NCR5380_select(instance, cmd); + if (hostdata->connected != cmd) { + complete_cmd(instance, cmd); + result = FAILED; + goto out; + } + } + + if (hostdata->connected == cmd) { + dsprintk(NDEBUG_ABORT, instance, "abort: cmd %p is connected\n", cmd); + hostdata->connected = NULL; + if (do_abort(instance)) { + set_host_byte(cmd, DID_ERROR); + complete_cmd(instance, cmd); + result = FAILED; + goto out; + } + set_host_byte(cmd, DID_ABORT); +#ifdef REAL_DMA + hostdata->dma_len = 0; +#endif + if (cmd->cmnd[0] == REQUEST_SENSE) + complete_cmd(instance, cmd); + else { + struct NCR5380_cmd *ncmd = scsi_cmd_priv(cmd); + + /* Perform autosense for this command */ + list_add(&ncmd->list, &hostdata->autosense); + } + } + + if (list_find_cmd(&hostdata->autosense, cmd)) { + dsprintk(NDEBUG_ABORT, instance, + "abort: found %p on sense queue\n", cmd); + spin_unlock_irqrestore(&hostdata->lock, flags); + queue_work(hostdata->work_q, &hostdata->main_task); + msleep(1000); + spin_lock_irqsave(&hostdata->lock, flags); + if (list_del_cmd(&hostdata->autosense, cmd)) { + dsprintk(NDEBUG_ABORT, instance, + "abort: removed %p from sense queue\n", cmd); + set_host_byte(cmd, DID_ABORT); + complete_cmd(instance, cmd); + goto out; + } + } + + if (hostdata->connected == cmd) { + dsprintk(NDEBUG_ABORT, instance, "abort: cmd %p is connected\n", cmd); + hostdata->connected = NULL; + if (do_abort(instance)) { + set_host_byte(cmd, DID_ERROR); + complete_cmd(instance, cmd); + result = FAILED; + goto out; + } + set_host_byte(cmd, DID_ABORT); +#ifdef REAL_DMA + hostdata->dma_len = 0; +#endif + complete_cmd(instance, cmd); + } + +out: + if (result == FAILED) + dsprintk(NDEBUG_ABORT, instance, "abort: failed to abort %p\n", cmd); + else + dsprintk(NDEBUG_ABORT, instance, "abort: successfully aborted %p\n", cmd); + + queue_work(hostdata->work_q, &hostdata->main_task); spin_unlock_irqrestore(&hostdata->lock, flags); - return FAILED; + return result; } diff --git a/drivers/scsi/atari_NCR5380.c b/drivers/scsi/atari_NCR5380.c index 1fcfbd82474d..e3b362380a74 100644 --- a/drivers/scsi/atari_NCR5380.c +++ b/drivers/scsi/atari_NCR5380.c @@ -2480,41 +2480,168 @@ static void NCR5380_reselect(struct Scsi_Host *instance) } -/* - * Function : int NCR5380_abort (struct scsi_cmnd *cmd) - * - * Purpose : abort a command - * - * Inputs : cmd - the scsi_cmnd to abort, code - code to set the - * host byte of the result field to, if zero DID_ABORTED is - * used. - * - * Returns : SUCCESS - success, FAILED on failure. - * - * XXX - there is no way to abort the command that is currently - * connected, you have to wait for it to complete. If this is - * a problem, we could implement longjmp() / setjmp(), setjmp() - * called where the loop started in NCR5380_main(). +/** + * list_find_cmd - test for presence of a command in a linked list + * @haystack: list of commands + * @needle: command to search for + */ + +static bool list_find_cmd(struct list_head *haystack, + struct scsi_cmnd *needle) +{ + struct NCR5380_cmd *ncmd; + + list_for_each_entry(ncmd, haystack, list) + if (NCR5380_to_scmd(ncmd) == needle) + return true; + return false; +} + +/** + * list_remove_cmd - remove a command from linked list + * @haystack: list of commands + * @needle: command to remove */ -static -int NCR5380_abort(struct scsi_cmnd *cmd) +static bool list_del_cmd(struct list_head *haystack, + struct scsi_cmnd *needle) +{ + if (list_find_cmd(haystack, needle)) { + struct NCR5380_cmd *ncmd = scsi_cmd_priv(needle); + + list_del(&ncmd->list); + return true; + } + return false; +} + +/** + * NCR5380_abort - scsi host eh_abort_handler() method + * @cmd: the command to be aborted + * + * Try to abort a given command by removing it from queues and/or sending + * the target an abort message. This may not succeed in causing a target + * to abort the command. Nonetheless, the low-level driver must forget about + * the command because the mid-layer reclaims it and it may be re-issued. + * + * The normal path taken by a command is as follows. For EH we trace this + * same path to locate and abort the command. + * + * unissued -> selecting -> [unissued -> selecting ->]... connected -> + * [disconnected -> connected ->]... + * [autosense -> connected ->] done + * + * If cmd is unissued then just remove it. + * If cmd is disconnected, try to select the target. + * If cmd is connected, try to send an abort message. + * If cmd is waiting for autosense, give it a chance to complete but check + * that it isn't left connected. + * If cmd was not found at all then presumably it has already been completed, + * in which case return SUCCESS to try to avoid further EH measures. + * If the command has not completed yet, we must not fail to find it. + */ + +static int NCR5380_abort(struct scsi_cmnd *cmd) { struct Scsi_Host *instance = cmd->device->host; struct NCR5380_hostdata *hostdata = shost_priv(instance); unsigned long flags; + int result = SUCCESS; spin_lock_irqsave(&hostdata->lock, flags); #if (NDEBUG & NDEBUG_ANY) - scmd_printk(KERN_INFO, cmd, "aborting command\n"); + scmd_printk(KERN_INFO, cmd, __func__); #endif NCR5380_dprint(NDEBUG_ANY, instance); NCR5380_dprint_phase(NDEBUG_ANY, instance); + if (list_del_cmd(&hostdata->unissued, cmd)) { + dsprintk(NDEBUG_ABORT, instance, + "abort: removed %p from issue queue\n", cmd); + cmd->result = DID_ABORT << 16; + cmd->scsi_done(cmd); /* No tag or busy flag to worry about */ + } + + if (list_del_cmd(&hostdata->disconnected, cmd)) { + dsprintk(NDEBUG_ABORT, instance, + "abort: removed %p from disconnected list\n", cmd); + cmd->result = DID_ERROR << 16; + if (!hostdata->connected) + NCR5380_select(instance, cmd); + if (hostdata->connected != cmd) { + complete_cmd(instance, cmd); + result = FAILED; + goto out; + } + } + + if (hostdata->connected == cmd) { + dsprintk(NDEBUG_ABORT, instance, "abort: cmd %p is connected\n", cmd); + hostdata->connected = NULL; + if (do_abort(instance)) { + set_host_byte(cmd, DID_ERROR); + complete_cmd(instance, cmd); + result = FAILED; + goto out; + } + set_host_byte(cmd, DID_ABORT); +#ifdef REAL_DMA + hostdata->dma_len = 0; +#endif + if (cmd->cmnd[0] == REQUEST_SENSE) + complete_cmd(instance, cmd); + else { + struct NCR5380_cmd *ncmd = scsi_cmd_priv(cmd); + + /* Perform autosense for this command */ + list_add(&ncmd->list, &hostdata->autosense); + } + } + + if (list_find_cmd(&hostdata->autosense, cmd)) { + dsprintk(NDEBUG_ABORT, instance, + "abort: found %p on sense queue\n", cmd); + spin_unlock_irqrestore(&hostdata->lock, flags); + queue_work(hostdata->work_q, &hostdata->main_task); + msleep(1000); + spin_lock_irqsave(&hostdata->lock, flags); + if (list_del_cmd(&hostdata->autosense, cmd)) { + dsprintk(NDEBUG_ABORT, instance, + "abort: removed %p from sense queue\n", cmd); + set_host_byte(cmd, DID_ABORT); + complete_cmd(instance, cmd); + goto out; + } + } + + if (hostdata->connected == cmd) { + dsprintk(NDEBUG_ABORT, instance, "abort: cmd %p is connected\n", cmd); + hostdata->connected = NULL; + if (do_abort(instance)) { + set_host_byte(cmd, DID_ERROR); + complete_cmd(instance, cmd); + result = FAILED; + goto out; + } + set_host_byte(cmd, DID_ABORT); +#ifdef REAL_DMA + hostdata->dma_len = 0; +#endif + complete_cmd(instance, cmd); + } + +out: + if (result == FAILED) + dsprintk(NDEBUG_ABORT, instance, "abort: failed to abort %p\n", cmd); + else + dsprintk(NDEBUG_ABORT, instance, "abort: successfully aborted %p\n", cmd); + + queue_work(hostdata->work_q, &hostdata->main_task); + maybe_release_dma_irq(instance); spin_unlock_irqrestore(&hostdata->lock, flags); - return FAILED; + return result; } -- cgit From 707d62b37fbb1de74da6e5cf263bcd8223ae3cf7 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sun, 3 Jan 2016 16:06:02 +1100 Subject: ncr5380: Fix EH during arbitration and selection During arbitration and selection, the relevant command is invisible to exception handlers and can be found only in a pointer on the stack of a different thread. When eh_abort_handler can't find a given command, it can't decide whether that command was completed already or is still in arbitration or selection phase. But it must return either SUCCESS (e.g. command completed earlier) or FAILED (could not abort the nexus, try bus reset). The solution is to make sure all commands belonging to the LLD are always visible to exception handlers. Add another scsi_cmnd pointer to the hostdata struct to track the command in arbitration or selection phase. Replace 'retain_dma_irq' with the new 'selecting' pointer, to bring atari_NCR5380.c into line with NCR5380.c. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Ondrej Zary Tested-by: Michael Schmitz Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.c | 76 ++++++++++++++++++++++++++++++---------- drivers/scsi/NCR5380.h | 4 +-- drivers/scsi/atari_NCR5380.c | 82 ++++++++++++++++++++++++++++++++------------ 3 files changed, 119 insertions(+), 43 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index d24852b2a7f3..32355b62808b 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -912,9 +912,9 @@ static void NCR5380_main(struct work_struct *work) * entire unit. */ - if (!NCR5380_select(instance, cmd)) { - dsprintk(NDEBUG_MAIN, instance, "main: selected target %d for command %p\n", - scmd_id(cmd), cmd); + cmd = NCR5380_select(instance, cmd); + if (!cmd) { + dsprintk(NDEBUG_MAIN, instance, "main: select complete\n"); } else { dsprintk(NDEBUG_MAIN | NDEBUG_QUEUES, instance, "main: select failed, returning %p to queue\n", cmd); @@ -1061,9 +1061,9 @@ static irqreturn_t NCR5380_intr(int irq, void *dev_id) * Inputs : instance - instantiation of the 5380 driver on which this * target lives, cmd - SCSI command to execute. * - * Returns : -1 if selection failed but should be retried. - * 0 if selection failed and should not be retried. - * 0 if selection succeeded completely (hostdata->connected == cmd). + * Returns cmd if selection failed but should be retried, + * NULL if selection failed and should not be retried, or + * NULL if selection succeeded (hostdata->connected == cmd). * * Side effects : * If bus busy, arbitration failed, etc, NCR5380_select() will exit @@ -1081,7 +1081,8 @@ static irqreturn_t NCR5380_intr(int irq, void *dev_id) * Locks: caller holds hostdata lock in IRQ mode */ -static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd) +static struct scsi_cmnd *NCR5380_select(struct Scsi_Host *instance, + struct scsi_cmnd *cmd) { struct NCR5380_hostdata *hostdata = shost_priv(instance); unsigned char tmp[3], phase; @@ -1092,6 +1093,15 @@ static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd) NCR5380_dprint(NDEBUG_ARBITRATION, instance); dprintk(NDEBUG_ARBITRATION, "scsi%d : starting arbitration, id = %d\n", instance->host_no, instance->this_id); + /* + * Arbitration and selection phases are slow and involve dropping the + * lock, so we have to watch out for EH. An exception handler may + * change 'selecting' to NULL. This function will then return NULL + * so that the caller will forget about 'cmd'. (During information + * transfer phases, EH may change 'connected' to NULL.) + */ + hostdata->selecting = cmd; + /* * Set the phase bits to 0, otherwise the NCR5380 won't drive the * data bus during SELECTION. @@ -1117,13 +1127,13 @@ static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd) spin_lock_irq(&hostdata->lock); if (!(NCR5380_read(MODE_REG) & MR_ARBITRATE)) { /* Reselection interrupt */ - return -1; + goto out; } if (err < 0) { NCR5380_write(MODE_REG, MR_BASE); shost_printk(KERN_ERR, instance, "select: arbitration timeout\n"); - return -1; + goto out; } spin_unlock_irq(&hostdata->lock); @@ -1135,7 +1145,7 @@ static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd) NCR5380_write(MODE_REG, MR_BASE); dprintk(NDEBUG_ARBITRATION, "scsi%d : lost arbitration, deasserting MR_ARBITRATE\n", instance->host_no); spin_lock_irq(&hostdata->lock); - return -1; + goto out; } /* After/during arbitration, BSY should be asserted. @@ -1159,7 +1169,13 @@ static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd) /* NCR5380_reselect() clears MODE_REG after a reselection interrupt */ if (!(NCR5380_read(MODE_REG) & MR_ARBITRATE)) - return -1; + goto out; + + if (!hostdata->selecting) { + NCR5380_write(MODE_REG, MR_BASE); + NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); + goto out; + } dprintk(NDEBUG_ARBITRATION, "scsi%d : won arbitration\n", instance->host_no); @@ -1232,18 +1248,21 @@ static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd) if (!hostdata->connected) NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); printk("scsi%d : reselection after won arbitration?\n", instance->host_no); - return -1; + goto out; } if (err < 0) { spin_lock_irq(&hostdata->lock); NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - cmd->result = DID_BAD_TARGET << 16; - complete_cmd(instance, cmd); NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); - dprintk(NDEBUG_SELECTION, "scsi%d : target did not respond within 250ms\n", - instance->host_no); - return 0; + /* Can't touch cmd if it has been reclaimed by the scsi ML */ + if (hostdata->selecting) { + cmd->result = DID_BAD_TARGET << 16; + complete_cmd(instance, cmd); + dsprintk(NDEBUG_SELECTION, instance, "target did not respond within 250ms\n"); + cmd = NULL; + } + goto out; } /* @@ -1279,7 +1298,11 @@ static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd) shost_printk(KERN_ERR, instance, "select: REQ timeout\n"); NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); - return -1; + goto out; + } + if (!hostdata->selecting) { + do_abort(instance); + goto out; } dprintk(NDEBUG_SELECTION, "scsi%d : target %d selected, going into MESSAGE OUT phase.\n", instance->host_no, cmd->device->id); @@ -1300,7 +1323,13 @@ static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd) initialize_SCp(cmd); - return 0; + cmd = NULL; + +out: + if (!hostdata->selecting) + return NULL; + hostdata->selecting = NULL; + return cmd; } /* @@ -2352,6 +2381,15 @@ static int NCR5380_abort(struct scsi_cmnd *cmd) cmd->scsi_done(cmd); /* No tag or busy flag to worry about */ } + if (hostdata->selecting == cmd) { + dsprintk(NDEBUG_ABORT, instance, + "abort: cmd %p == selecting\n", cmd); + hostdata->selecting = NULL; + cmd->result = DID_ABORT << 16; + complete_cmd(instance, cmd); + goto out; + } + if (list_del_cmd(&hostdata->disconnected, cmd)) { dsprintk(NDEBUG_ABORT, instance, "abort: removed %p from disconnected list\n", cmd); diff --git a/drivers/scsi/NCR5380.h b/drivers/scsi/NCR5380.h index 81e077afa8db..ee83ab5f32e8 100644 --- a/drivers/scsi/NCR5380.h +++ b/drivers/scsi/NCR5380.h @@ -255,6 +255,7 @@ struct NCR5380_hostdata { #endif unsigned char last_message; /* last message OUT */ struct scsi_cmnd *connected; /* currently connected cmnd */ + struct scsi_cmnd *selecting; /* cmnd to be connected */ struct list_head unissued; /* waiting to be issued */ struct list_head autosense; /* priority issue queue */ struct list_head disconnected; /* waiting for reconnect */ @@ -265,7 +266,6 @@ struct NCR5380_hostdata { char info[256]; int read_overruns; /* number of bytes to cut from a * transfer to handle chip overruns */ - int retain_dma_intr; struct work_struct main_task; #ifdef SUPPORT_TAGS struct tag_alloc TagAlloc[8][8]; /* 8 targets and 8 LUNs */ @@ -329,7 +329,7 @@ static irqreturn_t NCR5380_intr(int irq, void *dev_id); static void NCR5380_main(struct work_struct *work); static const char *NCR5380_info(struct Scsi_Host *instance); static void NCR5380_reselect(struct Scsi_Host *instance); -static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd); +static struct scsi_cmnd *NCR5380_select(struct Scsi_Host *, struct scsi_cmnd *); #if defined(PSEUDO_DMA) || defined(REAL_DMA) || defined(REAL_DMA_POLL) static int NCR5380_transfer_dma(struct Scsi_Host *instance, unsigned char *phase, int *count, unsigned char **data); #endif diff --git a/drivers/scsi/atari_NCR5380.c b/drivers/scsi/atari_NCR5380.c index e3b362380a74..4a88a7a355eb 100644 --- a/drivers/scsi/atari_NCR5380.c +++ b/drivers/scsi/atari_NCR5380.c @@ -885,7 +885,7 @@ static inline void maybe_release_dma_irq(struct Scsi_Host *instance) list_empty(&hostdata->unissued) && list_empty(&hostdata->autosense) && !hostdata->connected && - !hostdata->retain_dma_intr) + !hostdata->selecting) NCR5380_release_dma_irq(instance); } @@ -1006,14 +1006,11 @@ static void NCR5380_main(struct work_struct *work) #ifdef SUPPORT_TAGS cmd_get_tag(cmd, cmd->cmnd[0] != REQUEST_SENSE); #endif - hostdata->retain_dma_intr++; - if (!NCR5380_select(instance, cmd)) { - dsprintk(NDEBUG_MAIN, instance, "main: selected target %d for command %p\n", - scmd_id(cmd), cmd); - hostdata->retain_dma_intr--; + cmd = NCR5380_select(instance, cmd); + if (!cmd) { + dsprintk(NDEBUG_MAIN, instance, "main: select complete\n"); maybe_release_dma_irq(instance); } else { - hostdata->retain_dma_intr--; dsprintk(NDEBUG_MAIN | NDEBUG_QUEUES, instance, "main: select failed, returning %p to queue\n", cmd); requeue_cmd(instance, cmd); @@ -1241,9 +1238,9 @@ static irqreturn_t NCR5380_intr(int irq, void *dev_id) * Inputs : instance - instantiation of the 5380 driver on which this * target lives, cmd - SCSI command to execute. * - * Returns : -1 if selection failed but should be retried. - * 0 if selection failed and should not be retried. - * 0 if selection succeeded completely (hostdata->connected == cmd). + * Returns cmd if selection failed but should be retried, + * NULL if selection failed and should not be retried, or + * NULL if selection succeeded (hostdata->connected == cmd). * * Side effects : * If bus busy, arbitration failed, etc, NCR5380_select() will exit @@ -1259,7 +1256,8 @@ static irqreturn_t NCR5380_intr(int irq, void *dev_id) * cmd->result host byte set to DID_BAD_TARGET. */ -static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd) +static struct scsi_cmnd *NCR5380_select(struct Scsi_Host *instance, + struct scsi_cmnd *cmd) { struct NCR5380_hostdata *hostdata = shost_priv(instance); unsigned char tmp[3], phase; @@ -1271,6 +1269,15 @@ static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd) dprintk(NDEBUG_ARBITRATION, "scsi%d: starting arbitration, id = %d\n", HOSTNO, instance->this_id); + /* + * Arbitration and selection phases are slow and involve dropping the + * lock, so we have to watch out for EH. An exception handler may + * change 'selecting' to NULL. This function will then return NULL + * so that the caller will forget about 'cmd'. (During information + * transfer phases, EH may change 'connected' to NULL.) + */ + hostdata->selecting = cmd; + /* * Set the phase bits to 0, otherwise the NCR5380 won't drive the * data bus during SELECTION. @@ -1296,13 +1303,13 @@ static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd) spin_lock_irq(&hostdata->lock); if (!(NCR5380_read(MODE_REG) & MR_ARBITRATE)) { /* Reselection interrupt */ - return -1; + goto out; } if (err < 0) { NCR5380_write(MODE_REG, MR_BASE); shost_printk(KERN_ERR, instance, "select: arbitration timeout\n"); - return -1; + goto out; } spin_unlock_irq(&hostdata->lock); @@ -1317,7 +1324,7 @@ static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd) dprintk(NDEBUG_ARBITRATION, "scsi%d: lost arbitration, deasserting MR_ARBITRATE\n", HOSTNO); spin_lock_irq(&hostdata->lock); - return -1; + goto out; } /* After/during arbitration, BSY should be asserted. @@ -1341,7 +1348,13 @@ static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd) /* NCR5380_reselect() clears MODE_REG after a reselection interrupt */ if (!(NCR5380_read(MODE_REG) & MR_ARBITRATE)) - return -1; + goto out; + + if (!hostdata->selecting) { + NCR5380_write(MODE_REG, MR_BASE); + NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); + goto out; + } dprintk(NDEBUG_ARBITRATION, "scsi%d: won arbitration\n", HOSTNO); @@ -1417,17 +1430,21 @@ static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd) NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); printk(KERN_ERR "scsi%d: reselection after won arbitration?\n", HOSTNO); - return -1; + goto out; } if (err < 0) { spin_lock_irq(&hostdata->lock); NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - cmd->result = DID_BAD_TARGET << 16; - complete_cmd(instance, cmd); NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); - dprintk(NDEBUG_SELECTION, "scsi%d: target did not respond within 250ms\n", HOSTNO); - return 0; + /* Can't touch cmd if it has been reclaimed by the scsi ML */ + if (hostdata->selecting) { + cmd->result = DID_BAD_TARGET << 16; + complete_cmd(instance, cmd); + dsprintk(NDEBUG_SELECTION, instance, "target did not respond within 250ms\n"); + cmd = NULL; + } + goto out; } /* @@ -1463,7 +1480,11 @@ static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd) shost_printk(KERN_ERR, instance, "select: REQ timeout\n"); NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); - return -1; + goto out; + } + if (!hostdata->selecting) { + do_abort(instance); + goto out; } dprintk(NDEBUG_SELECTION, "scsi%d: target %d selected, going into MESSAGE OUT phase.\n", @@ -1499,7 +1520,13 @@ static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd) initialize_SCp(cmd); - return 0; + cmd = NULL; + +out: + if (!hostdata->selecting) + return NULL; + hostdata->selecting = NULL; + return cmd; } /* @@ -2563,6 +2590,15 @@ static int NCR5380_abort(struct scsi_cmnd *cmd) cmd->scsi_done(cmd); /* No tag or busy flag to worry about */ } + if (hostdata->selecting == cmd) { + dsprintk(NDEBUG_ABORT, instance, + "abort: cmd %p == selecting\n", cmd); + hostdata->selecting = NULL; + cmd->result = DID_ABORT << 16; + complete_cmd(instance, cmd); + goto out; + } + if (list_del_cmd(&hostdata->disconnected, cmd)) { dsprintk(NDEBUG_ABORT, instance, "abort: removed %p from disconnected list\n", cmd); @@ -2680,6 +2716,8 @@ static int NCR5380_bus_reset(struct scsi_cmnd *cmd) * commands! */ + hostdata->selecting = NULL; + if (hostdata->connected) dsprintk(NDEBUG_ABORT, instance, "reset aborted a connected command\n"); hostdata->connected = NULL; -- cgit From 62717f537e1b325665711166c33cd2d06fd6a5cd Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sun, 3 Jan 2016 16:06:03 +1100 Subject: ncr5380: Implement new eh_bus_reset_handler NCR5380.c lacks a sane eh_bus_reset_handler. The atari_NCR5380.c code is much better but it should not throw out the issue queue (that would be a host reset) and it neglects to set the result code for commands that it throws out. Fix these bugs and keep the two core drivers in sync. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Ondrej Zary Tested-by: Michael Schmitz Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.c | 50 +++++++++++++++++++++++++++++++++++++++++++- drivers/scsi/atari_NCR5380.c | 39 ++++++++++++++++++++-------------- 2 files changed, 72 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index 32355b62808b..b46e0879b4d6 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -2482,18 +2482,66 @@ static int NCR5380_bus_reset(struct scsi_cmnd *cmd) { struct Scsi_Host *instance = cmd->device->host; struct NCR5380_hostdata *hostdata = shost_priv(instance); + int i; unsigned long flags; + struct NCR5380_cmd *ncmd; spin_lock_irqsave(&hostdata->lock, flags); #if (NDEBUG & NDEBUG_ANY) - scmd_printk(KERN_INFO, cmd, "performing bus reset\n"); + scmd_printk(KERN_INFO, cmd, __func__); #endif NCR5380_dprint(NDEBUG_ANY, instance); NCR5380_dprint_phase(NDEBUG_ANY, instance); do_reset(instance); + /* reset NCR registers */ + NCR5380_write(MODE_REG, MR_BASE); + NCR5380_write(TARGET_COMMAND_REG, 0); + NCR5380_write(SELECT_ENABLE_REG, 0); + + /* After the reset, there are no more connected or disconnected commands + * and no busy units; so clear the low-level status here to avoid + * conflicts when the mid-level code tries to wake up the affected + * commands! + */ + + hostdata->selecting = NULL; + + list_for_each_entry(ncmd, &hostdata->disconnected, list) { + struct scsi_cmnd *cmd = NCR5380_to_scmd(ncmd); + + set_host_byte(cmd, DID_RESET); + cmd->scsi_done(cmd); + } + + list_for_each_entry(ncmd, &hostdata->autosense, list) { + struct scsi_cmnd *cmd = NCR5380_to_scmd(ncmd); + + set_host_byte(cmd, DID_RESET); + cmd->scsi_done(cmd); + } + + if (hostdata->connected) { + set_host_byte(hostdata->connected, DID_RESET); + complete_cmd(instance, hostdata->connected); + hostdata->connected = NULL; + } + + if (hostdata->sensing) { + set_host_byte(hostdata->connected, DID_RESET); + complete_cmd(instance, hostdata->sensing); + hostdata->sensing = NULL; + } + + for (i = 0; i < 8; ++i) + hostdata->busy[i] = 0; +#ifdef REAL_DMA + hostdata->dma_len = 0; +#endif + + queue_work(hostdata->work_q, &hostdata->main_task); spin_unlock_irqrestore(&hostdata->lock, flags); return SUCCESS; diff --git a/drivers/scsi/atari_NCR5380.c b/drivers/scsi/atari_NCR5380.c index 4a88a7a355eb..d6717610a65e 100644 --- a/drivers/scsi/atari_NCR5380.c +++ b/drivers/scsi/atari_NCR5380.c @@ -2694,11 +2694,12 @@ static int NCR5380_bus_reset(struct scsi_cmnd *cmd) struct NCR5380_hostdata *hostdata = shost_priv(instance); int i; unsigned long flags; + struct NCR5380_cmd *ncmd; spin_lock_irqsave(&hostdata->lock, flags); #if (NDEBUG & NDEBUG_ANY) - scmd_printk(KERN_INFO, cmd, "performing bus reset\n"); + scmd_printk(KERN_INFO, cmd, __func__); #endif NCR5380_dprint(NDEBUG_ANY, instance); NCR5380_dprint_phase(NDEBUG_ANY, instance); @@ -2718,26 +2719,31 @@ static int NCR5380_bus_reset(struct scsi_cmnd *cmd) hostdata->selecting = NULL; - if (hostdata->connected) - dsprintk(NDEBUG_ABORT, instance, "reset aborted a connected command\n"); - hostdata->connected = NULL; + list_for_each_entry(ncmd, &hostdata->disconnected, list) { + struct scsi_cmnd *cmd = NCR5380_to_scmd(ncmd); - if (hostdata->sensing) { - complete_cmd(instance, hostdata->sensing); - hostdata->sensing = NULL; + set_host_byte(cmd, DID_RESET); + cmd->scsi_done(cmd); } - if (!list_empty(&hostdata->autosense)) - dsprintk(NDEBUG_ABORT, instance, "reset aborted autosense list\n"); - INIT_LIST_HEAD(&hostdata->autosense); + list_for_each_entry(ncmd, &hostdata->autosense, list) { + struct scsi_cmnd *cmd = NCR5380_to_scmd(ncmd); - if (!list_empty(&hostdata->unissued)) - dsprintk(NDEBUG_ABORT, instance, "reset aborted unissued list\n"); - INIT_LIST_HEAD(&hostdata->unissued); + set_host_byte(cmd, DID_RESET); + cmd->scsi_done(cmd); + } - if (!list_empty(&hostdata->disconnected)) - dsprintk(NDEBUG_ABORT, instance, "reset aborted disconnected list\n"); - INIT_LIST_HEAD(&hostdata->disconnected); + if (hostdata->connected) { + set_host_byte(hostdata->connected, DID_RESET); + complete_cmd(instance, hostdata->connected); + hostdata->connected = NULL; + } + + if (hostdata->sensing) { + set_host_byte(hostdata->connected, DID_RESET); + complete_cmd(instance, hostdata->sensing); + hostdata->sensing = NULL; + } #ifdef SUPPORT_TAGS free_all_tags(hostdata); @@ -2748,6 +2754,7 @@ static int NCR5380_bus_reset(struct scsi_cmnd *cmd) hostdata->dma_len = 0; #endif + queue_work(hostdata->work_q, &hostdata->main_task); maybe_release_dma_irq(instance); spin_unlock_irqrestore(&hostdata->lock, flags); -- cgit From 6a6ff4ac0d2d2a706d2a55a35e42e7a77397e45a Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sun, 3 Jan 2016 16:06:04 +1100 Subject: atari_NCR5380: Remove HOSTNO macro from printk() and seq_printf() calls Remove the HOSTNO macro that is peculiar to atari_NCR5380.c and contributes to the problem of divergence of the NCR5380 core drivers. Keep NCR5380.c in sync. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Ondrej Zary Tested-by: Michael Schmitz Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.c | 17 +++++++++-------- drivers/scsi/atari_NCR5380.c | 23 +++++++++-------------- 2 files changed, 18 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index b46e0879b4d6..35464ce90f36 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -418,10 +418,10 @@ static void NCR5380_print_phase(struct Scsi_Host *instance) status = NCR5380_read(STATUS_REG); if (!(status & SR_REQ)) - printk("scsi%d : REQ not asserted, phase unknown.\n", instance->host_no); + shost_printk(KERN_DEBUG, instance, "REQ not asserted, phase unknown.\n"); else { for (i = 0; (phases[i].value != PHASE_UNKNOWN) && (phases[i].value != (status & PHASE_MASK)); ++i); - printk("scsi%d : phase %s\n", instance->host_no, phases[i].name); + shost_printk(KERN_DEBUG, instance, "phase %s\n", phases[i].name); } } #endif @@ -1247,7 +1247,7 @@ static struct scsi_cmnd *NCR5380_select(struct Scsi_Host *instance, NCR5380_reselect(instance); if (!hostdata->connected) NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); - printk("scsi%d : reselection after won arbitration?\n", instance->host_no); + shost_printk(KERN_ERR, instance, "reselection after won arbitration?\n"); goto out; } @@ -1852,7 +1852,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { switch (phase) { case PHASE_DATAOUT: #if (NDEBUG & NDEBUG_NO_DATAOUT) - printk("scsi%d : NDEBUG_NO_DATAOUT set, attempted DATAOUT aborted\n", instance->host_no); + shost_printk(KERN_DEBUG, instance, "NDEBUG_NO_DATAOUT set, attempted DATAOUT aborted\n"); sink = 1; do_abort(instance); cmd->result = DID_ERROR << 16; @@ -2053,10 +2053,11 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { tmp = 0; } } else if (len) { - printk("scsi%d: error receiving extended message\n", instance->host_no); + shost_printk(KERN_ERR, instance, "error receiving extended message\n"); tmp = 0; } else { - printk("scsi%d: extended message code %02x length %d is too long\n", instance->host_no, extended_msg[2], extended_msg[1]); + shost_printk(KERN_NOTICE, instance, "extended message code %02x length %d is too long\n", + extended_msg[2], extended_msg[1]); tmp = 0; } @@ -2072,7 +2073,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { */ default: if (!tmp) { - printk("scsi%d: rejecting message ", instance->host_no); + shost_printk(KERN_ERR, instance, "rejecting message "); spi_print_msg(extended_msg); printk("\n"); } else if (tmp != EXTENDED_MESSAGE) @@ -2118,7 +2119,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { cmd->SCp.Status = tmp; break; default: - printk("scsi%d : unknown phase\n", instance->host_no); + shost_printk(KERN_ERR, instance, "unknown phase\n"); NCR5380_dprint(NDEBUG_ANY, instance); } /* switch(phase) */ } else { diff --git a/drivers/scsi/atari_NCR5380.c b/drivers/scsi/atari_NCR5380.c index d6717610a65e..4517eaa395c2 100644 --- a/drivers/scsi/atari_NCR5380.c +++ b/drivers/scsi/atari_NCR5380.c @@ -569,12 +569,12 @@ static void NCR5380_print_phase(struct Scsi_Host *instance) status = NCR5380_read(STATUS_REG); if (!(status & SR_REQ)) - printk(KERN_DEBUG "scsi%d: REQ not asserted, phase unknown.\n", HOSTNO); + shost_printk(KERN_DEBUG, instance, "REQ not asserted, phase unknown.\n"); else { for (i = 0; (phases[i].value != PHASE_UNKNOWN) && (phases[i].value != (status & PHASE_MASK)); ++i) ; - printk(KERN_DEBUG "scsi%d: phase %s\n", HOSTNO, phases[i].name); + shost_printk(KERN_DEBUG, instance, "phase %s\n", phases[i].name); } } @@ -1428,8 +1428,7 @@ static struct scsi_cmnd *NCR5380_select(struct Scsi_Host *instance, NCR5380_reselect(instance); if (!hostdata->connected) NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); - printk(KERN_ERR "scsi%d: reselection after won arbitration?\n", - HOSTNO); + shost_printk(KERN_ERR, instance, "reselection after won arbitration?\n"); goto out; } @@ -1957,8 +1956,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) switch (phase) { case PHASE_DATAOUT: #if (NDEBUG & NDEBUG_NO_DATAOUT) - printk("scsi%d: NDEBUG_NO_DATAOUT set, attempted DATAOUT " - "aborted\n", HOSTNO); + shost_printk(KERN_DEBUG, instance, "NDEBUG_NO_DATAOUT set, attempted DATAOUT aborted\n"); sink = 1; do_abort(instance); cmd->result = DID_ERROR << 16; @@ -2219,13 +2217,11 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) tmp = 0; } } else if (len) { - printk(KERN_NOTICE "scsi%d: error receiving " - "extended message\n", HOSTNO); + shost_printk(KERN_ERR, instance, "error receiving extended message\n"); tmp = 0; } else { - printk(KERN_NOTICE "scsi%d: extended message " - "code %02x length %d is too long\n", - HOSTNO, extended_msg[2], extended_msg[1]); + shost_printk(KERN_NOTICE, instance, "extended message code %02x length %d is too long\n", + extended_msg[2], extended_msg[1]); tmp = 0; } @@ -2241,8 +2237,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) */ default: if (!tmp) { - printk(KERN_INFO "scsi%d: rejecting message ", - instance->host_no); + shost_printk(KERN_ERR, instance, "rejecting message "); spi_print_msg(extended_msg); printk("\n"); } else if (tmp != EXTENDED_MESSAGE) @@ -2291,7 +2286,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) cmd->SCp.Status = tmp; break; default: - printk("scsi%d: unknown phase\n", HOSTNO); + shost_printk(KERN_ERR, instance, "unknown phase\n"); NCR5380_dprint(NDEBUG_ANY, instance); } /* switch(phase) */ } else { -- cgit From b746545f8bb0c4280c247353d61ac93620f5ef17 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sun, 3 Jan 2016 16:06:05 +1100 Subject: atari_NCR5380: Eliminate HOSTNO macro Keep the two core driver forks in sync. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Ondrej Zary Tested-by: Michael Schmitz Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.c | 71 +++++++++++++++--------------- drivers/scsi/atari_NCR5380.c | 102 ++++++++++++++++++++----------------------- 2 files changed, 84 insertions(+), 89 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index 35464ce90f36..9616f397e134 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -926,9 +926,8 @@ static void NCR5380_main(struct work_struct *work) && !hostdata->dmalen #endif ) { - dprintk(NDEBUG_MAIN, "scsi%d : main() : performing information transfer\n", instance->host_no); + dsprintk(NDEBUG_MAIN, instance, "main: performing information transfer\n"); NCR5380_information_transfer(instance); - dprintk(NDEBUG_MAIN, "scsi%d : main() : done set false\n", instance->host_no); done = 0; } } while (!done); @@ -986,8 +985,8 @@ static irqreturn_t NCR5380_intr(int irq, void *dev_id) unsigned char mr = NCR5380_read(MODE_REG); unsigned char sr = NCR5380_read(STATUS_REG); - dprintk(NDEBUG_INTR, "scsi%d: IRQ %d, BASR 0x%02x, SR 0x%02x, MR 0x%02x\n", - instance->host_no, irq, basr, sr, mr); + dsprintk(NDEBUG_INTR, instance, "IRQ %d, BASR 0x%02x, SR 0x%02x, MR 0x%02x\n", + irq, basr, sr, mr); #if defined(REAL_DMA) if ((mr & MR_DMA_MODE) || (mr & MR_MONITOR_BSY)) { @@ -996,7 +995,7 @@ static irqreturn_t NCR5380_intr(int irq, void *dev_id) * for End of DMA errata need to happen in DMA Mode. */ - dprintk(NDEBUG_INTR, "scsi%d: interrupt in DMA mode\n", intance->host_no); + dsprintk(NDEBUG_INTR, instance, "interrupt in DMA mode\n"); int transferred; @@ -1023,8 +1022,7 @@ static irqreturn_t NCR5380_intr(int irq, void *dev_id) NCR5380_write(SELECT_ENABLE_REG, 0); NCR5380_read(RESET_PARITY_INTERRUPT_REG); - dprintk(NDEBUG_INTR, "scsi%d: interrupt with SEL and IO\n", - instance->host_no); + dsprintk(NDEBUG_INTR, instance, "interrupt with SEL and IO\n"); if (!hostdata->connected) { NCR5380_reselect(instance); @@ -1036,7 +1034,7 @@ static irqreturn_t NCR5380_intr(int irq, void *dev_id) /* Probably Bus Reset */ NCR5380_read(RESET_PARITY_INTERRUPT_REG); - dprintk(NDEBUG_INTR, "scsi%d: unknown interrupt\n", instance->host_no); + dsprintk(NDEBUG_INTR, instance, "unknown interrupt\n"); } handled = 1; } else { @@ -1091,7 +1089,8 @@ static struct scsi_cmnd *NCR5380_select(struct Scsi_Host *instance, int err; NCR5380_dprint(NDEBUG_ARBITRATION, instance); - dprintk(NDEBUG_ARBITRATION, "scsi%d : starting arbitration, id = %d\n", instance->host_no, instance->this_id); + dsprintk(NDEBUG_ARBITRATION, instance, "starting arbitration, id = %d\n", + instance->this_id); /* * Arbitration and selection phases are slow and involve dropping the @@ -1143,7 +1142,7 @@ static struct scsi_cmnd *NCR5380_select(struct Scsi_Host *instance, /* Check for lost arbitration */ if ((NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_LOST) || (NCR5380_read(CURRENT_SCSI_DATA_REG) & hostdata->id_higher_mask) || (NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_LOST)) { NCR5380_write(MODE_REG, MR_BASE); - dprintk(NDEBUG_ARBITRATION, "scsi%d : lost arbitration, deasserting MR_ARBITRATE\n", instance->host_no); + dsprintk(NDEBUG_ARBITRATION, instance, "lost arbitration, deasserting MR_ARBITRATE\n"); spin_lock_irq(&hostdata->lock); goto out; } @@ -1177,7 +1176,7 @@ static struct scsi_cmnd *NCR5380_select(struct Scsi_Host *instance, goto out; } - dprintk(NDEBUG_ARBITRATION, "scsi%d : won arbitration\n", instance->host_no); + dsprintk(NDEBUG_ARBITRATION, instance, "won arbitration\n"); /* * Now that we have won arbitration, start Selection process, asserting @@ -1231,7 +1230,7 @@ static struct scsi_cmnd *NCR5380_select(struct Scsi_Host *instance, udelay(1); - dprintk(NDEBUG_SELECTION, "scsi%d : selecting target %d\n", instance->host_no, scmd_id(cmd)); + dsprintk(NDEBUG_SELECTION, instance, "selecting target %d\n", scmd_id(cmd)); /* * The SCSI specification calls for a 250 ms timeout for the actual @@ -1305,7 +1304,8 @@ static struct scsi_cmnd *NCR5380_select(struct Scsi_Host *instance, goto out; } - dprintk(NDEBUG_SELECTION, "scsi%d : target %d selected, going into MESSAGE OUT phase.\n", instance->host_no, cmd->device->id); + dsprintk(NDEBUG_SELECTION, instance, "target %d selected, going into MESSAGE OUT phase.\n", + scmd_id(cmd)); tmp[0] = IDENTIFY(((instance->irq == NO_IRQ) ? 0 : 1), cmd->device->lun); len = 1; @@ -1315,7 +1315,7 @@ static struct scsi_cmnd *NCR5380_select(struct Scsi_Host *instance, data = tmp; phase = PHASE_MSGOUT; NCR5380_transfer_pio(instance, &phase, &len, &data); - dprintk(NDEBUG_SELECTION, "scsi%d : nexus established.\n", instance->host_no); + dsprintk(NDEBUG_SELECTION, instance, "nexus established.\n"); /* XXX need to handle errors here */ hostdata->connected = cmd; @@ -1362,11 +1362,6 @@ static int NCR5380_transfer_pio(struct Scsi_Host *instance, unsigned char *phase int c = *count; unsigned char *d = *data; - if (!(p & SR_IO)) - dprintk(NDEBUG_PIO, "scsi%d : pio write %d bytes\n", instance->host_no, c); - else - dprintk(NDEBUG_PIO, "scsi%d : pio read %d bytes\n", instance->host_no, c); - /* * The NCR5380 chip will only drive the SCSI bus when the * phase specified in the appropriate bits of the TARGET COMMAND @@ -1384,12 +1379,12 @@ static int NCR5380_transfer_pio(struct Scsi_Host *instance, unsigned char *phase if (NCR5380_poll_politely(instance, STATUS_REG, SR_REQ, SR_REQ, HZ) < 0) break; - dprintk(NDEBUG_HANDSHAKE, "scsi%d : REQ detected\n", instance->host_no); + dsprintk(NDEBUG_HANDSHAKE, instance, "REQ asserted\n"); /* Check for phase mismatch */ if ((NCR5380_read(STATUS_REG) & PHASE_MASK) != p) { - dprintk(NDEBUG_HANDSHAKE, "scsi%d : phase mismatch\n", instance->host_no); - NCR5380_dprint_phase(NDEBUG_HANDSHAKE, instance); + dsprintk(NDEBUG_PIO, instance, "phase mismatch\n"); + NCR5380_dprint_phase(NDEBUG_PIO, instance); break; } /* Do actual transfer from SCSI bus to / from memory */ @@ -1426,7 +1421,7 @@ static int NCR5380_transfer_pio(struct Scsi_Host *instance, unsigned char *phase STATUS_REG, SR_REQ, 0, 5 * HZ) < 0) break; - dprintk(NDEBUG_HANDSHAKE, "scsi%d : req false, handshake complete\n", instance->host_no); + dsprintk(NDEBUG_HANDSHAKE, instance, "REQ negated, handshake complete\n"); /* * We have several special cases to consider during REQ/ACK handshaking : @@ -1447,7 +1442,7 @@ static int NCR5380_transfer_pio(struct Scsi_Host *instance, unsigned char *phase } } while (--c); - dprintk(NDEBUG_PIO, "scsi%d : residual %d\n", instance->host_no, c); + dsprintk(NDEBUG_PIO, instance, "residual %d\n", c); *count = c; *data = d; @@ -1597,8 +1592,10 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, unsigned char *phase if (!(hostdata->flags & FLAG_NO_DMA_FIXUPS)) c -= 2; } - dprintk(NDEBUG_DMA, "scsi%d : initializing DMA channel %d for %s, %d bytes %s %0x\n", instance->host_no, instance->dma_channel, (p & SR_IO) ? "reading" : "writing", c, (p & SR_IO) ? "to" : "from", (unsigned) d); hostdata->dma_len = (p & SR_IO) ? NCR5380_dma_read_setup(instance, d, c) : NCR5380_dma_write_setup(instance, d, c); + + dsprintk(NDEBUG_DMA, instance, "initializing DMA %s: length %d, address %p\n", + (p & SR_IO) ? "receive" : "send", c, *data); #endif NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(p)); @@ -1700,7 +1697,8 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, unsigned char *phase } } - dprintk(NDEBUG_DMA, "scsi%d : polled DMA transfer complete, basr 0x%X, sr 0x%X\n", instance->host_no, tmp, NCR5380_read(STATUS_REG)); + dsprintk(NDEBUG_DMA, "polled DMA transfer complete, basr 0x%02x, sr 0x%02x\n", + tmp, NCR5380_read(STATUS_REG)); NCR5380_write(MODE_REG, MR_BASE); NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); @@ -1870,7 +1868,9 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { --cmd->SCp.buffers_residual; cmd->SCp.this_residual = cmd->SCp.buffer->length; cmd->SCp.ptr = sg_virt(cmd->SCp.buffer); - dprintk(NDEBUG_INFORMATION, "scsi%d : %d bytes and %d buffers left\n", instance->host_no, cmd->SCp.this_residual, cmd->SCp.buffers_residual); + dsprintk(NDEBUG_INFORMATION, instance, "%d bytes and %d buffers left\n", + cmd->SCp.this_residual, + cmd->SCp.buffers_residual); } /* * The preferred transfer method is going to be @@ -2025,14 +2025,15 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { spin_unlock_irq(&hostdata->lock); - dprintk(NDEBUG_EXTENDED, "scsi%d : receiving extended message\n", instance->host_no); + dsprintk(NDEBUG_EXTENDED, instance, "receiving extended message\n"); len = 2; data = extended_msg + 1; phase = PHASE_MSGIN; NCR5380_transfer_pio(instance, &phase, &len, &data); - - dprintk(NDEBUG_EXTENDED, "scsi%d : length=%d, code=0x%02x\n", instance->host_no, (int) extended_msg[1], (int) extended_msg[2]); + dsprintk(NDEBUG_EXTENDED, instance, "length %d, code 0x%02x\n", + (int)extended_msg[1], + (int)extended_msg[2]); if (!len && extended_msg[1] > 0 && extended_msg[1] <= sizeof(extended_msg) - 2) { @@ -2043,7 +2044,8 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { phase = PHASE_MSGIN; NCR5380_transfer_pio(instance, &phase, &len, &data); - dprintk(NDEBUG_EXTENDED, "scsi%d : message received, residual %d\n", instance->host_no, len); + dsprintk(NDEBUG_EXTENDED, instance, "message received, residual %d\n", + len); switch (extended_msg[2]) { case EXTENDED_SDTR: @@ -2160,7 +2162,8 @@ static void NCR5380_reselect(struct Scsi_Host *instance) { NCR5380_write(MODE_REG, MR_BASE); target_mask = NCR5380_read(CURRENT_SCSI_DATA_REG) & ~(hostdata->id_mask); - dprintk(NDEBUG_RESELECTION, "scsi%d : reselect\n", instance->host_no); + + dsprintk(NDEBUG_RESELECTION, instance, "reselect\n"); /* * At this point, we have detected that our SCSI ID is on the bus, @@ -2249,8 +2252,8 @@ static void NCR5380_reselect(struct Scsi_Host *instance) { NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); hostdata->connected = tmp; - dprintk(NDEBUG_RESELECTION, "scsi%d : nexus established, target = %d, lun = %llu, tag = %d\n", - instance->host_no, tmp->device->id, tmp->device->lun, tmp->tag); + dsprintk(NDEBUG_RESELECTION, instance, "nexus established, target %d, lun %llu, tag %d\n", + scmd_id(tmp), tmp->device->lun, tmp->tag); } /* diff --git a/drivers/scsi/atari_NCR5380.c b/drivers/scsi/atari_NCR5380.c index 4517eaa395c2..0e0f93f7e13e 100644 --- a/drivers/scsi/atari_NCR5380.c +++ b/drivers/scsi/atari_NCR5380.c @@ -175,8 +175,6 @@ * possible) function may be used. */ -#define HOSTNO instance->host_no - static int do_abort(struct Scsi_Host *); static void do_reset(struct Scsi_Host *); @@ -1024,10 +1022,8 @@ static void NCR5380_main(struct work_struct *work) && !hostdata->dma_len #endif ) { - dprintk(NDEBUG_MAIN, "scsi%d: main: performing information transfer\n", - HOSTNO); + dsprintk(NDEBUG_MAIN, instance, "main: performing information transfer\n"); NCR5380_information_transfer(instance); - dprintk(NDEBUG_MAIN, "scsi%d: main: done set false\n", HOSTNO); done = 0; } } while (!done); @@ -1064,7 +1060,7 @@ static void NCR5380_dma_complete(struct Scsi_Host *instance) (BASR_PHASE_MATCH|BASR_ACK)) { saved_data = NCR5380_read(INPUT_DATA_REG); overrun = 1; - dprintk(NDEBUG_DMA, "scsi%d: read overrun handled\n", HOSTNO); + dsprintk(NDEBUG_DMA, instance, "read overrun handled\n"); } } } @@ -1169,8 +1165,8 @@ static irqreturn_t NCR5380_intr(int irq, void *dev_id) unsigned char mr = NCR5380_read(MODE_REG); unsigned char sr = NCR5380_read(STATUS_REG); - dprintk(NDEBUG_INTR, "scsi%d: IRQ %d, BASR 0x%02x, SR 0x%02x, MR 0x%02x\n", - HOSTNO, irq, basr, sr, mr); + dsprintk(NDEBUG_INTR, instance, "IRQ %d, BASR 0x%02x, SR 0x%02x, MR 0x%02x\n", + irq, basr, sr, mr); #if defined(REAL_DMA) if ((mr & MR_DMA_MODE) || (mr & MR_MONITOR_BSY)) { @@ -1179,7 +1175,7 @@ static irqreturn_t NCR5380_intr(int irq, void *dev_id) * for End of DMA errata need to happen in DMA Mode. */ - dprintk(NDEBUG_INTR, "scsi%d: interrupt in DMA mode\n", HOSTNO); + dsprintk(NDEBUG_INTR, instance, "interrupt in DMA mode\n"); if (hostdata->connected) { NCR5380_dma_complete(instance); @@ -1196,8 +1192,7 @@ static irqreturn_t NCR5380_intr(int irq, void *dev_id) NCR5380_write(SELECT_ENABLE_REG, 0); NCR5380_read(RESET_PARITY_INTERRUPT_REG); - dprintk(NDEBUG_INTR, "scsi%d: interrupt with SEL and IO\n", - HOSTNO); + dsprintk(NDEBUG_INTR, instance, "interrupt with SEL and IO\n"); if (!hostdata->connected) { NCR5380_reselect(instance); @@ -1209,7 +1204,7 @@ static irqreturn_t NCR5380_intr(int irq, void *dev_id) /* Probably Bus Reset */ NCR5380_read(RESET_PARITY_INTERRUPT_REG); - dprintk(NDEBUG_INTR, "scsi%d: unknown interrupt\n", HOSTNO); + dsprintk(NDEBUG_INTR, instance, "unknown interrupt\n"); #ifdef SUN3_SCSI_VME dregs->csr |= CSR_DMA_ENABLE; #endif @@ -1266,8 +1261,8 @@ static struct scsi_cmnd *NCR5380_select(struct Scsi_Host *instance, int err; NCR5380_dprint(NDEBUG_ARBITRATION, instance); - dprintk(NDEBUG_ARBITRATION, "scsi%d: starting arbitration, id = %d\n", HOSTNO, - instance->this_id); + dsprintk(NDEBUG_ARBITRATION, instance, "starting arbitration, id = %d\n", + instance->this_id); /* * Arbitration and selection phases are slow and involve dropping the @@ -1321,8 +1316,7 @@ static struct scsi_cmnd *NCR5380_select(struct Scsi_Host *instance, (NCR5380_read(CURRENT_SCSI_DATA_REG) & hostdata->id_higher_mask) || (NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_LOST)) { NCR5380_write(MODE_REG, MR_BASE); - dprintk(NDEBUG_ARBITRATION, "scsi%d: lost arbitration, deasserting MR_ARBITRATE\n", - HOSTNO); + dsprintk(NDEBUG_ARBITRATION, instance, "lost arbitration, deasserting MR_ARBITRATE\n"); spin_lock_irq(&hostdata->lock); goto out; } @@ -1356,7 +1350,7 @@ static struct scsi_cmnd *NCR5380_select(struct Scsi_Host *instance, goto out; } - dprintk(NDEBUG_ARBITRATION, "scsi%d: won arbitration\n", HOSTNO); + dsprintk(NDEBUG_ARBITRATION, instance, "won arbitration\n"); /* * Now that we have won arbitration, start Selection process, asserting @@ -1412,7 +1406,7 @@ static struct scsi_cmnd *NCR5380_select(struct Scsi_Host *instance, udelay(1); - dprintk(NDEBUG_SELECTION, "scsi%d: selecting target %d\n", HOSTNO, cmd->device->id); + dsprintk(NDEBUG_SELECTION, instance, "selecting target %d\n", scmd_id(cmd)); /* * The SCSI specification calls for a 250 ms timeout for the actual @@ -1486,8 +1480,8 @@ static struct scsi_cmnd *NCR5380_select(struct Scsi_Host *instance, goto out; } - dprintk(NDEBUG_SELECTION, "scsi%d: target %d selected, going into MESSAGE OUT phase.\n", - HOSTNO, cmd->device->id); + dsprintk(NDEBUG_SELECTION, instance, "target %d selected, going into MESSAGE OUT phase.\n", + scmd_id(cmd)); tmp[0] = IDENTIFY(1, cmd->device->lun); #ifdef SUPPORT_TAGS @@ -1506,7 +1500,7 @@ static struct scsi_cmnd *NCR5380_select(struct Scsi_Host *instance, data = tmp; phase = PHASE_MSGOUT; NCR5380_transfer_pio(instance, &phase, &len, &data); - dprintk(NDEBUG_SELECTION, "scsi%d: nexus established.\n", HOSTNO); + dsprintk(NDEBUG_SELECTION, instance, "nexus established.\n"); /* XXX need to handle errors here */ hostdata->connected = cmd; @@ -1578,11 +1572,11 @@ static int NCR5380_transfer_pio(struct Scsi_Host *instance, if (NCR5380_poll_politely(instance, STATUS_REG, SR_REQ, SR_REQ, HZ) < 0) break; - dprintk(NDEBUG_HANDSHAKE, "scsi%d: REQ detected\n", HOSTNO); + dsprintk(NDEBUG_HANDSHAKE, instance, "REQ asserted\n"); /* Check for phase mismatch */ if ((NCR5380_read(STATUS_REG) & PHASE_MASK) != p) { - dprintk(NDEBUG_PIO, "scsi%d: phase mismatch\n", HOSTNO); + dsprintk(NDEBUG_PIO, instance, "phase mismatch\n"); NCR5380_dprint_phase(NDEBUG_PIO, instance); break; } @@ -1624,7 +1618,7 @@ static int NCR5380_transfer_pio(struct Scsi_Host *instance, STATUS_REG, SR_REQ, 0, 5 * HZ) < 0) break; - dprintk(NDEBUG_HANDSHAKE, "scsi%d: req false, handshake complete\n", HOSTNO); + dsprintk(NDEBUG_HANDSHAKE, instance, "REQ negated, handshake complete\n"); /* * We have several special cases to consider during REQ/ACK handshaking : @@ -1645,7 +1639,7 @@ static int NCR5380_transfer_pio(struct Scsi_Host *instance, } } while (--c); - dprintk(NDEBUG_PIO, "scsi%d: residual %d\n", HOSTNO, c); + dsprintk(NDEBUG_PIO, instance, "residual %d\n", c); *count = c; *data = d; @@ -1791,9 +1785,8 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, } hostdata->dma_len = c; - dprintk(NDEBUG_DMA, "scsi%d: initializing DMA for %s, %d bytes %s %p\n", - instance->host_no, (p & SR_IO) ? "reading" : "writing", - c, (p & SR_IO) ? "to" : "from", *data); + dsprintk(NDEBUG_DMA, instance, "initializing DMA %s: length %d, address %p\n", + (p & SR_IO) ? "receive" : "send", c, *data); /* netbsd turns off ints here, why not be safe and do it too */ @@ -1829,9 +1822,8 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, if (hostdata->read_overruns && (p & SR_IO)) c -= hostdata->read_overruns; - dprintk(NDEBUG_DMA, "scsi%d: initializing DMA for %s, %d bytes %s %p\n", - HOSTNO, (p & SR_IO) ? "reading" : "writing", - c, (p & SR_IO) ? "to" : "from", d); + dsprintk(NDEBUG_DMA, instance, "initializing DMA %s: length %d, address %p\n", + (p & SR_IO) ? "receive" : "send", c, d); NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(p)); NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE | MR_MONITOR_BSY | @@ -1978,9 +1970,9 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) * they are at contiguous physical addresses. */ merge_contiguous_buffers(cmd); - dprintk(NDEBUG_INFORMATION, "scsi%d: %d bytes and %d buffers left\n", - HOSTNO, cmd->SCp.this_residual, - cmd->SCp.buffers_residual); + dsprintk(NDEBUG_INFORMATION, instance, "%d bytes and %d buffers left\n", + cmd->SCp.this_residual, + cmd->SCp.buffers_residual); } /* @@ -2068,11 +2060,12 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) #ifdef SUPPORT_TAGS cmd_free_tag(cmd); if (status_byte(cmd->SCp.Status) == QUEUE_FULL) { - struct tag_alloc *ta = &hostdata->TagAlloc[scmd_id(cmd)][cmd->device->lun]; - dprintk(NDEBUG_TAGS, "scsi%d: target %d lun %llu returned " - "QUEUE_FULL after %d commands\n", - HOSTNO, cmd->device->id, cmd->device->lun, - ta->nr_allocated); + u8 lun = cmd->device->lun; + struct tag_alloc *ta = &hostdata->TagAlloc[scmd_id(cmd)][lun]; + + dsprintk(NDEBUG_TAGS, instance, + "QUEUE_FULL %p target %d lun %d nr_allocated %d\n", + cmd, scmd_id(cmd), lun, ta->nr_allocated); if (ta->queue_size > ta->nr_allocated) ta->queue_size = ta->nr_allocated; } @@ -2126,10 +2119,8 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) cmd->device->tagged_supported = 0; hostdata->busy[cmd->device->id] |= (1 << cmd->device->lun); cmd->tag = TAG_NONE; - dprintk(NDEBUG_TAGS, "scsi%d: target %d lun %llu rejected " - "QUEUE_TAG message; tagged queuing " - "disabled\n", - HOSTNO, cmd->device->id, cmd->device->lun); + dsprintk(NDEBUG_TAGS, instance, "target %d lun %llu rejected QUEUE_TAG message; tagged queuing disabled\n", + scmd_id(cmd), cmd->device->lun); break; } break; @@ -2188,14 +2179,15 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) spin_unlock_irq(&hostdata->lock); - dprintk(NDEBUG_EXTENDED, "scsi%d: receiving extended message\n", HOSTNO); + dsprintk(NDEBUG_EXTENDED, instance, "receiving extended message\n"); len = 2; data = extended_msg + 1; phase = PHASE_MSGIN; NCR5380_transfer_pio(instance, &phase, &len, &data); - dprintk(NDEBUG_EXTENDED, "scsi%d: length=%d, code=0x%02x\n", HOSTNO, - (int)extended_msg[1], (int)extended_msg[2]); + dsprintk(NDEBUG_EXTENDED, instance, "length %d, code 0x%02x\n", + (int)extended_msg[1], + (int)extended_msg[2]); if (!len && extended_msg[1] > 0 && extended_msg[1] <= sizeof(extended_msg) - 2) { @@ -2206,8 +2198,8 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) phase = PHASE_MSGIN; NCR5380_transfer_pio(instance, &phase, &len, &data); - dprintk(NDEBUG_EXTENDED, "scsi%d: message received, residual %d\n", - HOSTNO, len); + dsprintk(NDEBUG_EXTENDED, instance, "message received, residual %d\n", + len); switch (extended_msg[2]) { case EXTENDED_SDTR: @@ -2335,7 +2327,7 @@ static void NCR5380_reselect(struct Scsi_Host *instance) target_mask = NCR5380_read(CURRENT_SCSI_DATA_REG) & ~(hostdata->id_mask); - dprintk(NDEBUG_RESELECTION, "scsi%d: reselect\n", HOSTNO); + dsprintk(NDEBUG_RESELECTION, instance, "reselect\n"); /* * At this point, we have detected that our SCSI ID is on the bus, @@ -2405,8 +2397,8 @@ static void NCR5380_reselect(struct Scsi_Host *instance) if (!NCR5380_transfer_pio(instance, &phase, &len, &data) && msg[1] == SIMPLE_QUEUE_TAG) tag = msg[2]; - dprintk(NDEBUG_TAGS, "scsi%d: target mask %02x, lun %d sent tag %d at " - "reselection\n", HOSTNO, target_mask, lun, tag); + dsprintk(NDEBUG_TAGS, instance, "reselect: target mask %02x, lun %d sent tag %d\n", + target_mask, lun, tag); } #endif @@ -2491,14 +2483,14 @@ static void NCR5380_reselect(struct Scsi_Host *instance) if (!NCR5380_transfer_pio(instance, &phase, &len, &data) && msg[1] == SIMPLE_QUEUE_TAG) tag = msg[2]; - dprintk(NDEBUG_TAGS, "scsi%d: target mask %02x, lun %d sent tag %d at reselection\n" - HOSTNO, target_mask, lun, tag); + dsprintk(NDEBUG_TAGS, instance, "reselect: target mask %02x, lun %d sent tag %d\n" + target_mask, lun, tag); } #endif hostdata->connected = tmp; - dprintk(NDEBUG_RESELECTION, "scsi%d: nexus established, target = %d, lun = %llu, tag = %d\n", - HOSTNO, tmp->device->id, tmp->device->lun, tmp->tag); + dsprintk(NDEBUG_RESELECTION, instance, "nexus established, target %d, lun %llu, tag %d\n", + scmd_id(tmp), tmp->device->lun, tmp->tag); } -- cgit From cd46140a9a2f8fe0208262dc5f4d1fba15c93063 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sun, 3 Jan 2016 16:06:06 +1100 Subject: atari_scsi, sun3_scsi: Remove global Scsi_Host pointer This refactoring removes two global Scsi_Host pointers. This improves consistency with other ncr5380 drivers. Adopting the same conventions as the other drivers makes them easier to read. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Michael Schmitz Signed-off-by: Martin K. Petersen --- drivers/scsi/atari_NCR5380.c | 5 +-- drivers/scsi/atari_scsi.c | 29 +++++++++--------- drivers/scsi/sun3_scsi.c | 72 +++++++++++--------------------------------- 3 files changed, 36 insertions(+), 70 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/atari_NCR5380.c b/drivers/scsi/atari_NCR5380.c index 0e0f93f7e13e..b36fadab422b 100644 --- a/drivers/scsi/atari_NCR5380.c +++ b/drivers/scsi/atari_NCR5380.c @@ -1920,7 +1920,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) /* this command setup for dma yet? */ if ((count >= DMA_MIN_SIZE) && (sun3_dma_setup_done != cmd)) { if (cmd->request->cmd_type == REQ_TYPE_FS) { - sun3scsi_dma_setup(d, count, + sun3scsi_dma_setup(instance, d, count, rq_data_dir(cmd->request)); sun3_dma_setup_done = cmd; } @@ -2458,7 +2458,8 @@ static void NCR5380_reselect(struct Scsi_Host *instance) } /* setup this command for dma if not already */ if ((count >= DMA_MIN_SIZE) && (sun3_dma_setup_done != tmp)) { - sun3scsi_dma_setup(d, count, rq_data_dir(tmp->request)); + sun3scsi_dma_setup(instance, d, count, + rq_data_dir(tmp->request)); sun3_dma_setup_done = tmp; } } diff --git a/drivers/scsi/atari_scsi.c b/drivers/scsi/atari_scsi.c index 263cf06a8f30..78d1b2963f2c 100644 --- a/drivers/scsi/atari_scsi.c +++ b/drivers/scsi/atari_scsi.c @@ -159,14 +159,10 @@ static inline unsigned long SCSI_DMA_GETADR(void) return adr; } -#define HOSTDATA_DMALEN (((struct NCR5380_hostdata *) \ - (atari_scsi_host->hostdata))->dma_len) - #ifdef REAL_DMA static void atari_scsi_fetch_restbytes(void); #endif -static struct Scsi_Host *atari_scsi_host; static unsigned char (*atari_scsi_reg_read)(unsigned char reg); static void (*atari_scsi_reg_write)(unsigned char reg, unsigned char value); @@ -262,15 +258,17 @@ static void scsi_dma_buserr(int irq, void *dummy) #endif -static irqreturn_t scsi_tt_intr(int irq, void *dummy) +static irqreturn_t scsi_tt_intr(int irq, void *dev) { #ifdef REAL_DMA + struct Scsi_Host *instance = dev; + struct NCR5380_hostdata *hostdata = shost_priv(instance); int dma_stat; dma_stat = tt_scsi_dma.dma_ctrl; - dprintk(NDEBUG_INTR, "scsi%d: NCR5380 interrupt, DMA status = %02x\n", - atari_scsi_host->host_no, dma_stat & 0xff); + dsprintk(NDEBUG_INTR, instance, "NCR5380 interrupt, DMA status = %02x\n", + dma_stat & 0xff); /* Look if it was the DMA that has interrupted: First possibility * is that a bus error occurred... @@ -293,7 +291,8 @@ static irqreturn_t scsi_tt_intr(int irq, void *dummy) * data reg! */ if ((dma_stat & 0x02) && !(dma_stat & 0x40)) { - atari_dma_residual = HOSTDATA_DMALEN - (SCSI_DMA_READ_P(dma_addr) - atari_dma_startaddr); + atari_dma_residual = hostdata->dma_len - + (SCSI_DMA_READ_P(dma_addr) - atari_dma_startaddr); dprintk(NDEBUG_DMA, "SCSI DMA: There are %ld residual bytes.\n", atari_dma_residual); @@ -345,15 +344,17 @@ static irqreturn_t scsi_tt_intr(int irq, void *dummy) #endif /* REAL_DMA */ - NCR5380_intr(irq, dummy); + NCR5380_intr(irq, dev); return IRQ_HANDLED; } -static irqreturn_t scsi_falcon_intr(int irq, void *dummy) +static irqreturn_t scsi_falcon_intr(int irq, void *dev) { #ifdef REAL_DMA + struct Scsi_Host *instance = dev; + struct NCR5380_hostdata *hostdata = shost_priv(instance); int dma_stat; /* Turn off DMA and select sector counter register before @@ -388,7 +389,7 @@ static irqreturn_t scsi_falcon_intr(int irq, void *dummy) printk(KERN_ERR "SCSI DMA error: %ld bytes lost in " "ST-DMA fifo\n", transferred & 15); - atari_dma_residual = HOSTDATA_DMALEN - transferred; + atari_dma_residual = hostdata->dma_len - transferred; dprintk(NDEBUG_DMA, "SCSI DMA: There are %ld residual bytes.\n", atari_dma_residual); } else @@ -400,13 +401,14 @@ static irqreturn_t scsi_falcon_intr(int irq, void *dummy) * data to the original destination address. */ memcpy(atari_dma_orig_addr, phys_to_virt(atari_dma_startaddr), - HOSTDATA_DMALEN - atari_dma_residual); + hostdata->dma_len - atari_dma_residual); atari_dma_orig_addr = NULL; } #endif /* REAL_DMA */ - NCR5380_intr(irq, dummy); + NCR5380_intr(irq, dev); + return IRQ_HANDLED; } @@ -873,7 +875,6 @@ static int __init atari_scsi_probe(struct platform_device *pdev) error = -ENOMEM; goto fail_alloc; } - atari_scsi_host = instance; instance->irq = irq->start; diff --git a/drivers/scsi/sun3_scsi.c b/drivers/scsi/sun3_scsi.c index c10782b4843e..b9de487bbd31 100644 --- a/drivers/scsi/sun3_scsi.c +++ b/drivers/scsi/sun3_scsi.c @@ -56,9 +56,9 @@ #define NCR5380_info sun3scsi_info #define NCR5380_dma_read_setup(instance, data, count) \ - sun3scsi_dma_setup(data, count, 0) + sun3scsi_dma_setup(instance, data, count, 0) #define NCR5380_dma_write_setup(instance, data, count) \ - sun3scsi_dma_setup(data, count, 1) + sun3scsi_dma_setup(instance, data, count, 1) #define NCR5380_dma_residual(instance) \ sun3scsi_dma_residual(instance) #define NCR5380_dma_xfer_len(instance, cmd, phase) \ @@ -99,7 +99,6 @@ static unsigned char *sun3_dma_orig_addr; static unsigned long sun3_dma_orig_count; static int sun3_dma_active; static unsigned long last_residual; -static struct Scsi_Host *default_instance; /* * NCR 5380 register access functions @@ -142,8 +141,9 @@ static inline void sun3_udc_write(unsigned short val, unsigned char reg) // safe bits for the CSR #define CSR_GOOD 0x060f -static irqreturn_t scsi_sun3_intr(int irq, void *dummy) +static irqreturn_t scsi_sun3_intr(int irq, void *dev) { + struct Scsi_Host *instance = dev; unsigned short csr = dregs->csr; int handled = 0; @@ -152,46 +152,24 @@ static irqreturn_t scsi_sun3_intr(int irq, void *dummy) #endif if(csr & ~CSR_GOOD) { - if(csr & CSR_DMA_BUSERR) { - printk("scsi%d: bus error in dma\n", default_instance->host_no); - } - - if(csr & CSR_DMA_CONFLICT) { - printk("scsi%d: dma conflict\n", default_instance->host_no); - } + if (csr & CSR_DMA_BUSERR) + shost_printk(KERN_ERR, instance, "bus error in DMA\n"); + if (csr & CSR_DMA_CONFLICT) + shost_printk(KERN_ERR, instance, "DMA conflict\n"); handled = 1; } if(csr & (CSR_SDB_INT | CSR_DMA_INT)) { - NCR5380_intr(irq, dummy); + NCR5380_intr(irq, dev); handled = 1; } return IRQ_RETVAL(handled); } -/* - * Debug stuff - to be called on NMI, or sysrq key. Use at your own risk; - * reentering NCR5380_print_status seems to have ugly side effects - */ - -/* this doesn't seem to get used at all -- sam */ -#if 0 -void sun3_sun3_debug (void) -{ - unsigned long flags; - - if (default_instance) { - local_irq_save(flags); - NCR5380_print_status(default_instance); - local_irq_restore(flags); - } -} -#endif - - /* sun3scsi_dma_setup() -- initialize the dma controller for a read/write */ -static unsigned long sun3scsi_dma_setup(void *data, unsigned long count, int write_flag) +static unsigned long sun3scsi_dma_setup(struct Scsi_Host *instance, + void *data, unsigned long count, int write_flag) { void *addr; @@ -243,10 +221,9 @@ static unsigned long sun3scsi_dma_setup(void *data, unsigned long count, int wri dregs->csr |= CSR_FIFO; if(dregs->fifo_count != count) { - printk("scsi%d: fifo_mismatch %04x not %04x\n", - default_instance->host_no, dregs->fifo_count, - (unsigned int) count); - NCR5380_dprint(NDEBUG_DMA, default_instance); + shost_printk(KERN_ERR, instance, "FIFO mismatch %04x not %04x\n", + dregs->fifo_count, (unsigned int) count); + NCR5380_dprint(NDEBUG_DMA, instance); } /* setup udc */ @@ -281,21 +258,6 @@ static unsigned long sun3scsi_dma_setup(void *data, unsigned long count, int wri } -#ifndef SUN3_SCSI_VME -static inline unsigned long sun3scsi_dma_count(struct Scsi_Host *instance) -{ - unsigned short resid; - - dregs->udc_addr = 0x32; - udelay(SUN3_DMA_DELAY); - resid = dregs->udc_data; - udelay(SUN3_DMA_DELAY); - resid *= 2; - - return (unsigned long) resid; -} -#endif - static inline unsigned long sun3scsi_dma_residual(struct Scsi_Host *instance) { return last_residual; @@ -393,7 +355,10 @@ static int sun3scsi_dma_finish(int write_flag) } } - count = sun3scsi_dma_count(default_instance); + dregs->udc_addr = 0x32; + udelay(SUN3_DMA_DELAY); + count = 2 * dregs->udc_data; + udelay(SUN3_DMA_DELAY); fifo = dregs->fifo_count; last_residual = fifo; @@ -547,7 +512,6 @@ static int __init sun3_scsi_probe(struct platform_device *pdev) error = -ENOMEM; goto fail_alloc; } - default_instance = instance; instance->io_port = (unsigned long)ioaddr; instance->irq = irq->start; -- cgit From 0a4e36125451165847c6d4e7d5633d92e53f5c69 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sun, 3 Jan 2016 16:06:07 +1100 Subject: ncr5380: Fix soft lockups Because of the rudimentary design of the chip, it is necessary to poll the SCSI bus signals during PIO and this tends to hog the CPU. The driver will accept new commands while others execute, and this causes a soft lockup because the workqueue item will not terminate until the issue queue is emptied. When exercising dmx3191d using sequential IO from dd, the driver is sent 512 KiB WRITE commands and 128 KiB READs. For a PIO transfer, the rate is is only about 300 KiB/s, so these are long-running commands. And although PDMA may run at several MiB/s, interrupts are disabled for the duration of the transfer. Fix the unresponsiveness and soft lockup issues by calling cond_resched() after each command is completed and by limiting max_sectors for drivers that don't implement real DMA. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Ondrej Zary Tested-by: Michael Schmitz Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.c | 6 ++++-- drivers/scsi/arm/cumana_1.c | 1 + drivers/scsi/arm/oak.c | 1 + drivers/scsi/atari_NCR5380.c | 6 ++++-- drivers/scsi/dmx3191d.c | 1 + drivers/scsi/dtc.c | 1 + drivers/scsi/g_NCR5380.c | 1 + drivers/scsi/mac_scsi.c | 1 + drivers/scsi/pas16.c | 1 + drivers/scsi/t128.c | 1 + 10 files changed, 16 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index 9616f397e134..38b03af36a6a 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -890,10 +890,10 @@ static void NCR5380_main(struct work_struct *work) struct scsi_cmnd *cmd; int done; - spin_lock_irq(&hostdata->lock); do { done = 1; + spin_lock_irq(&hostdata->lock); while (!hostdata->connected && (cmd = dequeue_next_cmd(instance))) { @@ -930,8 +930,10 @@ static void NCR5380_main(struct work_struct *work) NCR5380_information_transfer(instance); done = 0; } + spin_unlock_irq(&hostdata->lock); + if (!done) + cond_resched(); } while (!done); - spin_unlock_irq(&hostdata->lock); } #ifndef DONT_USE_INTR diff --git a/drivers/scsi/arm/cumana_1.c b/drivers/scsi/arm/cumana_1.c index b526ba579ba3..221f18c5df93 100644 --- a/drivers/scsi/arm/cumana_1.c +++ b/drivers/scsi/arm/cumana_1.c @@ -209,6 +209,7 @@ static struct scsi_host_template cumanascsi_template = { .use_clustering = DISABLE_CLUSTERING, .proc_name = "CumanaSCSI-1", .cmd_size = NCR5380_CMD_SIZE, + .max_sectors = 128, }; static int cumanascsi1_probe(struct expansion_card *ec, diff --git a/drivers/scsi/arm/oak.c b/drivers/scsi/arm/oak.c index 70e648513275..1fab1d1896b1 100644 --- a/drivers/scsi/arm/oak.c +++ b/drivers/scsi/arm/oak.c @@ -115,6 +115,7 @@ static struct scsi_host_template oakscsi_template = { .use_clustering = DISABLE_CLUSTERING, .proc_name = "oakscsi", .cmd_size = NCR5380_CMD_SIZE, + .max_sectors = 128, }; static int oakscsi_probe(struct expansion_card *ec, const struct ecard_id *id) diff --git a/drivers/scsi/atari_NCR5380.c b/drivers/scsi/atari_NCR5380.c index b36fadab422b..a01921dfed0b 100644 --- a/drivers/scsi/atari_NCR5380.c +++ b/drivers/scsi/atari_NCR5380.c @@ -976,10 +976,10 @@ static void NCR5380_main(struct work_struct *work) * alter queues and touch the Falcon lock. */ - spin_lock_irq(&hostdata->lock); do { done = 1; + spin_lock_irq(&hostdata->lock); while (!hostdata->connected && (cmd = dequeue_next_cmd(instance))) { @@ -1026,8 +1026,10 @@ static void NCR5380_main(struct work_struct *work) NCR5380_information_transfer(instance); done = 0; } + spin_unlock_irq(&hostdata->lock); + if (!done) + cond_resched(); } while (!done); - spin_unlock_irq(&hostdata->lock); } diff --git a/drivers/scsi/dmx3191d.c b/drivers/scsi/dmx3191d.c index ddb4e616bfed..6c14e68b9e1a 100644 --- a/drivers/scsi/dmx3191d.c +++ b/drivers/scsi/dmx3191d.c @@ -62,6 +62,7 @@ static struct scsi_host_template dmx3191d_driver_template = { .cmd_per_lun = 2, .use_clustering = DISABLE_CLUSTERING, .cmd_size = NCR5380_CMD_SIZE, + .max_sectors = 128, }; static int dmx3191d_probe_one(struct pci_dev *pdev, diff --git a/drivers/scsi/dtc.c b/drivers/scsi/dtc.c index f6166e34e3b0..6c736b071cf4 100644 --- a/drivers/scsi/dtc.c +++ b/drivers/scsi/dtc.c @@ -453,5 +453,6 @@ static struct scsi_host_template driver_template = { .cmd_per_lun = 2, .use_clustering = DISABLE_CLUSTERING, .cmd_size = NCR5380_CMD_SIZE, + .max_sectors = 128, }; #include "scsi_module.c" diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c index 30472064170e..cd79ef402d7a 100644 --- a/drivers/scsi/g_NCR5380.c +++ b/drivers/scsi/g_NCR5380.c @@ -729,6 +729,7 @@ static struct scsi_host_template driver_template = { .cmd_per_lun = 2, .use_clustering = DISABLE_CLUSTERING, .cmd_size = NCR5380_CMD_SIZE, + .max_sectors = 128, }; #include "scsi_module.c" diff --git a/drivers/scsi/mac_scsi.c b/drivers/scsi/mac_scsi.c index 18f74b4a0b95..bb2381314a2b 100644 --- a/drivers/scsi/mac_scsi.c +++ b/drivers/scsi/mac_scsi.c @@ -324,6 +324,7 @@ static struct scsi_host_template mac_scsi_template = { .cmd_per_lun = 2, .use_clustering = DISABLE_CLUSTERING, .cmd_size = NCR5380_CMD_SIZE, + .max_sectors = 128, }; static int __init mac_scsi_probe(struct platform_device *pdev) diff --git a/drivers/scsi/pas16.c b/drivers/scsi/pas16.c index 77789405f4a9..512037e27783 100644 --- a/drivers/scsi/pas16.c +++ b/drivers/scsi/pas16.c @@ -563,6 +563,7 @@ static struct scsi_host_template driver_template = { .cmd_per_lun = 2, .use_clustering = DISABLE_CLUSTERING, .cmd_size = NCR5380_CMD_SIZE, + .max_sectors = 128, }; #include "scsi_module.c" diff --git a/drivers/scsi/t128.c b/drivers/scsi/t128.c index e50881ab9eb4..4615fda60dbd 100644 --- a/drivers/scsi/t128.c +++ b/drivers/scsi/t128.c @@ -407,5 +407,6 @@ static struct scsi_host_template driver_template = { .cmd_per_lun = 2, .use_clustering = DISABLE_CLUSTERING, .cmd_size = NCR5380_CMD_SIZE, + .max_sectors = 128, }; #include "scsi_module.c" -- cgit From c16df32e5f4c5c0bd8c8f6ade82141f2debddc3c Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sun, 3 Jan 2016 16:06:08 +1100 Subject: ncr5380: Cleanup comments The CVS revision log is not nearly as useful as the history/history.git repo, so remove it. Roman's commentary at the top of his driver repeats the same information elsewhere in the file so remove it. Also remove some other redundant or obsolete comments. Both the driver and the datasheets confusingly refer to a DMA access for a SCSI WRITE command as a "DMA write". Similarly a SCSI READ command is called a "DMA read". This is the opposite of the usual convention. Thankfully, the chip documentation and driver code also use "DMA send" and "DMA receive", so adopt this terminology. This removes some unimportant discrepancies between the two core driver forks so that 'diff' can be used to reveal the important ones, to facilitate reunification. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Ondrej Zary Tested-by: Michael Schmitz Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.c | 170 ++++++++++--------------------------------- drivers/scsi/atari_NCR5380.c | 109 ++++----------------------- 2 files changed, 54 insertions(+), 225 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index 38b03af36a6a..b968b3012e27 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -25,45 +25,8 @@ */ /* - * Revision 1.10 1998/9/2 Alan Cox - * (alan@lxorguk.ukuu.org.uk) - * Fixed up the timer lockups reported so far. Things still suck. Looking - * forward to 2.3 and per device request queues. Then it'll be possible to - * SMP thread this beast and improve life no end. - - * Revision 1.9 1997/7/27 Ronald van Cuijlenborg - * (ronald.van.cuijlenborg@tip.nl or nutty@dds.nl) - * (hopefully) fixed and enhanced USLEEP - * added support for DTC3181E card (for Mustek scanner) - * - - * Revision 1.8 Ingmar Baumgart - * (ingmar@gonzo.schwaben.de) - * added support for NCR53C400a card - * - - * Revision 1.7 1996/3/2 Ray Van Tassle (rayvt@comm.mot.com) - * added proc_info - * added support needed for DTC 3180/3280 - * fixed a couple of bugs - * - - * Revision 1.5 1994/01/19 09:14:57 drew - * Fixed udelay() hack that was being used on DATAOUT phases - * instead of a proper wait for the final handshake. - * - * Revision 1.4 1994/01/19 06:44:25 drew - * *** empty log message *** - * - * Revision 1.3 1994/01/19 05:24:40 drew - * Added support for TCR LAST_BYTE_SENT bit. - * - * Revision 1.2 1994/01/15 06:14:11 drew - * REAL DMA support, bug fixes. - * - * Revision 1.1 1994/01/15 06:00:54 drew - * Initial revision - * + * With contributions from Ray Van Tassle, Ingmar Baumgart, + * Ronald van Cuijlenborg, Alan Cox and others. */ /* @@ -98,12 +61,6 @@ * transfer - some PC's will use the I/O bus, 68K's must use * memory mapped) and drops this file in their 'C' wrapper. * - * (Note from hch: unfortunately it was not enough for the different - * m68k folks and instead of improving this driver they copied it - * and hacked it up for their needs. As a consequence they lost - * most updates to this driver. Maybe someone will fix all these - * drivers to use a common core one day..) - * * As far as command queueing, two queues are maintained for * each 5380 in the system - commands that haven't been issued yet, * and commands that are currently executing. This means that an @@ -180,9 +137,6 @@ * rely on phase mismatch and EOP interrupts to determine end * of phase. * - * Defaults for these will be provided although the user may want to adjust - * these to allocate CPU resources to the SCSI driver or "real" code. - * * These macros MUST be defined : * * NCR5380_read(register) - read from the specified register @@ -219,7 +173,7 @@ static int do_abort(struct Scsi_Host *); static void do_reset(struct Scsi_Host *); -/* +/** * initialize_SCp - init the scsi pointer field * @cmd: command block to set up * @@ -368,8 +322,6 @@ mrs[] = { * @instance: adapter state to dump * * Print the SCSI bus signals for debugging purposes - * - * Locks: caller holds hostdata lock (not essential) */ static void NCR5380_print(struct Scsi_Host *instance) @@ -402,13 +354,11 @@ static void NCR5380_print(struct Scsi_Host *instance) } -/* +/** * NCR5380_print_phase - show SCSI phase * @instance: adapter to dump * * Print the current SCSI phase for debugging purposes - * - * Locks: none */ static void NCR5380_print_phase(struct Scsi_Host *instance) @@ -452,8 +402,6 @@ static irqreturn_t __init probe_intr(int irq, void *dev_id) * * Autoprobe for the IRQ line used by the NCR5380 by triggering an IRQ * and then looking to see what interrupt actually turned up. - * - * Locks: none, irqs must be enabled on entry */ static int __init __maybe_unused NCR5380_probe_irq(struct Scsi_Host *instance, @@ -503,8 +451,6 @@ static int __init __maybe_unused NCR5380_probe_irq(struct Scsi_Host *instance, * @instance: relevant scsi host instance * * For use as the host template info() handler. - * - * Locks: none */ static const char *NCR5380_info(struct Scsi_Host *instance) @@ -554,20 +500,6 @@ static void prepare_info(struct Scsi_Host *instance) } #ifdef PSEUDO_DMA -/******************************************/ -/* - * /proc/scsi/[dtc pas16 t128 generic]/[0-ASC_NUM_BOARD_SUPPORTED] - * - * *buffer: I/O buffer - * **start: if inout == FALSE pointer into buffer where user read should start - * offset: current offset - * length: length of buffer - * hostno: Scsi_Host host_no - * inout: TRUE - user is writing; FALSE - user is reading - * - * Return the number of bytes read from or written - */ - static int __maybe_unused NCR5380_write_info(struct Scsi_Host *instance, char *buffer, int length) { @@ -601,8 +533,6 @@ static int __maybe_unused NCR5380_show_info(struct seq_file *m, * set correctly. I don't care about the irq and other fields. * * Returns 0 for success - * - * Locks: interrupts must be enabled when we are called */ static int NCR5380_init(struct Scsi_Host *instance, int flags) @@ -877,9 +807,6 @@ static void requeue_cmd(struct Scsi_Host *instance, struct scsi_cmnd *cmd) * be done on the NCR5380 host adapters in a system. Both * NCR5380_queue_command() and NCR5380_intr() will try to start it * in case it is not running. - * - * Locks: called as its own thread with no locks held. Takes the - * host lock and called routines may take the isa dma lock. */ static void NCR5380_main(struct work_struct *work) @@ -1077,8 +1004,6 @@ static irqreturn_t NCR5380_intr(int irq, void *dev_id) * * If failed (no target) : cmd->scsi_done() will be called, and the * cmd->result host byte set to DID_BAD_TARGET. - * - * Locks: caller holds hostdata lock in IRQ mode */ static struct scsi_cmnd *NCR5380_select(struct Scsi_Host *instance, @@ -1567,8 +1492,6 @@ timeout: * is in same phase. * * Also, *phase, *count, *data are modified in place. - * - * Locks: io_request lock held by caller */ @@ -1645,39 +1568,38 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, unsigned char *phase } while ((tmp & BASR_PHASE_MATCH) && !(tmp & (BASR_BUSY_ERROR | BASR_END_DMA_TRANSFER))); /* - At this point, either we've completed DMA, or we have a phase mismatch, - or we've unexpectedly lost BUSY (which is a real error). - - For write DMAs, we want to wait until the last byte has been - transferred out over the bus before we turn off DMA mode. Alas, there - seems to be no terribly good way of doing this on a 5380 under all - conditions. For non-scatter-gather operations, we can wait until REQ - and ACK both go false, or until a phase mismatch occurs. Gather-writes - are nastier, since the device will be expecting more data than we - are prepared to send it, and REQ will remain asserted. On a 53C8[01] we - could test LAST BIT SENT to assure transfer (I imagine this is precisely - why this signal was added to the newer chips) but on the older 538[01] - this signal does not exist. The workaround for this lack is a watchdog; - we bail out of the wait-loop after a modest amount of wait-time if - the usual exit conditions are not met. Not a terribly clean or - correct solution :-% - - Reads are equally tricky due to a nasty characteristic of the NCR5380. - If the chip is in DMA mode for an READ, it will respond to a target's - REQ by latching the SCSI data into the INPUT DATA register and asserting - ACK, even if it has _already_ been notified by the DMA controller that - the current DMA transfer has completed! If the NCR5380 is then taken - out of DMA mode, this already-acknowledged byte is lost. - - This is not a problem for "one DMA transfer per command" reads, because - the situation will never arise... either all of the data is DMA'ed - properly, or the target switches to MESSAGE IN phase to signal a - disconnection (either operation bringing the DMA to a clean halt). - However, in order to handle scatter-reads, we must work around the - problem. The chosen fix is to DMA N-2 bytes, then check for the - condition before taking the NCR5380 out of DMA mode. One or two extra - bytes are transferred via PIO as necessary to fill out the original - request. + * At this point, either we've completed DMA, or we have a phase mismatch, + * or we've unexpectedly lost BUSY (which is a real error). + * + * For DMA sends, we want to wait until the last byte has been + * transferred out over the bus before we turn off DMA mode. Alas, there + * seems to be no terribly good way of doing this on a 5380 under all + * conditions. For non-scatter-gather operations, we can wait until REQ + * and ACK both go false, or until a phase mismatch occurs. Gather-sends + * are nastier, since the device will be expecting more data than we + * are prepared to send it, and REQ will remain asserted. On a 53C8[01] we + * could test Last Byte Sent to assure transfer (I imagine this is precisely + * why this signal was added to the newer chips) but on the older 538[01] + * this signal does not exist. The workaround for this lack is a watchdog; + * we bail out of the wait-loop after a modest amount of wait-time if + * the usual exit conditions are not met. Not a terribly clean or + * correct solution :-% + * + * DMA receive is equally tricky due to a nasty characteristic of the NCR5380. + * If the chip is in DMA receive mode, it will respond to a target's + * REQ by latching the SCSI data into the INPUT DATA register and asserting + * ACK, even if it has _already_ been notified by the DMA controller that + * the current DMA transfer has completed! If the NCR5380 is then taken + * out of DMA mode, this already-acknowledged byte is lost. This is + * not a problem for "one DMA transfer per READ command", because + * the situation will never arise... either all of the data is DMA'ed + * properly, or the target switches to MESSAGE IN phase to signal a + * disconnection (either operation bringing the DMA to a clean halt). + * However, in order to handle scatter-receive, we must work around the + * problem. The chosen fix is to DMA N-2 bytes, then check for the + * condition before taking the NCR5380 out of DMA mode. One or two extra + * bytes are transferred via PIO as necessary to fill out the original + * request. */ if (p & SR_IO) { @@ -1813,8 +1735,6 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, unsigned char *phase * * XXX Note : we need to watch for bus free or a reset condition here * to recover from an unexpected bus free condition. - * - * Locks: io_request_lock held by caller in IRQ mode */ static void NCR5380_information_transfer(struct Scsi_Host *instance) { @@ -2009,18 +1929,10 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); break; case EXTENDED_MESSAGE: -/* - * Extended messages are sent in the following format : - * Byte - * 0 EXTENDED_MESSAGE == 1 - * 1 length (includes one byte for code, doesn't - * include first two bytes) - * 2 code - * 3..length+1 arguments - * - * Start the extended message buffer with the EXTENDED_MESSAGE - * byte, since spi_print_msg() wants the whole thing. - */ + /* + * Start the message buffer with the EXTENDED_MESSAGE + * byte, since spi_print_msg() wants the whole thing. + */ extended_msg[0] = EXTENDED_MESSAGE; /* Accept first byte by clearing ACK */ NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); @@ -2142,8 +2054,6 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { * nexus has been reestablished, * * Inputs : instance - this instance of the NCR5380. - * - * Locks: io_request_lock held by caller if IRQ driven */ static void NCR5380_reselect(struct Scsi_Host *instance) { diff --git a/drivers/scsi/atari_NCR5380.c b/drivers/scsi/atari_NCR5380.c index a01921dfed0b..aeaeea5169e4 100644 --- a/drivers/scsi/atari_NCR5380.c +++ b/drivers/scsi/atari_NCR5380.c @@ -24,47 +24,7 @@ * 1+ (800) 334-5454 */ -/* - * ++roman: To port the 5380 driver to the Atari, I had to do some changes in - * this file, too: - * - * - Some of the debug statements were incorrect (undefined variables and the - * like). I fixed that. - * - * - In information_transfer(), I think a #ifdef was wrong. Looking at the - * possible DMA transfer size should also happen for REAL_DMA. I added this - * in the #if statement. - * - * - When using real DMA, information_transfer() should return in a DATAOUT - * phase after starting the DMA. It has nothing more to do. - * - * - The interrupt service routine should run main after end of DMA, too (not - * only after RESELECTION interrupts). Additionally, it should _not_ test - * for more interrupts after running main, since a DMA process may have - * been started and interrupts are turned on now. The new int could happen - * inside the execution of NCR5380_intr(), leading to recursive - * calls. - * - * - I've added a function merge_contiguous_buffers() that tries to - * merge scatter-gather buffers that are located at contiguous - * physical addresses and can be processed with the same DMA setup. - * Since most scatter-gather operations work on a page (4K) of - * 4 buffers (1K), in more than 90% of all cases three interrupts and - * DMA setup actions are saved. - * - * - I've deleted all the stuff for AUTOPROBE_IRQ, REAL_DMA_POLL, PSEUDO_DMA - * and USLEEP, because these were messing up readability and will never be - * needed for Atari SCSI. - * - * - I've revised the NCR5380_main() calling scheme (relax the 'main_running' - * stuff), and 'main' is executed in a bottom half if awoken by an - * interrupt. - * - * - The code was quite cluttered up by "#if (NDEBUG & NDEBUG_*) printk..." - * constructs. In my eyes, this made the source rather unreadable, so I - * finally replaced that by the *_PRINTK() macros. - * - */ +/* Ported to Atari by Roman Hodek and others. */ /* Adapted for the sun3 by Sam Creasey. */ @@ -344,17 +304,15 @@ static void free_all_tags(struct NCR5380_hostdata *hostdata) #endif /* SUPPORT_TAGS */ - -/* - * Function: void merge_contiguous_buffers( struct scsi_cmnd *cmd ) - * - * Purpose: Try to merge several scatter-gather requests into one DMA - * transfer. This is possible if the scatter buffers lie on - * physical contiguous addresses. - * - * Parameters: struct scsi_cmnd *cmd - * The command to work on. The first scatter buffer's data are - * assumed to be already transferred into ptr/this_residual. +/** + * merge_contiguous_buffers - coalesce scatter-gather list entries + * @cmd: command requesting IO + * + * Try to merge several scatter-gather buffers into one DMA transfer. + * This is possible if the scatter buffers lie on physically + * contiguous addresses. The first scatter-gather buffer's data are + * assumed to be already transferred into cmd->SCp.this_residual. + * Every buffer merged avoids an interrupt and a DMA setup operation. */ static void merge_contiguous_buffers(struct scsi_cmnd *cmd) @@ -406,9 +364,7 @@ static inline void initialize_SCp(struct scsi_cmnd *cmd) cmd->SCp.buffers_residual = scsi_sg_count(cmd) - 1; cmd->SCp.ptr = sg_virt(cmd->SCp.buffer); cmd->SCp.this_residual = cmd->SCp.buffer->length; - /* ++roman: Try to merge some scatter-buffers if they are at - * contiguous physical addresses. - */ + merge_contiguous_buffers(cmd); } else { cmd->SCp.buffer = NULL; @@ -556,8 +512,6 @@ static struct { * @instance: adapter to dump * * Print the current SCSI phase for debugging purposes - * - * Locks: none */ static void NCR5380_print_phase(struct Scsi_Host *instance) @@ -583,8 +537,6 @@ static void NCR5380_print_phase(struct Scsi_Host *instance) * @instance: relevant scsi host instance * * For use as the host template info() handler. - * - * Locks: none */ static const char *NCR5380_info(struct Scsi_Host *instance) @@ -829,20 +781,6 @@ static int NCR5380_queue_command(struct Scsi_Host *instance, cmd->result = 0; /* - * Insert the cmd into the issue queue. Note that REQUEST SENSE - * commands are added to the head of the queue since any command will - * clear the contingent allegiance condition that exists and the - * sense data is only guaranteed to be valid while the condition exists. - */ - - /* ++guenther: now that the issue queue is being set up, we can lock ST-DMA. - * Otherwise a running NCR5380_main may steal the lock. - * Lock before actually inserting due to fairness reasons explained in - * atari_scsi.c. If we insert first, then it's impossible for this driver - * to release the lock. - * Stop timer for this command while waiting for the lock, or timeouts - * may happen (and they really do), and it's no good if the command doesn't - * appear in any of the queues. * ++roman: Just disabling the NCR interrupt isn't sufficient here, * because also a timer int can trigger an abort or reset, which would * alter queues and touch the lock. @@ -958,8 +896,6 @@ static void requeue_cmd(struct Scsi_Host *instance, struct scsi_cmnd *cmd) * be done on the NCR5380 host adapters in a system. Both * NCR5380_queue_command() and NCR5380_intr() will try to start it * in case it is not running. - * - * Locks: called as its own thread with no locks held. */ static void NCR5380_main(struct work_struct *work) @@ -1041,7 +977,6 @@ static void NCR5380_main(struct work_struct *work) * mismatch occurs (which would finish the DMA transfer). * * Inputs : instance - this instance of the NCR5380. - * */ static void NCR5380_dma_complete(struct Scsi_Host *instance) @@ -1766,7 +1701,6 @@ timeout: * is in same phase. * * Also, *phase, *count, *data are modified in place. - * */ @@ -1968,9 +1902,6 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) --cmd->SCp.buffers_residual; cmd->SCp.this_residual = cmd->SCp.buffer->length; cmd->SCp.ptr = sg_virt(cmd->SCp.buffer); - /* ++roman: Try to merge some scatter-buffers if - * they are at contiguous physical addresses. - */ merge_contiguous_buffers(cmd); dsprintk(NDEBUG_INFORMATION, instance, "%d bytes and %d buffers left\n", cmd->SCp.this_residual, @@ -2007,7 +1938,8 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) /* * If the watchdog timer fires, all future * accesses to this device will use the - * polled-IO. */ + * polled-IO. + */ scmd_printk(KERN_INFO, cmd, "switching to slow handshake\n"); cmd->device->borken = 1; @@ -2099,10 +2031,6 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) /* Enable reselect interrupts */ NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); - /* ++roman: For Falcon SCSI, release the lock on the - * ST-DMA here if no other commands are waiting on the - * disconnected queue. - */ maybe_release_dma_irq(instance); return; case MESSAGE_REJECT: @@ -2164,15 +2092,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) break; case EXTENDED_MESSAGE: /* - * Extended messages are sent in the following format : - * Byte - * 0 EXTENDED_MESSAGE == 1 - * 1 length (includes one byte for code, doesn't - * include first two bytes) - * 2 code - * 3..length+1 arguments - * - * Start the extended message buffer with the EXTENDED_MESSAGE + * Start the message buffer with the EXTENDED_MESSAGE * byte, since spi_print_msg() wants the whole thing. */ extended_msg[0] = EXTENDED_MESSAGE; @@ -2299,7 +2219,6 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) * nexus has been reestablished, * * Inputs : instance - this instance of the NCR5380. - * */ -- cgit From aff0cf9a7e098ecf1651f6f3a8cb0fbe272d6cf4 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sun, 3 Jan 2016 16:06:09 +1100 Subject: ncr5380: Fix trailing whitespace using regexp This patch is the result of the following substitution. It removes any tabs and spaces at the end of a line. perl -i -pe 's,[\t ]+$,,' drivers/scsi/{atari_,}NCR5380.c This removes some unimportant discrepancies between the two core driver forks so that the important ones become obvious, to facilitate reunification. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Ondrej Zary Tested-by: Michael Schmitz Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.c | 372 ++++++++++++++++++++++++------------------------- 1 file changed, 186 insertions(+), 186 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index b968b3012e27..f674420c131d 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -1,4 +1,4 @@ -/* +/* * NCR 5380 generic driver routines. These should make it *trivial* * to implement 5380 SCSI drivers under Linux with a non-trantor * architecture. @@ -6,12 +6,12 @@ * Note that these routines also work with NR53c400 family chips. * * Copyright 1993, Drew Eckhardt - * Visionary Computing + * Visionary Computing * (Unix and Linux consulting and custom programming) * drew@colorado.edu * +1 (303) 666-5836 * - * For more information, please consult + * For more information, please consult * * NCR 5380 Family * SCSI Protocol Controller @@ -30,16 +30,16 @@ */ /* - * Further development / testing that should be done : + * Further development / testing that should be done : * 1. Cleanup the NCR5380_transfer_dma function and DMA operation complete - * code so that everything does the same thing that's done at the + * code so that everything does the same thing that's done at the * end of a pseudo-DMA read operation. * * 2. Fix REAL_DMA (interrupt driven, polled works fine) - - * basically, transfer size needs to be reduced by one + * basically, transfer size needs to be reduced by one * and the last byte read as is done with PSEUDO_DMA. - * - * 4. Test SCSI-II tagged queueing (I have no devices which support + * + * 4. Test SCSI-II tagged queueing (I have no devices which support * tagged queueing) */ @@ -56,27 +56,27 @@ /* * Design * - * This is a generic 5380 driver. To use it on a different platform, + * This is a generic 5380 driver. To use it on a different platform, * one simply writes appropriate system specific macros (ie, data - * transfer - some PC's will use the I/O bus, 68K's must use + * transfer - some PC's will use the I/O bus, 68K's must use * memory mapped) and drops this file in their 'C' wrapper. * - * As far as command queueing, two queues are maintained for + * As far as command queueing, two queues are maintained for * each 5380 in the system - commands that haven't been issued yet, - * and commands that are currently executing. This means that an - * unlimited number of commands may be queued, letting - * more commands propagate from the higher driver levels giving higher - * throughput. Note that both I_T_L and I_T_L_Q nexuses are supported, - * allowing multiple commands to propagate all the way to a SCSI-II device + * and commands that are currently executing. This means that an + * unlimited number of commands may be queued, letting + * more commands propagate from the higher driver levels giving higher + * throughput. Note that both I_T_L and I_T_L_Q nexuses are supported, + * allowing multiple commands to propagate all the way to a SCSI-II device * while a command is already executing. * * - * Issues specific to the NCR5380 : + * Issues specific to the NCR5380 : * - * When used in a PIO or pseudo-dma mode, the NCR5380 is a braindead - * piece of hardware that requires you to sit in a loop polling for - * the REQ signal as long as you are connected. Some devices are - * brain dead (ie, many TEXEL CD ROM drives) and won't disconnect + * When used in a PIO or pseudo-dma mode, the NCR5380 is a braindead + * piece of hardware that requires you to sit in a loop polling for + * the REQ signal as long as you are connected. Some devices are + * brain dead (ie, many TEXEL CD ROM drives) and won't disconnect * while doing long seek operations. [...] These * broken devices are the exception rather than the rule and I'd rather * spend my time optimizing for the normal case. @@ -87,23 +87,23 @@ * which is started from a workqueue for each NCR5380 host in the * system. It attempts to establish I_T_L or I_T_L_Q nexuses by * removing the commands from the issue queue and calling - * NCR5380_select() if a nexus is not established. + * NCR5380_select() if a nexus is not established. * * Once a nexus is established, the NCR5380_information_transfer() * phase goes through the various phases as instructed by the target. * if the target goes into MSG IN and sends a DISCONNECT message, * the command structure is placed into the per instance disconnected - * queue, and NCR5380_main tries to find more work. If the target is + * queue, and NCR5380_main tries to find more work. If the target is * idle for too long, the system will try to sleep. * * If a command has disconnected, eventually an interrupt will trigger, * calling NCR5380_intr() which will in turn call NCR5380_reselect * to reestablish a nexus. This will run main if necessary. * - * On command termination, the done function will be called as + * On command termination, the done function will be called as * appropriate. * - * SCSI pointers are maintained in the SCp field of SCSI command + * SCSI pointers are maintained in the SCp field of SCSI command * structures, being initialized after the command is connected * in NCR5380_select, and set as appropriate in NCR5380_information_transfer. * Note that in violation of the standard, an implicit SAVE POINTERS operation @@ -113,18 +113,18 @@ /* * Using this file : * This file a skeleton Linux SCSI driver for the NCR 5380 series - * of chips. To use it, you write an architecture specific functions + * of chips. To use it, you write an architecture specific functions * and macros and include this file in your driver. * - * These macros control options : - * AUTOPROBE_IRQ - if defined, the NCR5380_probe_irq() function will be + * These macros control options : + * AUTOPROBE_IRQ - if defined, the NCR5380_probe_irq() function will be * defined. - * + * * AUTOSENSE - if defined, REQUEST SENSE will be performed automatically - * for commands that return with a CHECK CONDITION status. + * for commands that return with a CHECK CONDITION status. * * DIFFERENTIAL - if defined, NCR53c81 chips will use external differential - * transceivers. + * transceivers. * * DONT_USE_INTR - if defined, never use interrupts, even if we probe or * override-configure an IRQ. @@ -134,25 +134,25 @@ * REAL_DMA - if defined, REAL DMA is used during the data transfer phases. * * REAL_DMA_POLL - if defined, REAL DMA is used but the driver doesn't - * rely on phase mismatch and EOP interrupts to determine end + * rely on phase mismatch and EOP interrupts to determine end * of phase. * * These macros MUST be defined : - * + * * NCR5380_read(register) - read from the specified register * - * NCR5380_write(register, value) - write to the specific register + * NCR5380_write(register, value) - write to the specific register * - * NCR5380_implementation_fields - additional fields needed for this + * NCR5380_implementation_fields - additional fields needed for this * specific implementation of the NCR5380 * * Either real DMA *or* pseudo DMA may be implemented - * REAL functions : + * REAL functions : * NCR5380_REAL_DMA should be defined if real DMA is to be used. - * Note that the DMA setup functions should return the number of bytes + * Note that the DMA setup functions should return the number of bytes * that they were able to program the controller for. * - * Also note that generic i386/PC versions of these macros are + * Also note that generic i386/PC versions of these macros are * available as NCR5380_i386_dma_write_setup, * NCR5380_i386_dma_read_setup, and NCR5380_i386_dma_residual. * @@ -165,7 +165,7 @@ * NCR5380_pread(instance, dst, count); * * The generic driver is initialized by calling NCR5380_init(instance), - * after setting the appropriate host specific fields and ID. If the + * after setting the appropriate host specific fields and ID. If the * driver wishes to autoprobe for an IRQ line, the NCR5380_probe_irq(instance, * possible) function may be used. */ @@ -182,8 +182,8 @@ static void do_reset(struct Scsi_Host *); static inline void initialize_SCp(struct scsi_cmnd *cmd) { - /* - * Initialize the Scsi Pointer field so that all of the commands in the + /* + * Initialize the Scsi Pointer field so that all of the commands in the * various queues are valid. */ @@ -268,12 +268,12 @@ static struct { unsigned char value; const char *name; } phases[] __maybe_unused = { - {PHASE_DATAOUT, "DATAOUT"}, - {PHASE_DATAIN, "DATAIN"}, - {PHASE_CMDOUT, "CMDOUT"}, - {PHASE_STATIN, "STATIN"}, - {PHASE_MSGOUT, "MSGOUT"}, - {PHASE_MSGIN, "MSGIN"}, + {PHASE_DATAOUT, "DATAOUT"}, + {PHASE_DATAIN, "DATAIN"}, + {PHASE_CMDOUT, "CMDOUT"}, + {PHASE_STATIN, "STATIN"}, + {PHASE_MSGOUT, "MSGOUT"}, + {PHASE_MSGIN, "MSGIN"}, {PHASE_UNKNOWN, "UNKNOWN"} }; @@ -281,39 +281,39 @@ static struct { static struct { unsigned char mask; const char *name; -} signals[] = { - {SR_DBP, "PARITY"}, - {SR_RST, "RST"}, - {SR_BSY, "BSY"}, - {SR_REQ, "REQ"}, - {SR_MSG, "MSG"}, - {SR_CD, "CD"}, - {SR_IO, "IO"}, - {SR_SEL, "SEL"}, +} signals[] = { + {SR_DBP, "PARITY"}, + {SR_RST, "RST"}, + {SR_BSY, "BSY"}, + {SR_REQ, "REQ"}, + {SR_MSG, "MSG"}, + {SR_CD, "CD"}, + {SR_IO, "IO"}, + {SR_SEL, "SEL"}, {0, NULL} -}, +}, basrs[] = { - {BASR_ATN, "ATN"}, - {BASR_ACK, "ACK"}, + {BASR_ATN, "ATN"}, + {BASR_ACK, "ACK"}, {0, NULL} -}, -icrs[] = { - {ICR_ASSERT_RST, "ASSERT RST"}, - {ICR_ASSERT_ACK, "ASSERT ACK"}, - {ICR_ASSERT_BSY, "ASSERT BSY"}, - {ICR_ASSERT_SEL, "ASSERT SEL"}, - {ICR_ASSERT_ATN, "ASSERT ATN"}, - {ICR_ASSERT_DATA, "ASSERT DATA"}, +}, +icrs[] = { + {ICR_ASSERT_RST, "ASSERT RST"}, + {ICR_ASSERT_ACK, "ASSERT ACK"}, + {ICR_ASSERT_BSY, "ASSERT BSY"}, + {ICR_ASSERT_SEL, "ASSERT SEL"}, + {ICR_ASSERT_ATN, "ASSERT ATN"}, + {ICR_ASSERT_DATA, "ASSERT DATA"}, {0, NULL} -}, -mrs[] = { - {MR_BLOCK_DMA_MODE, "MODE BLOCK DMA"}, - {MR_TARGET, "MODE TARGET"}, - {MR_ENABLE_PAR_CHECK, "MODE PARITY CHECK"}, - {MR_ENABLE_PAR_INTR, "MODE PARITY INTR"}, - {MR_MONITOR_BSY, "MODE MONITOR BSY"}, - {MR_DMA_MODE, "MODE DMA"}, - {MR_ARBITRATE, "MODE ARBITRATION"}, +}, +mrs[] = { + {MR_BLOCK_DMA_MODE, "MODE BLOCK DMA"}, + {MR_TARGET, "MODE TARGET"}, + {MR_ENABLE_PAR_CHECK, "MODE PARITY CHECK"}, + {MR_ENABLE_PAR_INTR, "MODE PARITY INTR"}, + {MR_MONITOR_BSY, "MODE MONITOR BSY"}, + {MR_DMA_MODE, "MODE DMA"}, + {MR_ARBITRATE, "MODE ARBITRATION"}, {0, NULL} }; @@ -388,7 +388,7 @@ static int probe_irq __initdata; * Set a flag to indicate the IRQ in question was received. This is * used by the IRQ probe code. */ - + static irqreturn_t __init probe_intr(int irq, void *dev_id) { probe_irq = irq; @@ -420,7 +420,7 @@ static int __init __maybe_unused NCR5380_probe_irq(struct Scsi_Host *instance, /* * A interrupt is triggered whenever BSY = false, SEL = true - * and a bit set in the SELECT_ENABLE_REG is asserted on the + * and a bit set in the SELECT_ENABLE_REG is asserted on the * SCSI bus. * * Note that the bus is only driven when the phase control signals @@ -435,7 +435,7 @@ static int __init __maybe_unused NCR5380_probe_irq(struct Scsi_Host *instance, while (probe_irq == NO_IRQ && time_before(jiffies, timeout)) schedule_timeout_uninterruptible(1); - + NCR5380_write(SELECT_ENABLE_REG, 0); NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); @@ -530,7 +530,7 @@ static int __maybe_unused NCR5380_show_info(struct seq_file *m, * with flags OR'd into the initial flags value. * * Notes : I assume that the host, hostno, and id bits have been - * set correctly. I don't care about the irq and other fields. + * set correctly. I don't care about the irq and other fields. * * Returns 0 for success */ @@ -561,7 +561,7 @@ static int NCR5380_init(struct Scsi_Host *instance, int flags) INIT_LIST_HEAD(&hostdata->disconnected); hostdata->flags = flags; - + INIT_WORK(&hostdata->main_task, NCR5380_main); hostdata->work_q = alloc_workqueue("ncr5380_%d", WQ_UNBOUND | WQ_MEM_RECLAIM, @@ -720,10 +720,10 @@ static int NCR5380_queue_command(struct Scsi_Host *instance, spin_lock_irqsave(&hostdata->lock, flags); - /* - * Insert the cmd into the issue queue. Note that REQUEST SENSE + /* + * Insert the cmd into the issue queue. Note that REQUEST SENSE * commands are added to the head of the queue since any command will - * clear the contingent allegiance condition that exists and the + * clear the contingent allegiance condition that exists and the * sense data is only guaranteed to be valid while the condition exists. */ @@ -803,9 +803,9 @@ static void requeue_cmd(struct Scsi_Host *instance, struct scsi_cmnd *cmd) /** * NCR5380_main - NCR state machines * - * NCR5380_main is a coroutine that runs as long as more work can - * be done on the NCR5380 host adapters in a system. Both - * NCR5380_queue_command() and NCR5380_intr() will try to start it + * NCR5380_main is a coroutine that runs as long as more work can + * be done on the NCR5380 host adapters in a system. Both + * NCR5380_queue_command() and NCR5380_intr() will try to start it * in case it is not running. */ @@ -816,7 +816,7 @@ static void NCR5380_main(struct work_struct *work) struct Scsi_Host *instance = hostdata->host; struct scsi_cmnd *cmd; int done; - + do { done = 1; @@ -975,37 +975,37 @@ static irqreturn_t NCR5380_intr(int irq, void *dev_id) return IRQ_RETVAL(handled); } -#endif +#endif -/* +/* * Function : int NCR5380_select(struct Scsi_Host *instance, * struct scsi_cmnd *cmd) * * Purpose : establishes I_T_L or I_T_L_Q nexus for new or existing command, - * including ARBITRATION, SELECTION, and initial message out for - * IDENTIFY and queue messages. + * including ARBITRATION, SELECTION, and initial message out for + * IDENTIFY and queue messages. * - * Inputs : instance - instantiation of the 5380 driver on which this + * Inputs : instance - instantiation of the 5380 driver on which this * target lives, cmd - SCSI command to execute. - * + * * Returns cmd if selection failed but should be retried, * NULL if selection failed and should not be retried, or * NULL if selection succeeded (hostdata->connected == cmd). * - * Side effects : - * If bus busy, arbitration failed, etc, NCR5380_select() will exit + * Side effects : + * If bus busy, arbitration failed, etc, NCR5380_select() will exit * with registers as they should have been on entry - ie * SELECT_ENABLE will be set appropriately, the NCR5380 * will cease to drive any SCSI bus signals. * - * If successful : I_T_L or I_T_L_Q nexus will be established, - * instance->connected will be set to cmd. + * If successful : I_T_L or I_T_L_Q nexus will be established, + * instance->connected will be set to cmd. * SELECT interrupt will be disabled. * - * If failed (no target) : cmd->scsi_done() will be called, and the + * If failed (no target) : cmd->scsi_done() will be called, and the * cmd->result host byte set to DID_BAD_TARGET. */ - + static struct scsi_cmnd *NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd) { @@ -1028,14 +1028,14 @@ static struct scsi_cmnd *NCR5380_select(struct Scsi_Host *instance, */ hostdata->selecting = cmd; - /* - * Set the phase bits to 0, otherwise the NCR5380 won't drive the + /* + * Set the phase bits to 0, otherwise the NCR5380 won't drive the * data bus during SELECTION. */ NCR5380_write(TARGET_COMMAND_REG, 0); - /* + /* * Start arbitration. */ @@ -1081,8 +1081,8 @@ static struct scsi_cmnd *NCR5380_select(struct Scsi_Host *instance, NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_SEL | ICR_ASSERT_BSY); - /* - * Again, bus clear + bus settle time is 1.2us, however, this is + /* + * Again, bus clear + bus settle time is 1.2us, however, this is * a minimum so we'll udelay ceil(1.2) */ @@ -1105,14 +1105,14 @@ static struct scsi_cmnd *NCR5380_select(struct Scsi_Host *instance, dsprintk(NDEBUG_ARBITRATION, instance, "won arbitration\n"); - /* - * Now that we have won arbitration, start Selection process, asserting + /* + * Now that we have won arbitration, start Selection process, asserting * the host and target ID's on the SCSI bus. */ NCR5380_write(OUTPUT_DATA_REG, (hostdata->id_mask | (1 << scmd_id(cmd)))); - /* + /* * Raise ATN while SEL is true before BSY goes false from arbitration, * since this is the only way to guarantee that we'll get a MESSAGE OUT * phase immediately after selection. @@ -1121,7 +1121,7 @@ static struct scsi_cmnd *NCR5380_select(struct Scsi_Host *instance, NCR5380_write(INITIATOR_COMMAND_REG, (ICR_BASE | ICR_ASSERT_BSY | ICR_ASSERT_DATA | ICR_ASSERT_ATN | ICR_ASSERT_SEL)); NCR5380_write(MODE_REG, MR_BASE); - /* + /* * Reselect interrupts must be turned off prior to the dropping of BSY, * otherwise we will trigger an interrupt. */ @@ -1130,7 +1130,7 @@ static struct scsi_cmnd *NCR5380_select(struct Scsi_Host *instance, spin_unlock_irq(&hostdata->lock); /* - * The initiator shall then wait at least two deskew delays and release + * The initiator shall then wait at least two deskew delays and release * the BSY signal. */ udelay(1); /* wingel -- wait two bus deskew delay >2*45ns */ @@ -1138,17 +1138,17 @@ static struct scsi_cmnd *NCR5380_select(struct Scsi_Host *instance, /* Reset BSY */ NCR5380_write(INITIATOR_COMMAND_REG, (ICR_BASE | ICR_ASSERT_DATA | ICR_ASSERT_ATN | ICR_ASSERT_SEL)); - /* + /* * Something weird happens when we cease to drive BSY - looks - * like the board/chip is letting us do another read before the + * like the board/chip is letting us do another read before the * appropriate propagation delay has expired, and we're confusing * a BSY signal from ourselves as the target's response to SELECTION. * * A small delay (the 'C++' frontend breaks the pipeline with an * unnecessary jump, making it work on my 386-33/Trantor T128, the - * tighter 'C' code breaks and requires this) solves the problem - - * the 1 us delay is arbitrary, and only used because this delay will - * be the same on other platforms and since it works here, it should + * tighter 'C' code breaks and requires this) solves the problem - + * the 1 us delay is arbitrary, and only used because this delay will + * be the same on other platforms and since it works here, it should * work there. * * wingel suggests that this could be due to failing to wait @@ -1159,8 +1159,8 @@ static struct scsi_cmnd *NCR5380_select(struct Scsi_Host *instance, dsprintk(NDEBUG_SELECTION, instance, "selecting target %d\n", scmd_id(cmd)); - /* - * The SCSI specification calls for a 250 ms timeout for the actual + /* + * The SCSI specification calls for a 250 ms timeout for the actual * selection. */ @@ -1191,9 +1191,9 @@ static struct scsi_cmnd *NCR5380_select(struct Scsi_Host *instance, goto out; } - /* - * No less than two deskew delays after the initiator detects the - * BSY signal is true, it shall release the SEL signal and may + /* + * No less than two deskew delays after the initiator detects the + * BSY signal is true, it shall release the SEL signal and may * change the DATA BUS. -wingel */ @@ -1202,11 +1202,11 @@ static struct scsi_cmnd *NCR5380_select(struct Scsi_Host *instance, NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN); /* - * Since we followed the SCSI spec, and raised ATN while SEL + * Since we followed the SCSI spec, and raised ATN while SEL * was true but before BSY was false during selection, the information * transfer phase should be a MESSAGE OUT phase so that we can send the * IDENTIFY message. - * + * * If SCSI-II tagged queuing is enabled, we also send a SIMPLE_QUEUE_TAG * message (2 bytes) with a tag ID that we increment with every command * until it wraps back to 0. @@ -1259,16 +1259,16 @@ out: return cmd; } -/* - * Function : int NCR5380_transfer_pio (struct Scsi_Host *instance, +/* + * Function : int NCR5380_transfer_pio (struct Scsi_Host *instance, * unsigned char *phase, int *count, unsigned char **data) * * Purpose : transfers data in given phase using polled I/O * - * Inputs : instance - instance of driver, *phase - pointer to - * what phase is expected, *count - pointer to number of + * Inputs : instance - instance of driver, *phase - pointer to + * what phase is expected, *count - pointer to number of * bytes to transfer, **data - pointer to data pointer. - * + * * Returns : -1 when different phase is entered without transferring * maximum number of bytes, 0 if all bytes or transferred or exit * is in same phase. @@ -1279,7 +1279,7 @@ out: */ /* - * Note : this code is not as quick as it could be, however it + * Note : this code is not as quick as it could be, however it * IS 100% reliable, and for the actual data transfer where speed * counts, we will always do a pseudo DMA or DMA transfer. */ @@ -1289,8 +1289,8 @@ static int NCR5380_transfer_pio(struct Scsi_Host *instance, unsigned char *phase int c = *count; unsigned char *d = *data; - /* - * The NCR5380 chip will only drive the SCSI bus when the + /* + * The NCR5380 chip will only drive the SCSI bus when the * phase specified in the appropriate bits of the TARGET COMMAND * REGISTER match the STATUS REGISTER */ @@ -1298,9 +1298,9 @@ static int NCR5380_transfer_pio(struct Scsi_Host *instance, unsigned char *phase NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(p)); do { - /* - * Wait for assertion of REQ, after which the phase bits will be - * valid + /* + * Wait for assertion of REQ, after which the phase bits will be + * valid */ if (NCR5380_poll_politely(instance, STATUS_REG, SR_REQ, SR_REQ, HZ) < 0) @@ -1322,7 +1322,7 @@ static int NCR5380_transfer_pio(struct Scsi_Host *instance, unsigned char *phase ++d; - /* + /* * The SCSI standard suggests that in MSGOUT phase, the initiator * should drop ATN on the last byte of the message phase * after REQ has been asserted for the handshake but before @@ -1351,11 +1351,11 @@ static int NCR5380_transfer_pio(struct Scsi_Host *instance, unsigned char *phase dsprintk(NDEBUG_HANDSHAKE, instance, "REQ negated, handshake complete\n"); /* - * We have several special cases to consider during REQ/ACK handshaking : - * 1. We were in MSGOUT phase, and we are on the last byte of the + * We have several special cases to consider during REQ/ACK handshaking : + * 1. We were in MSGOUT phase, and we are on the last byte of the * message. ATN must be dropped as ACK is dropped. * - * 2. We are in a MSGIN phase, and we are on the last byte of the + * 2. We are in a MSGIN phase, and we are on the last byte of the * message. We must exit with ACK asserted, so that the calling * code may raise ATN before dropping ACK to reject the message. * @@ -1400,7 +1400,7 @@ static int NCR5380_transfer_pio(struct Scsi_Host *instance, unsigned char *phase * it. When the driver is initialized, the NCR5380_intr() handler has not yet * been installed. And when in EH we may have released the ST DMA interrupt. */ - + static void do_reset(struct Scsi_Host *instance) { unsigned long flags; @@ -1432,12 +1432,12 @@ static int do_abort(struct Scsi_Host *instance) /* Request message out phase */ NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN); - /* - * Wait for the target to indicate a valid phase by asserting - * REQ. Once this happens, we'll have either a MSGOUT phase - * and can immediately send the ABORT message, or we'll have some + /* + * Wait for the target to indicate a valid phase by asserting + * REQ. Once this happens, we'll have either a MSGOUT phase + * and can immediately send the ABORT message, or we'll have some * other phase and will have to source/sink data. - * + * * We really don't care what value was on the bus or what value * the target sees, so we just handshake. */ @@ -1447,7 +1447,7 @@ static int do_abort(struct Scsi_Host *instance) goto timeout; tmp = NCR5380_read(STATUS_REG) & PHASE_MASK; - + NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(tmp)); if (tmp != PHASE_MSGOUT) { @@ -1476,17 +1476,17 @@ timeout: } #if defined(REAL_DMA) || defined(PSEUDO_DMA) || defined (REAL_DMA_POLL) -/* - * Function : int NCR5380_transfer_dma (struct Scsi_Host *instance, +/* + * Function : int NCR5380_transfer_dma (struct Scsi_Host *instance, * unsigned char *phase, int *count, unsigned char **data) * * Purpose : transfers data in given phase using either real * or pseudo DMA. * - * Inputs : instance - instance of driver, *phase - pointer to - * what phase is expected, *count - pointer to number of + * Inputs : instance - instance of driver, *phase - pointer to + * what phase is expected, *count - pointer to number of * bytes to transfer, **data - pointer to data pointer. - * + * * Returns : -1 when different phase is entered without transferring * maximum number of bytes, 0 if all bytes or transferred or exit * is in same phase. @@ -1533,7 +1533,7 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, unsigned char *phase #else /* * Note : on my sample board, watch-dog timeouts occurred when interrupts - * were not disabled for the duration of a single DMA transfer, from + * were not disabled for the duration of a single DMA transfer, from * before the setting of DMA mode to after transfer of the last byte. */ @@ -1546,7 +1546,7 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, unsigned char *phase dprintk(NDEBUG_DMA, "scsi%d : mode reg = 0x%X\n", instance->host_no, NCR5380_read(MODE_REG)); - /* + /* * On the PAS16 at least I/O recovery delays are not needed here. * Everyone else seems to want them. */ @@ -1661,24 +1661,24 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, unsigned char *phase hostdata->flags & FLAG_NO_DMA_FIXUP ? c : c - 1); if (!foo && !(hostdata->flags & FLAG_NO_DMA_FIXUP)) { /* - * We can't disable DMA mode after successfully transferring + * We can't disable DMA mode after successfully transferring * what we plan to be the last byte, since that would open up - * a race condition where if the target asserted REQ before + * a race condition where if the target asserted REQ before * we got the DMA mode reset, the NCR5380 would have latched * an additional byte into the INPUT DATA register and we'd * have dropped it. - * - * The workaround was to transfer one fewer bytes than we - * intended to with the pseudo-DMA read function, wait for + * + * The workaround was to transfer one fewer bytes than we + * intended to with the pseudo-DMA read function, wait for * the chip to latch the last byte, read it, and then disable * pseudo-DMA mode. - * + * * After REQ is asserted, the NCR5380 asserts DRQ and ACK. * REQ is deasserted when ACK is asserted, and not reasserted * until ACK goes false. Since the NCR5380 won't lower ACK * until DACK is asserted, which won't happen unless we twiddle - * the DMA port or we take the NCR5380 out of DMA mode, we - * can guarantee that we won't handshake another extra + * the DMA port or we take the NCR5380 out of DMA mode, we + * can guarantee that we won't handshake another extra * byte. */ @@ -1698,8 +1698,8 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, unsigned char *phase foo = NCR5380_pwrite(instance, d, c); if (!foo && !(hostdata->flags & FLAG_NO_DMA_FIXUP)) { /* - * Wait for the last byte to be sent. If REQ is being asserted for - * the byte we're interested, we'll ACK it and it will go false. + * Wait for the last byte to be sent. If REQ is being asserted for + * the byte we're interested, we'll ACK it and it will go false. */ if (NCR5380_poll_politely2(instance, BUS_AND_STATUS_REG, BASR_DRQ, BASR_DRQ, @@ -1723,17 +1723,17 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, unsigned char *phase /* * Function : NCR5380_information_transfer (struct Scsi_Host *instance) * - * Purpose : run through the various SCSI phases and do as the target - * directs us to. Operates on the currently connected command, + * Purpose : run through the various SCSI phases and do as the target + * directs us to. Operates on the currently connected command, * instance->connected. * * Inputs : instance, instance for which we are doing commands * - * Side effects : SCSI things happen, the disconnected queue will be + * Side effects : SCSI things happen, the disconnected queue will be * modified if a command disconnects, *instance->connected will * change. * - * XXX Note : we need to watch for bus free or a reset condition here + * XXX Note : we need to watch for bus free or a reset condition here * to recover from an unexpected bus free condition. */ @@ -1780,7 +1780,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { return; #endif case PHASE_DATAIN: - /* + /* * If there is no room left in the current buffer in the * scatter-gather list, move onto the next one. */ @@ -1795,7 +1795,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { cmd->SCp.buffers_residual); } /* - * The preferred transfer method is going to be + * The preferred transfer method is going to be * PSEUDO-DMA for systems that are strictly PIO, * since we can let the hardware do the handshaking. * @@ -1871,8 +1871,8 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { complete_cmd(instance, cmd); } - /* - * Restore phase bits to 0 so an interrupted selection, + /* + * Restore phase bits to 0 so an interrupted selection, * arbitration can resume. */ NCR5380_write(TARGET_COMMAND_REG, 0); @@ -1903,8 +1903,8 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { instance, "connected command %p for target %d lun %llu moved to disconnected queue\n", cmd, scmd_id(cmd), cmd->device->lun); - /* - * Restore phase bits to 0 so an interrupted selection, + /* + * Restore phase bits to 0 so an interrupted selection, * arbitration can resume. */ NCR5380_write(TARGET_COMMAND_REG, 0); @@ -1913,14 +1913,14 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); return; } - /* + /* * The SCSI data pointer is *IMPLICITLY* saved on a disconnect - * operation, in violation of the SCSI spec so we can safely + * operation, in violation of the SCSI spec so we can safely * ignore SAVE/RESTORE pointers calls. * - * Unfortunately, some disks violate the SCSI spec and + * Unfortunately, some disks violate the SCSI spec and * don't issue the required SAVE_POINTERS message before - * disconnecting, and we have to break spec to remain + * disconnecting, and we have to break spec to remain * compatible. */ case SAVE_POINTERS: @@ -1983,8 +1983,8 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { /* Fall through to reject message */ - /* - * If we get something weird that we aren't expecting, + /* + * If we get something weird that we aren't expecting, * reject it. */ default: @@ -2021,10 +2021,10 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { case PHASE_CMDOUT: len = cmd->cmd_len; data = cmd->cmnd; - /* - * XXX for performance reasons, on machines with a - * PSEUDO-DMA architecture we should probably - * use the dma transfer function. + /* + * XXX for performance reasons, on machines with a + * PSEUDO-DMA architecture we should probably + * use the dma transfer function. */ NCR5380_transfer_pio(instance, &phase, &len, &data); break; @@ -2049,10 +2049,10 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { /* * Function : void NCR5380_reselect (struct Scsi_Host *instance) * - * Purpose : does reselection, initializing the instance->connected + * Purpose : does reselection, initializing the instance->connected * field to point to the scsi_cmnd for which the I_T_L or I_T_L_Q * nexus has been reestablished, - * + * * Inputs : instance - this instance of the NCR5380. */ @@ -2077,7 +2077,7 @@ static void NCR5380_reselect(struct Scsi_Host *instance) { dsprintk(NDEBUG_RESELECTION, instance, "reselect\n"); - /* + /* * At this point, we have detected that our SCSI ID is on the bus, * SEL is true and BSY was false for at least one bus settle delay * (400 ns). @@ -2172,7 +2172,7 @@ static void NCR5380_reselect(struct Scsi_Host *instance) { * Function : void NCR5380_dma_complete (struct Scsi_Host *instance) * * Purpose : called by interrupt handler when DMA finishes or a phase - * mismatch occurs (which would finish the DMA transfer). + * mismatch occurs (which would finish the DMA transfer). * * Inputs : instance - this instance of the NCR5380. * @@ -2190,7 +2190,7 @@ static void NCR5380_dma_complete(NCR5380_instance * instance) { * * Wait for final byte to transfer, ie wait for ACK to go false. * - * We should use the Last Byte Sent bit, unfortunately this is + * We should use the Last Byte Sent bit, unfortunately this is * not available on the 5380/5381 (only the various CMOS chips) * * FIXME: timeout, and need to handle long timeout/irq case -- cgit From 594d4ba36c0a03967da37ee6e7675ede1a67abb4 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sun, 3 Jan 2016 16:06:10 +1100 Subject: ncr5380: Fix whitespace in comments using regexp Hanging indentation was a poor choice for the text inside comments. It has been used in the wrong places and done badly elsewhere. There is little consistency within any file. One fork of the core driver uses tabs for this indentation while the other uses spaces. Better to use flush-left alignment throughout. This patch is the result of the following substitution. It replaces tabs and spaces at the start of a comment line with a single space. perl -i -pe 's,^(\t*[/ ]\*)[ \t]+,$1 ,' drivers/scsi/{atari_,}NCR5380.c This removes some unimportant discrepancies between the two core driver forks so that the important ones become obvious, to facilitate reunification. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Ondrej Zary Tested-by: Michael Schmitz Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.c | 204 +++++++++++++++++++++---------------------- drivers/scsi/atari_NCR5380.c | 106 +++++++++++----------- 2 files changed, 155 insertions(+), 155 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index f674420c131d..eb21803eab3b 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -1,15 +1,15 @@ /* * NCR 5380 generic driver routines. These should make it *trivial* - * to implement 5380 SCSI drivers under Linux with a non-trantor - * architecture. + * to implement 5380 SCSI drivers under Linux with a non-trantor + * architecture. * - * Note that these routines also work with NR53c400 family chips. + * Note that these routines also work with NR53c400 family chips. * * Copyright 1993, Drew Eckhardt - * Visionary Computing - * (Unix and Linux consulting and custom programming) - * drew@colorado.edu - * +1 (303) 666-5836 + * Visionary Computing + * (Unix and Linux consulting and custom programming) + * drew@colorado.edu + * +1 (303) 666-5836 * * For more information, please consult * @@ -32,15 +32,15 @@ /* * Further development / testing that should be done : * 1. Cleanup the NCR5380_transfer_dma function and DMA operation complete - * code so that everything does the same thing that's done at the - * end of a pseudo-DMA read operation. + * code so that everything does the same thing that's done at the + * end of a pseudo-DMA read operation. * * 2. Fix REAL_DMA (interrupt driven, polled works fine) - - * basically, transfer size needs to be reduced by one - * and the last byte read as is done with PSEUDO_DMA. + * basically, transfer size needs to be reduced by one + * and the last byte read as is done with PSEUDO_DMA. * * 4. Test SCSI-II tagged queueing (I have no devices which support - * tagged queueing) + * tagged queueing) */ #ifndef notyet @@ -118,24 +118,24 @@ * * These macros control options : * AUTOPROBE_IRQ - if defined, the NCR5380_probe_irq() function will be - * defined. + * defined. * * AUTOSENSE - if defined, REQUEST SENSE will be performed automatically - * for commands that return with a CHECK CONDITION status. + * for commands that return with a CHECK CONDITION status. * * DIFFERENTIAL - if defined, NCR53c81 chips will use external differential - * transceivers. + * transceivers. * * DONT_USE_INTR - if defined, never use interrupts, even if we probe or - * override-configure an IRQ. + * override-configure an IRQ. * * PSEUDO_DMA - if defined, PSEUDO DMA is used during the data transfer phases. * * REAL_DMA - if defined, REAL DMA is used during the data transfer phases. * * REAL_DMA_POLL - if defined, REAL DMA is used but the driver doesn't - * rely on phase mismatch and EOP interrupts to determine end - * of phase. + * rely on phase mismatch and EOP interrupts to determine end + * of phase. * * These macros MUST be defined : * @@ -144,17 +144,17 @@ * NCR5380_write(register, value) - write to the specific register * * NCR5380_implementation_fields - additional fields needed for this - * specific implementation of the NCR5380 + * specific implementation of the NCR5380 * * Either real DMA *or* pseudo DMA may be implemented * REAL functions : * NCR5380_REAL_DMA should be defined if real DMA is to be used. * Note that the DMA setup functions should return the number of bytes - * that they were able to program the controller for. + * that they were able to program the controller for. * * Also note that generic i386/PC versions of these macros are - * available as NCR5380_i386_dma_write_setup, - * NCR5380_i386_dma_read_setup, and NCR5380_i386_dma_residual. + * available as NCR5380_i386_dma_write_setup, + * NCR5380_i386_dma_read_setup, and NCR5380_i386_dma_residual. * * NCR5380_dma_write_setup(instance, src, count) - initialize * NCR5380_dma_read_setup(instance, dst, count) - initialize @@ -174,10 +174,10 @@ static int do_abort(struct Scsi_Host *); static void do_reset(struct Scsi_Host *); /** - * initialize_SCp - init the scsi pointer field - * @cmd: command block to set up + * initialize_SCp - init the scsi pointer field + * @cmd: command block to set up * - * Set up the internal fields in the SCSI command. + * Set up the internal fields in the SCSI command. */ static inline void initialize_SCp(struct scsi_cmnd *cmd) @@ -318,10 +318,10 @@ mrs[] = { }; /** - * NCR5380_print - print scsi bus signals - * @instance: adapter state to dump + * NCR5380_print - print scsi bus signals + * @instance: adapter state to dump * - * Print the SCSI bus signals for debugging purposes + * Print the SCSI bus signals for debugging purposes */ static void NCR5380_print(struct Scsi_Host *instance) @@ -355,10 +355,10 @@ static void NCR5380_print(struct Scsi_Host *instance) /** - * NCR5380_print_phase - show SCSI phase - * @instance: adapter to dump + * NCR5380_print_phase - show SCSI phase + * @instance: adapter to dump * - * Print the current SCSI phase for debugging purposes + * Print the current SCSI phase for debugging purposes */ static void NCR5380_print_phase(struct Scsi_Host *instance) @@ -380,13 +380,13 @@ static void NCR5380_print_phase(struct Scsi_Host *instance) static int probe_irq __initdata; /** - * probe_intr - helper for IRQ autoprobe - * @irq: interrupt number - * @dev_id: unused - * @regs: unused + * probe_intr - helper for IRQ autoprobe + * @irq: interrupt number + * @dev_id: unused + * @regs: unused * - * Set a flag to indicate the IRQ in question was received. This is - * used by the IRQ probe code. + * Set a flag to indicate the IRQ in question was received. This is + * used by the IRQ probe code. */ static irqreturn_t __init probe_intr(int irq, void *dev_id) @@ -396,12 +396,12 @@ static irqreturn_t __init probe_intr(int irq, void *dev_id) } /** - * NCR5380_probe_irq - find the IRQ of an NCR5380 - * @instance: NCR5380 controller - * @possible: bitmask of ISA IRQ lines + * NCR5380_probe_irq - find the IRQ of an NCR5380 + * @instance: NCR5380 controller + * @possible: bitmask of ISA IRQ lines * - * Autoprobe for the IRQ line used by the NCR5380 by triggering an IRQ - * and then looking to see what interrupt actually turned up. + * Autoprobe for the IRQ line used by the NCR5380 by triggering an IRQ + * and then looking to see what interrupt actually turned up. */ static int __init __maybe_unused NCR5380_probe_irq(struct Scsi_Host *instance, @@ -447,10 +447,10 @@ static int __init __maybe_unused NCR5380_probe_irq(struct Scsi_Host *instance, } /** - * NCR58380_info - report driver and host information - * @instance: relevant scsi host instance + * NCR58380_info - report driver and host information + * @instance: relevant scsi host instance * - * For use as the host template info() handler. + * For use as the host template info() handler. */ static const char *NCR5380_info(struct Scsi_Host *instance) @@ -522,17 +522,17 @@ static int __maybe_unused NCR5380_show_info(struct seq_file *m, #endif /** - * NCR5380_init - initialise an NCR5380 - * @instance: adapter to configure - * @flags: control flags + * NCR5380_init - initialise an NCR5380 + * @instance: adapter to configure + * @flags: control flags * - * Initializes *instance and corresponding 5380 chip, - * with flags OR'd into the initial flags value. + * Initializes *instance and corresponding 5380 chip, + * with flags OR'd into the initial flags value. * - * Notes : I assume that the host, hostno, and id bits have been - * set correctly. I don't care about the irq and other fields. + * Notes : I assume that the host, hostno, and id bits have been + * set correctly. I don't care about the irq and other fields. * - * Returns 0 for success + * Returns 0 for success */ static int NCR5380_init(struct Scsi_Host *instance, int flags) @@ -648,8 +648,8 @@ static int NCR5380_maybe_reset_bus(struct Scsi_Host *instance) } /** - * NCR5380_exit - remove an NCR5380 - * @instance: adapter to remove + * NCR5380_exit - remove an NCR5380 + * @instance: adapter to remove */ static void NCR5380_exit(struct Scsi_Host *instance) @@ -801,12 +801,12 @@ static void requeue_cmd(struct Scsi_Host *instance, struct scsi_cmnd *cmd) } /** - * NCR5380_main - NCR state machines + * NCR5380_main - NCR state machines * - * NCR5380_main is a coroutine that runs as long as more work can - * be done on the NCR5380 host adapters in a system. Both - * NCR5380_queue_command() and NCR5380_intr() will try to start it - * in case it is not running. + * NCR5380_main is a coroutine that runs as long as more work can + * be done on the NCR5380 host adapters in a system. Both + * NCR5380_queue_command() and NCR5380_intr() will try to start it + * in case it is not running. */ static void NCR5380_main(struct work_struct *work) @@ -979,31 +979,31 @@ static irqreturn_t NCR5380_intr(int irq, void *dev_id) /* * Function : int NCR5380_select(struct Scsi_Host *instance, - * struct scsi_cmnd *cmd) + * struct scsi_cmnd *cmd) * * Purpose : establishes I_T_L or I_T_L_Q nexus for new or existing command, - * including ARBITRATION, SELECTION, and initial message out for - * IDENTIFY and queue messages. + * including ARBITRATION, SELECTION, and initial message out for + * IDENTIFY and queue messages. * * Inputs : instance - instantiation of the 5380 driver on which this - * target lives, cmd - SCSI command to execute. + * target lives, cmd - SCSI command to execute. * * Returns cmd if selection failed but should be retried, * NULL if selection failed and should not be retried, or * NULL if selection succeeded (hostdata->connected == cmd). * * Side effects : - * If bus busy, arbitration failed, etc, NCR5380_select() will exit - * with registers as they should have been on entry - ie - * SELECT_ENABLE will be set appropriately, the NCR5380 - * will cease to drive any SCSI bus signals. + * If bus busy, arbitration failed, etc, NCR5380_select() will exit + * with registers as they should have been on entry - ie + * SELECT_ENABLE will be set appropriately, the NCR5380 + * will cease to drive any SCSI bus signals. * - * If successful : I_T_L or I_T_L_Q nexus will be established, - * instance->connected will be set to cmd. - * SELECT interrupt will be disabled. + * If successful : I_T_L or I_T_L_Q nexus will be established, + * instance->connected will be set to cmd. + * SELECT interrupt will be disabled. * - * If failed (no target) : cmd->scsi_done() will be called, and the - * cmd->result host byte set to DID_BAD_TARGET. + * If failed (no target) : cmd->scsi_done() will be called, and the + * cmd->result host byte set to DID_BAD_TARGET. */ static struct scsi_cmnd *NCR5380_select(struct Scsi_Host *instance, @@ -1212,8 +1212,8 @@ static struct scsi_cmnd *NCR5380_select(struct Scsi_Host *instance, * until it wraps back to 0. * * XXX - it turns out that there are some broken SCSI-II devices, - * which claim to support tagged queuing but fail when more than - * some number of commands are issued at once. + * which claim to support tagged queuing but fail when more than + * some number of commands are issued at once. */ /* Wait for start of REQ/ACK handshake */ @@ -1261,19 +1261,19 @@ out: /* * Function : int NCR5380_transfer_pio (struct Scsi_Host *instance, - * unsigned char *phase, int *count, unsigned char **data) + * unsigned char *phase, int *count, unsigned char **data) * * Purpose : transfers data in given phase using polled I/O * * Inputs : instance - instance of driver, *phase - pointer to - * what phase is expected, *count - pointer to number of - * bytes to transfer, **data - pointer to data pointer. + * what phase is expected, *count - pointer to number of + * bytes to transfer, **data - pointer to data pointer. * * Returns : -1 when different phase is entered without transferring - * maximum number of bytes, 0 if all bytes or transferred or exit - * is in same phase. + * maximum number of bytes, 0 if all bytes or transferred or exit + * is in same phase. * - * Also, *phase, *count, *data are modified in place. + * Also, *phase, *count, *data are modified in place. * * XXX Note : handling for bus free may be useful. */ @@ -1353,11 +1353,11 @@ static int NCR5380_transfer_pio(struct Scsi_Host *instance, unsigned char *phase /* * We have several special cases to consider during REQ/ACK handshaking : * 1. We were in MSGOUT phase, and we are on the last byte of the - * message. ATN must be dropped as ACK is dropped. + * message. ATN must be dropped as ACK is dropped. * * 2. We are in a MSGIN phase, and we are on the last byte of the - * message. We must exit with ACK asserted, so that the calling - * code may raise ATN before dropping ACK to reject the message. + * message. We must exit with ACK asserted, so that the calling + * code may raise ATN before dropping ACK to reject the message. * * 3. ACK and ATN are clear and the target may proceed as normal. */ @@ -1478,20 +1478,20 @@ timeout: #if defined(REAL_DMA) || defined(PSEUDO_DMA) || defined (REAL_DMA_POLL) /* * Function : int NCR5380_transfer_dma (struct Scsi_Host *instance, - * unsigned char *phase, int *count, unsigned char **data) + * unsigned char *phase, int *count, unsigned char **data) * * Purpose : transfers data in given phase using either real - * or pseudo DMA. + * or pseudo DMA. * * Inputs : instance - instance of driver, *phase - pointer to - * what phase is expected, *count - pointer to number of - * bytes to transfer, **data - pointer to data pointer. + * what phase is expected, *count - pointer to number of + * bytes to transfer, **data - pointer to data pointer. * * Returns : -1 when different phase is entered without transferring - * maximum number of bytes, 0 if all bytes or transferred or exit - * is in same phase. + * maximum number of bytes, 0 if all bytes or transferred or exit + * is in same phase. * - * Also, *phase, *count, *data are modified in place. + * Also, *phase, *count, *data are modified in place. */ @@ -1547,8 +1547,8 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, unsigned char *phase dprintk(NDEBUG_DMA, "scsi%d : mode reg = 0x%X\n", instance->host_no, NCR5380_read(MODE_REG)); /* - * On the PAS16 at least I/O recovery delays are not needed here. - * Everyone else seems to want them. + * On the PAS16 at least I/O recovery delays are not needed here. + * Everyone else seems to want them. */ if (p & SR_IO) { @@ -1724,17 +1724,17 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, unsigned char *phase * Function : NCR5380_information_transfer (struct Scsi_Host *instance) * * Purpose : run through the various SCSI phases and do as the target - * directs us to. Operates on the currently connected command, - * instance->connected. + * directs us to. Operates on the currently connected command, + * instance->connected. * * Inputs : instance, instance for which we are doing commands * * Side effects : SCSI things happen, the disconnected queue will be - * modified if a command disconnects, *instance->connected will - * change. + * modified if a command disconnects, *instance->connected will + * change. * * XXX Note : we need to watch for bus free or a reset condition here - * to recover from an unexpected bus free condition. + * to recover from an unexpected bus free condition. */ static void NCR5380_information_transfer(struct Scsi_Host *instance) { @@ -2050,8 +2050,8 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { * Function : void NCR5380_reselect (struct Scsi_Host *instance) * * Purpose : does reselection, initializing the instance->connected - * field to point to the scsi_cmnd for which the I_T_L or I_T_L_Q - * nexus has been reestablished, + * field to point to the scsi_cmnd for which the I_T_L or I_T_L_Q + * nexus has been reestablished, * * Inputs : instance - this instance of the NCR5380. */ @@ -2172,12 +2172,12 @@ static void NCR5380_reselect(struct Scsi_Host *instance) { * Function : void NCR5380_dma_complete (struct Scsi_Host *instance) * * Purpose : called by interrupt handler when DMA finishes or a phase - * mismatch occurs (which would finish the DMA transfer). + * mismatch occurs (which would finish the DMA transfer). * * Inputs : instance - this instance of the NCR5380. * * Returns : pointer to the scsi_cmnd structure for which the I_T_L - * nexus has been reestablished, on failure NULL is returned. + * nexus has been reestablished, on failure NULL is returned. */ #ifdef REAL_DMA diff --git a/drivers/scsi/atari_NCR5380.c b/drivers/scsi/atari_NCR5380.c index aeaeea5169e4..b66ea632c76b 100644 --- a/drivers/scsi/atari_NCR5380.c +++ b/drivers/scsi/atari_NCR5380.c @@ -1,15 +1,15 @@ /* * NCR 5380 generic driver routines. These should make it *trivial* - * to implement 5380 SCSI drivers under Linux with a non-trantor - * architecture. + * to implement 5380 SCSI drivers under Linux with a non-trantor + * architecture. * - * Note that these routines also work with NR53c400 family chips. + * Note that these routines also work with NR53c400 family chips. * * Copyright 1993, Drew Eckhardt - * Visionary Computing - * (Unix and Linux consulting and custom programming) - * drew@colorado.edu - * +1 (303) 666-5836 + * Visionary Computing + * (Unix and Linux consulting and custom programming) + * drew@colorado.edu + * +1 (303) 666-5836 * * For more information, please consult * @@ -93,10 +93,10 @@ * * These macros control options : * AUTOSENSE - if defined, REQUEST SENSE will be performed automatically - * for commands that return with a CHECK CONDITION status. + * for commands that return with a CHECK CONDITION status. * * DIFFERENTIAL - if defined, NCR53c81 chips will use external differential - * transceivers. + * transceivers. * * REAL_DMA - if defined, REAL DMA is used during the data transfer phases. * @@ -109,17 +109,17 @@ * NCR5380_write(register, value) - write to the specific register * * NCR5380_implementation_fields - additional fields needed for this - * specific implementation of the NCR5380 + * specific implementation of the NCR5380 * * Either real DMA *or* pseudo DMA may be implemented * REAL functions : * NCR5380_REAL_DMA should be defined if real DMA is to be used. * Note that the DMA setup functions should return the number of bytes - * that they were able to program the controller for. + * that they were able to program the controller for. * * Also note that generic i386/PC versions of these macros are - * available as NCR5380_i386_dma_write_setup, - * NCR5380_i386_dma_read_setup, and NCR5380_i386_dma_residual. + * available as NCR5380_i386_dma_write_setup, + * NCR5380_i386_dma_read_setup, and NCR5380_i386_dma_residual. * * NCR5380_dma_write_setup(instance, src, count) - initialize * NCR5380_dma_read_setup(instance, dst, count) - initialize @@ -974,7 +974,7 @@ static void NCR5380_main(struct work_struct *work) * Function : void NCR5380_dma_complete (struct Scsi_Host *instance) * * Purpose : Called by interrupt handler when DMA finishes or a phase - * mismatch occurs (which would finish the DMA transfer). + * mismatch occurs (which would finish the DMA transfer). * * Inputs : instance - this instance of the NCR5380. */ @@ -1161,31 +1161,31 @@ static irqreturn_t NCR5380_intr(int irq, void *dev_id) /* * Function : int NCR5380_select(struct Scsi_Host *instance, - * struct scsi_cmnd *cmd) + * struct scsi_cmnd *cmd) * * Purpose : establishes I_T_L or I_T_L_Q nexus for new or existing command, - * including ARBITRATION, SELECTION, and initial message out for - * IDENTIFY and queue messages. + * including ARBITRATION, SELECTION, and initial message out for + * IDENTIFY and queue messages. * * Inputs : instance - instantiation of the 5380 driver on which this - * target lives, cmd - SCSI command to execute. + * target lives, cmd - SCSI command to execute. * * Returns cmd if selection failed but should be retried, * NULL if selection failed and should not be retried, or * NULL if selection succeeded (hostdata->connected == cmd). * * Side effects : - * If bus busy, arbitration failed, etc, NCR5380_select() will exit - * with registers as they should have been on entry - ie - * SELECT_ENABLE will be set appropriately, the NCR5380 - * will cease to drive any SCSI bus signals. + * If bus busy, arbitration failed, etc, NCR5380_select() will exit + * with registers as they should have been on entry - ie + * SELECT_ENABLE will be set appropriately, the NCR5380 + * will cease to drive any SCSI bus signals. * - * If successful : I_T_L or I_T_L_Q nexus will be established, - * instance->connected will be set to cmd. - * SELECT interrupt will be disabled. + * If successful : I_T_L or I_T_L_Q nexus will be established, + * instance->connected will be set to cmd. + * SELECT interrupt will be disabled. * - * If failed (no target) : cmd->scsi_done() will be called, and the - * cmd->result host byte set to DID_BAD_TARGET. + * If failed (no target) : cmd->scsi_done() will be called, and the + * cmd->result host byte set to DID_BAD_TARGET. */ static struct scsi_cmnd *NCR5380_select(struct Scsi_Host *instance, @@ -1398,8 +1398,8 @@ static struct scsi_cmnd *NCR5380_select(struct Scsi_Host *instance, * until it wraps back to 0. * * XXX - it turns out that there are some broken SCSI-II devices, - * which claim to support tagged queuing but fail when more than - * some number of commands are issued at once. + * which claim to support tagged queuing but fail when more than + * some number of commands are issued at once. */ /* Wait for start of REQ/ACK handshake */ @@ -1461,19 +1461,19 @@ out: /* * Function : int NCR5380_transfer_pio (struct Scsi_Host *instance, - * unsigned char *phase, int *count, unsigned char **data) + * unsigned char *phase, int *count, unsigned char **data) * * Purpose : transfers data in given phase using polled I/O * * Inputs : instance - instance of driver, *phase - pointer to - * what phase is expected, *count - pointer to number of - * bytes to transfer, **data - pointer to data pointer. + * what phase is expected, *count - pointer to number of + * bytes to transfer, **data - pointer to data pointer. * * Returns : -1 when different phase is entered without transferring - * maximum number of bytes, 0 if all bytes are transferred or exit - * is in same phase. + * maximum number of bytes, 0 if all bytes are transferred or exit + * is in same phase. * - * Also, *phase, *count, *data are modified in place. + * Also, *phase, *count, *data are modified in place. * * XXX Note : handling for bus free may be useful. */ @@ -1560,11 +1560,11 @@ static int NCR5380_transfer_pio(struct Scsi_Host *instance, /* * We have several special cases to consider during REQ/ACK handshaking : * 1. We were in MSGOUT phase, and we are on the last byte of the - * message. ATN must be dropped as ACK is dropped. + * message. ATN must be dropped as ACK is dropped. * * 2. We are in a MSGIN phase, and we are on the last byte of the - * message. We must exit with ACK asserted, so that the calling - * code may raise ATN before dropping ACK to reject the message. + * message. We must exit with ACK asserted, so that the calling + * code may raise ATN before dropping ACK to reject the message. * * 3. ACK and ATN are clear and the target may proceed as normal. */ @@ -1687,20 +1687,20 @@ timeout: #if defined(REAL_DMA) /* * Function : int NCR5380_transfer_dma (struct Scsi_Host *instance, - * unsigned char *phase, int *count, unsigned char **data) + * unsigned char *phase, int *count, unsigned char **data) * * Purpose : transfers data in given phase using either real - * or pseudo DMA. + * or pseudo DMA. * * Inputs : instance - instance of driver, *phase - pointer to - * what phase is expected, *count - pointer to number of - * bytes to transfer, **data - pointer to data pointer. + * what phase is expected, *count - pointer to number of + * bytes to transfer, **data - pointer to data pointer. * * Returns : -1 when different phase is entered without transferring - * maximum number of bytes, 0 if all bytes or transferred or exit - * is in same phase. + * maximum number of bytes, 0 if all bytes or transferred or exit + * is in same phase. * - * Also, *phase, *count, *data are modified in place. + * Also, *phase, *count, *data are modified in place. */ @@ -1799,17 +1799,17 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, * Function : NCR5380_information_transfer (struct Scsi_Host *instance) * * Purpose : run through the various SCSI phases and do as the target - * directs us to. Operates on the currently connected command, - * instance->connected. + * directs us to. Operates on the currently connected command, + * instance->connected. * * Inputs : instance, instance for which we are doing commands * * Side effects : SCSI things happen, the disconnected queue will be - * modified if a command disconnects, *instance->connected will - * change. + * modified if a command disconnects, *instance->connected will + * change. * * XXX Note : we need to watch for bus free or a reset condition here - * to recover from an unexpected bus free condition. + * to recover from an unexpected bus free condition. */ static void NCR5380_information_transfer(struct Scsi_Host *instance) @@ -1919,7 +1919,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) */ /* ++roman: I suggest, this should be - * #if def(REAL_DMA) + * #if def(REAL_DMA) * instead of leaving REAL_DMA out. */ @@ -2215,8 +2215,8 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) * Function : void NCR5380_reselect (struct Scsi_Host *instance) * * Purpose : does reselection, initializing the instance->connected - * field to point to the scsi_cmnd for which the I_T_L or I_T_L_Q - * nexus has been reestablished, + * field to point to the scsi_cmnd for which the I_T_L or I_T_L_Q + * nexus has been reestablished, * * Inputs : instance - this instance of the NCR5380. */ -- cgit From 0d2cf867e44278ec1a0ba4419d9718336d308acb Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sun, 3 Jan 2016 16:06:11 +1100 Subject: ncr5380: Merge changes from atari_NCR5380.c In the past, NCR5380.c was overlooked by those working on atari_NCR5380.c and this caused needless divergence. All of the changes in this patch were taken from atari_NCR5380.c. This removes some unimportant discrepancies between the two core driver forks so that 'diff' can be used to reveal the important ones, to facilitate reunification. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Ondrej Zary Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.c | 155 +++++++++++++++++++++++++++---------------------- 1 file changed, 87 insertions(+), 68 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index eb21803eab3b..3c7000da7511 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -174,7 +174,7 @@ static int do_abort(struct Scsi_Host *); static void do_reset(struct Scsi_Host *); /** - * initialize_SCp - init the scsi pointer field + * initialize_SCp - init the scsi pointer field * @cmd: command block to set up * * Set up the internal fields in the SCSI command. @@ -264,19 +264,6 @@ static inline int NCR5380_poll_politely(struct Scsi_Host *instance, reg, bit, val, wait); } -static struct { - unsigned char value; - const char *name; -} phases[] __maybe_unused = { - {PHASE_DATAOUT, "DATAOUT"}, - {PHASE_DATAIN, "DATAIN"}, - {PHASE_CMDOUT, "CMDOUT"}, - {PHASE_STATIN, "STATIN"}, - {PHASE_MSGOUT, "MSGOUT"}, - {PHASE_MSGIN, "MSGIN"}, - {PHASE_UNKNOWN, "UNKNOWN"} -}; - #if NDEBUG static struct { unsigned char mask; @@ -311,6 +298,7 @@ mrs[] = { {MR_TARGET, "MODE TARGET"}, {MR_ENABLE_PAR_CHECK, "MODE PARITY CHECK"}, {MR_ENABLE_PAR_INTR, "MODE PARITY INTR"}, + {MR_ENABLE_EOP_INTR, "MODE EOP INTR"}, {MR_MONITOR_BSY, "MODE MONITOR BSY"}, {MR_DMA_MODE, "MODE DMA"}, {MR_ARBITRATE, "MODE ARBITRATION"}, @@ -318,8 +306,8 @@ mrs[] = { }; /** - * NCR5380_print - print scsi bus signals - * @instance: adapter state to dump + * NCR5380_print - print scsi bus signals + * @instance: adapter state to dump * * Print the SCSI bus signals for debugging purposes */ @@ -353,9 +341,21 @@ static void NCR5380_print(struct Scsi_Host *instance) printk("\n"); } +static struct { + unsigned char value; + const char *name; +} phases[] = { + {PHASE_DATAOUT, "DATAOUT"}, + {PHASE_DATAIN, "DATAIN"}, + {PHASE_CMDOUT, "CMDOUT"}, + {PHASE_STATIN, "STATIN"}, + {PHASE_MSGOUT, "MSGOUT"}, + {PHASE_MSGIN, "MSGIN"}, + {PHASE_UNKNOWN, "UNKNOWN"} +}; /** - * NCR5380_print_phase - show SCSI phase + * NCR5380_print_phase - show SCSI phase * @instance: adapter to dump * * Print the current SCSI phase for debugging purposes @@ -370,7 +370,9 @@ static void NCR5380_print_phase(struct Scsi_Host *instance) if (!(status & SR_REQ)) shost_printk(KERN_DEBUG, instance, "REQ not asserted, phase unknown.\n"); else { - for (i = 0; (phases[i].value != PHASE_UNKNOWN) && (phases[i].value != (status & PHASE_MASK)); ++i); + for (i = 0; (phases[i].value != PHASE_UNKNOWN) && + (phases[i].value != (status & PHASE_MASK)); ++i) + ; shost_printk(KERN_DEBUG, instance, "phase %s\n", phases[i].name); } } @@ -511,7 +513,7 @@ static int __maybe_unused NCR5380_write_info(struct Scsi_Host *instance, } static int __maybe_unused NCR5380_show_info(struct seq_file *m, - struct Scsi_Host *instance) + struct Scsi_Host *instance) { struct NCR5380_hostdata *hostdata = shost_priv(instance); @@ -522,7 +524,7 @@ static int __maybe_unused NCR5380_show_info(struct seq_file *m, #endif /** - * NCR5380_init - initialise an NCR5380 + * NCR5380_init - initialise an NCR5380 * @instance: adapter to configure * @flags: control flags * @@ -530,7 +532,7 @@ static int __maybe_unused NCR5380_show_info(struct seq_file *m, * with flags OR'd into the initial flags value. * * Notes : I assume that the host, hostno, and id bits have been - * set correctly. I don't care about the irq and other fields. + * set correctly. I don't care about the irq and other fields. * * Returns 0 for success */ @@ -541,10 +543,9 @@ static int NCR5380_init(struct Scsi_Host *instance, int flags) int i; unsigned long deadline; - if(in_interrupt()) - printk(KERN_ERR "NCR5380_init called with interrupts off!\n"); - + hostdata->host = instance; hostdata->id_mask = 1 << instance->this_id; + hostdata->id_higher_mask = 0; for (i = hostdata->id_mask; i <= 0x80; i <<= 1) if (i > hostdata->id_mask) hostdata->id_higher_mask |= i; @@ -569,8 +570,6 @@ static int NCR5380_init(struct Scsi_Host *instance, int flags) if (!hostdata->work_q) return -ENOMEM; - hostdata->host = instance; - prepare_info(instance); NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); @@ -648,8 +647,10 @@ static int NCR5380_maybe_reset_bus(struct Scsi_Host *instance) } /** - * NCR5380_exit - remove an NCR5380 + * NCR5380_exit - remove an NCR5380 * @instance: adapter to remove + * + * Assumes that no more work can be queued (e.g. by NCR5380_intr). */ static void NCR5380_exit(struct Scsi_Host *instance) @@ -714,7 +715,7 @@ static int NCR5380_queue_command(struct Scsi_Host *instance, cmd->scsi_done(cmd); return 0; } -#endif /* (NDEBUG & NDEBUG_NO_WRITE) */ +#endif /* (NDEBUG & NDEBUG_NO_WRITE) */ cmd->result = 0; @@ -801,7 +802,7 @@ static void requeue_cmd(struct Scsi_Host *instance, struct scsi_cmnd *cmd) } /** - * NCR5380_main - NCR state machines + * NCR5380_main - NCR state machines * * NCR5380_main is a coroutine that runs as long as more work can * be done on the NCR5380 host adapters in a system. Both @@ -1067,7 +1068,9 @@ static struct scsi_cmnd *NCR5380_select(struct Scsi_Host *instance, udelay(3); /* Check for lost arbitration */ - if ((NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_LOST) || (NCR5380_read(CURRENT_SCSI_DATA_REG) & hostdata->id_higher_mask) || (NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_LOST)) { + if ((NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_LOST) || + (NCR5380_read(CURRENT_SCSI_DATA_REG) & hostdata->id_higher_mask) || + (NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_LOST)) { NCR5380_write(MODE_REG, MR_BASE); dsprintk(NDEBUG_ARBITRATION, instance, "lost arbitration, deasserting MR_ARBITRATE\n"); spin_lock_irq(&hostdata->lock); @@ -1133,7 +1136,7 @@ static struct scsi_cmnd *NCR5380_select(struct Scsi_Host *instance, * The initiator shall then wait at least two deskew delays and release * the BSY signal. */ - udelay(1); /* wingel -- wait two bus deskew delay >2*45ns */ + udelay(1); /* wingel -- wait two bus deskew delay >2*45ns */ /* Reset BSY */ NCR5380_write(INITIATOR_COMMAND_REG, (ICR_BASE | ICR_ASSERT_DATA | ICR_ASSERT_ATN | ICR_ASSERT_SEL)); @@ -1270,7 +1273,7 @@ out: * bytes to transfer, **data - pointer to data pointer. * * Returns : -1 when different phase is entered without transferring - * maximum number of bytes, 0 if all bytes or transferred or exit + * maximum number of bytes, 0 if all bytes are transferred or exit * is in same phase. * * Also, *phase, *count, *data are modified in place. @@ -1284,7 +1287,10 @@ out: * counts, we will always do a pseudo DMA or DMA transfer. */ -static int NCR5380_transfer_pio(struct Scsi_Host *instance, unsigned char *phase, int *count, unsigned char **data) { +static int NCR5380_transfer_pio(struct Scsi_Host *instance, + unsigned char *phase, int *count, + unsigned char **data) +{ unsigned char p = *phase, tmp; int c = *count; unsigned char *d = *data; @@ -1295,7 +1301,7 @@ static int NCR5380_transfer_pio(struct Scsi_Host *instance, unsigned char *phase * REGISTER match the STATUS REGISTER */ - NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(p)); + NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(p)); do { /* @@ -1314,6 +1320,7 @@ static int NCR5380_transfer_pio(struct Scsi_Host *instance, unsigned char *phase NCR5380_dprint_phase(NDEBUG_PIO, instance); break; } + /* Do actual transfer from SCSI bus to / from memory */ if (!(p & SR_IO)) NCR5380_write(OUTPUT_DATA_REG, *d); @@ -1451,12 +1458,14 @@ static int do_abort(struct Scsi_Host *instance) NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(tmp)); if (tmp != PHASE_MSGOUT) { - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN | ICR_ASSERT_ACK); + NCR5380_write(INITIATOR_COMMAND_REG, + ICR_BASE | ICR_ASSERT_ATN | ICR_ASSERT_ACK); rc = NCR5380_poll_politely(instance, STATUS_REG, SR_REQ, 0, 3 * HZ); if (rc < 0) goto timeout; NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN); } + tmp = ABORT; msgptr = &tmp; len = 1; @@ -1495,7 +1504,11 @@ timeout: */ -static int NCR5380_transfer_dma(struct Scsi_Host *instance, unsigned char *phase, int *count, unsigned char **data) { +static int NCR5380_transfer_dma(struct Scsi_Host *instance, + unsigned char *phase, int *count, + unsigned char **data) +{ + struct NCR5380_hostdata *hostdata = shost_priv(instance); register int c = *count; register unsigned char p = *phase; register unsigned char *d = *data; @@ -1506,8 +1519,6 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, unsigned char *phase unsigned char saved_data = 0, overrun = 0, residue; #endif - struct NCR5380_hostdata *hostdata = shost_priv(instance); - if ((tmp = (NCR5380_read(STATUS_REG) & PHASE_MASK)) != p) { *phase = tmp; return -1; @@ -1737,7 +1748,8 @@ static int NCR5380_transfer_dma(struct Scsi_Host *instance, unsigned char *phase * to recover from an unexpected bus free condition. */ -static void NCR5380_information_transfer(struct Scsi_Host *instance) { +static void NCR5380_information_transfer(struct Scsi_Host *instance) +{ struct NCR5380_hostdata *hostdata = shost_priv(instance); unsigned char msgout = NOP; int sink = 0; @@ -1764,11 +1776,13 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(tmp)); NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN | ICR_ASSERT_ACK); - while (NCR5380_read(STATUS_REG) & SR_REQ); + while (NCR5380_read(STATUS_REG) & SR_REQ) + ; NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN); sink = 0; continue; } + switch (phase) { case PHASE_DATAOUT: #if (NDEBUG & NDEBUG_NO_DATAOUT) @@ -1794,6 +1808,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { cmd->SCp.this_residual, cmd->SCp.buffers_residual); } + /* * The preferred transfer method is going to be * PSEUDO-DMA for systems that are strictly PIO, @@ -1812,13 +1827,15 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { if (transfersize) { len = transfersize; - if (NCR5380_transfer_dma(instance, &phase, &len, (unsigned char **) &cmd->SCp.ptr)) { + if (NCR5380_transfer_dma(instance, &phase, + &len, (unsigned char **)&cmd->SCp.ptr)) { /* - * If the watchdog timer fires, all future accesses to this - * device will use the polled-IO. + * If the watchdog timer fires, all future + * accesses to this device will use the + * polled-IO. */ scmd_printk(KERN_INFO, cmd, - "switching to slow handshake\n"); + "switching to slow handshake\n"); cmd->device->borken = 1; sink = 1; do_abort(instance); @@ -1894,25 +1911,24 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { break; } break; - case DISCONNECT:{ - /* Accept message by clearing ACK */ - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - hostdata->connected = NULL; - list_add(&ncmd->list, &hostdata->disconnected); - dsprintk(NDEBUG_INFORMATION | NDEBUG_QUEUES, - instance, "connected command %p for target %d lun %llu moved to disconnected queue\n", - cmd, scmd_id(cmd), cmd->device->lun); + case DISCONNECT: + /* Accept message by clearing ACK */ + NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); + hostdata->connected = NULL; + list_add(&ncmd->list, &hostdata->disconnected); + dsprintk(NDEBUG_INFORMATION | NDEBUG_QUEUES, + instance, "connected command %p for target %d lun %llu moved to disconnected queue\n", + cmd, scmd_id(cmd), cmd->device->lun); - /* - * Restore phase bits to 0 so an interrupted selection, - * arbitration can resume. - */ - NCR5380_write(TARGET_COMMAND_REG, 0); + /* + * Restore phase bits to 0 so an interrupted selection, + * arbitration can resume. + */ + NCR5380_write(TARGET_COMMAND_REG, 0); - /* Enable reselect interrupts */ - NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); - return; - } + /* Enable reselect interrupts */ + NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); + return; /* * The SCSI data pointer is *IMPLICITLY* saved on a disconnect * operation, in violation of the SCSI spec so we can safely @@ -1994,15 +2010,17 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { printk("\n"); } else if (tmp != EXTENDED_MESSAGE) scmd_printk(KERN_INFO, cmd, - "rejecting unknown message %02x\n",tmp); + "rejecting unknown message %02x\n", + tmp); else scmd_printk(KERN_INFO, cmd, - "rejecting unknown extended message code %02x, length %d\n", extended_msg[1], extended_msg[0]); + "rejecting unknown extended message code %02x, length %d\n", + extended_msg[1], extended_msg[0]); msgout = MESSAGE_REJECT; NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN); break; - } /* switch (tmp) */ + } /* switch (tmp) */ break; case PHASE_MSGOUT: len = 1; @@ -2037,7 +2055,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { default: shost_printk(KERN_ERR, instance, "unknown phase\n"); NCR5380_dprint(NDEBUG_ANY, instance); - } /* switch(phase) */ + } /* switch(phase) */ } else { spin_unlock_irq(&hostdata->lock); NCR5380_poll_politely(instance, STATUS_REG, SR_REQ, SR_REQ, HZ); @@ -2056,7 +2074,8 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { * Inputs : instance - this instance of the NCR5380. */ -static void NCR5380_reselect(struct Scsi_Host *instance) { +static void NCR5380_reselect(struct Scsi_Host *instance) +{ struct NCR5380_hostdata *hostdata = shost_priv(instance); unsigned char target_mask; unsigned char lun, phase; @@ -2153,8 +2172,8 @@ static void NCR5380_reselect(struct Scsi_Host *instance) { shost_printk(KERN_ERR, instance, "target bitmask 0x%02x lun %d not in disconnected queue.\n", target_mask, lun); /* - * Since we have an established nexus that we can't do anything with, - * we must abort it. + * Since we have an established nexus that we can't do anything + * with, we must abort it. */ do_abort(instance); return; -- cgit From ac15c3bcbd5b989762487949963e2498da292803 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sun, 3 Jan 2016 16:06:12 +1100 Subject: atari_NCR5380: Merge changes from NCR5380.c In the past, atari_NCR5380.c was overlooked by those working on NCR5380.c and this caused needless divergence. All of the changes in this patch were taken from NCR5380.c. This removes some unimportant discrepancies between the two core driver forks so that 'diff' can be used to reveal the important ones, to facilitate reunification. Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Michael Schmitz Signed-off-by: Martin K. Petersen --- drivers/scsi/atari_NCR5380.c | 84 +++++++++++++++++++++++++++----------------- 1 file changed, 52 insertions(+), 32 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/atari_NCR5380.c b/drivers/scsi/atari_NCR5380.c index b66ea632c76b..144ae0bb951b 100644 --- a/drivers/scsi/atari_NCR5380.c +++ b/drivers/scsi/atari_NCR5380.c @@ -443,22 +443,39 @@ static struct { unsigned char mask; const char *name; } signals[] = { - { SR_DBP, "PARITY"}, { SR_RST, "RST" }, { SR_BSY, "BSY" }, - { SR_REQ, "REQ" }, { SR_MSG, "MSG" }, { SR_CD, "CD" }, { SR_IO, "IO" }, - { SR_SEL, "SEL" }, {0, NULL} -}, basrs[] = { - {BASR_ATN, "ATN"}, {BASR_ACK, "ACK"}, {0, NULL} -}, icrs[] = { - {ICR_ASSERT_RST, "ASSERT RST"},{ICR_ASSERT_ACK, "ASSERT ACK"}, - {ICR_ASSERT_BSY, "ASSERT BSY"}, {ICR_ASSERT_SEL, "ASSERT SEL"}, - {ICR_ASSERT_ATN, "ASSERT ATN"}, {ICR_ASSERT_DATA, "ASSERT DATA"}, + {SR_DBP, "PARITY"}, + {SR_RST, "RST"}, + {SR_BSY, "BSY"}, + {SR_REQ, "REQ"}, + {SR_MSG, "MSG"}, + {SR_CD, "CD"}, + {SR_IO, "IO"}, + {SR_SEL, "SEL"}, {0, NULL} -}, mrs[] = { - {MR_BLOCK_DMA_MODE, "MODE BLOCK DMA"}, {MR_TARGET, "MODE TARGET"}, - {MR_ENABLE_PAR_CHECK, "MODE PARITY CHECK"}, {MR_ENABLE_PAR_INTR, - "MODE PARITY INTR"}, {MR_ENABLE_EOP_INTR,"MODE EOP INTR"}, +}, +basrs[] = { + {BASR_ATN, "ATN"}, + {BASR_ACK, "ACK"}, + {0, NULL} +}, +icrs[] = { + {ICR_ASSERT_RST, "ASSERT RST"}, + {ICR_ASSERT_ACK, "ASSERT ACK"}, + {ICR_ASSERT_BSY, "ASSERT BSY"}, + {ICR_ASSERT_SEL, "ASSERT SEL"}, + {ICR_ASSERT_ATN, "ASSERT ATN"}, + {ICR_ASSERT_DATA, "ASSERT DATA"}, + {0, NULL} +}, +mrs[] = { + {MR_BLOCK_DMA_MODE, "MODE BLOCK DMA"}, + {MR_TARGET, "MODE TARGET"}, + {MR_ENABLE_PAR_CHECK, "MODE PARITY CHECK"}, + {MR_ENABLE_PAR_INTR, "MODE PARITY INTR"}, + {MR_ENABLE_EOP_INTR, "MODE EOP INTR"}, {MR_MONITOR_BSY, "MODE MONITOR BSY"}, - {MR_DMA_MODE, "MODE DMA"}, {MR_ARBITRATE, "MODE ARBITRATION"}, + {MR_DMA_MODE, "MODE DMA"}, + {MR_ARBITRATE, "MODE ARBITRATION"}, {0, NULL} }; @@ -502,8 +519,12 @@ static struct { unsigned char value; const char *name; } phases[] = { - {PHASE_DATAOUT, "DATAOUT"}, {PHASE_DATAIN, "DATAIN"}, {PHASE_CMDOUT, "CMDOUT"}, - {PHASE_STATIN, "STATIN"}, {PHASE_MSGOUT, "MSGOUT"}, {PHASE_MSGIN, "MSGIN"}, + {PHASE_DATAOUT, "DATAOUT"}, + {PHASE_DATAIN, "DATAIN"}, + {PHASE_CMDOUT, "CMDOUT"}, + {PHASE_STATIN, "STATIN"}, + {PHASE_MSGOUT, "MSGOUT"}, + {PHASE_MSGIN, "MSGIN"}, {PHASE_UNKNOWN, "UNKNOWN"} }; @@ -529,7 +550,6 @@ static void NCR5380_print_phase(struct Scsi_Host *instance) shost_printk(KERN_DEBUG, instance, "phase %s\n", phases[i].name); } } - #endif /** @@ -1488,9 +1508,9 @@ static int NCR5380_transfer_pio(struct Scsi_Host *instance, unsigned char *phase, int *count, unsigned char **data) { - register unsigned char p = *phase, tmp; - register int c = *count; - register unsigned char *d = *data; + unsigned char p = *phase, tmp; + int c = *count; + unsigned char *d = *data; /* * The NCR5380 chip will only drive the SCSI bus when the @@ -1557,17 +1577,17 @@ static int NCR5380_transfer_pio(struct Scsi_Host *instance, dsprintk(NDEBUG_HANDSHAKE, instance, "REQ negated, handshake complete\n"); - /* - * We have several special cases to consider during REQ/ACK handshaking : - * 1. We were in MSGOUT phase, and we are on the last byte of the - * message. ATN must be dropped as ACK is dropped. - * - * 2. We are in a MSGIN phase, and we are on the last byte of the - * message. We must exit with ACK asserted, so that the calling - * code may raise ATN before dropping ACK to reject the message. - * - * 3. ACK and ATN are clear and the target may proceed as normal. - */ +/* + * We have several special cases to consider during REQ/ACK handshaking : + * 1. We were in MSGOUT phase, and we are on the last byte of the + * message. ATN must be dropped as ACK is dropped. + * + * 2. We are in a MSGIN phase, and we are on the last byte of the + * message. We must exit with ACK asserted, so that the calling + * code may raise ATN before dropping ACK to reject the message. + * + * 3. ACK and ATN are clear and the target may proceed as normal. + */ if (!(p == PHASE_MSGIN && c == 1)) { if (p == PHASE_MSGOUT && c > 1) NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN); @@ -1632,7 +1652,7 @@ static void do_reset(struct Scsi_Host *instance) static int do_abort(struct Scsi_Host *instance) { - unsigned char tmp, *msgptr, phase; + unsigned char *msgptr, phase, tmp; int len; int rc; -- cgit From 3d07d22b3d475ba9b0adfe083c537ee1ada034c8 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Sun, 3 Jan 2016 16:06:13 +1100 Subject: ncr5380: Cleanup whitespace and parentheses Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Tested-by: Ondrej Zary Tested-by: Michael Schmitz Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.c | 30 +++++++++++++++++++----------- drivers/scsi/atari_NCR5380.c | 26 +++++++++++++------------- 2 files changed, 32 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index 3c7000da7511..d72867257346 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -1113,7 +1113,7 @@ static struct scsi_cmnd *NCR5380_select(struct Scsi_Host *instance, * the host and target ID's on the SCSI bus. */ - NCR5380_write(OUTPUT_DATA_REG, (hostdata->id_mask | (1 << scmd_id(cmd)))); + NCR5380_write(OUTPUT_DATA_REG, hostdata->id_mask | (1 << scmd_id(cmd))); /* * Raise ATN while SEL is true before BSY goes false from arbitration, @@ -1121,7 +1121,8 @@ static struct scsi_cmnd *NCR5380_select(struct Scsi_Host *instance, * phase immediately after selection. */ - NCR5380_write(INITIATOR_COMMAND_REG, (ICR_BASE | ICR_ASSERT_BSY | ICR_ASSERT_DATA | ICR_ASSERT_ATN | ICR_ASSERT_SEL)); + NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_BSY | + ICR_ASSERT_DATA | ICR_ASSERT_ATN | ICR_ASSERT_SEL); NCR5380_write(MODE_REG, MR_BASE); /* @@ -1139,7 +1140,8 @@ static struct scsi_cmnd *NCR5380_select(struct Scsi_Host *instance, udelay(1); /* wingel -- wait two bus deskew delay >2*45ns */ /* Reset BSY */ - NCR5380_write(INITIATOR_COMMAND_REG, (ICR_BASE | ICR_ASSERT_DATA | ICR_ASSERT_ATN | ICR_ASSERT_SEL)); + NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_DATA | + ICR_ASSERT_ATN | ICR_ASSERT_SEL); /* * Something weird happens when we cease to drive BSY - looks @@ -1249,7 +1251,7 @@ static struct scsi_cmnd *NCR5380_select(struct Scsi_Host *instance, /* XXX need to handle errors here */ hostdata->connected = cmd; - hostdata->busy[cmd->device->id] |= (1 << (cmd->device->lun & 0xFF)); + hostdata->busy[cmd->device->id] |= 1 << cmd->device->lun; initialize_SCp(cmd); @@ -1340,11 +1342,14 @@ static int NCR5380_transfer_pio(struct Scsi_Host *instance, if (!((p & SR_MSG) && c > 1)) { NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_DATA); NCR5380_dprint(NDEBUG_PIO, instance); - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_DATA | ICR_ASSERT_ACK); + NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | + ICR_ASSERT_DATA | ICR_ASSERT_ACK); } else { - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_DATA | ICR_ASSERT_ATN); + NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | + ICR_ASSERT_DATA | ICR_ASSERT_ATN); NCR5380_dprint(NDEBUG_PIO, instance); - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_DATA | ICR_ASSERT_ATN | ICR_ASSERT_ACK); + NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | + ICR_ASSERT_DATA | ICR_ASSERT_ATN | ICR_ASSERT_ACK); } } else { NCR5380_dprint(NDEBUG_PIO, instance); @@ -1775,10 +1780,12 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) if (sink && (phase != PHASE_MSGOUT)) { NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(tmp)); - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN | ICR_ASSERT_ACK); + NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN | + ICR_ASSERT_ACK); while (NCR5380_read(STATUS_REG) & SR_REQ) ; - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN); + NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | + ICR_ASSERT_ATN); sink = 0; continue; } @@ -1848,8 +1855,9 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) #endif /* defined(PSEUDO_DMA) || defined(REAL_DMA_POLL) */ { spin_unlock_irq(&hostdata->lock); - NCR5380_transfer_pio(instance, &phase, (int *) &cmd->SCp.this_residual, (unsigned char **) - &cmd->SCp.ptr); + NCR5380_transfer_pio(instance, &phase, + (int *)&cmd->SCp.this_residual, + (unsigned char **)&cmd->SCp.ptr); spin_lock_irq(&hostdata->lock); } break; diff --git a/drivers/scsi/atari_NCR5380.c b/drivers/scsi/atari_NCR5380.c index 144ae0bb951b..e65478651ca9 100644 --- a/drivers/scsi/atari_NCR5380.c +++ b/drivers/scsi/atari_NCR5380.c @@ -1314,7 +1314,7 @@ static struct scsi_cmnd *NCR5380_select(struct Scsi_Host *instance, * the host and target ID's on the SCSI bus. */ - NCR5380_write(OUTPUT_DATA_REG, (hostdata->id_mask | (1 << cmd->device->id))); + NCR5380_write(OUTPUT_DATA_REG, hostdata->id_mask | (1 << scmd_id(cmd))); /* * Raise ATN while SEL is true before BSY goes false from arbitration, @@ -1322,8 +1322,8 @@ static struct scsi_cmnd *NCR5380_select(struct Scsi_Host *instance, * phase immediately after selection. */ - NCR5380_write(INITIATOR_COMMAND_REG, (ICR_BASE | ICR_ASSERT_BSY | - ICR_ASSERT_DATA | ICR_ASSERT_ATN | ICR_ASSERT_SEL )); + NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_BSY | + ICR_ASSERT_DATA | ICR_ASSERT_ATN | ICR_ASSERT_SEL); NCR5380_write(MODE_REG, MR_BASE); /* @@ -1341,8 +1341,8 @@ static struct scsi_cmnd *NCR5380_select(struct Scsi_Host *instance, udelay(1); /* wingel -- wait two bus deskew delay >2*45ns */ /* Reset BSY */ - NCR5380_write(INITIATOR_COMMAND_REG, (ICR_BASE | ICR_ASSERT_DATA | - ICR_ASSERT_ATN | ICR_ASSERT_SEL)); + NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_DATA | + ICR_ASSERT_ATN | ICR_ASSERT_SEL); /* * Something weird happens when we cease to drive BSY - looks @@ -1462,7 +1462,7 @@ static struct scsi_cmnd *NCR5380_select(struct Scsi_Host *instance, hostdata->connected = cmd; #ifndef SUPPORT_TAGS - hostdata->busy[cmd->device->id] |= (1 << cmd->device->lun); + hostdata->busy[cmd->device->id] |= 1 << cmd->device->lun; #endif #ifdef SUN3_SCSI_VME dregs->csr |= CSR_INTR; @@ -1558,13 +1558,13 @@ static int NCR5380_transfer_pio(struct Scsi_Host *instance, NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_DATA); NCR5380_dprint(NDEBUG_PIO, instance); NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | - ICR_ASSERT_DATA | ICR_ASSERT_ACK); + ICR_ASSERT_DATA | ICR_ASSERT_ACK); } else { NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | - ICR_ASSERT_DATA | ICR_ASSERT_ATN); + ICR_ASSERT_DATA | ICR_ASSERT_ATN); NCR5380_dprint(NDEBUG_PIO, instance); NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | - ICR_ASSERT_DATA | ICR_ASSERT_ATN | ICR_ASSERT_ACK); + ICR_ASSERT_DATA | ICR_ASSERT_ATN | ICR_ASSERT_ACK); } } else { NCR5380_dprint(NDEBUG_PIO, instance); @@ -1892,11 +1892,11 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(tmp)); NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN | - ICR_ASSERT_ACK); + ICR_ASSERT_ACK); while (NCR5380_read(STATUS_REG) & SR_REQ) ; NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | - ICR_ASSERT_ATN); + ICR_ASSERT_ATN); sink = 0; continue; } @@ -1985,8 +1985,8 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { spin_unlock_irq(&hostdata->lock); NCR5380_transfer_pio(instance, &phase, - (int *)&cmd->SCp.this_residual, - (unsigned char **)&cmd->SCp.ptr); + (int *)&cmd->SCp.this_residual, + (unsigned char **)&cmd->SCp.ptr); spin_lock_irq(&hostdata->lock); } #if defined(CONFIG_SUN3) && defined(REAL_DMA) -- cgit From f03946210d67be9a33ad63f6a0eed7cdf8c28334 Mon Sep 17 00:00:00 2001 From: Ondrej Zary Date: Sun, 3 Jan 2016 16:06:14 +1100 Subject: ncr5380: Fix pseudo DMA transfers on 53C400 Pseudo-DMA (PDMA) has been broken for ages, resulting in hangs on 53C400-based cards. According to 53C400 datasheet, PDMA transfer length must be a multiple of 128. Check if that's true and use PIO if it's not. This makes PDMA work on 53C400 (Canon FG2-5202). Signed-off-by: Ondrej Zary Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/g_NCR5380.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c index cd79ef402d7a..454b565c0417 100644 --- a/drivers/scsi/g_NCR5380.c +++ b/drivers/scsi/g_NCR5380.c @@ -702,6 +702,10 @@ static int generic_NCR5380_dma_xfer_len(struct scsi_cmnd *cmd) !(cmd->SCp.this_residual % transfersize)) transfersize = 32 * 1024; + /* 53C400 datasheet: non-modulo-128-byte transfers should use PIO */ + if (transfersize % 128) + transfersize = 0; + return transfersize; } -- cgit From 12150797d064e2936154a8c01be24ce1b0115cfe Mon Sep 17 00:00:00 2001 From: Ondrej Zary Date: Sun, 3 Jan 2016 16:06:15 +1100 Subject: ncr5380: Use runtime register mapping Convert compile-time C400_ register mapping to runtime mapping. This removes the weird negative register offsets and allows adding additional mappings. While at it, convert read/write loops into insb/outsb. Signed-off-by: Ondrej Zary Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/NCR5380.h | 13 +------ drivers/scsi/g_NCR5380.c | 88 ++++++++++++++++++++++-------------------------- drivers/scsi/g_NCR5380.h | 12 ++++--- 3 files changed, 49 insertions(+), 64 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/NCR5380.h b/drivers/scsi/NCR5380.h index ee83ab5f32e8..a79288682a74 100644 --- a/drivers/scsi/NCR5380.h +++ b/drivers/scsi/NCR5380.h @@ -163,8 +163,7 @@ /* Write any value to this register to start an ini mode DMA receive */ #define START_DMA_INITIATOR_RECEIVE_REG 7 /* wo */ -#define C400_CONTROL_STATUS_REG NCR53C400_register_offset-8 /* rw */ - +/* NCR 53C400(A) Control Status Register bits: */ #define CSR_RESET 0x80 /* wo Resets 53c400 */ #define CSR_53C80_REG 0x80 /* ro 5380 registers busy */ #define CSR_TRANS_DIR 0x40 /* rw Data transfer direction */ @@ -181,16 +180,6 @@ #define CSR_BASE CSR_53C80_INTR #endif -/* Number of 128-byte blocks to be transferred */ -#define C400_BLOCK_COUNTER_REG NCR53C400_register_offset-7 /* rw */ - -/* Resume transfer after disconnect */ -#define C400_RESUME_TRANSFER_REG NCR53C400_register_offset-6 /* wo */ - -/* Access to host buffer stack */ -#define C400_HOST_BUFFER NCR53C400_register_offset-4 /* rw */ - - /* Note : PHASE_* macros are based on the values of the STATUS register */ #define PHASE_MASK (SR_MSG | SR_CD | SR_IO) diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c index 454b565c0417..ddc0a18974d4 100644 --- a/drivers/scsi/g_NCR5380.c +++ b/drivers/scsi/g_NCR5380.c @@ -253,6 +253,7 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt) }; int flags; struct Scsi_Host *instance; + struct NCR5380_hostdata *hostdata; #ifdef SCSI_G_NCR5380_MEM unsigned long base; void __iomem *iomem; @@ -394,6 +395,7 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt) instance = scsi_register(tpnt, sizeof(struct NCR5380_hostdata)); if (instance == NULL) goto out_release; + hostdata = shost_priv(instance); #ifndef SCSI_G_NCR5380_MEM instance->io_port = overrides[current_override].NCR5380_map_name; @@ -403,18 +405,27 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt) * On NCR53C400 boards, NCR5380 registers are mapped 8 past * the base address. */ - if (overrides[current_override].board == BOARD_NCR53C400) + if (overrides[current_override].board == BOARD_NCR53C400) { instance->io_port += 8; + hostdata->c400_ctl_status = 0; + hostdata->c400_blk_cnt = 1; + hostdata->c400_host_buf = 4; + } #else instance->base = overrides[current_override].NCR5380_map_name; - ((struct NCR5380_hostdata *)instance->hostdata)->iomem = iomem; + hostdata->iomem = iomem; + if (overrides[current_override].board == BOARD_NCR53C400) { + hostdata->c400_ctl_status = 0x100; + hostdata->c400_blk_cnt = 0x101; + hostdata->c400_host_buf = 0x104; + } #endif if (NCR5380_init(instance, flags)) goto out_unregister; if (overrides[current_override].board == BOARD_NCR53C400) - NCR5380_write(C400_CONTROL_STATUS_REG, CSR_BASE); + NCR5380_write(hostdata->c400_ctl_status, CSR_BASE); NCR5380_maybe_reset_bus(instance); @@ -522,31 +533,25 @@ generic_NCR5380_biosparam(struct scsi_device *sdev, struct block_device *bdev, static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst, int len) { -#ifdef SCSI_G_NCR5380_MEM struct NCR5380_hostdata *hostdata = shost_priv(instance); -#endif int blocks = len / 128; int start = 0; - int bl; - NCR5380_write(C400_CONTROL_STATUS_REG, CSR_BASE | CSR_TRANS_DIR); - NCR5380_write(C400_BLOCK_COUNTER_REG, blocks); + NCR5380_write(hostdata->c400_ctl_status, CSR_BASE | CSR_TRANS_DIR); + NCR5380_write(hostdata->c400_blk_cnt, blocks); while (1) { - if ((bl = NCR5380_read(C400_BLOCK_COUNTER_REG)) == 0) { + if (NCR5380_read(hostdata->c400_blk_cnt) == 0) break; - } - if (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_GATED_53C80_IRQ) { + if (NCR5380_read(hostdata->c400_ctl_status) & CSR_GATED_53C80_IRQ) { printk(KERN_ERR "53C400r: Got 53C80_IRQ start=%d, blocks=%d\n", start, blocks); return -1; } - while (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_HOST_BUF_NOT_RDY); + while (NCR5380_read(hostdata->c400_ctl_status) & CSR_HOST_BUF_NOT_RDY) + ; /* FIXME - no timeout */ #ifndef SCSI_G_NCR5380_MEM - { - int i; - for (i = 0; i < 128; i++) - dst[start + i] = NCR5380_read(C400_HOST_BUFFER); - } + insb(instance->io_port + hostdata->c400_host_buf, + dst + start, 128); #else /* implies SCSI_G_NCR5380_MEM */ memcpy_fromio(dst + start, @@ -557,17 +562,12 @@ static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst, } if (blocks) { - while (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_HOST_BUF_NOT_RDY) - { - // FIXME - no timeout - } + while (NCR5380_read(hostdata->c400_ctl_status) & CSR_HOST_BUF_NOT_RDY) + ; /* FIXME - no timeout */ #ifndef SCSI_G_NCR5380_MEM - { - int i; - for (i = 0; i < 128; i++) - dst[start + i] = NCR5380_read(C400_HOST_BUFFER); - } + insb(instance->io_port + hostdata->c400_host_buf, + dst + start, 128); #else /* implies SCSI_G_NCR5380_MEM */ memcpy_fromio(dst + start, @@ -577,7 +577,7 @@ static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst, blocks--; } - if (!(NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_GATED_53C80_IRQ)) + if (!(NCR5380_read(hostdata->c400_ctl_status) & CSR_GATED_53C80_IRQ)) printk("53C400r: no 53C80 gated irq after transfer"); #if 0 @@ -585,7 +585,7 @@ static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst, * DON'T DO THIS - THEY NEVER ARRIVE! */ printk("53C400r: Waiting for 53C80 registers\n"); - while (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_53C80_REG) + while (NCR5380_read(hostdata->c400_ctl_status) & CSR_53C80_REG) ; #endif if (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_END_DMA_TRANSFER)) @@ -606,32 +606,26 @@ static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst, static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src, int len) { -#ifdef SCSI_G_NCR5380_MEM struct NCR5380_hostdata *hostdata = shost_priv(instance); -#endif int blocks = len / 128; int start = 0; - int bl; int i; - NCR5380_write(C400_CONTROL_STATUS_REG, CSR_BASE); - NCR5380_write(C400_BLOCK_COUNTER_REG, blocks); + NCR5380_write(hostdata->c400_ctl_status, CSR_BASE); + NCR5380_write(hostdata->c400_blk_cnt, blocks); while (1) { - if (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_GATED_53C80_IRQ) { + if (NCR5380_read(hostdata->c400_ctl_status) & CSR_GATED_53C80_IRQ) { printk(KERN_ERR "53C400w: Got 53C80_IRQ start=%d, blocks=%d\n", start, blocks); return -1; } - if ((bl = NCR5380_read(C400_BLOCK_COUNTER_REG)) == 0) { + if (NCR5380_read(hostdata->c400_blk_cnt) == 0) break; - } - while (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_HOST_BUF_NOT_RDY) + while (NCR5380_read(hostdata->c400_ctl_status) & CSR_HOST_BUF_NOT_RDY) ; // FIXME - timeout #ifndef SCSI_G_NCR5380_MEM - { - for (i = 0; i < 128; i++) - NCR5380_write(C400_HOST_BUFFER, src[start + i]); - } + outsb(instance->io_port + hostdata->c400_host_buf, + src + start, 128); #else /* implies SCSI_G_NCR5380_MEM */ memcpy_toio(hostdata->iomem + NCR53C400_host_buffer, @@ -641,14 +635,12 @@ static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src, blocks--; } if (blocks) { - while (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_HOST_BUF_NOT_RDY) + while (NCR5380_read(hostdata->c400_ctl_status) & CSR_HOST_BUF_NOT_RDY) ; // FIXME - no timeout #ifndef SCSI_G_NCR5380_MEM - { - for (i = 0; i < 128; i++) - NCR5380_write(C400_HOST_BUFFER, src[start + i]); - } + outsb(instance->io_port + hostdata->c400_host_buf, + src + start, 128); #else /* implies SCSI_G_NCR5380_MEM */ memcpy_toio(hostdata->iomem + NCR53C400_host_buffer, @@ -660,7 +652,7 @@ static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src, #if 0 printk("53C400w: waiting for registers to be available\n"); - THEY NEVER DO ! while (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_53C80_REG); + THEY NEVER DO ! while (NCR5380_read(hostdata->c400_ctl_status) & CSR_53C80_REG); printk("53C400w: Got em\n"); #endif @@ -668,7 +660,7 @@ static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src, /* All documentation says to check for this. Maybe my hardware is too * fast. Waiting for it seems to work fine! KLL */ - while (!(i = NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_GATED_53C80_IRQ)) + while (!(i = NCR5380_read(hostdata->c400_ctl_status) & CSR_GATED_53C80_IRQ)) ; // FIXME - no timeout /* diff --git a/drivers/scsi/g_NCR5380.h b/drivers/scsi/g_NCR5380.h index fd201e94f66b..c5e57b7588c1 100644 --- a/drivers/scsi/g_NCR5380.h +++ b/drivers/scsi/g_NCR5380.h @@ -29,7 +29,6 @@ #define NCR5380_map_type int #define NCR5380_map_name port -#define NCR53C400_register_offset 0 #ifdef CONFIG_SCSI_GENERIC_NCR53C400 #define NCR5380_region_size 16 @@ -42,7 +41,10 @@ #define NCR5380_write(reg, value) \ outb(value, instance->io_port + (reg)) -#define NCR5380_implementation_fields /* none */ +#define NCR5380_implementation_fields \ + int c400_ctl_status; \ + int c400_blk_cnt; \ + int c400_host_buf; #else /* therefore SCSI_G_NCR5380_MEM */ @@ -50,7 +52,6 @@ #define NCR5380_map_type unsigned long #define NCR5380_map_name base -#define NCR53C400_register_offset 0x108 #define NCR53C400_mem_base 0x3880 #define NCR53C400_host_buffer 0x3900 #define NCR5380_region_size 0x3a00 @@ -63,7 +64,10 @@ NCR53C400_mem_base + (reg)) #define NCR5380_implementation_fields \ - void __iomem *iomem; + void __iomem *iomem; \ + int c400_ctl_status; \ + int c400_blk_cnt; \ + int c400_host_buf; #endif -- cgit From cecf3beef0ef311b5b375b6307fd5dc3f5dc3edb Mon Sep 17 00:00:00 2001 From: Ondrej Zary Date: Sun, 3 Jan 2016 16:06:16 +1100 Subject: ncr5380: Enable PDMA for NCR53C400A Add I/O register mapping for NCR53C400A and enable PDMA mode to improve performance and fix non-working IRQ. Tested with HP C2502 (and user-space enabler). Signed-off-by: Ondrej Zary Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/g_NCR5380.c | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c index ddc0a18974d4..53e437744c4f 100644 --- a/drivers/scsi/g_NCR5380.c +++ b/drivers/scsi/g_NCR5380.c @@ -323,7 +323,7 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt) #endif break; case BOARD_NCR53C400A: - flags = FLAG_NO_PSEUDO_DMA; + flags = FLAG_NO_DMA_FIXUP; ports = ncr_53c400a_ports; break; case BOARD_DTC3181E: @@ -405,27 +405,42 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt) * On NCR53C400 boards, NCR5380 registers are mapped 8 past * the base address. */ - if (overrides[current_override].board == BOARD_NCR53C400) { + switch (overrides[current_override].board) { + case BOARD_NCR53C400: instance->io_port += 8; hostdata->c400_ctl_status = 0; hostdata->c400_blk_cnt = 1; hostdata->c400_host_buf = 4; + break; + case BOARD_NCR53C400A: + hostdata->c400_ctl_status = 9; + hostdata->c400_blk_cnt = 10; + hostdata->c400_host_buf = 8; + break; } #else instance->base = overrides[current_override].NCR5380_map_name; hostdata->iomem = iomem; - if (overrides[current_override].board == BOARD_NCR53C400) { + switch (overrides[current_override].board) { + case BOARD_NCR53C400: hostdata->c400_ctl_status = 0x100; hostdata->c400_blk_cnt = 0x101; hostdata->c400_host_buf = 0x104; + break; + case BOARD_NCR53C400A: + pr_err(DRV_MODULE_NAME ": unknown register offsets\n"); + goto out_unregister; } #endif if (NCR5380_init(instance, flags)) goto out_unregister; - if (overrides[current_override].board == BOARD_NCR53C400) + switch (overrides[current_override].board) { + case BOARD_NCR53C400: + case BOARD_NCR53C400A: NCR5380_write(hostdata->c400_ctl_status, CSR_BASE); + } NCR5380_maybe_reset_bus(instance); -- cgit From aeb51152bb55451f7a3ddb8c1ec4d4bc19d4a195 Mon Sep 17 00:00:00 2001 From: Ondrej Zary Date: Sun, 3 Jan 2016 16:06:17 +1100 Subject: ncr5380: Enable PDMA for DTC chips Add I/O register mapping for DTC chips and enable PDMA mode. These chips have 16-bit wide HOST BUFFER register and it must be read by 16-bit accesses (we lose data otherwise). Large PIO transfers crash at least the DTCT-436P chip (all reads result in 0xFF) so this patch actually makes it work. The chip also crashes when we bang on the C400 host status register too heavily after PDMA write - a small udelay is needed. Tested on DTCT-436P and verified that it does not break 53C400A. Signed-off-by: Ondrej Zary Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/g_NCR5380.c | 38 +++++++++++++++++++++++++++++++------- drivers/scsi/g_NCR5380.h | 3 ++- 2 files changed, 33 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c index 53e437744c4f..87060c49693b 100644 --- a/drivers/scsi/g_NCR5380.c +++ b/drivers/scsi/g_NCR5380.c @@ -327,7 +327,7 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt) ports = ncr_53c400a_ports; break; case BOARD_DTC3181E: - flags = FLAG_NO_PSEUDO_DMA; + flags = FLAG_NO_DMA_FIXUP; ports = dtc_3181e_ports; break; } @@ -400,6 +400,7 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt) #ifndef SCSI_G_NCR5380_MEM instance->io_port = overrides[current_override].NCR5380_map_name; instance->n_io_port = region_size; + hostdata->io_width = 1; /* 8-bit PDMA by default */ /* * On NCR53C400 boards, NCR5380 registers are mapped 8 past @@ -412,6 +413,9 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt) hostdata->c400_blk_cnt = 1; hostdata->c400_host_buf = 4; break; + case BOARD_DTC3181E: + hostdata->io_width = 2; /* 16-bit PDMA */ + /* fall through */ case BOARD_NCR53C400A: hostdata->c400_ctl_status = 9; hostdata->c400_blk_cnt = 10; @@ -427,6 +431,7 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt) hostdata->c400_blk_cnt = 0x101; hostdata->c400_host_buf = 0x104; break; + case BOARD_DTC3181E: case BOARD_NCR53C400A: pr_err(DRV_MODULE_NAME ": unknown register offsets\n"); goto out_unregister; @@ -438,6 +443,7 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt) switch (overrides[current_override].board) { case BOARD_NCR53C400: + case BOARD_DTC3181E: case BOARD_NCR53C400A: NCR5380_write(hostdata->c400_ctl_status, CSR_BASE); } @@ -565,7 +571,11 @@ static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst, ; /* FIXME - no timeout */ #ifndef SCSI_G_NCR5380_MEM - insb(instance->io_port + hostdata->c400_host_buf, + if (hostdata->io_width == 2) + insw(instance->io_port + hostdata->c400_host_buf, + dst + start, 64); + else + insb(instance->io_port + hostdata->c400_host_buf, dst + start, 128); #else /* implies SCSI_G_NCR5380_MEM */ @@ -581,7 +591,11 @@ static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst, ; /* FIXME - no timeout */ #ifndef SCSI_G_NCR5380_MEM - insb(instance->io_port + hostdata->c400_host_buf, + if (hostdata->io_width == 2) + insw(instance->io_port + hostdata->c400_host_buf, + dst + start, 64); + else + insb(instance->io_port + hostdata->c400_host_buf, dst + start, 128); #else /* implies SCSI_G_NCR5380_MEM */ @@ -639,7 +653,11 @@ static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src, while (NCR5380_read(hostdata->c400_ctl_status) & CSR_HOST_BUF_NOT_RDY) ; // FIXME - timeout #ifndef SCSI_G_NCR5380_MEM - outsb(instance->io_port + hostdata->c400_host_buf, + if (hostdata->io_width == 2) + outsw(instance->io_port + hostdata->c400_host_buf, + src + start, 64); + else + outsb(instance->io_port + hostdata->c400_host_buf, src + start, 128); #else /* implies SCSI_G_NCR5380_MEM */ @@ -654,7 +672,11 @@ static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src, ; // FIXME - no timeout #ifndef SCSI_G_NCR5380_MEM - outsb(instance->io_port + hostdata->c400_host_buf, + if (hostdata->io_width == 2) + outsw(instance->io_port + hostdata->c400_host_buf, + src + start, 64); + else + outsb(instance->io_port + hostdata->c400_host_buf, src + start, 128); #else /* implies SCSI_G_NCR5380_MEM */ @@ -675,8 +697,10 @@ static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src, /* All documentation says to check for this. Maybe my hardware is too * fast. Waiting for it seems to work fine! KLL */ - while (!(i = NCR5380_read(hostdata->c400_ctl_status) & CSR_GATED_53C80_IRQ)) - ; // FIXME - no timeout + while (!(i = NCR5380_read(hostdata->c400_ctl_status) & CSR_GATED_53C80_IRQ)) { + udelay(4); /* DTC436 chip hangs without this */ + /* FIXME - no timeout */ + } /* * I know. i is certainly != 0 here but the loop is new. See previous diff --git a/drivers/scsi/g_NCR5380.h b/drivers/scsi/g_NCR5380.h index c5e57b7588c1..5ab64d96b576 100644 --- a/drivers/scsi/g_NCR5380.h +++ b/drivers/scsi/g_NCR5380.h @@ -44,7 +44,8 @@ #define NCR5380_implementation_fields \ int c400_ctl_status; \ int c400_blk_cnt; \ - int c400_host_buf; + int c400_host_buf; \ + int io_width; #else /* therefore SCSI_G_NCR5380_MEM */ -- cgit From 42fc6370c95df507b925b11372e8baa17eb0da41 Mon Sep 17 00:00:00 2001 From: Ondrej Zary Date: Sun, 3 Jan 2016 16:06:18 +1100 Subject: ncr5380: Fix wait for 53C80 registers registers after PDMA The check for 53C80 registers accessibility was commented out because it was broken (inverted). Fix and enable it. Signed-off-by: Ondrej Zary Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/g_NCR5380.c | 37 ++++++------------------------------- 1 file changed, 6 insertions(+), 31 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c index 87060c49693b..5030cc0dd90a 100644 --- a/drivers/scsi/g_NCR5380.c +++ b/drivers/scsi/g_NCR5380.c @@ -609,14 +609,10 @@ static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst, if (!(NCR5380_read(hostdata->c400_ctl_status) & CSR_GATED_53C80_IRQ)) printk("53C400r: no 53C80 gated irq after transfer"); -#if 0 - /* - * DON'T DO THIS - THEY NEVER ARRIVE! - */ - printk("53C400r: Waiting for 53C80 registers\n"); - while (NCR5380_read(hostdata->c400_ctl_status) & CSR_53C80_REG) + /* wait for 53C80 registers to be available */ + while (!(NCR5380_read(hostdata->c400_ctl_status) & CSR_53C80_REG)) ; -#endif + if (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_END_DMA_TRANSFER)) printk(KERN_ERR "53C400r: no end dma signal\n"); @@ -638,7 +634,6 @@ static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src, struct NCR5380_hostdata *hostdata = shost_priv(instance); int blocks = len / 128; int start = 0; - int i; NCR5380_write(hostdata->c400_ctl_status, CSR_BASE); NCR5380_write(hostdata->c400_blk_cnt, blocks); @@ -687,36 +682,16 @@ static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src, blocks--; } -#if 0 - printk("53C400w: waiting for registers to be available\n"); - THEY NEVER DO ! while (NCR5380_read(hostdata->c400_ctl_status) & CSR_53C80_REG); - printk("53C400w: Got em\n"); -#endif - - /* Let's wait for this instead - could be ugly */ - /* All documentation says to check for this. Maybe my hardware is too - * fast. Waiting for it seems to work fine! KLL - */ - while (!(i = NCR5380_read(hostdata->c400_ctl_status) & CSR_GATED_53C80_IRQ)) { + /* 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 */ } - /* - * I know. i is certainly != 0 here but the loop is new. See previous - * comment. - */ - if (i) { - if (!((i = NCR5380_read(BUS_AND_STATUS_REG)) & BASR_END_DMA_TRANSFER)) - printk(KERN_ERR "53C400w: No END OF DMA bit - WHOOPS! BASR=%0x\n", i); - } else - printk(KERN_ERR "53C400w: no 53C80 gated irq after transfer (last block)\n"); - -#if 0 if (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_END_DMA_TRANSFER)) { printk(KERN_ERR "53C400w: no end dma signal\n"); } -#endif + while (!(NCR5380_read(TARGET_COMMAND_REG) & TCR_LAST_BYTE_SENT)) ; // TIMEOUT return 0; -- cgit From c6084cbce435fbf800f47026896137b3bae483c3 Mon Sep 17 00:00:00 2001 From: Ondrej Zary Date: Sun, 3 Jan 2016 16:06:19 +1100 Subject: ncr5380: Add support for HP C2502 HP C2502 cards (based on 53C400A chips) use different magic numbers for software-based I/O address configuration than other cards. The configuration is also extended to allow setting the IRQ. Move the configuration to a new function magic_configure() and move magic the magic numbers into an array. Add new magic numbers for these HP cards and hp_c2502 module parameter to use them, e.g.: modprobe g_NCR5380 ncr_irq=7 ncr_addr=0x280 hp_c2502=1 Tested with HP C2502 and DTCT-436P. Signed-off-by: Ondrej Zary Signed-off-by: Finn Thain Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/g_NCR5380.c | 74 +++++++++++++++++++++++++++++++++++++----------- drivers/scsi/g_NCR5380.h | 1 + 2 files changed, 59 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c index 5030cc0dd90a..90091e693020 100644 --- a/drivers/scsi/g_NCR5380.c +++ b/drivers/scsi/g_NCR5380.c @@ -80,6 +80,7 @@ static int ncr_5380; static int ncr_53c400; static int ncr_53c400a; static int dtc_3181e; +static int hp_c2502; static struct override { NCR5380_map_type NCR5380_map_name; @@ -225,6 +226,30 @@ static int __init do_DTC3181E_setup(char *str) #endif +#ifndef SCSI_G_NCR5380_MEM +/* + * Configure I/O address of 53C400A or DTC436 by writing magic numbers + * to ports 0x779 and 0x379. + */ +static void magic_configure(int idx, u8 irq, u8 magic[]) +{ + u8 cfg = 0; + + outb(magic[0], 0x779); + outb(magic[1], 0x379); + outb(magic[2], 0x379); + outb(magic[3], 0x379); + outb(magic[4], 0x379); + + /* allowed IRQs for HP C2502 */ + if (irq != 2 && irq != 3 && irq != 4 && irq != 5 && irq != 7) + irq = 0; + if (idx >= 0 && idx <= 7) + cfg = 0x80 | idx | (irq << 4); + outb(cfg, 0x379); +} +#endif + /** * generic_NCR5380_detect - look for NCR5380 controllers * @tpnt: the scsi template @@ -241,8 +266,10 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt) static int current_override; int count; unsigned int *ports; + u8 *magic = NULL; #ifndef SCSI_G_NCR5380_MEM int i; + int port_idx = -1; unsigned long region_size = 16; #endif static unsigned int __initdata ncr_53c400a_ports[] = { @@ -251,6 +278,12 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt) static unsigned int __initdata dtc_3181e_ports[] = { 0x220, 0x240, 0x280, 0x2a0, 0x2c0, 0x300, 0x320, 0x340, 0 }; + static u8 ncr_53c400a_magic[] __initdata = { /* 53C400A & DTC436 */ + 0x59, 0xb9, 0xc5, 0xae, 0xa6 + }; + static u8 hp_c2502_magic[] __initdata = { /* HP C2502 */ + 0x0f, 0x22, 0xf0, 0x20, 0x80 + }; int flags; struct Scsi_Host *instance; struct NCR5380_hostdata *hostdata; @@ -273,6 +306,8 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt) overrides[0].board = BOARD_NCR53C400A; else if (dtc_3181e) overrides[0].board = BOARD_DTC3181E; + else if (hp_c2502) + overrides[0].board = BOARD_HP_C2502; #ifndef SCSI_G_NCR5380_MEM if (!current_override && isapnp_present()) { struct pnp_dev *dev = NULL; @@ -325,24 +360,26 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt) case BOARD_NCR53C400A: flags = FLAG_NO_DMA_FIXUP; ports = ncr_53c400a_ports; + magic = ncr_53c400a_magic; + break; + case BOARD_HP_C2502: + flags = FLAG_NO_DMA_FIXUP; + ports = ncr_53c400a_ports; + magic = hp_c2502_magic; break; case BOARD_DTC3181E: flags = FLAG_NO_DMA_FIXUP; ports = dtc_3181e_ports; + magic = ncr_53c400a_magic; break; } #ifndef SCSI_G_NCR5380_MEM - if (ports) { + if (ports && magic) { /* wakeup sequence for the NCR53C400A and DTC3181E */ /* Disable the adapter and look for a free io port */ - outb(0x59, 0x779); - outb(0xb9, 0x379); - outb(0xc5, 0x379); - outb(0xae, 0x379); - outb(0xa6, 0x379); - outb(0x00, 0x379); + magic_configure(-1, 0, magic); if (overrides[current_override].NCR5380_map_name != PORT_AUTO) for (i = 0; ports[i]; i++) { @@ -361,17 +398,12 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt) } if (ports[i]) { /* At this point we have our region reserved */ - outb(0x59, 0x779); - outb(0xb9, 0x379); - outb(0xc5, 0x379); - outb(0xae, 0x379); - outb(0xa6, 0x379); - outb(0x80 | i, 0x379); /* set io port to be used */ + magic_configure(i, 0, magic); /* no IRQ yet */ outb(0xc0, ports[i] + 9); if (inb(ports[i] + 9) != 0x80) continue; - else - overrides[current_override].NCR5380_map_name = ports[i]; + overrides[current_override].NCR5380_map_name = ports[i]; + port_idx = i; } else continue; } @@ -417,6 +449,7 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt) hostdata->io_width = 2; /* 16-bit PDMA */ /* fall through */ case BOARD_NCR53C400A: + case BOARD_HP_C2502: hostdata->c400_ctl_status = 9; hostdata->c400_blk_cnt = 10; hostdata->c400_host_buf = 8; @@ -433,6 +466,7 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt) break; case BOARD_DTC3181E: case BOARD_NCR53C400A: + case BOARD_HP_C2502: pr_err(DRV_MODULE_NAME ": unknown register offsets\n"); goto out_unregister; } @@ -445,6 +479,7 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt) case BOARD_NCR53C400: case BOARD_DTC3181E: case BOARD_NCR53C400A: + case BOARD_HP_C2502: NCR5380_write(hostdata->c400_ctl_status, CSR_BASE); } @@ -459,12 +494,18 @@ static int __init generic_NCR5380_detect(struct scsi_host_template *tpnt) if (instance->irq == 255) instance->irq = NO_IRQ; - if (instance->irq != NO_IRQ) + if (instance->irq != NO_IRQ) { +#ifndef SCSI_G_NCR5380_MEM + /* set IRQ for HP C2502 */ + if (overrides[current_override].board == BOARD_HP_C2502) + magic_configure(port_idx, instance->irq, magic); +#endif if (request_irq(instance->irq, generic_NCR5380_intr, 0, "NCR5380", instance)) { printk(KERN_WARNING "scsi%d : IRQ%d not free, interrupts disabled\n", instance->host_no, instance->irq); instance->irq = NO_IRQ; } + } if (instance->irq == NO_IRQ) { printk(KERN_INFO "scsi%d : interrupts not enabled. for better interactive performance,\n", instance->host_no); @@ -751,6 +792,7 @@ module_param(ncr_5380, int, 0); module_param(ncr_53c400, int, 0); module_param(ncr_53c400a, int, 0); module_param(dtc_3181e, int, 0); +module_param(hp_c2502, int, 0); MODULE_LICENSE("GPL"); #if !defined(SCSI_G_NCR5380_MEM) && defined(MODULE) diff --git a/drivers/scsi/g_NCR5380.h b/drivers/scsi/g_NCR5380.h index 5ab64d96b576..6f3d2ac4f185 100644 --- a/drivers/scsi/g_NCR5380.h +++ b/drivers/scsi/g_NCR5380.h @@ -88,6 +88,7 @@ #define BOARD_NCR53C400 1 #define BOARD_NCR53C400A 2 #define BOARD_DTC3181E 3 +#define BOARD_HP_C2502 4 #endif /* GENERIC_NCR5380_H */ -- cgit From 9055082fb100cc66e20c048251d05159f5f2cfba Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Thu, 7 Jan 2016 16:34:05 -0600 Subject: scsi: add Synology to 1024 sector blacklist Another iscsi target that cannot handle large IOs, but does not tell us a limit. The Synology iSCSI targets report: Block limits VPD page (SBC): Write same no zero (WSNZ): 0 Maximum compare and write length: 0 blocks Optimal transfer length granularity: 0 blocks Maximum transfer length: 0 blocks Optimal transfer length: 0 blocks Maximum prefetch length: 0 blocks Maximum unmap LBA count: 0 Maximum unmap block descriptor count: 0 Optimal unmap granularity: 0 Unmap granularity alignment valid: 0 Unmap granularity alignment: 0 Maximum write same length: 0x0 blocks and the size of the command it can handle seems to depend on how much memory it can allocate at the time. This results in IO errors when handling large IOs. This patch just has us use the old 1024 default sectors for this target by adding it to the scsi blacklist. We do not have good contacs with this vendors, so I have not been able to try and fix on their side. I have posted this a long while back, but it was not merged. This version just fixes it up for merge/patch failures in the original version. Reported-by: Ancoron Luciferis Reported-by: Michael Meyers Signed-off-by: Mike Christie Signed-off-by: Martin K. Petersen Cc: # 4.1+ --- drivers/scsi/scsi_devinfo.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c index 2c1160c7ec92..47b9d13f97b8 100644 --- a/drivers/scsi/scsi_devinfo.c +++ b/drivers/scsi/scsi_devinfo.c @@ -227,6 +227,7 @@ static struct { {"Promise", "VTrak E610f", NULL, BLIST_SPARSELUN | BLIST_NO_RSOC}, {"Promise", "", NULL, BLIST_SPARSELUN}, {"QNAP", "iSCSI Storage", NULL, BLIST_MAX_1024}, + {"SYNOLOGY", "iSCSI Storage", NULL, BLIST_MAX_1024}, {"QUANTUM", "XP34301", "1071", BLIST_NOTQ}, {"REGAL", "CDC-4X", NULL, BLIST_MAX5LUN | BLIST_SINGLELUN}, {"SanDisk", "ImageMate CF-SD1", NULL, BLIST_FORCELUN}, -- cgit From d63c7dd5bcb9441af0526d370c43a65ca2c980d9 Mon Sep 17 00:00:00 2001 From: Insu Yun Date: Wed, 6 Jan 2016 12:44:01 -0500 Subject: ipr: Fix out-of-bounds null overwrite Return value of snprintf is not bound by size value, 2nd argument. (https://www.kernel.org/doc/htmldocs/kernel-api/API-snprintf.html). Return value is number of printed chars, can be larger than 2nd argument. Therefore, it can write null byte out of bounds ofbuffer. Since snprintf puts null, it does not need to put additional null byte. Signed-off-by: Insu Yun Reviewed-by: Shane Seymour Signed-off-by: Martin K. Petersen --- drivers/scsi/ipr.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index 536cd5a80422..1c3759bab80b 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c @@ -4003,13 +4003,12 @@ static ssize_t ipr_store_update_fw(struct device *dev, struct ipr_sglist *sglist; char fname[100]; char *src; - int len, result, dnld_size; + int result, dnld_size; if (!capable(CAP_SYS_ADMIN)) return -EACCES; - len = snprintf(fname, 99, "%s", buf); - fname[len-1] = '\0'; + snprintf(fname, sizeof(fname), "%s", buf); if (request_firmware(&fw_entry, fname, &ioa_cfg->pdev->dev)) { dev_err(&ioa_cfg->pdev->dev, "Firmware file %s not found\n", fname); -- cgit From 8ceec33223f0cf8849d47dbe2203ce82c9875d09 Mon Sep 17 00:00:00 2001 From: John Garry Date: Mon, 21 Dec 2015 19:35:07 +0800 Subject: hisi_sas: Fix v1 itct masks The mask fields are for quad-words, so add ULL suffix. Also unreferenced ITCT_HDR_BREAK_REPLY and ITCT_HDR_MAX_BURST are removed. Fixes: 50af155b6c ("hisi_sas: Add v1 hardware reg") Signed-off-by: John Garry Reviewed-by: Shane Seymour Reviewed-by: Matthew R. Ochs Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 29 ++++++++++++----------------- 1 file changed, 12 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c index d54381149c0d..0af682cafa0b 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c @@ -247,41 +247,36 @@ /* ITCT header */ /* qw0 */ #define ITCT_HDR_DEV_TYPE_OFF 0 -#define ITCT_HDR_DEV_TYPE_MSK (0x3 << ITCT_HDR_DEV_TYPE_OFF) +#define ITCT_HDR_DEV_TYPE_MSK (0x3ULL << ITCT_HDR_DEV_TYPE_OFF) #define ITCT_HDR_VALID_OFF 2 -#define ITCT_HDR_VALID_MSK (0x1 << ITCT_HDR_VALID_OFF) -#define ITCT_HDR_BREAK_REPLY_ENA_OFF 3 -#define ITCT_HDR_BREAK_REPLY_ENA_MSK (0x1 << ITCT_HDR_BREAK_REPLY_ENA_OFF) +#define ITCT_HDR_VALID_MSK (0x1ULL << ITCT_HDR_VALID_OFF) #define ITCT_HDR_AWT_CONTROL_OFF 4 -#define ITCT_HDR_AWT_CONTROL_MSK (0x1 << ITCT_HDR_AWT_CONTROL_OFF) +#define ITCT_HDR_AWT_CONTROL_MSK (0x1ULL << ITCT_HDR_AWT_CONTROL_OFF) #define ITCT_HDR_MAX_CONN_RATE_OFF 5 -#define ITCT_HDR_MAX_CONN_RATE_MSK (0xf << ITCT_HDR_MAX_CONN_RATE_OFF) +#define ITCT_HDR_MAX_CONN_RATE_MSK (0xfULL << ITCT_HDR_MAX_CONN_RATE_OFF) #define ITCT_HDR_VALID_LINK_NUM_OFF 9 -#define ITCT_HDR_VALID_LINK_NUM_MSK (0xf << ITCT_HDR_VALID_LINK_NUM_OFF) +#define ITCT_HDR_VALID_LINK_NUM_MSK (0xfULL << ITCT_HDR_VALID_LINK_NUM_OFF) #define ITCT_HDR_PORT_ID_OFF 13 -#define ITCT_HDR_PORT_ID_MSK (0x7 << ITCT_HDR_PORT_ID_OFF) +#define ITCT_HDR_PORT_ID_MSK (0x7ULL << ITCT_HDR_PORT_ID_OFF) #define ITCT_HDR_SMP_TIMEOUT_OFF 16 -#define ITCT_HDR_SMP_TIMEOUT_MSK (0xffff << ITCT_HDR_SMP_TIMEOUT_OFF) -#define ITCT_HDR_MAX_BURST_BYTES_OFF 16 -#define ITCT_HDR_MAX_BURST_BYTES_MSK (0xffffffff << \ - ITCT_MAX_BURST_BYTES_OFF) +#define ITCT_HDR_SMP_TIMEOUT_MSK (0xffffULL << ITCT_HDR_SMP_TIMEOUT_OFF) /* qw1 */ #define ITCT_HDR_MAX_SAS_ADDR_OFF 0 #define ITCT_HDR_MAX_SAS_ADDR_MSK (0xffffffffffffffff << \ ITCT_HDR_MAX_SAS_ADDR_OFF) /* qw2 */ #define ITCT_HDR_IT_NEXUS_LOSS_TL_OFF 0 -#define ITCT_HDR_IT_NEXUS_LOSS_TL_MSK (0xffff << \ +#define ITCT_HDR_IT_NEXUS_LOSS_TL_MSK (0xffffULL << \ ITCT_HDR_IT_NEXUS_LOSS_TL_OFF) #define ITCT_HDR_BUS_INACTIVE_TL_OFF 16 -#define ITCT_HDR_BUS_INACTIVE_TL_MSK (0xffff << \ +#define ITCT_HDR_BUS_INACTIVE_TL_MSK (0xffffULL << \ ITCT_HDR_BUS_INACTIVE_TL_OFF) #define ITCT_HDR_MAX_CONN_TL_OFF 32 -#define ITCT_HDR_MAX_CONN_TL_MSK (0xffff << \ +#define ITCT_HDR_MAX_CONN_TL_MSK (0xffffULL << \ ITCT_HDR_MAX_CONN_TL_OFF) #define ITCT_HDR_REJ_OPEN_TL_OFF 48 -#define ITCT_HDR_REJ_OPEN_TL_MSK (0xffff << \ - ITCT_REJ_OPEN_TL_OFF) +#define ITCT_HDR_REJ_OPEN_TL_MSK (0xffffULL << \ + ITCT_HDR_REJ_OPEN_TL_OFF) /* Err record header */ #define ERR_HDR_DMA_TX_ERR_TYPE_OFF 0 -- cgit From 8fb88201b4303159638976c2c4c4769fc89d64d1 Mon Sep 17 00:00:00 2001 From: John Garry Date: Mon, 21 Dec 2015 19:35:08 +0800 Subject: hisi_sas: Fix typo in setup_itct_v1_hw() We were doing a arithmetic comparison instead of logical shift by accident. Mis-programming the itct did not seem to make a difference to operation. Fixes: abda97c2fe874 ("hisi_sas: Add dev_found") Signed-off-by: John Garry Reviewed-by: Matthew R. Ochs Reviewed-by: Shane Seymour Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c index 0af682cafa0b..38ff575775f1 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c @@ -528,10 +528,10 @@ static void setup_itct_v1_hw(struct hisi_hba *hisi_hba, itct->sas_addr = __swab64(itct->sas_addr); /* qw2 */ - itct->qw2 = cpu_to_le64((500 < ITCT_HDR_IT_NEXUS_LOSS_TL_OFF) | - (0xff00 < ITCT_HDR_BUS_INACTIVE_TL_OFF) | - (0xff00 < ITCT_HDR_MAX_CONN_TL_OFF) | - (0xff00 < ITCT_HDR_REJ_OPEN_TL_OFF)); + itct->qw2 = cpu_to_le64((500ULL << ITCT_HDR_IT_NEXUS_LOSS_TL_OFF) | + (0xff00ULL << ITCT_HDR_BUS_INACTIVE_TL_OFF) | + (0xff00ULL << ITCT_HDR_MAX_CONN_TL_OFF) | + (0xff00ULL << ITCT_HDR_REJ_OPEN_TL_OFF)); } static void free_device_v1_hw(struct hisi_hba *hisi_hba, -- cgit From 4e09bff3301ac570cb5d68277e755f1759edfeb2 Mon Sep 17 00:00:00 2001 From: John Garry Date: Mon, 21 Dec 2015 19:35:09 +0800 Subject: hisi_sas: Use u64 for qw0 in free_device_v1_hw() By reading in itct.qw0 into a 32b variable the top 32 bits were being lost. In practice this was OK as they were zeroes. Fixes: 27a3f229 ("hisi_sas: Add cq interrupt") Signed-off-by: John Garry Reviewed-by: Matthew R. Ochs Reviewed-by: Shane Seymour Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c index 38ff575775f1..057fdeb720ac 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c @@ -539,7 +539,8 @@ static void free_device_v1_hw(struct hisi_hba *hisi_hba, { u64 dev_id = sas_dev->device_id; struct hisi_sas_itct *itct = &hisi_hba->itct[dev_id]; - u32 qw0, reg_val = hisi_sas_read32(hisi_hba, CFG_AGING_TIME); + u64 qw0; + u32 reg_val = hisi_sas_read32(hisi_hba, CFG_AGING_TIME); reg_val |= CFG_AGING_TIME_ITCT_REL_MSK; hisi_sas_write32(hisi_hba, CFG_AGING_TIME, reg_val); -- cgit From 4f44f35dd8cf0818c51f399611ef868ebfdaccba Mon Sep 17 00:00:00 2001 From: "Ryan C. Underwood" Date: Thu, 24 Dec 2015 21:45:27 -0800 Subject: 3w-xxxx: Pass through compat mode ioctls This allows 32-bit userspace tools (tw_cli, smartctl) to work on a 64-bit system. The command buffer is opaque to us, so, no word size problems. Signed-off-by: Ryan C. Underwood Reviewed-by: Shane Seymour Reviewed-by: Matthew R. Ochs Signed-off-by: Martin K. Petersen --- drivers/scsi/3w-xxxx.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/scsi/3w-xxxx.c b/drivers/scsi/3w-xxxx.c index 2940bd769936..25aba1613e21 100644 --- a/drivers/scsi/3w-xxxx.c +++ b/drivers/scsi/3w-xxxx.c @@ -1045,6 +1045,9 @@ static int tw_chrdev_open(struct inode *inode, struct file *file) static const struct file_operations tw_fops = { .owner = THIS_MODULE, .unlocked_ioctl = tw_chrdev_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = tw_chrdev_ioctl, +#endif .open = tw_chrdev_open, .release = NULL, .llseek = noop_llseek, -- cgit From 856690ca98059388f9f7e0afc8f0d7441a965e35 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 8 Jan 2016 14:01:36 +0300 Subject: cxgbi: Typo in MODULE_PARM_DESC The module_param is "cxgb3i_rx_credit_thres" so the MODULE_PARM_DESC() should match that. Signed-off-by: Dan Carpenter Reviewed-by: Matthew R. Ochs Signed-off-by: Martin K. Petersen --- drivers/scsi/cxgbi/cxgb3i/cxgb3i.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c b/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c index 0e2bee937fe8..e22a268fd311 100644 --- a/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c +++ b/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c @@ -57,7 +57,7 @@ MODULE_PARM_DESC(cxgb3i_snd_win, "TCP send window in bytes (default=128KB)"); static int cxgb3i_rx_credit_thres = 10 * 1024; module_param(cxgb3i_rx_credit_thres, int, 0644); -MODULE_PARM_DESC(rx_credit_thres, +MODULE_PARM_DESC(cxgb3i_rx_credit_thres, "RX credits return threshold in bytes (default=10KB)"); static unsigned int cxgb3i_max_connect = 8 * 1024; -- cgit From 74e26784f1c50469585f483cf404c2b1d621c101 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 8 Jan 2016 14:02:04 +0300 Subject: storvsc: Fix typo in MODULE_PARM_DESC The module_param is "storvsc_vcpus_per_sub_channel" so we need to use that for MODULE_PARM_DESC() as well. Signed-off-by: Dan Carpenter Reviewed-by: Matthew R. Ochs Signed-off-by: Martin K. Petersen --- drivers/scsi/storvsc_drv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index 41c115c230d9..55627d097873 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -390,7 +390,7 @@ module_param(storvsc_ringbuffer_size, int, S_IRUGO); MODULE_PARM_DESC(storvsc_ringbuffer_size, "Ring buffer size (bytes)"); module_param(storvsc_vcpus_per_sub_channel, int, S_IRUGO); -MODULE_PARM_DESC(vcpus_per_sub_channel, "Ratio of VCPUs to subchannels"); +MODULE_PARM_DESC(storvsc_vcpus_per_sub_channel, "Ratio of VCPUs to subchannels"); /* * Timeout in seconds for all devices managed by this driver. */ -- cgit From 7296f62f0322d808362b21064deb34f20799c20d Mon Sep 17 00:00:00 2001 From: Nicholas Krause Date: Tue, 5 Jan 2016 14:32:54 -0500 Subject: megaraid: Fix possible NULL pointer deference in mraid_mm_ioctl This adds the needed check after the call to the function mraid_mm_alloc_kioc in order to make sure that this function has not returned NULL and therefore makes sure we do not deference a NULL pointer if one is returned by mraid_mm_alloc_kioc. Further more add needed comments explaining that this function call can return NULL if the list head is empty for the pointer passed in order to allow furture users to understand this required pointer check. Signed-off-by: Nicholas Krause Acked-by: Sumit Saxena Signed-off-by: Martin K. Petersen --- drivers/scsi/megaraid/megaraid_mm.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/scsi/megaraid/megaraid_mm.c b/drivers/scsi/megaraid/megaraid_mm.c index a70692779a16..4cf9ed96414f 100644 --- a/drivers/scsi/megaraid/megaraid_mm.c +++ b/drivers/scsi/megaraid/megaraid_mm.c @@ -179,8 +179,12 @@ mraid_mm_ioctl(struct file *filep, unsigned int cmd, unsigned long arg) /* * The following call will block till a kioc is available + * or return NULL if the list head is empty for the pointer + * of type mraid_mmapt passed to mraid_mm_alloc_kioc */ kioc = mraid_mm_alloc_kioc(adp); + if (!kioc) + return -ENXIO; /* * User sent the old mimd_t ioctl packet. Convert it to uioc_t. -- cgit From a290dd57926cb0c54eec7ea506885119e296b755 Mon Sep 17 00:00:00 2001 From: Sudip Mukherjee Date: Tue, 5 Jan 2016 18:10:50 +0530 Subject: imm: Use new parport device model Modify imm driver to use the new parallel port device model. Signed-off-by: Sudip Mukherjee Reviewed-by: Matthew R. Ochs Signed-off-by: Martin K. Petersen --- drivers/scsi/imm.c | 50 +++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 43 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/imm.c b/drivers/scsi/imm.c index 4e1a632ccf16..f8b88fa78e62 100644 --- a/drivers/scsi/imm.c +++ b/drivers/scsi/imm.c @@ -43,6 +43,7 @@ typedef struct { unsigned dp:1; /* Data phase present */ unsigned rd:1; /* Read data in data phase */ unsigned wanted:1; /* Parport sharing busy flag */ + unsigned int dev_no; /* Device number */ wait_queue_head_t *waiting; struct Scsi_Host *host; struct list_head list; @@ -1120,15 +1121,40 @@ static struct scsi_host_template imm_template = { static LIST_HEAD(imm_hosts); +/* + * Finds the first available device number that can be alloted to the + * new imm device and returns the address of the previous node so that + * we can add to the tail and have a list in the ascending order. + */ + +static inline imm_struct *find_parent(void) +{ + imm_struct *dev, *par = NULL; + unsigned int cnt = 0; + + if (list_empty(&imm_hosts)) + return NULL; + + list_for_each_entry(dev, &imm_hosts, list) { + if (dev->dev_no != cnt) + return par; + cnt++; + par = dev; + } + + return par; +} + static int __imm_attach(struct parport *pb) { struct Scsi_Host *host; - imm_struct *dev; + imm_struct *dev, *temp; DECLARE_WAIT_QUEUE_HEAD_ONSTACK(waiting); DEFINE_WAIT(wait); int ports; int modes, ppb; int err = -ENOMEM; + struct pardev_cb imm_cb; init_waitqueue_head(&waiting); @@ -1141,9 +1167,15 @@ static int __imm_attach(struct parport *pb) dev->mode = IMM_AUTODETECT; INIT_LIST_HEAD(&dev->list); - dev->dev = parport_register_device(pb, "imm", NULL, imm_wakeup, - NULL, 0, dev); + temp = find_parent(); + if (temp) + dev->dev_no = temp->dev_no + 1; + + memset(&imm_cb, 0, sizeof(imm_cb)); + imm_cb.private = dev; + imm_cb.wakeup = imm_wakeup; + dev->dev = parport_register_dev_model(pb, "imm", &imm_cb, dev->dev_no); if (!dev->dev) goto out; @@ -1207,7 +1239,10 @@ static int __imm_attach(struct parport *pb) host->unique_id = pb->number; *(imm_struct **)&host->hostdata = dev; dev->host = host; - list_add_tail(&dev->list, &imm_hosts); + if (!temp) + list_add_tail(&dev->list, &imm_hosts); + else + list_add_tail(&dev->list, &temp->list); err = scsi_add_host(host, NULL); if (err) goto out2; @@ -1245,9 +1280,10 @@ static void imm_detach(struct parport *pb) } static struct parport_driver imm_driver = { - .name = "imm", - .attach = imm_attach, - .detach = imm_detach, + .name = "imm", + .match_port = imm_attach, + .detach = imm_detach, + .devmodel = true, }; static int __init imm_driver_init(void) -- cgit