To: linus, akpm, jejb Cc: lkml, linux-scsi Subject: [PATCH] M68k: Fix Amiga7xx, BVME6000, and MVME16x 53c7xx SCSI From: Kars de Jong M68k: Fix Amiga7xx, BVME6000, and MVME16x 53c7xx SCSI Like was suggested before, the 53c7xx driver should probably be ditched and its users (bvme6000, amiga7xx, and mvme16x) should be converted to use the 53c700 driver instead. --- arch/m68k/configs/amiga_defconfig | 2 arch/m68k/configs/bvme6000_defconfig | 2 arch/m68k/configs/mvme16x_defconfig | 2 arch/m68k/defconfig | 2 drivers/scsi/53c7xx.c | 447 +++++++++++++++++------------------ drivers/scsi/53c7xx.h | 26 +- drivers/scsi/Kconfig | 6 drivers/scsi/amiga7xx.c | 15 - drivers/scsi/amiga7xx.h | 23 - drivers/scsi/bvme6000.c | 15 - drivers/scsi/bvme6000.h | 24 - drivers/scsi/mvme16x.c | 15 - drivers/scsi/mvme16x.h | 24 - 13 files changed, 290 insertions(+), 313 deletions(-) --- linux-2.6.10-rc1/arch/m68k/configs/amiga_defconfig 2004-10-30 14:17:59.000000000 +0200 +++ linux-m68k-2.6.10-rc1/arch/m68k/configs/amiga_defconfig 2004-10-30 13:58:49.000000000 +0200 @@ -234,7 +234,9 @@ CONFIG_CYBERSTORMII_SCSI=y CONFIG_BLZ2060_SCSI=y CONFIG_BLZ1230_SCSI=y CONFIG_FASTLANE_SCSI=y +CONFIG_SCSI_AMIGA7XX=y CONFIG_OKTAGON_SCSI=y +CONFIG_SCSI_NCR53C7xx_FAST=y # # Old CD-ROM drivers (not SCSI, not IDE) --- linux-2.6.10-rc1/arch/m68k/configs/bvme6000_defconfig 2004-10-30 14:17:59.000000000 +0200 +++ linux-m68k-2.6.10-rc1/arch/m68k/configs/bvme6000_defconfig 2004-10-30 13:59:00.000000000 +0200 @@ -162,6 +162,8 @@ CONFIG_SCSI_CONSTANTS=y # # CONFIG_SCSI_SATA is not set # CONFIG_SCSI_DEBUG is not set +CONFIG_BVME6000_SCSI=y +CONFIG_SCSI_NCR53C7xx_FAST=y # # Multi-device support (RAID and LVM) --- linux-2.6.10-rc1/arch/m68k/configs/mvme16x_defconfig 2004-10-30 14:17:59.000000000 +0200 +++ linux-m68k-2.6.10-rc1/arch/m68k/configs/mvme16x_defconfig 2004-10-30 13:59:13.000000000 +0200 @@ -162,6 +162,8 @@ CONFIG_SCSI_CONSTANTS=y # # CONFIG_SCSI_SATA is not set # CONFIG_SCSI_DEBUG is not set +CONFIG_MVME16x_SCSI=y +CONFIG_SCSI_NCR53C7xx_FAST=y # # Multi-device support (RAID and LVM) --- linux-2.6.10-rc1/arch/m68k/defconfig 28 Oct 2004 20:14:06 -0000 1.6 +++ linux-m68k-2.6.10-rc1/arch/m68k/defconfig 30 Oct 2004 12:37:23 -0000 @@ -164,7 +164,9 @@ CONFIG_GVP11_SCSI=y # CONFIG_BLZ2060_SCSI is not set # CONFIG_BLZ1230_SCSI is not set # CONFIG_FASTLANE_SCSI is not set +CONFIG_SCSI_AMIGA7XX=y # CONFIG_OKTAGON_SCSI is not set +CONFIG_SCSI_NCR53C7xx_FAST=y # # Multi-device support (RAID and LVM) --- linux-2.6.10-rc1/drivers/scsi/53c7xx.c 2004-07-12 09:48:10.000000000 +0200 +++ linux-m68k-2.6.10-rc1/drivers/scsi/53c7xx.c 2004-10-30 13:55:34.000000000 +0200 @@ -306,7 +306,7 @@ static int check_address (unsigned long addr, int size); static void dump_events (struct Scsi_Host *host, int count); -static Scsi_Cmnd * return_outstanding_commands (struct Scsi_Host *host, +static struct scsi_cmnd * return_outstanding_commands (struct Scsi_Host *host, int free, int issue); static void hard_reset (struct Scsi_Host *host); static void ncr_scsi_reset (struct Scsi_Host *host); @@ -315,7 +315,7 @@ static void set_synchronous (struct Scsi int scntl3, int now_connected); static int datapath_residual (struct Scsi_Host *host); static const char * sbcl_to_phase (int sbcl); -static void print_progress (Scsi_Cmnd *cmd); +static void print_progress (struct scsi_cmnd *cmd); static void print_queues (struct Scsi_Host *host); static void process_issue_queue (unsigned long flags); static int shutdown (struct Scsi_Host *host); @@ -341,9 +341,8 @@ static int NCR53c7x0_dstat_sir_intr (str static void NCR53c7x0_soft_reset (struct Scsi_Host *host); /* Size of event list (per host adapter) */ -static int track_events = 0; -static struct Scsi_Host *first_host = NULL; /* Head of list of NCR boards */ -static struct scsi_host_template *the_template = NULL; +static int track_events; +static struct scsi_host_template *the_template; /* NCR53c710 script handling code */ @@ -665,8 +664,11 @@ static const unsigned char wdtr_message[ static struct Scsi_Host * find_host (int host) { - struct Scsi_Host *h; - for (h = first_host; h && h->host_no != host; h = h->next); + struct Scsi_Host *h, *s; + list_for_each_entry_safe(h, s, &the_template->legacy_hosts, sht_legacy_list) { + if (h->host_no == host) + break; + } if (!h) { printk (KERN_ALERT "scsi%d not found\n", host); return NULL; @@ -714,14 +716,14 @@ request_synchronous (int host, int targe } hostdata = (struct NCR53c7x0_hostdata *)h->hostdata[0]; - local_irq_save(flags); + spin_lock_irqsave(host->host_lock, flags); if (hostdata->initiate_sdtr & (1 << target)) { - local_irq_restore(flags); + spin_unlock_irqrestore(host->host_lock, flags); printk (KERN_ALERT "target %d already doing SDTR\n", target); return -1; } hostdata->initiate_sdtr |= (1 << target); - local_irq_restore(flags); + spin_unlock_irqrestore(host->host_lock, flags); return 0; } #endif @@ -1032,9 +1034,6 @@ NCR53c7x0_init (struct Scsi_Host *host) ccf = clock_to_ccf_710 (expected_clock); - for (i = 0; i < 16; ++i) - hostdata->cmd_allocated[i] = 0; - if (hostdata->init_save_regs) hostdata->init_save_regs (host); if (hostdata->init_fixup) @@ -1042,7 +1041,6 @@ NCR53c7x0_init (struct Scsi_Host *host) if (!the_template) { the_template = host->hostt; - first_host = host; } /* @@ -1305,7 +1303,6 @@ ncr53c7xx_init (Scsi_Host_Template *tpnt hostdata->free->size = max_cmd_size; hostdata->free->free = NULL; hostdata->free->next = NULL; - hostdata->extra_allocate = 0; /* Allocate command start code space */ hostdata->schedule = (chip == 700 || chip == 70066) ? @@ -1588,10 +1585,10 @@ NCR53c7xx_run_tests (struct Scsi_Host *h /* The NCR chip _must_ be idle to run the test scripts */ - local_irq_save(flags); + spin_lock_irqsave(host->host_lock, flags); if (!hostdata->idle) { printk ("scsi%d : chip not idle, aborting tests\n", host->host_no); - local_irq_restore(flags); + spin_unlock_irqrestore(host->host_lock, flags); return -1; } @@ -1615,7 +1612,7 @@ NCR53c7xx_run_tests (struct Scsi_Host *h NCR53c7x0_write8 (DCNTL_REG, hostdata->saved_dcntl | DCNTL_SSM | DCNTL_STD); printk (" started\n"); - local_irq_restore(flags); + spin_unlock_irqrestore(host->host_lock, flags); /* * This is currently a .5 second timeout, since (in theory) no slow @@ -1654,7 +1651,7 @@ NCR53c7xx_run_tests (struct Scsi_Host *h hostdata->script, start); printk ("scsi%d : DSPS = 0x%x\n", host->host_no, NCR53c7x0_read32(DSPS_REG)); - local_irq_restore(flags); + spin_unlock_irqrestore(host->host_lock, flags); return -1; } hostdata->test_running = 0; @@ -1692,7 +1689,7 @@ NCR53c7xx_run_tests (struct Scsi_Host *h local_irq_disable(); if (!hostdata->idle) { printk ("scsi%d : chip not idle, aborting tests\n", host->host_no); - local_irq_restore(flags); + spin_unlock_irqrestore(host->host_lock, flags); return -1; } @@ -1708,7 +1705,7 @@ NCR53c7xx_run_tests (struct Scsi_Host *h if (hostdata->options & OPTION_DEBUG_TRACE) NCR53c7x0_write8 (DCNTL_REG, hostdata->saved_dcntl | DCNTL_SSM | DCNTL_STD); - local_irq_restore(flags); + spin_unlock_irqrestore(host->host_lock, flags); timeout = jiffies + 5 * HZ; /* arbitrary */ while ((hostdata->test_completed == -1) && time_before(jiffies, timeout)) @@ -1730,19 +1727,19 @@ NCR53c7xx_run_tests (struct Scsi_Host *h host->host_no, i); if (!hostdata->idle) { printk("scsi%d : not idle\n", host->host_no); - local_irq_restore(flags); + spin_unlock_irqrestore(host->host_lock, flags); return -1; } } else if (hostdata->test_completed == -1) { printk ("scsi%d : test 2 timed out\n", host->host_no); - local_irq_restore(flags); + spin_unlock_irqrestore(host->host_lock, flags); return -1; } hostdata->test_running = 0; } } - local_irq_restore(flags); + spin_unlock_irqrestore(host->host_lock, flags); return 0; } @@ -1758,7 +1755,7 @@ NCR53c7xx_run_tests (struct Scsi_Host *h static void NCR53c7xx_dsa_fixup (struct NCR53c7x0_cmd *cmd) { - Scsi_Cmnd *c = cmd->cmd; + struct scsi_cmnd *c = cmd->cmd; struct Scsi_Host *host = c->device->host; struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) host->hostdata[0]; @@ -1844,7 +1841,7 @@ run_process_issue_queue(void) { * * Purpose : mark SCSI command as finished, OR'ing the host portion * of the result word into the result field of the corresponding - * Scsi_Cmnd structure, and removing it from the internal queues. + * scsi_cmnd structure, and removing it from the internal queues. * * Inputs : cmd - command, result - entire result field * @@ -1855,7 +1852,7 @@ run_process_issue_queue(void) { static void abnormal_finished (struct NCR53c7x0_cmd *cmd, int result) { - Scsi_Cmnd *c = cmd->cmd; + struct scsi_cmnd *c = cmd->cmd; struct Scsi_Host *host = c->device->host; struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) host->hostdata[0]; @@ -1869,7 +1866,7 @@ abnormal_finished (struct NCR53c7x0_cmd printk ("scsi%d: abnormal finished\n", host->host_no); #endif - local_irq_save(flags); + spin_lock_irqsave(host->host_lock, flags); found = 0; /* * Traverse the NCR issue array until we find a match or run out @@ -1952,7 +1949,7 @@ abnormal_finished (struct NCR53c7x0_cmd c->result = result; c->scsi_done(c); - local_irq_restore(flags); + spin_unlock_irqrestore(host->host_lock, flags); run_process_issue_queue(); } @@ -1974,7 +1971,7 @@ intr_break (struct Scsi_Host *host, stru NCR53c7x0_local_declare(); struct NCR53c7x0_break *bp; #if 0 - Scsi_Cmnd *c = cmd ? cmd->cmd : NULL; + struct scsi_cmnd *c = cmd ? cmd->cmd : NULL; #endif u32 *dsp; struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) @@ -1987,7 +1984,7 @@ intr_break (struct Scsi_Host *host, stru * dump the appropriate debugging information to standard * output. */ - local_irq_save(flags); + spin_lock_irqsave(host->host_lock, flags); dsp = (u32 *) bus_to_virt(NCR53c7x0_read32(DSP_REG)); for (bp = hostdata->breakpoints; bp && bp->address != dsp; bp = bp->next); @@ -2009,7 +2006,7 @@ intr_break (struct Scsi_Host *host, stru * instruction in bytes. */ - local_irq_restore(flags); + spin_unlock_irqrestore(host->host_lock, flags); } /* * Function : static void print_synchronous (const char *prefix, @@ -2251,7 +2248,7 @@ NCR53c7x0_dstat_sir_intr (struct Scsi_Ho NCR53c7x0_cmd *cmd) { NCR53c7x0_local_declare(); int print; - Scsi_Cmnd *c = cmd ? cmd->cmd : NULL; + struct scsi_cmnd *c = cmd ? cmd->cmd : NULL; struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) host->hostdata[0]; u32 dsps,*dsp; /* Argument of the INT instruction */ @@ -2915,7 +2912,7 @@ NCR53c7x0_soft_reset (struct Scsi_Host * host->hostdata[0]; NCR53c7x0_local_setup(host); - local_irq_save(flags); + spin_lock_irqsave(host->host_lock, flags); /* Disable scsi chip and s/w level 7 ints */ @@ -3016,12 +3013,12 @@ NCR53c7x0_soft_reset (struct Scsi_Host * } #endif /* Anything needed for your hardware? */ - local_irq_restore(flags); + spin_unlock_irqrestore(host->host_lock, flags); } /* - * Function static struct NCR53c7x0_cmd *allocate_cmd (Scsi_Cmnd *cmd) + * Function static struct NCR53c7x0_cmd *allocate_cmd (struct scsi_cmnd *cmd) * * Purpose : Return the first free NCR53c7x0_cmd structure (which are * reused in a LIFO manner to minimize cache thrashing). @@ -3048,86 +3045,25 @@ my_free_page (void *addr, int dummy) } static struct NCR53c7x0_cmd * -allocate_cmd (Scsi_Cmnd *cmd) { +allocate_cmd (struct scsi_cmnd *cmd) { struct Scsi_Host *host = cmd->device->host; struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) host->hostdata[0]; - u32 real; /* Real address */ - int size; /* Size of *tmp */ struct NCR53c7x0_cmd *tmp; unsigned long flags; if (hostdata->options & OPTION_DEBUG_ALLOCATION) printk ("scsi%d : num_cmds = %d, can_queue = %d\n" - " target = %d, lun = %d, %s\n", + " target = %d, lun = %d\n", host->host_no, hostdata->num_cmds, host->can_queue, - cmd->device->id, cmd->device->lun, (hostdata->cmd_allocated[cmd->device->id] & - (1 << cmd->device->lun)) ? "already allocated" : "not allocated"); - -/* - * If we have not yet reserved commands for this I_T_L nexus, and - * the device exists (as indicated by permanent Scsi_Cmnd structures - * being allocated under 1.3.x, or being outside of scan_scsis in - * 1.2.x), do so now. - */ - if (!(hostdata->cmd_allocated[cmd->device->id] & (1 << cmd->device->lun)) && - cmd->device && cmd->device->has_cmdblocks) { - if ((hostdata->extra_allocate + hostdata->num_cmds) < host->can_queue) - hostdata->extra_allocate += host->cmd_per_lun; - hostdata->cmd_allocated[cmd->device->id] |= (1 << cmd->device->lun); - } - - for (; hostdata->extra_allocate > 0 ; --hostdata->extra_allocate, - ++hostdata->num_cmds) { - /* historically, kmalloc has returned unaligned addresses; pad so we - have enough room to ROUNDUP */ - size = hostdata->max_cmd_size + sizeof (void *); -#ifdef FORCE_DSA_ALIGNMENT - /* - * 53c710 rev.0 doesn't have an add-with-carry instruction. - * Ensure we allocate enough memory to force alignment. - */ - size += 256; -#endif -/* FIXME: for ISA bus '7xx chips, we need to or GFP_DMA in here */ + cmd->device->id, cmd->device->lun); - if (size > 4096) { - printk (KERN_ERR "53c7xx: allocate_cmd size > 4K\n"); - return NULL; - } - real = get_zeroed_page(GFP_ATOMIC); - if (real == 0) - return NULL; - memset((void *)real, 0, 4096); - cache_push(virt_to_phys((void *)real), 4096); - cache_clear(virt_to_phys((void *)real), 4096); - kernel_set_cachemode((void *)real, 4096, IOMAP_NOCACHE_SER); - tmp = ROUNDUP(real, void *); -#ifdef FORCE_DSA_ALIGNMENT - { - if (((u32)tmp & 0xff) > CmdPageStart) - tmp = (struct NCR53c7x0_cmd *)((u32)tmp + 255); - tmp = (struct NCR53c7x0_cmd *)(((u32)tmp & ~0xff) + CmdPageStart); -#if 0 - printk ("scsi: size = %d, real = 0x%08x, tmp set to 0x%08x\n", - size, real, (u32)tmp); -#endif - } -#endif - tmp->real = (void *)real; - tmp->size = size; - tmp->free = ((void (*)(void *, int)) my_free_page); - local_irq_save(flags); - tmp->next = hostdata->free; - hostdata->free = tmp; - local_irq_restore(flags); - } - local_irq_save(flags); + spin_lock_irqsave(host->host_lock, flags); tmp = (struct NCR53c7x0_cmd *) hostdata->free; if (tmp) { hostdata->free = tmp->next; } - local_irq_restore(flags); + spin_unlock_irqrestore(host->host_lock, flags); if (!tmp) printk ("scsi%d : can't allocate command for target %d lun %d\n", host->host_no, cmd->device->id, cmd->device->lun); @@ -3135,11 +3071,11 @@ allocate_cmd (Scsi_Cmnd *cmd) { } /* - * Function static struct NCR53c7x0_cmd *create_cmd (Scsi_Cmnd *cmd) + * Function static struct NCR53c7x0_cmd *create_cmd (struct scsi_cmnd *cmd) * * * Purpose : allocate a NCR53c7x0_cmd structure, initialize it based on the - * Scsi_Cmnd structure passed in cmd, including dsa and Linux field + * scsi_cmnd structure passed in cmd, including dsa and Linux field * initialization, and dsa code relocation. * * Inputs : cmd - SCSI command @@ -3148,7 +3084,7 @@ allocate_cmd (Scsi_Cmnd *cmd) { * NULL on failure. */ static struct NCR53c7x0_cmd * -create_cmd (Scsi_Cmnd *cmd) { +create_cmd (struct scsi_cmnd *cmd) { NCR53c7x0_local_declare(); struct Scsi_Host *host = cmd->device->host; struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) @@ -3172,7 +3108,7 @@ create_cmd (Scsi_Cmnd *cmd) { return NULL; /* - * Copy CDB and initialised result fields from Scsi_Cmnd to NCR53c7x0_cmd. + * Copy CDB and initialised result fields from scsi_cmnd to NCR53c7x0_cmd. * We do this because NCR53c7x0_cmd may have a special cache mode * selected to cope with lack of bus snooping, etc. */ @@ -3315,7 +3251,7 @@ create_cmd (Scsi_Cmnd *cmd) { patch_dsa_32(tmp->dsa, dsa_next, 0, 0); /* - * XXX is this giving 53c710 access to the Scsi_Cmnd in some way? + * XXX is this giving 53c710 access to the scsi_cmnd in some way? * Do we need to change it for caching reasons? */ patch_dsa_32(tmp->dsa, dsa_cmnd, 0, virt_to_bus(cmd)); @@ -3346,17 +3282,17 @@ create_cmd (Scsi_Cmnd *cmd) { memcpy ((void *) (tmp->select + 1), (void *) wdtr_message, sizeof(wdtr_message)); patch_dsa_32(tmp->dsa, dsa_msgout, 0, 1 + sizeof(wdtr_message)); - local_irq_save(flags); + spin_lock_irqsave(host->host_lock, flags); hostdata->initiate_wdtr &= ~(1 << cmd->device->id); - local_irq_restore(flags); + spin_unlock_irqrestore(host->host_lock, flags); } else if (hostdata->initiate_sdtr & (1 << cmd->device->id)) { memcpy ((void *) (tmp->select + 1), (void *) sdtr_message, sizeof(sdtr_message)); patch_dsa_32(tmp->dsa, dsa_msgout, 0, 1 + sizeof(sdtr_message)); tmp->flags |= CMD_FLAG_SDTR; - local_irq_save(flags); + spin_lock_irqsave(host->host_lock, flags); hostdata->initiate_sdtr &= ~(1 << cmd->device->id); - local_irq_restore(flags); + spin_unlock_irqrestore(host->host_lock, flags); } #if 1 @@ -3569,8 +3505,8 @@ create_cmd (Scsi_Cmnd *cmd) { } /* - * Function : int NCR53c7xx_queue_command (Scsi_Cmnd *cmd, - * void (*done)(Scsi_Cmnd *)) + * Function : int NCR53c7xx_queue_command (struct scsi_cmnd *cmd, + * void (*done)(struct scsi_cmnd *)) * * Purpose : enqueues a SCSI command * @@ -3584,18 +3520,18 @@ create_cmd (Scsi_Cmnd *cmd) { * twiddling done to the host specific fields of cmd. If the * process_issue_queue coroutine isn't running, it is restarted. * - * NOTE : we use the host_scribble field of the Scsi_Cmnd structure to + * NOTE : we use the host_scribble field of the scsi_cmnd structure to * hold our own data, and pervert the ptr field of the SCp field * to create a linked list. */ int -NCR53c7xx_queue_command (Scsi_Cmnd *cmd, void (* done)(Scsi_Cmnd *)) { +NCR53c7xx_queue_command (struct scsi_cmnd *cmd, void (* done)(struct scsi_cmnd *)) { struct Scsi_Host *host = cmd->device->host; struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) host->hostdata[0]; unsigned long flags; - Scsi_Cmnd *tmp; + struct scsi_cmnd *tmp; cmd->scsi_done = done; cmd->host_scribble = NULL; @@ -3613,7 +3549,7 @@ NCR53c7xx_queue_command (Scsi_Cmnd *cmd, } #endif - local_irq_save(flags); + spin_lock_irqsave(host->host_lock, flags); if ((hostdata->options & (OPTION_DEBUG_INIT_ONLY|OPTION_DEBUG_PROBE_ONLY)) || ((hostdata->options & OPTION_DEBUG_TARGET_LIMIT) && !(hostdata->debug_lun_limit[cmd->device->id] & (1 << cmd->device->lun))) @@ -3628,7 +3564,7 @@ NCR53c7xx_queue_command (Scsi_Cmnd *cmd, cmd->device->id, cmd->device->lun); cmd->result = (DID_BAD_TARGET << 16); done(cmd); - local_irq_restore(flags); + spin_unlock_irqrestore(host->host_lock, flags); return 0; } @@ -3637,7 +3573,7 @@ NCR53c7xx_queue_command (Scsi_Cmnd *cmd, printk("scsi%d : maximum commands exceeded\n", host->host_no); cmd->result = (DID_BAD_TARGET << 16); done(cmd); - local_irq_restore(flags); + spin_unlock_irqrestore(host->host_lock, flags); return 0; } @@ -3649,7 +3585,7 @@ NCR53c7xx_queue_command (Scsi_Cmnd *cmd, host->host_no); cmd->result = (DID_BAD_TARGET << 16); done(cmd); - local_irq_restore(flags); + spin_unlock_irqrestore(host->host_lock, flags); return 0; } } @@ -3598,7 +3597,8 @@ NCR53c7xx_queue_command (struct scsi_cmn cmd->result = 0xffff; /* The NCR will overwrite message and status with valid data */ - cmd->host_scribble = (unsigned char *) tmp = create_cmd (cmd); + tmp = (struct scsi_cmnd *)create_cmd (cmd); + cmd->host_scribble = (unsigned char *)tmp; /* * REQUEST SENSE commands are inserted at the head of the queue @@ -3672,18 +3608,18 @@ NCR53c7xx_queue_command (Scsi_Cmnd *cmd, cmd->SCp.ptr = (unsigned char *) hostdata->issue_queue; hostdata->issue_queue = cmd; } else { - for (tmp = (Scsi_Cmnd *) hostdata->issue_queue; tmp->SCp.ptr; - tmp = (Scsi_Cmnd *) tmp->SCp.ptr); + for (tmp = (struct scsi_cmnd *) hostdata->issue_queue; tmp->SCp.ptr; + tmp = (struct scsi_cmnd *) tmp->SCp.ptr); tmp->SCp.ptr = (unsigned char *) cmd; } - local_irq_restore(flags); + spin_unlock_irqrestore(host->host_lock, flags); run_process_issue_queue(); return 0; } /* * Function : void to_schedule_list (struct Scsi_Host *host, - * struct NCR53c7x0_hostdata * hostdata, Scsi_Cmnd *cmd) + * struct NCR53c7x0_hostdata * hostdata, struct scsi_cmnd *cmd) * * Purpose : takes a SCSI command which was just removed from the * issue queue, and deals with it by inserting it in the first @@ -3704,7 +3640,7 @@ static __inline__ void to_schedule_list (struct Scsi_Host *host, struct NCR53c7x0_hostdata *hostdata, struct NCR53c7x0_cmd *cmd) { NCR53c7x0_local_declare(); - Scsi_Cmnd *tmp = cmd->cmd; + struct scsi_cmnd *tmp = cmd->cmd; unsigned long flags; /* dsa start is negative, so subtraction is used */ volatile u32 *ncrcurrent; @@ -3716,7 +3652,7 @@ to_schedule_list (struct Scsi_Host *host virt_to_bus(hostdata->dsa), hostdata->dsa); #endif - local_irq_save(flags); + spin_lock_irqsave(host->host_lock, flags); /* * Work around race condition : if an interrupt fired and we @@ -3729,7 +3665,7 @@ to_schedule_list (struct Scsi_Host *host cmd->next = (struct NCR53c7x0_cmd *) hostdata->free; hostdata->free = cmd; tmp->scsi_done(tmp); - local_irq_restore(flags); + spin_unlock_irqrestore(host->host_lock, flags); return; } @@ -3759,7 +3695,7 @@ to_schedule_list (struct Scsi_Host *host cmd->next = (struct NCR53c7x0_cmd *) hostdata->free; hostdata->free = cmd; tmp->scsi_done(tmp); - local_irq_restore(flags); + spin_unlock_irqrestore(host->host_lock, flags); return; } @@ -3780,12 +3716,12 @@ to_schedule_list (struct Scsi_Host *host NCR53c7x0_write8(hostdata->istat, ISTAT_10_SIGP); } - local_irq_restore(flags); + spin_unlock_irqrestore(host->host_lock, flags); } /* * Function : busyp (struct Scsi_Host *host, struct NCR53c7x0_hostdata - * *hostdata, Scsi_Cmnd *cmd) + * *hostdata, struct scsi_cmnd *cmd) * * Purpose : decide if we can pass the given SCSI command on to the * device in question or not. @@ -3795,7 +3731,7 @@ to_schedule_list (struct Scsi_Host *host static __inline__ int busyp (struct Scsi_Host *host, struct NCR53c7x0_hostdata *hostdata, - Scsi_Cmnd *cmd) { + struct scsi_cmnd *cmd) { /* FIXME : in the future, this needs to accommodate SCSI-II tagged queuing, and we may be able to play with fairness here a bit. */ @@ -3821,8 +3757,8 @@ busyp (struct Scsi_Host *host, struct NC static void process_issue_queue (unsigned long flags) { - Scsi_Cmnd *tmp, *prev; - struct Scsi_Host *host; + struct scsi_cmnd *tmp, *prev; + struct Scsi_Host *host, *s; struct NCR53c7x0_hostdata *hostdata; int done; @@ -3840,14 +3776,13 @@ process_issue_queue (unsigned long flags do { local_irq_disable(); /* Freeze request queues */ done = 1; - for (host = first_host; host && host->hostt == the_template; - host = host->next) { + list_for_each_entry_safe(host, s, &the_template->legacy_hosts, sht_legacy_list) { hostdata = (struct NCR53c7x0_hostdata *) host->hostdata[0]; - local_irq_disable(); + spin_lock_irq(host->host_lock); if (hostdata->issue_queue) { if (hostdata->state == STATE_DISABLED) { - tmp = (Scsi_Cmnd *) hostdata->issue_queue; - hostdata->issue_queue = (Scsi_Cmnd *) tmp->SCp.ptr; + tmp = (struct scsi_cmnd *) hostdata->issue_queue; + hostdata->issue_queue = (struct scsi_cmnd *) tmp->SCp.ptr; tmp->result = (DID_BAD_TARGET << 16); if (tmp->host_scribble) { ((struct NCR53c7x0_cmd *)tmp->host_scribble)->next = @@ -3859,15 +3794,15 @@ process_issue_queue (unsigned long flags tmp->scsi_done (tmp); done = 0; } else - for (tmp = (Scsi_Cmnd *) hostdata->issue_queue, - prev = NULL; tmp; prev = tmp, tmp = (Scsi_Cmnd *) + for (tmp = (struct scsi_cmnd *) hostdata->issue_queue, + prev = NULL; tmp; prev = tmp, tmp = (struct scsi_cmnd *) tmp->SCp.ptr) if (!tmp->host_scribble || !busyp (host, hostdata, tmp)) { if (prev) prev->SCp.ptr = tmp->SCp.ptr; else - hostdata->issue_queue = (Scsi_Cmnd *) + hostdata->issue_queue = (struct scsi_cmnd *) tmp->SCp.ptr; tmp->SCp.ptr = NULL; if (tmp->host_scribble) { @@ -3892,6 +3827,7 @@ process_issue_queue (unsigned long flags done = 0; } /* if target/lun is not busy */ } /* if hostdata->issue_queue */ + spin_unlock(host->host_lock); if (!done) local_irq_restore(flags); } /* for host */ @@ -4102,7 +4038,7 @@ void dump_log(void) int cnt = 0; int i = insn_log_index; int size; - struct Scsi_Host *host = first_host; + struct Scsi_Host *host = (struct Scsi_Host *)the_template->legacy_hosts->next; while (cnt < 4096) { printk ("%08x (+%6x): ", insn_log[i], (insn_log[i] - (u32)&(((struct NCR53c7x0_hostdata *)host->hostdata[0])->script))/4); @@ -4160,14 +4096,14 @@ NCR53c7x0_intfly (struct Scsi_Host *host * completion. */ - local_irq_save(flags); + spin_lock_irqsave(host->host_lock, flags); restart: for (cmd_prev_ptr = (struct NCR53c7x0_cmd **)&(hostdata->running_list), cmd = (struct NCR53c7x0_cmd *) hostdata->running_list; cmd ; cmd_prev_ptr = (struct NCR53c7x0_cmd **) &(cmd->next), cmd = (struct NCR53c7x0_cmd *) cmd->next) { - Scsi_Cmnd *tmp; + struct scsi_cmnd *tmp; if (!cmd) { printk("scsi%d : very weird.\n", host->host_no); @@ -4175,7 +4111,7 @@ restart: } if (!(tmp = cmd->cmd)) { - printk("scsi%d : weird. NCR53c7x0_cmd has no Scsi_Cmnd\n", + printk("scsi%d : weird. NCR53c7x0_cmd has no scsi_cmnd\n", host->host_no); continue; } @@ -4214,7 +4150,7 @@ restart: tmp->scsi_done(tmp); goto restart; } - local_irq_restore(flags); + spin_unlock_irqrestore(host->host_lock, flags); if (!search_found) { printk ("scsi%d : WARNING : INTFLY with no completed commands.\n", @@ -4249,7 +4185,7 @@ NCR53c7x0_intr (int irq, void *dev_id, s struct NCR53c7x0_cmd *cmd; /* command which halted */ u32 *dsa; /* DSA */ int handled = 0; - + unsigned long flags; #ifdef NCR_DEBUG char buf[80]; /* Debugging sprintf buffer */ size_t buflen; /* Length of same */ @@ -4258,6 +4194,7 @@ NCR53c7x0_intr (int irq, void *dev_id, s host = (struct Scsi_Host *)dev_id; hostdata = (struct NCR53c7x0_hostdata *) host->hostdata[0]; NCR53c7x0_local_setup(host); + spin_lock_irqsave(host->host_lock, flags); /* * Only read istat once per loop, since reading it again will unstack @@ -4350,7 +4287,8 @@ NCR53c7x0_intr (int irq, void *dev_id, s } } } - return IRQ_HANDLED; + spin_unlock_irqrestore(host->host_lock, flags); + return IRQ_RETVAL(handled); } @@ -4359,7 +4297,7 @@ NCR53c7x0_intr (int irq, void *dev_id, s * * Purpose : Assuming that the NCR SCSI processor is currently * halted, break the currently established nexus. Clean - * up of the NCR53c7x0_cmd and Scsi_Cmnd structures should + * up of the NCR53c7x0_cmd and scsi_cmnd structures should * be done on receipt of the abort interrupt. * * Inputs : host - SCSI host @@ -4898,12 +4836,12 @@ intr_dma (struct Scsi_Host *host, struct /* Don't print instr. until we write DSP at end of intr function */ } else if (hostdata->options & OPTION_DEBUG_SINGLE) { print_insn (host, dsp, "s ", 0); - local_irq_save(flags); + spin_lock_irqsave(host->host_lock, flags); /* XXX - should we do this, or can we get away with writing dsp? */ NCR53c7x0_write8 (DCNTL_REG, (NCR53c7x0_read8(DCNTL_REG) & ~DCNTL_SSM) | DCNTL_STD); - local_irq_restore(flags); + spin_unlock_irqrestore(host->host_lock, flags); } else { printk(KERN_ALERT "scsi%d : unexpected single step interrupt at\n" " ", host->host_no); @@ -5126,7 +5064,7 @@ print_insn (struct Scsi_Host *host, cons } /* - * Function : int NCR53c7xx_abort (Scsi_Cmnd *cmd) + * Function : int NCR53c7xx_abort (struct scsi_cmnd *cmd) * * Purpose : Abort an errant SCSI command, doing all necessary * cleanup of the issue_queue, running_list, shared Linux/NCR @@ -5138,14 +5076,14 @@ print_insn (struct Scsi_Host *host, cons */ int -NCR53c7xx_abort (Scsi_Cmnd *cmd) { +NCR53c7xx_abort (struct scsi_cmnd *cmd) { NCR53c7x0_local_declare(); struct Scsi_Host *host = cmd->device->host; struct NCR53c7x0_hostdata *hostdata = host ? (struct NCR53c7x0_hostdata *) host->hostdata[0] : NULL; unsigned long flags; struct NCR53c7x0_cmd *curr, **prev; - Scsi_Cmnd *me, **last; + struct scsi_cmnd *me, **last; #if 0 static long cache_pid = -1; #endif @@ -5154,10 +5092,10 @@ NCR53c7xx_abort (Scsi_Cmnd *cmd) { if (!host) { printk ("Bogus SCSI command pid %ld; no host structure\n", cmd->pid); - return SCSI_ABORT_ERROR; + return FAILED; } else if (!hostdata) { printk ("Bogus SCSI host %d; no hostdata\n", host->host_no); - return SCSI_ABORT_ERROR; + return FAILED; } NCR53c7x0_local_setup(host); @@ -5178,11 +5117,11 @@ NCR53c7xx_abort (Scsi_Cmnd *cmd) { if (NCR53c7x0_read8(hostdata->istat) & (ISTAT_DIP|ISTAT_SIP)) { printk ("scsi%d : dropped interrupt for command %ld\n", host->host_no, cmd->pid); - NCR53c7x0_intr (host->irq, NULL, NULL); - return SCSI_ABORT_BUSY; + NCR53c7x0_intr (host->irq, NULL); + return FAILED; } - local_irq_save(flags); + spin_lock_irqsave(host->host_lock, flags); #if 0 if (cache_pid == cmd->pid) panic ("scsi%d : bloody fetus %d\n", host->host_no, cmd->pid); @@ -5200,13 +5138,13 @@ NCR53c7xx_abort (Scsi_Cmnd *cmd) { * pull the command out of the old queue, and call it aborted. */ - for (me = (Scsi_Cmnd *) hostdata->issue_queue, - last = (Scsi_Cmnd **) &(hostdata->issue_queue); - me && me != cmd; last = (Scsi_Cmnd **)&(me->SCp.ptr), - me = (Scsi_Cmnd *)me->SCp.ptr); + for (me = (struct scsi_cmnd *) hostdata->issue_queue, + last = (struct scsi_cmnd **) &(hostdata->issue_queue); + me && me != cmd; last = (struct scsi_cmnd **)&(me->SCp.ptr), + me = (struct scsi_cmnd *)me->SCp.ptr); if (me) { - *last = (Scsi_Cmnd *) me->SCp.ptr; + *last = (struct scsi_cmnd *) me->SCp.ptr; if (me->host_scribble) { ((struct NCR53c7x0_cmd *)me->host_scribble)->next = hostdata->free; hostdata->free = (struct NCR53c7x0_cmd *) me->host_scribble; @@ -5216,9 +5154,9 @@ NCR53c7xx_abort (Scsi_Cmnd *cmd) { cmd->scsi_done(cmd); printk ("scsi%d : found command %ld in Linux issue queue\n", host->host_no, me->pid); - local_irq_restore(flags); + spin_unlock_irqrestore(host->host_lock, flags); run_process_issue_queue(); - return SCSI_ABORT_SUCCESS; + return SUCCESS; } /* @@ -5242,13 +5180,13 @@ NCR53c7xx_abort (Scsi_Cmnd *cmd) { cmd->scsi_done(cmd); printk ("scsi%d : found finished command %ld in running list\n", host->host_no, cmd->pid); - local_irq_restore(flags); - return SCSI_ABORT_NOT_RUNNING; + spin_unlock_irqrestore(host->host_lock, flags); + return SUCCESS; } else { printk ("scsi%d : DANGER : command running, can not abort.\n", cmd->device->host->host_no); - local_irq_restore(flags); - return SCSI_ABORT_BUSY; + spin_unlock_irqrestore(host->host_lock, flags); + return FAILED; } } @@ -5279,21 +5217,20 @@ NCR53c7xx_abort (Scsi_Cmnd *cmd) { */ --hostdata->busy[cmd->device->id][cmd->device->lun]; } - local_irq_restore(flags); + spin_unlock_irqrestore(host->host_lock, flags); cmd->scsi_done(cmd); /* * We need to run process_issue_queue since termination of this command * may allow another queued command to execute first? */ - return SCSI_ABORT_NOT_RUNNING; + return SUCCESS; } /* - * Function : int NCR53c7xx_reset (Scsi_Cmnd *cmd) + * Function : int NCR53c7xx_reset (struct scsi_cmnd *cmd) * - * Purpose : perform a hard reset of the SCSI bus and NCR - * chip. + * Purpose : perform a hard reset of the SCSI bus. * * Inputs : cmd - command which caused the SCSI RESET * @@ -5301,12 +5238,12 @@ NCR53c7xx_abort (Scsi_Cmnd *cmd) { */ int -NCR53c7xx_reset (Scsi_Cmnd *cmd, unsigned int reset_flags) { +NCR53c7xx_reset (struct scsi_cmnd *cmd) { NCR53c7x0_local_declare(); unsigned long flags; int found = 0; struct NCR53c7x0_cmd * c; - Scsi_Cmnd *tmp; + struct scsi_cmnd *tmp; /* * When we call scsi_done(), it's going to wake up anything sleeping on the * resources which were in use by the aborted commands, and we'll start to @@ -5321,19 +5258,19 @@ NCR53c7xx_reset (Scsi_Cmnd *cmd, unsigne * pointer), do our reinitialization, and then call the done function for * each command. */ - Scsi_Cmnd *nuke_list = NULL; + struct scsi_cmnd *nuke_list = NULL; struct Scsi_Host *host = cmd->device->host; struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) host->hostdata[0]; NCR53c7x0_local_setup(host); - local_irq_save(flags); + spin_lock_irqsave(host->host_lock, flags); ncr_halt (host); print_lots (host); dump_events (host, 30); ncr_scsi_reset (host); for (tmp = nuke_list = return_outstanding_commands (host, 1 /* free */, - 0 /* issue */ ); tmp; tmp = (Scsi_Cmnd *) tmp->SCp.buffer) + 0 /* issue */ ); tmp; tmp = (struct scsi_cmnd *) tmp->SCp.buffer) if (tmp == cmd) { found = 1; break; @@ -5356,19 +5293,21 @@ NCR53c7xx_reset (Scsi_Cmnd *cmd, unsigne } NCR53c7x0_driver_init (host); +#if 0 hostdata->soft_reset (host); +#endif if (hostdata->resets == 0) disable(host); else if (hostdata->resets != -1) --hostdata->resets; - local_irq_restore(flags); + spin_unlock_irqrestore(host->host_lock, flags); for (; nuke_list; nuke_list = tmp) { - tmp = (Scsi_Cmnd *) nuke_list->SCp.buffer; + tmp = (struct scsi_cmnd *) nuke_list->SCp.buffer; nuke_list->result = DID_RESET << 16; nuke_list->scsi_done (nuke_list); } - local_irq_restore(flags); - return SCSI_RESET_SUCCESS; + spin_unlock_irqrestore(host->host_lock, flags); + return SUCCESS; } /* @@ -5377,7 +5316,7 @@ NCR53c7xx_reset (Scsi_Cmnd *cmd, unsigne */ /* - * Function : int insn_to_offset (Scsi_Cmnd *cmd, u32 *insn) + * Function : int insn_to_offset (struct scsi_cmnd *cmd, u32 *insn) * * Purpose : convert instructions stored at NCR pointer into data * pointer offset. @@ -5390,7 +5329,7 @@ NCR53c7xx_reset (Scsi_Cmnd *cmd, unsigne static int -insn_to_offset (Scsi_Cmnd *cmd, u32 *insn) { +insn_to_offset (struct scsi_cmnd *cmd, u32 *insn) { struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) cmd->device->host->hostdata[0]; struct NCR53c7x0_cmd *ncmd = @@ -5444,7 +5383,7 @@ insn_to_offset (Scsi_Cmnd *cmd, u32 *ins /* - * Function : void print_progress (Scsi_Cmnd *cmd) + * Function : void print_progress (struct scsi_cmnd *cmd) * * Purpose : print the current location of the saved data pointer * @@ -5453,7 +5392,7 @@ insn_to_offset (Scsi_Cmnd *cmd, u32 *ins */ static void -print_progress (Scsi_Cmnd *cmd) { +print_progress (struct scsi_cmnd *cmd) { NCR53c7x0_local_declare(); struct NCR53c7x0_cmd *ncmd = (struct NCR53c7x0_cmd *) cmd->host_scribble; @@ -5511,7 +5450,7 @@ print_dsa (struct Scsi_Host *host, u32 * host->hostdata[0]; int i, len; char *ptr; - Scsi_Cmnd *cmd; + struct scsi_cmnd *cmd; if (check_address ((unsigned long) dsa, hostdata->dsa_end - hostdata->dsa_start) == -1) { @@ -5547,7 +5486,7 @@ print_dsa (struct Scsi_Host *host, u32 * printk(" + %d : select_indirect = 0x%x\n", hostdata->dsa_select, dsa[hostdata->dsa_select / sizeof(u32)]); - cmd = (Scsi_Cmnd *) bus_to_virt(dsa[hostdata->dsa_cmnd / sizeof(u32)]); + cmd = (struct scsi_cmnd *) bus_to_virt(dsa[hostdata->dsa_cmnd / sizeof(u32)]); printk(" + %d : dsa_cmnd = 0x%x ", hostdata->dsa_cmnd, (u32) virt_to_bus(cmd)); /* XXX Maybe we should access cmd->host_scribble->result here. RGH */ @@ -5587,16 +5526,16 @@ print_queues (struct Scsi_Host *host) { u32 *dsa, *next_dsa; volatile u32 *ncrcurrent; int left; - Scsi_Cmnd *cmd, *next_cmd; + struct scsi_cmnd *cmd, *next_cmd; unsigned long flags; printk ("scsi%d : issue queue\n", host->host_no); - for (left = host->can_queue, cmd = (Scsi_Cmnd *) hostdata->issue_queue; + for (left = host->can_queue, cmd = (struct scsi_cmnd *) hostdata->issue_queue; left >= 0 && cmd; cmd = next_cmd) { - next_cmd = (Scsi_Cmnd *) cmd->SCp.ptr; - local_irq_save(flags); + next_cmd = (struct scsi_cmnd *) cmd->SCp.ptr; + spin_lock_irqsave(host->host_lock, flags); if (cmd->host_scribble) { if (check_address ((unsigned long) (cmd->host_scribble), sizeof (cmd->host_scribble)) == -1) @@ -5609,7 +5548,7 @@ print_queues (struct Scsi_Host *host) { } else printk ("scsi%d : scsi pid %ld for target %d lun %d has no NCR53c7x0_cmd\n", host->host_no, cmd->pid, cmd->device->id, cmd->device->lun); - local_irq_restore(flags); + spin_unlock_irqrestore(host->host_lock, flags); } if (left <= 0) { @@ -5641,7 +5580,7 @@ print_queues (struct Scsi_Host *host) { dsa = bus_to_virt (hostdata->reconnect_dsa_head); left >= 0 && dsa; dsa = next_dsa) { - local_irq_save(flags); + spin_lock_irqsave(host->host_lock, flags); if (check_address ((unsigned long) dsa, sizeof(dsa)) == -1) { printk ("scsi%d: bad DSA pointer 0x%p", host->host_no, dsa); @@ -5652,7 +5591,7 @@ print_queues (struct Scsi_Host *host) { next_dsa = bus_to_virt(dsa[hostdata->dsa_next / sizeof(u32)]); print_dsa (host, dsa, ""); } - local_irq_restore(flags); + spin_unlock_irqrestore(host->host_lock, flags); } printk ("scsi%d : end reconnect_dsa_head\n", host->host_no); if (left < 0) @@ -5742,14 +5681,14 @@ shutdown (struct Scsi_Host *host) { struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) host->hostdata[0]; NCR53c7x0_local_setup(host); - local_irq_save(flags); + spin_lock_irqsave(host->host_lock, flags); /* Get in a state where we can reset the SCSI bus */ ncr_halt (host); ncr_scsi_reset (host); hostdata->soft_reset(host); disable (host); - local_irq_restore(flags); + spin_unlock_irqrestore(host->host_lock, flags); return 0; } @@ -5764,11 +5703,11 @@ ncr_scsi_reset (struct Scsi_Host *host) NCR53c7x0_local_declare(); unsigned long flags; NCR53c7x0_local_setup(host); - local_irq_save(flags); + spin_lock_irqsave(host->host_lock, flags); NCR53c7x0_write8(SCNTL1_REG, SCNTL1_RST); udelay(25); /* Minimum amount of time to assert RST */ NCR53c7x0_write8(SCNTL1_REG, 0); - local_irq_restore(flags); + spin_unlock_irqrestore(host->host_lock, flags); } /* @@ -5781,26 +5720,26 @@ hard_reset (struct Scsi_Host *host) { struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) host->hostdata[0]; unsigned long flags; - local_irq_save(flags); + spin_lock_irqsave(host->host_lock, flags); ncr_scsi_reset(host); NCR53c7x0_driver_init (host); if (hostdata->soft_reset) hostdata->soft_reset (host); - local_irq_restore(flags); + spin_unlock_irqrestore(host->host_lock, flags); } /* - * Function : Scsi_Cmnd *return_outstanding_commands (struct Scsi_Host *host, + * Function : struct scsi_cmnd *return_outstanding_commands (struct Scsi_Host *host, * int free, int issue) * * Purpose : return a linked list (using the SCp.buffer field as next, * so we don't perturb hostdata. We don't use a field of the * NCR53c7x0_cmd structure since we may not have allocated one - * for the command causing the reset.) of Scsi_Cmnd structures that + * for the command causing the reset.) of scsi_cmnd structures that * had propagated below the Linux issue queue level. If free is set, * free the NCR53c7x0_cmd structures which are associated with - * the Scsi_Cmnd structures, and clean up any internal + * the scsi_cmnd structures, and clean up any internal * NCR lists that the commands were on. If issue is set, * also return commands in the issue queue. * @@ -5810,14 +5749,14 @@ hard_reset (struct Scsi_Host *host) { * if the free flag is set. */ -static Scsi_Cmnd * +static struct scsi_cmnd * return_outstanding_commands (struct Scsi_Host *host, int free, int issue) { struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) host->hostdata[0]; struct NCR53c7x0_cmd *c; int i; u32 *ncrcurrent; - Scsi_Cmnd *list = NULL, *tmp; + struct scsi_cmnd *list = NULL, *tmp, *next_cmd; for (c = (struct NCR53c7x0_cmd *) hostdata->running_list; c; c = (struct NCR53c7x0_cmd *) c->next) { if (c->cmd->SCp.buffer) { @@ -5846,7 +5785,9 @@ return_outstanding_commands (struct Scsi } if (issue) { - for (tmp = (Scsi_Cmnd *) hostdata->issue_queue; tmp; tmp = tmp->next) { + for (tmp = (struct scsi_cmnd *) hostdata->issue_queue; tmp; tmp = next_cmd) { + next_cmd = (struct scsi_cmnd *) tmp->SCp.ptr; + if (tmp->SCp.buffer) { printk ("scsi%d : loop detected in issue queue!\n", host->host_no); @@ -5881,17 +5822,17 @@ disable (struct Scsi_Host *host) { struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) host->hostdata[0]; unsigned long flags; - Scsi_Cmnd *nuke_list, *tmp; - local_irq_save(flags); + struct scsi_cmnd *nuke_list, *tmp; + spin_lock_irqsave(host->host_lock, flags); if (hostdata->state != STATE_HALTED) ncr_halt (host); nuke_list = return_outstanding_commands (host, 1 /* free */, 1 /* issue */); hard_reset (host); hostdata->state = STATE_DISABLED; - local_irq_restore(flags); + spin_unlock_irqrestore(host->host_lock, flags); printk ("scsi%d : nuking commands\n", host->host_no); for (; nuke_list; nuke_list = tmp) { - tmp = (Scsi_Cmnd *) nuke_list->SCp.buffer; + tmp = (struct scsi_cmnd *) nuke_list->SCp.buffer; nuke_list->result = DID_ERROR << 16; nuke_list->scsi_done(nuke_list); } @@ -5921,7 +5862,7 @@ ncr_halt (struct Scsi_Host *host) { int stage; NCR53c7x0_local_setup(host); - local_irq_save(flags); + spin_lock_irqsave(host->host_lock, flags); /* Stage 0 : eat all interrupts Stage 1 : set ABORT Stage 2 : eat all but abort interrupts @@ -5956,7 +5897,7 @@ ncr_halt (struct Scsi_Host *host) { } } hostdata->state = STATE_HALTED; - local_irq_restore(flags); + spin_unlock_irqrestore(host->host_lock, flags); #if 0 print_lots (host); #endif @@ -6010,7 +5951,7 @@ dump_events (struct Scsi_Host *host, int * still be guaranteed that they're happening on the same * event structure. */ - local_irq_save(flags); + spin_lock_irqsave(host->host_lock, flags); #if 0 event = hostdata->events[i]; #else @@ -6018,7 +5959,7 @@ dump_events (struct Scsi_Host *host, int sizeof(event)); #endif - local_irq_restore(flags); + spin_unlock_irqrestore(host->host_lock, flags); printk ("scsi%d : %s event %d at %ld secs %ld usecs target %d lun %d\n", host->host_no, event_name (event.event), count, (long) event.time.tv_sec, (long) event.time.tv_usec, @@ -6053,6 +5994,72 @@ check_address (unsigned long addr, int s return (virt_to_phys((void *)addr) < PAGE_SIZE || virt_to_phys((void *)(addr + size)) > virt_to_phys(high_memory) ? -1 : 0); } +int +NCR53c7xx_slave_configure(struct scsi_device *sdev) { + struct Scsi_Host *host = sdev->host; + struct NCR53c7x0_hostdata *hostdata = + (struct NCR53c7x0_hostdata *) host->hostdata[0]; + struct NCR53c7x0_cmd *tmp; + u32 real; /* Real address */ + int size; /* Size of *tmp */ + unsigned long flags; + int extra_allocate = 0; + +/* + * Reserve commands for this I_T_L nexus. + */ + if (hostdata->num_cmds < host->can_queue) + extra_allocate = host->cmd_per_lun; + + for (; extra_allocate > 0 ; --extra_allocate, + ++hostdata->num_cmds) { + /* historically, kmalloc has returned unaligned addresses; pad so we + have enough room to ROUNDUP */ + size = hostdata->max_cmd_size + sizeof (void *); +#ifdef FORCE_DSA_ALIGNMENT + /* + * 53c710 rev.0 doesn't have an add-with-carry instruction. + * Ensure we allocate enough memory to force alignment. + */ + size += 256; +#endif +/* FIXME: for ISA bus '7xx chips, we need to or GFP_DMA in here */ + + if (size > 4096) { + printk (KERN_ERR "53c7xx: slave_configure size > 4K\n"); + return -ENOMEM; + } + real = get_zeroed_page(GFP_ATOMIC); + if (real == 0) + return -ENOMEM; + memset((void *)real, 0, 4096); + cache_push(virt_to_phys((void *)real), 4096); + cache_clear(virt_to_phys((void *)real), 4096); + kernel_set_cachemode((void *)real, 4096, IOMAP_NOCACHE_SER); + tmp = ROUNDUP(real, void *); +#ifdef FORCE_DSA_ALIGNMENT + { + if (((u32)tmp & 0xff) > CmdPageStart) + tmp = (struct NCR53c7x0_cmd *)((u32)tmp + 255); + tmp = (struct NCR53c7x0_cmd *)(((u32)tmp & ~0xff) + CmdPageStart); +#if 0 + printk ("scsi: size = %d, real = 0x%08x, tmp set to 0x%08x\n", + size, real, (u32)tmp); +#endif + } +#endif + tmp->real = (void *)real; + tmp->size = size; + tmp->free = ((void (*)(void *, int)) my_free_page); + spin_lock_irqsave(host->host_lock, flags); + tmp->next = hostdata->free; + hostdata->free = tmp; + spin_unlock_irqrestore(host->host_lock, flags); + } + + return 0; +} + #ifdef MODULE int NCR53c7x0_release(struct Scsi_Host *host) { @@ -6062,19 +6069,22 @@ NCR53c7x0_release(struct Scsi_Host *host shutdown (host); if (host->irq != SCSI_IRQ_NONE) { - int irq_count; - struct Scsi_Host *tmp; - for (irq_count = 0, tmp = first_host; tmp; tmp = tmp->next) - if (tmp->hostt == the_template && tmp->irq == host->irq) + int irq_count = 0; + struct Scsi_Host *tmp, *s; + list_for_each_entry_safe(tmp, s, &the_template->legacy_hosts, sht_legacy_list) { + if (tmp->irq == host->irq) ++irq_count; + } if (irq_count == 1) free_irq(host->irq, NULL); } +#ifdef CONFIG_ISA if (host->dma_channel != DMA_NONE) free_dma(host->dma_channel); +#endif if (host->io_port) release_region(host->io_port, host->n_io_port); - + for (cmd = (struct NCR53c7x0_cmd *) hostdata->free; cmd; cmd = tmp, --hostdata->num_cmds) { tmp = (struct NCR53c7x0_cmd *) cmd->next; --- linux-2.6.10-rc1/drivers/scsi/53c7xx.h 2004-04-28 15:47:29.000000000 +0200 +++ linux-m68k-2.6.10-rc1/drivers/scsi/53c7xx.h 2004-10-30 13:55:34.000000000 +0200 @@ -997,7 +997,7 @@ struct NCR53c7x0_event { u32 *dsa; /* What's in the DSA register now (virt) */ /* * A few things from that SCSI pid so we know what happened after - * the Scsi_Cmnd structure in question may have disappeared. + * the scsi_cmnd structure in question may have disappeared. */ unsigned long pid; /* The SCSI PID which caused this event */ @@ -1029,8 +1029,8 @@ struct NCR53c7x0_cmd { void (* free)(void *, int); /* Command to deallocate; NULL for structures allocated with scsi_register, etc. */ - Scsi_Cmnd *cmd; /* Associated Scsi_Cmnd - structure, Scsi_Cmnd points + struct scsi_cmnd *cmd; /* Associated scsi_cmnd + structure, scsi_cmnd points at NCR53c7x0_cmd using host_scribble structure */ @@ -1039,8 +1039,8 @@ struct NCR53c7x0_cmd { int flags; /* CMD_* flags */ - unsigned char cmnd[12]; /* CDB, copied from Scsi_Cmnd */ - int result; /* Copy to Scsi_Cmnd when done */ + unsigned char cmnd[12]; /* CDB, copied from scsi_cmnd */ + int result; /* Copy to scsi_cmnd when done */ struct { /* Private non-cached bounce buffer */ unsigned char buf[256]; @@ -1339,7 +1339,7 @@ struct NCR53c7x0_hostdata { volatile struct NCR53c7x0_synchronous sync[16] __attribute__ ((aligned (4))); - volatile Scsi_Cmnd *issue_queue + volatile struct scsi_cmnd *issue_queue __attribute__ ((aligned (4))); /* waiting to be issued by Linux driver */ @@ -1363,10 +1363,6 @@ struct NCR53c7x0_hostdata { */ volatile int num_cmds; /* Number of commands allocated */ - volatile int extra_allocate; - volatile unsigned char cmd_allocated[16]; /* Have we allocated commands - for this target yet? If not, - do so ASAP */ volatile unsigned char busy[16][8]; /* number of commands executing on each target */ @@ -1589,11 +1585,11 @@ struct NCR53c7x0_hostdata { /* Patch field in dsa structure (assignment should be +=?) */ #define patch_dsa_32(dsa, symbol, word, value) \ { \ - (dsa)[(hostdata->##symbol - hostdata->dsa_start) / sizeof(u32) \ + (dsa)[(hostdata->symbol - hostdata->dsa_start) / sizeof(u32) \ + (word)] = (value); \ if (hostdata->options & OPTION_DEBUG_DSA) \ printk("scsi : dsa %s symbol %s(%d) word %d now 0x%x\n", \ - #dsa, #symbol, hostdata->##symbol, \ + #dsa, #symbol, hostdata->symbol, \ (word), (u32) (value)); \ } @@ -1603,6 +1599,12 @@ struct NCR53c7x0_hostdata { extern int ncr53c7xx_init(struct scsi_host_template *tpnt, int board, int chip, unsigned long base, int io_port, int irq, int dma, long long options, int clock); +extern const char *NCR53c7x0_info(void); +extern int NCR53c7xx_queue_command(struct scsi_cmnd *, void (*done)(struct scsi_cmnd *)); +extern int NCR53c7xx_abort(struct scsi_cmnd *); +extern int NCR53c7x0_release (struct Scsi_Host *); +extern int NCR53c7xx_reset(struct scsi_cmnd *); +extern int NCR53c7xx_slave_configure(struct scsi_device *); #endif /* NCR53c710_C */ #endif /* NCR53c710_H */ --- linux-2.6.10-rc1/drivers/scsi/Kconfig 2004-09-13 21:57:48.000000000 +0200 +++ linux-m68k-2.6.10-rc1/drivers/scsi/Kconfig 2004-10-30 13:57:46.000000000 +0200 @@ -1588,7 +1589,8 @@ config FASTLANE_SCSI config SCSI_AMIGA7XX bool "Amiga NCR53c710 SCSI support (EXPERIMENTAL)" - depends on AMIGA && SCSI && EXPERIMENTAL && BROKEN + depends on AMIGA && SCSI && EXPERIMENTAL + select SCSI_SPI_ATTRS help Support for various NCR53c710-based SCSI controllers on the Amiga. This includes: @@ -1685,7 +1686,7 @@ config MVME147_SCSI config MVME16x_SCSI bool "NCR53C710 SCSI driver for MVME16x" - depends on MVME16x && SCSI && BROKEN + depends on MVME16x && SCSI select SCSI_SPI_ATTRS help The Motorola MVME162, 166, 167, 172 and 177 boards use the NCR53C710 @@ -1693,7 +1694,7 @@ config MVME16x_SCSI config BVME6000_SCSI bool "NCR53C710 SCSI driver for BVME6000" - depends on BVME6000 && SCSI && BROKEN + depends on BVME6000 && SCSI select SCSI_SPI_ATTRS help The BVME4000 and BVME6000 boards from BVM Ltd use the NCR53C710 --- linux-2.6.10-rc1/drivers/scsi/amiga7xx.c 2004-07-12 09:48:11.000000000 +0200 +++ linux-m68k-2.6.10-rc1/drivers/scsi/amiga7xx.c 2004-10-30 13:55:34.000000000 +0200 @@ -27,8 +27,14 @@ #include "scsi.h" #include #include "53c7xx.h" -#include "amiga7xx.h" +#ifndef CMD_PER_LUN +#define CMD_PER_LUN 3 +#endif + +#ifndef CAN_QUEUE +#define CAN_QUEUE 24 +#endif static int amiga7xx_register_one(Scsi_Host_Template *tpnt, unsigned long address) @@ -115,8 +121,10 @@ static int amiga7xx_release(struct Scsi_ { if (shost->irq) free_irq(shost->irq, NULL); +#ifdef CONFIG_ISA if (shost->dma_channel != 0xff) free_dma(shost->dma_channel); +#endif if (shost->io_port && shost->n_io_port) release_region(shost->io_port, shost->n_io_port); scsi_unregister(shost); @@ -128,8 +136,9 @@ static Scsi_Host_Template driver_templat .detect = amiga7xx_detect, .release = amiga7xx_release, .queuecommand = NCR53c7xx_queue_command, - .abort = NCR53c7xx_abort, - .reset = NCR53c7xx_reset, + .eh_abort_handler = NCR53c7xx_abort, + .eh_bus_reset_handler = NCR53c7xx_reset, + .slave_configure = NCR53c7xx_slave_configure, .can_queue = 24, .this_id = 7, .sg_tablesize = 63, --- linux-2.6.10-rc1/drivers/scsi/amiga7xx.h 2004-04-28 11:02:40.000000000 +0200 +++ linux-m68k-2.6.10-rc1/drivers/scsi/amiga7xx.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,23 +0,0 @@ -#ifndef AMIGA7XX_H - -#include - -int amiga7xx_detect(struct scsi_host_template *); -const char *NCR53c7x0_info(void); -int NCR53c7xx_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); -int NCR53c7xx_abort(Scsi_Cmnd *); -int NCR53c7x0_release (struct Scsi_Host *); -int NCR53c7xx_reset(Scsi_Cmnd *, unsigned int); -void NCR53c7x0_intr(int irq, void *dev_id); - -#ifndef CMD_PER_LUN -#define CMD_PER_LUN 3 -#endif - -#ifndef CAN_QUEUE -#define CAN_QUEUE 24 -#endif - -#include - -#endif /* AMIGA7XX_H */ --- linux-2.6.10-rc1/drivers/scsi/bvme6000.c 2004-07-12 09:48:11.000000000 +0200 +++ linux-m68k-2.6.10-rc1/drivers/scsi/bvme6000.c 2004-10-30 13:55:35.000000000 +0200 @@ -19,10 +19,16 @@ #include "scsi.h" #include #include "53c7xx.h" -#include "bvme6000.h" #include +#ifndef CMD_PER_LUN +#define CMD_PER_LUN 3 +#endif + +#ifndef CAN_QUEUE +#define CAN_QUEUE 24 +#endif int bvme6000_scsi_detect(Scsi_Host_Template *tpnt) { @@ -52,8 +58,10 @@ static int bvme6000_scsi_release(struct { if (shost->irq) free_irq(shost->irq, NULL); +#ifdef CONFIG_ISA if (shost->dma_channel != 0xff) free_dma(shost->dma_channel); +#endif if (shost->io_port && shost->n_io_port) release_region(shost->io_port, shost->n_io_port); scsi_unregister(shost); @@ -65,8 +73,9 @@ static Scsi_Host_Template driver_templat .detect = bvme6000_scsi_detect, .release = bvme6000_scsi_release, .queuecommand = NCR53c7xx_queue_command, - .abort = NCR53c7xx_abort, - .reset = NCR53c7xx_reset, + .eh_abort_handler = NCR53c7xx_abort, + .eh_bus_reset_handler = NCR53c7xx_reset, + .slave_configure = NCR53c7xx_slave_configure, .can_queue = 24, .this_id = 7, .sg_tablesize = 63, --- linux-2.6.10-rc1/drivers/scsi/bvme6000.h 2004-04-28 11:02:40.000000000 +0200 +++ linux-m68k-2.6.10-rc1/drivers/scsi/bvme6000.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,24 +0,0 @@ -#ifndef BVME6000_SCSI_H -#define BVME6000_SCSI_H - -#include - -int bvme6000_scsi_detect(struct scsi_host_template *); -const char *NCR53c7x0_info(void); -int NCR53c7xx_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); -int NCR53c7xx_abort(Scsi_Cmnd *); -int NCR53c7x0_release (struct Scsi_Host *); -int NCR53c7xx_reset(Scsi_Cmnd *, unsigned int); -void NCR53c7x0_intr(int irq, void *dev_id); - -#ifndef CMD_PER_LUN -#define CMD_PER_LUN 3 -#endif - -#ifndef CAN_QUEUE -#define CAN_QUEUE 24 -#endif - -#include - -#endif /* BVME6000_SCSI_H */ --- linux-2.6.10-rc1/drivers/scsi/mvme16x.c 2004-07-12 09:48:12.000000000 +0200 +++ linux-m68k-2.6.10-rc1/drivers/scsi/mvme16x.c 2004-10-30 13:55:35.000000000 +0200 @@ -17,10 +17,16 @@ #include "scsi.h" #include #include "53c7xx.h" -#include "mvme16x.h" #include +#ifndef CMD_PER_LUN +#define CMD_PER_LUN 3 +#endif + +#ifndef CAN_QUEUE +#define CAN_QUEUE 24 +#endif int mvme16x_scsi_detect(Scsi_Host_Template *tpnt) { @@ -54,8 +60,10 @@ static int mvme16x_scsi_release(struct S { if (shost->irq) free_irq(shost->irq, NULL); +#ifdef CONFIG_ISA if (shost->dma_channel != 0xff) free_dma(shost->dma_channel); +#endif if (shost->io_port && shost->n_io_port) release_region(shost->io_port, shost->n_io_port); scsi_unregister(shost); @@ -67,8 +75,9 @@ static Scsi_Host_Template driver_templat .detect = mvme16x_scsi_detect, .release = mvme16x_scsi_release, .queuecommand = NCR53c7xx_queue_command, - .abort = NCR53c7xx_abort, - .reset = NCR53c7xx_reset, + .eh_abort_handler = NCR53c7xx_abort, + .eh_bus_reset_handler = NCR53c7xx_reset, + .slave_configure = NCR53c7xx_slave_configure, .can_queue = 24, .this_id = 7, .sg_tablesize = 63, --- linux-2.6.10-rc1/drivers/scsi/mvme16x.h 2004-04-28 11:02:40.000000000 +0200 +++ linux-m68k-2.6.10-rc1/drivers/scsi/mvme16x.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,24 +0,0 @@ -#ifndef MVME16x_SCSI_H -#define MVME16x_SCSI_H - -#include - -int mvme16x_scsi_detect(struct scsi_host_template *); -const char *NCR53c7x0_info(void); -int NCR53c7xx_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); -int NCR53c7xx_abort(Scsi_Cmnd *); -int NCR53c7x0_release (struct Scsi_Host *); -int NCR53c7xx_reset(Scsi_Cmnd *, unsigned int); -void NCR53c7x0_intr(int irq, void *dev_id); - -#ifndef CMD_PER_LUN -#define CMD_PER_LUN 3 -#endif - -#ifndef CAN_QUEUE -#define CAN_QUEUE 24 -#endif - -#include - -#endif /* MVME16x_SCSI_H */