tree-wide: fix assorted typos all over the place
[safe/jmp/linux-2.6] / drivers / scsi / sym53c8xx_2 / sym_glue.c
index 3ed3ed8..2b38f6a 100644 (file)
@@ -39,7 +39,6 @@
  */
 #include <linux/ctype.h>
 #include <linux/init.h>
-#include <linux/interrupt.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/spinlock.h>
 #define NAME53C                "sym53c"
 #define NAME53C8XX     "sym53c8xx"
 
-#define IRQ_FMT "%d"
-#define IRQ_PRM(x) (x)
-
 struct sym_driver_setup sym_driver_setup = SYM_LINUX_DRIVER_SETUP;
 unsigned int sym_debug_flags = 0;
 
 static char *excl_string;
 static char *safe_string;
 module_param_named(cmd_per_lun, sym_driver_setup.max_tag, ushort, 0);
-module_param_string(tag_ctrl, sym_driver_setup.tag_ctrl, 100, 0);
 module_param_named(burst, sym_driver_setup.burst_order, byte, 0);
 module_param_named(led, sym_driver_setup.scsi_led, byte, 0);
 module_param_named(diff, sym_driver_setup.scsi_diff, byte, 0);
@@ -78,7 +73,6 @@ module_param_named(excl, excl_string, charp, 0);
 module_param_named(safe, safe_string, charp, 0);
 
 MODULE_PARM_DESC(cmd_per_lun, "The maximum number of tags to use by default");
-MODULE_PARM_DESC(tag_ctrl, "More detailed control over tags per LUN");
 MODULE_PARM_DESC(burst, "Maximum burst.  0 to disable, 255 to read from registers");
 MODULE_PARM_DESC(led, "Set to 1 to enable LED support");
 MODULE_PARM_DESC(diff, "0 for no differential mode, 1 for BIOS, 2 for always, 3 for not GPIO3");
@@ -169,14 +163,6 @@ void sym_xpt_async_bus_reset(struct sym_hcb *np)
 }
 
 /*
- *  Tell the SCSI layer about a BUS DEVICE RESET message sent.
- */
-void sym_xpt_async_sent_bdr(struct sym_hcb *np, int target)
-{
-       printf_notice("%s: TARGET %d has been reset.\n", sym_name(np), target);
-}
-
-/*
  *  Choose the more appropriate CAM status if 
  *  the IO encountered an extended error.
  */
@@ -221,10 +207,9 @@ void sym_set_cam_result_error(struct sym_hcb *np, struct sym_ccb *cp, int resid)
                        /*
                         *  Bounce back the sense data to user.
                         */
-                       memset(&cmd->sense_buffer, 0, sizeof(cmd->sense_buffer));
+                       memset(cmd->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
                        memcpy(cmd->sense_buffer, cp->sns_bbuf,
-                             min(sizeof(cmd->sense_buffer),
-                                 (size_t)SYM_SNS_BBUF_LEN));
+                              min(SCSI_SENSE_BUFFERSIZE, SYM_SNS_BBUF_LEN));
 #if 0
                        /*
                         *  If the device reports a UNIT ATTENTION condition 
@@ -394,7 +379,7 @@ int sym_setup_data_and_start(struct sym_hcb *np, struct scsi_cmnd *cmd, struct s
         */
        switch (dir) {
        case DMA_BIDIRECTIONAL:
-               printk("%s: got DMA_BIDIRECTIONAL command", sym_name(np));
+               scmd_printk(KERN_INFO, cmd, "got DMA_BIDIRECTIONAL command");
                sym_set_cam_status(cmd, DID_ERROR);
                goto out_abort;
        case DMA_TO_DEVICE:
@@ -503,14 +488,16 @@ static void sym_timer(struct sym_hcb *np)
 /*
  *  PCI BUS error handler.
  */
-void sym_log_bus_error(struct sym_hcb *np)
+void sym_log_bus_error(struct Scsi_Host *shost)
 {
-       u_short pci_sts;
-       pci_read_config_word(np->s.device, PCI_STATUS, &pci_sts);
+       struct sym_data *sym_data = shost_priv(shost);
+       struct pci_dev *pdev = sym_data->pdev;
+       unsigned short pci_sts;
+       pci_read_config_word(pdev, PCI_STATUS, &pci_sts);
        if (pci_sts & 0xf900) {
-               pci_write_config_word(np->s.device, PCI_STATUS, pci_sts);
-               printf("%s: PCI STATUS = 0x%04x\n",
-                       sym_name(np), pci_sts & 0xf900);
+               pci_write_config_word(pdev, PCI_STATUS, pci_sts);
+               shost_printk(KERN_WARNING, shost,
+                       "PCI bus error: status = 0x%04x\n", pci_sts & 0xf900);
        }
 }
 
@@ -532,8 +519,8 @@ static int sym53c8xx_queue_command(struct scsi_cmnd *cmd,
         *  Shorten our settle_time if needed for 
         *  this command not to time out.
         */
-       if (np->s.settle_time_valid && cmd->timeout_per_command) {
-               unsigned long tlimit = jiffies + cmd->timeout_per_command;
+       if (np->s.settle_time_valid && cmd->request->timeout) {
+               unsigned long tlimit = jiffies + cmd->request->timeout;
                tlimit -= SYM_CONF_TIMER_INTERVAL*2;
                if (time_after(np->s.settle_time, tlimit)) {
                        np->s.settle_time = tlimit;
@@ -554,21 +541,23 @@ static int sym53c8xx_queue_command(struct scsi_cmnd *cmd,
  */
 static irqreturn_t sym53c8xx_intr(int irq, void *dev_id)
 {
-       struct sym_hcb *np = dev_id;
+       struct Scsi_Host *shost = dev_id;
+       struct sym_data *sym_data = shost_priv(shost);
+       irqreturn_t result;
 
        /* Avoid spinloop trying to handle interrupts on frozen device */
-       if (pci_channel_offline(np->s.device))
+       if (pci_channel_offline(sym_data->pdev))
                return IRQ_NONE;
 
        if (DEBUG_FLAGS & DEBUG_TINY) printf_debug ("[");
 
-       spin_lock(np->s.host->host_lock);
-       sym_interrupt(np);
-       spin_unlock(np->s.host->host_lock);
+       spin_lock(shost->host_lock);
+       result = sym_interrupt(shost);
+       spin_unlock(shost->host_lock);
 
        if (DEBUG_FLAGS & DEBUG_TINY) printf_debug ("]\n");
 
-       return IRQ_HANDLED;
+       return result;
 }
 
 /*
@@ -599,16 +588,17 @@ static void sym53c8xx_timer(unsigned long npref)
  */
 static int sym_eh_handler(int op, char *opname, struct scsi_cmnd *cmd)
 {
-       struct sym_hcb *np = SYM_SOFTC_PTR(cmd);
        struct sym_ucmd *ucmd = SYM_UCMD_PTR(cmd);
-       struct Scsi_Host *host = cmd->device->host;
-       struct pci_dev *pdev = np->s.device;
+       struct Scsi_Host *shost = cmd->device->host;
+       struct sym_data *sym_data = shost_priv(shost);
+       struct pci_dev *pdev = sym_data->pdev;
+       struct sym_hcb *np = sym_data->ncb;
        SYM_QUEHEAD *qp;
        int cmd_queued = 0;
        int sts = -1;
        struct completion eh_done;
 
-       dev_warn(&cmd->device->sdev_gendev, "%s operation started.\n", opname);
+       scmd_printk(KERN_WARNING, cmd, "%s operation started\n", opname);
 
        /* We may be in an error condition because the PCI bus
         * went down. In this case, we need to wait until the
@@ -618,31 +608,29 @@ static int sym_eh_handler(int op, char *opname, struct scsi_cmnd *cmd)
         */
 #define WAIT_FOR_PCI_RECOVERY  35
        if (pci_channel_offline(pdev)) {
-               struct host_data *hostdata = shost_priv(host);
-               struct completion *io_reset;
                int finished_reset = 0;
                init_completion(&eh_done);
-               spin_lock_irq(host->host_lock);
+               spin_lock_irq(shost->host_lock);
                /* Make sure we didn't race */
                if (pci_channel_offline(pdev)) {
-                       if (!hostdata->io_reset)
-                               hostdata->io_reset = &eh_done;
-                       io_reset = hostdata->io_reset;
+                       BUG_ON(sym_data->io_reset);
+                       sym_data->io_reset = &eh_done;
                } else {
-                       io_reset = NULL;
-               }
-
-               if (!pci_channel_offline(pdev))
                        finished_reset = 1;
-               spin_unlock_irq(host->host_lock);
+               }
+               spin_unlock_irq(shost->host_lock);
                if (!finished_reset)
-                       finished_reset = wait_for_completion_timeout(io_reset,
+                       finished_reset = wait_for_completion_timeout
+                                               (sym_data->io_reset,
                                                WAIT_FOR_PCI_RECOVERY*HZ);
+               spin_lock_irq(shost->host_lock);
+               sym_data->io_reset = NULL;
+               spin_unlock_irq(shost->host_lock);
                if (!finished_reset)
                        return SCSI_FAILED;
        }
 
-       spin_lock_irq(host->host_lock);
+       spin_lock_irq(shost->host_lock);
        /* This one is queued in some place -> to wait for completion */
        FOR_EACH_QUEUED_ELEMENT(&np->busy_ccbq, qp) {
                struct sym_ccb *cp = sym_que_entry(qp, struct sym_ccb, link_ccbq);
@@ -667,7 +655,7 @@ static int sym_eh_handler(int op, char *opname, struct scsi_cmnd *cmd)
                break;
        case SYM_EH_HOST_RESET:
                sym_reset_scsi_bus(np, 0);
-               sym_start_up(np, 1);
+               sym_start_up(shost, 1);
                sts = 0;
                break;
        default:
@@ -681,13 +669,13 @@ static int sym_eh_handler(int op, char *opname, struct scsi_cmnd *cmd)
        if (cmd_queued) {
                init_completion(&eh_done);
                ucmd->eh_done = &eh_done;
-               spin_unlock_irq(host->host_lock);
+               spin_unlock_irq(shost->host_lock);
                if (!wait_for_completion_timeout(&eh_done, 5*HZ)) {
                        ucmd->eh_done = NULL;
                        sts = -2;
                }
        } else {
-               spin_unlock_irq(host->host_lock);
+               spin_unlock_irq(shost->host_lock);
        }
 
        dev_warn(&cmd->device->sdev_gendev, "%s operation %s.\n", opname,
@@ -744,69 +732,19 @@ static void sym_tune_dev_queuing(struct sym_tcb *tp, int lun, u_short reqtags)
        }
 }
 
-/*
- *  Linux select queue depths function
- */
-#define DEF_DEPTH      (sym_driver_setup.max_tag)
-#define ALL_TARGETS    -2
-#define NO_TARGET      -1
-#define ALL_LUNS       -2
-#define NO_LUN         -1
-
-static int device_queue_depth(struct sym_hcb *np, int target, int lun)
-{
-       int c, h, t, u, v;
-       char *p = sym_driver_setup.tag_ctrl;
-       char *ep;
-
-       h = -1;
-       t = NO_TARGET;
-       u = NO_LUN;
-       while ((c = *p++) != 0) {
-               v = simple_strtoul(p, &ep, 0);
-               switch(c) {
-               case '/':
-                       ++h;
-                       t = ALL_TARGETS;
-                       u = ALL_LUNS;
-                       break;
-               case 't':
-                       if (t != target)
-                               t = (target == v) ? v : NO_TARGET;
-                       u = ALL_LUNS;
-                       break;
-               case 'u':
-                       if (u != lun)
-                               u = (lun == v) ? v : NO_LUN;
-                       break;
-               case 'q':
-                       if (h == np->s.unit &&
-                               (t == ALL_TARGETS || t == target) &&
-                               (u == ALL_LUNS    || u == lun))
-                               return v;
-                       break;
-               case '-':
-                       t = ALL_TARGETS;
-                       u = ALL_LUNS;
-                       break;
-               default:
-                       break;
-               }
-               p = ep;
-       }
-       return DEF_DEPTH;
-}
-
 static int sym53c8xx_slave_alloc(struct scsi_device *sdev)
 {
        struct sym_hcb *np = sym_get_hcb(sdev->host);
        struct sym_tcb *tp = &np->target[sdev->id];
        struct sym_lcb *lp;
+       unsigned long flags;
+       int error;
 
        if (sdev->id >= SYM_CONF_MAX_TARGET || sdev->lun >= SYM_CONF_MAX_LUN)
                return -ENXIO;
 
-       tp->starget = sdev->sdev_target;
+       spin_lock_irqsave(np->s.host->host_lock, flags);
+
        /*
         * Fail the device init if the device is flagged NOSCAN at BOOT in
         * the NVRAM.  This may speed up boot and maintain coherency with
@@ -818,26 +756,37 @@ static int sym53c8xx_slave_alloc(struct scsi_device *sdev)
 
        if (tp->usrflags & SYM_SCAN_BOOT_DISABLED) {
                tp->usrflags &= ~SYM_SCAN_BOOT_DISABLED;
-               starget_printk(KERN_INFO, tp->starget,
+               starget_printk(KERN_INFO, sdev->sdev_target,
                                "Scan at boot disabled in NVRAM\n");
-               return -ENXIO;
+               error = -ENXIO;
+               goto out;
        }
 
        if (tp->usrflags & SYM_SCAN_LUNS_DISABLED) {
-               if (sdev->lun != 0)
-                       return -ENXIO;
-               starget_printk(KERN_INFO, tp->starget,
+               if (sdev->lun != 0) {
+                       error = -ENXIO;
+                       goto out;
+               }
+               starget_printk(KERN_INFO, sdev->sdev_target,
                                "Multiple LUNs disabled in NVRAM\n");
        }
 
        lp = sym_alloc_lcb(np, sdev->id, sdev->lun);
-       if (!lp)
-               return -ENOMEM;
+       if (!lp) {
+               error = -ENOMEM;
+               goto out;
+       }
+       if (tp->nlcb == 1)
+               tp->starget = sdev->sdev_target;
 
        spi_min_period(tp->starget) = tp->usr_period;
        spi_max_width(tp->starget) = tp->usr_width;
 
-       return 0;
+       error = 0;
+out:
+       spin_unlock_irqrestore(np->s.host->host_lock, flags);
+
+       return error;
 }
 
 /*
@@ -857,25 +806,20 @@ static int sym53c8xx_slave_configure(struct scsi_device *sdev)
 
        /*
         *  Select queue depth from driver setup.
-        *  Donnot use more than configured by user.
-        *  Use at least 2.
-        *  Donnot use more than our maximum.
+        *  Do not use more than configured by user.
+        *  Use at least 1.
+        *  Do not use more than our maximum.
         */
-       reqtags = device_queue_depth(np, sdev->id, sdev->lun);
+       reqtags = sym_driver_setup.max_tag;
        if (reqtags > tp->usrtags)
                reqtags = tp->usrtags;
        if (!sdev->tagged_supported)
                reqtags = 0;
-#if 1 /* Avoid to locally queue commands for no good reasons */
        if (reqtags > SYM_CONF_MAX_TAG)
                reqtags = SYM_CONF_MAX_TAG;
-       depth_to_use = (reqtags ? reqtags : 2);
-#else
-       depth_to_use = (reqtags ? SYM_CONF_MAX_TAG : 2);
-#endif
+       depth_to_use = reqtags ? reqtags : 1;
        scsi_adjust_queue_depth(sdev,
-                               (sdev->tagged_supported ?
-                                MSG_SIMPLE_TAG : 0),
+                               sdev->tagged_supported ? MSG_SIMPLE_TAG : 0,
                                depth_to_use);
        lp->s.scdev_depth = depth_to_use;
        sym_tune_dev_queuing(tp, sdev->lun, reqtags);
@@ -889,12 +833,34 @@ static int sym53c8xx_slave_configure(struct scsi_device *sdev)
 static void sym53c8xx_slave_destroy(struct scsi_device *sdev)
 {
        struct sym_hcb *np = sym_get_hcb(sdev->host);
-       struct sym_lcb *lp = sym_lp(&np->target[sdev->id], sdev->lun);
+       struct sym_tcb *tp = &np->target[sdev->id];
+       struct sym_lcb *lp = sym_lp(tp, sdev->lun);
+       unsigned long flags;
 
-       if (lp->itlq_tbl)
-               sym_mfree_dma(lp->itlq_tbl, SYM_CONF_MAX_TASK * 4, "ITLQ_TBL");
-       kfree(lp->cb_tags);
-       sym_mfree_dma(lp, sizeof(*lp), "LCB");
+       spin_lock_irqsave(np->s.host->host_lock, flags);
+
+       if (lp->busy_itlq || lp->busy_itl) {
+               /*
+                * This really shouldn't happen, but we can't return an error
+                * so let's try to stop all on-going I/O.
+                */
+               starget_printk(KERN_WARNING, tp->starget,
+                              "Removing busy LCB (%d)\n", sdev->lun);
+               sym_reset_scsi_bus(np, 1);
+       }
+
+       if (sym_free_lcb(np, sdev->id, sdev->lun) == 0) {
+               /*
+                * It was the last unit for this target.
+                */
+               tp->head.sval        = 0;
+               tp->head.wval        = np->rv_scntl3;
+               tp->head.uval        = 0;
+               tp->tgoal.check_nego = 1;
+               tp->starget          = NULL;
+       }
+
+       spin_unlock_irqrestore(np->s.host->host_lock, flags);
 }
 
 /*
@@ -960,6 +926,8 @@ static void sym_exec_user_command (struct sym_hcb *np, struct sym_usrcmd *uc)
                        if (!((uc->target >> t) & 1))
                                continue;
                        tp = &np->target[t];
+                       if (!tp->nlcb)
+                               continue;
 
                        switch (uc->cmd) {
 
@@ -1058,8 +1026,9 @@ static int is_keyword(char *ptr, int len, char *verb)
  * Parse a control command
  */
 
-static int sym_user_command(struct sym_hcb *np, char *buffer, int length)
+static int sym_user_command(struct Scsi_Host *shost, char *buffer, int length)
 {
+       struct sym_hcb *np = sym_get_hcb(shost);
        char *ptr       = buffer;
        int len         = length;
        struct sym_usrcmd cmd, *uc = &cmd;
@@ -1186,9 +1155,9 @@ printk("sym_user_command: data=%ld\n", uc->data);
        else {
                unsigned long flags;
 
-               spin_lock_irqsave(np->s.host->host_lock, flags);
-               sym_exec_user_command (np, uc);
-               spin_unlock_irqrestore(np->s.host->host_lock, flags);
+               spin_lock_irqsave(shost->host_lock, flags);
+               sym_exec_user_command(np, uc);
+               spin_unlock_irqrestore(shost->host_lock, flags);
        }
        return length;
 }
@@ -1244,8 +1213,11 @@ static int copy_info(struct info_str *info, char *fmt, ...)
 /*
  *  Copy formatted information into the input buffer.
  */
-static int sym_host_info(struct sym_hcb *np, char *ptr, off_t offset, int len)
+static int sym_host_info(struct Scsi_Host *shost, char *ptr, off_t offset, int len)
 {
+       struct sym_data *sym_data = shost_priv(shost);
+       struct pci_dev *pdev = sym_data->pdev;
+       struct sym_hcb *np = sym_data->ncb;
        struct info_str info;
 
        info.buffer     = ptr;
@@ -1255,9 +1227,9 @@ static int sym_host_info(struct sym_hcb *np, char *ptr, off_t offset, int len)
 
        copy_info(&info, "Chip " NAME53C "%s, device id 0x%x, "
                         "revision id 0x%x\n", np->s.chip_name,
-                        np->device_id, np->s.device->revision);
-       copy_info(&info, "At PCI address %s, IRQ " IRQ_FMT "\n",
-               pci_name(np->s.device), IRQ_PRM(np->s.device->irq));
+                        pdev->device, pdev->revision);
+       copy_info(&info, "At PCI address %s, IRQ %u\n",
+                        pci_name(pdev), pdev->irq);
        copy_info(&info, "Min. period factor %d, %s SCSI BUS%s\n",
                         (int) (np->minsync_dt ? np->minsync_dt : np->minsync),
                         np->maxwide ? "Wide" : "Narrow",
@@ -1276,15 +1248,14 @@ static int sym_host_info(struct sym_hcb *np, char *ptr, off_t offset, int len)
  *  - func = 0 means read  (returns adapter infos)
  *  - func = 1 means write (not yet merget from sym53c8xx)
  */
-static int sym53c8xx_proc_info(struct Scsi_Host *host, char *buffer,
+static int sym53c8xx_proc_info(struct Scsi_Host *shost, char *buffer,
                        char **start, off_t offset, int length, int func)
 {
-       struct sym_hcb *np = sym_get_hcb(host);
        int retv;
 
        if (func) {
 #ifdef SYM_LINUX_USER_COMMAND_SUPPORT
-               retv = sym_user_command(np, buffer, length);
+               retv = sym_user_command(shost, buffer, length);
 #else
                retv = -EINVAL;
 #endif
@@ -1292,7 +1263,7 @@ static int sym53c8xx_proc_info(struct Scsi_Host *host, char *buffer,
                if (start)
                        *start = buffer;
 #ifdef SYM_LINUX_USER_INFO_SUPPORT
-               retv = sym_host_info(np, buffer, offset, length);
+               retv = sym_host_info(shost, buffer, offset, length);
 #else
                retv = -EINVAL;
 #endif
@@ -1303,15 +1274,30 @@ static int sym53c8xx_proc_info(struct Scsi_Host *host, char *buffer,
 #endif /* SYM_LINUX_PROC_INFO_SUPPORT */
 
 /*
+ * Free resources claimed by sym_iomap_device().  Note that
+ * sym_free_resources() should be used instead of this function after calling
+ * sym_attach().
+ */
+static void __devinit
+sym_iounmap_device(struct sym_device *device)
+{
+       if (device->s.ioaddr)
+               pci_iounmap(device->pdev, device->s.ioaddr);
+       if (device->s.ramaddr)
+               pci_iounmap(device->pdev, device->s.ramaddr);
+}
+
+/*
  *     Free controller resources.
  */
-static void sym_free_resources(struct sym_hcb *np, struct pci_dev *pdev)
+static void sym_free_resources(struct sym_hcb *np, struct pci_dev *pdev,
+               int do_free_irq)
 {
        /*
         *  Free O/S specific resources.
         */
-       if (pdev->irq)
-               free_irq(pdev->irq, np);
+       if (do_free_irq)
+               free_irq(pdev->irq, np->s.host);
        if (np->s.ioaddr)
                pci_iounmap(pdev, np->s.ioaddr);
        if (np->s.ramaddr)
@@ -1325,31 +1311,6 @@ static void sym_free_resources(struct sym_hcb *np, struct pci_dev *pdev)
 }
 
 /*
- *  Ask/tell the system about DMA addressing.
- */
-static int sym_setup_bus_dma_mask(struct sym_hcb *np)
-{
-#if SYM_CONF_DMA_ADDRESSING_MODE > 0
-#if   SYM_CONF_DMA_ADDRESSING_MODE == 1
-#define        DMA_DAC_MASK    DMA_40BIT_MASK
-#elif SYM_CONF_DMA_ADDRESSING_MODE == 2
-#define        DMA_DAC_MASK    DMA_64BIT_MASK
-#endif
-       if ((np->features & FE_DAC) &&
-                       !pci_set_dma_mask(np->s.device, DMA_DAC_MASK)) {
-               np->use_dac = 1;
-               return 0;
-       }
-#endif
-
-       if (!pci_set_dma_mask(np->s.device, DMA_32BIT_MASK))
-               return 0;
-
-       printf_warning("%s: No suitable DMA available\n", sym_name(np));
-       return -1;
-}
-
-/*
  *  Host attach and initialisations.
  *
  *  Allocate host data and ncb structure.
@@ -1361,16 +1322,17 @@ static int sym_setup_bus_dma_mask(struct sym_hcb *np)
 static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt,
                int unit, struct sym_device *dev)
 {
-       struct host_data *host_data;
+       struct sym_data *sym_data;
        struct sym_hcb *np = NULL;
-       struct Scsi_Host *instance = NULL;
+       struct Scsi_Host *shost = NULL;
        struct pci_dev *pdev = dev->pdev;
        unsigned long flags;
        struct sym_fw *fw;
+       int do_free_irq = 0;
 
-       printk(KERN_INFO "sym%d: <%s> rev 0x%x at pci %s irq " IRQ_FMT "\n",
+       printk(KERN_INFO "sym%d: <%s> rev 0x%x at pci %s irq %u\n",
                unit, dev->chip.name, pdev->revision, pci_name(pdev),
-               IRQ_PRM(pdev->irq));
+               pdev->irq);
 
        /*
         *  Get the firmware for this chip.
@@ -1379,13 +1341,10 @@ static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt,
        if (!fw)
                goto attach_failed;
 
-       /*
-        *      Allocate host_data structure
-        */
-       instance = scsi_host_alloc(tpnt, sizeof(*host_data));
-       if (!instance)
+       shost = scsi_host_alloc(tpnt, sizeof(*sym_data));
+       if (!shost)
                goto attach_failed;
-       host_data = (struct host_data *) instance->hostdata;
+       sym_data = shost_priv(shost);
 
        /*
         *  Allocate immediately the host control block, 
@@ -1396,26 +1355,28 @@ static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt,
        np = __sym_calloc_dma(&pdev->dev, sizeof(*np), "HCB");
        if (!np)
                goto attach_failed;
-       np->s.device = pdev;
        np->bus_dmat = &pdev->dev; /* Result in 1 DMA pool per HBA */
-       host_data->ncb = np;
-       np->s.host = instance;
+       sym_data->ncb = np;
+       sym_data->pdev = pdev;
+       np->s.host = shost;
 
-       pci_set_drvdata(pdev, np);
+       pci_set_drvdata(pdev, shost);
 
        /*
         *  Copy some useful infos to the HCB.
         */
        np->hcb_ba      = vtobus(np);
        np->verbose     = sym_driver_setup.verbose;
-       np->s.device    = pdev;
        np->s.unit      = unit;
-       np->device_id   = dev->chip.device_id;
        np->features    = dev->chip.features;
        np->clock_divn  = dev->chip.nr_divisor;
        np->maxoffs     = dev->chip.offset_max;
        np->maxburst    = dev->chip.burst_max;
        np->myaddr      = dev->host_id;
+       np->mmio_ba     = (u32)dev->mmio_base;
+       np->ram_ba      = (u32)dev->ram_base;
+       np->s.ioaddr    = dev->s.ioaddr;
+       np->s.ramaddr   = dev->s.ramaddr;
 
        /*
         *  Edit its name.
@@ -1423,29 +1384,15 @@ static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt,
        strlcpy(np->s.chip_name, dev->chip.name, sizeof(np->s.chip_name));
        sprintf(np->s.inst_name, "sym%d", np->s.unit);
 
-       if (sym_setup_bus_dma_mask(np))
+       if ((SYM_CONF_DMA_ADDRESSING_MODE > 0) && (np->features & FE_DAC) &&
+                       !pci_set_dma_mask(pdev, DMA_DAC_MASK)) {
+               set_dac(np);
+       } else if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) {
+               printf_warning("%s: No suitable DMA available\n", sym_name(np));
                goto attach_failed;
-
-       /*
-        *  Try to map the controller chip to
-        *  virtual and physical memory.
-        */
-       np->mmio_ba = (u32)dev->mmio_base;
-       np->s.ioaddr    = dev->s.ioaddr;
-       np->s.ramaddr   = dev->s.ramaddr;
-       np->s.io_ws = (np->features & FE_IO256) ? 256 : 128;
-
-       /*
-        *  Map on-chip RAM if present and supported.
-        */
-       if (!(np->features & FE_RAM))
-               dev->ram_base = 0;
-       if (dev->ram_base) {
-               np->ram_ba = (u32)dev->ram_base;
-               np->ram_ws = (np->features & FE_RAM8K) ? 8192 : 4096;
        }
 
-       if (sym_hcb_attach(instance, fw, dev->nvram))
+       if (sym_hcb_attach(shost, fw, dev->nvram))
                goto attach_failed;
 
        /*
@@ -1453,24 +1400,26 @@ static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt,
         *  If we synchonize the C code with SCRIPTS on interrupt, 
         *  we do not want to share the INTR line at all.
         */
-       if (request_irq(pdev->irq, sym53c8xx_intr, IRQF_SHARED, NAME53C8XX, np)) {
-               printf_err("%s: request irq %d failure\n",
+       if (request_irq(pdev->irq, sym53c8xx_intr, IRQF_SHARED, NAME53C8XX,
+                       shost)) {
+               printf_err("%s: request irq %u failure\n",
                        sym_name(np), pdev->irq);
                goto attach_failed;
        }
+       do_free_irq = 1;
 
        /*
         *  After SCSI devices have been opened, we cannot
         *  reset the bus safely, so we do it here.
         */
-       spin_lock_irqsave(instance->host_lock, flags);
+       spin_lock_irqsave(shost->host_lock, flags);
        if (sym_reset_scsi_bus(np, 0))
                goto reset_failed;
 
        /*
         *  Start the SCRIPTS.
         */
-       sym_start_up(np, 1);
+       sym_start_up(shost, 1);
 
        /*
         *  Start the timer daemon
@@ -1485,37 +1434,38 @@ static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt,
         *  Fill Linux host instance structure
         *  and return success.
         */
-       instance->max_channel   = 0;
-       instance->this_id       = np->myaddr;
-       instance->max_id        = np->maxwide ? 16 : 8;
-       instance->max_lun       = SYM_CONF_MAX_LUN;
-       instance->unique_id     = pci_resource_start(pdev, 0);
-       instance->cmd_per_lun   = SYM_CONF_MAX_TAG;
-       instance->can_queue     = (SYM_CONF_MAX_START-2);
-       instance->sg_tablesize  = SYM_CONF_MAX_SG;
-       instance->max_cmd_len   = 16;
+       shost->max_channel      = 0;
+       shost->this_id          = np->myaddr;
+       shost->max_id           = np->maxwide ? 16 : 8;
+       shost->max_lun          = SYM_CONF_MAX_LUN;
+       shost->unique_id        = pci_resource_start(pdev, 0);
+       shost->cmd_per_lun      = SYM_CONF_MAX_TAG;
+       shost->can_queue        = (SYM_CONF_MAX_START-2);
+       shost->sg_tablesize     = SYM_CONF_MAX_SG;
+       shost->max_cmd_len      = 16;
        BUG_ON(sym2_transport_template == NULL);
-       instance->transportt    = sym2_transport_template;
+       shost->transportt       = sym2_transport_template;
 
        /* 53c896 rev 1 errata: DMA may not cross 16MB boundary */
        if (pdev->device == PCI_DEVICE_ID_NCR_53C896 && pdev->revision < 2)
-               instance->dma_boundary = 0xFFFFFF;
+               shost->dma_boundary = 0xFFFFFF;
 
-       spin_unlock_irqrestore(instance->host_lock, flags);
+       spin_unlock_irqrestore(shost->host_lock, flags);
 
-       return instance;
+       return shost;
 
  reset_failed:
        printf_err("%s: FATAL ERROR: CHECK SCSI BUS - CABLES, "
                   "TERMINATION, DEVICE POWER etc.!\n", sym_name(np));
-       spin_unlock_irqrestore(instance->host_lock, flags);
+       spin_unlock_irqrestore(shost->host_lock, flags);
  attach_failed:
-       if (!instance)
-               return NULL;
-       printf_info("%s: giving up ...\n", sym_name(np));
+       printf_info("sym%d: giving up ...\n", unit);
        if (np)
-               sym_free_resources(np, pdev);
-       scsi_host_put(instance);
+               sym_free_resources(np, pdev, do_free_irq);
+       else
+               sym_iounmap_device(dev);
+       if (shost)
+               scsi_host_put(shost);
 
        return NULL;
  }
@@ -1528,7 +1478,6 @@ static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt,
 static void __devinit sym_get_nvram(struct sym_device *devp, struct sym_nvram *nvp)
 {
        devp->nvram = nvp;
-       devp->device_id = devp->chip.device_id;
        nvp->type = 0;
 
        sym_read_nvram(devp, nvp);
@@ -1645,30 +1594,28 @@ static int __devinit sym_set_workarounds(struct sym_device *device)
 }
 
 /*
- *  Read and check the PCI configuration for any detected NCR 
- *  boards and save data for attaching after all boards have 
- *  been detected.
+ * Map HBA registers and on-chip SRAM (if present).
  */
-static void __devinit
-sym_init_device(struct pci_dev *pdev, struct sym_device *device)
+static int __devinit
+sym_iomap_device(struct sym_device *device)
 {
-       int i = 2;
+       struct pci_dev *pdev = device->pdev;
        struct pci_bus_region bus_addr;
-
-       device->host_id = SYM_SETUP_HOST_ID;
-       device->pdev = pdev;
+       int i = 2;
 
        pcibios_resource_to_bus(pdev, &bus_addr, &pdev->resource[1]);
        device->mmio_base = bus_addr.start;
 
-       /*
-        * If the BAR is 64-bit, resource 2 will be occupied by the
-        * upper 32 bits
-        */
-       if (!pdev->resource[i].flags)
-               i++;
-       pcibios_resource_to_bus(pdev, &bus_addr, &pdev->resource[i]);
-       device->ram_base = bus_addr.start;
+       if (device->chip.features & FE_RAM) {
+               /*
+                * If the BAR is 64-bit, resource 2 will be occupied by the
+                * upper 32 bits
+                */
+               if (!pdev->resource[i].flags)
+                       i++;
+               pcibios_resource_to_bus(pdev, &bus_addr, &pdev->resource[i]);
+               device->ram_base = bus_addr.start;
+       }
 
 #ifdef CONFIG_SCSI_SYM53C8XX_MMIO
        if (device->mmio_base)
@@ -1678,9 +1625,21 @@ sym_init_device(struct pci_dev *pdev, struct sym_device *device)
        if (!device->s.ioaddr)
                device->s.ioaddr = pci_iomap(pdev, 0,
                                                pci_resource_len(pdev, 0));
-       if (device->ram_base)
+       if (!device->s.ioaddr) {
+               dev_err(&pdev->dev, "could not map registers; giving up.\n");
+               return -EIO;
+       }
+       if (device->ram_base) {
                device->s.ramaddr = pci_iomap(pdev, i,
                                                pci_resource_len(pdev, i));
+               if (!device->s.ramaddr) {
+                       dev_warn(&pdev->dev,
+                               "could not map SRAM; continuing anyway.\n");
+                       device->ram_base = 0;
+               }
+       }
+
+       return 0;
 }
 
 /*
@@ -1736,8 +1695,9 @@ static void sym_config_pqs(struct pci_dev *pdev, struct sym_device *sym_dev)
  *  Detach the host.
  *  We have to free resources and halt the NCR chip.
  */
-static int sym_detach(struct sym_hcb *np, struct pci_dev *pdev)
+static int sym_detach(struct Scsi_Host *shost, struct pci_dev *pdev)
 {
+       struct sym_hcb *np = sym_get_hcb(shost);
        printk("%s: detaching ...\n", sym_name(np));
 
        del_timer_sync(&np->s.timer);
@@ -1753,7 +1713,8 @@ static int sym_detach(struct sym_hcb *np, struct pci_dev *pdev)
        udelay(10);
        OUTB(np, nc_istat, 0);
 
-       sym_free_resources(np, pdev);
+       sym_free_resources(np, pdev, 1);
+       scsi_host_put(shost);
 
        return 1;
 }
@@ -1775,7 +1736,6 @@ static struct scsi_host_template sym2_template = {
        .eh_host_reset_handler  = sym53c8xx_eh_host_reset_handler,
        .this_id                = 7,
        .use_clustering         = ENABLE_CLUSTERING,
-       .use_sg_chaining        = ENABLE_SG_CHAINING,
        .max_sectors            = 0xFFFF,
 #ifdef SYM_LINUX_PROC_INFO_SUPPORT
        .proc_info              = sym53c8xx_proc_info,
@@ -1790,10 +1750,14 @@ static int __devinit sym2_probe(struct pci_dev *pdev,
 {
        struct sym_device sym_dev;
        struct sym_nvram nvram;
-       struct Scsi_Host *instance;
+       struct Scsi_Host *shost;
+       int do_iounmap = 0;
+       int do_disable_device = 1;
 
        memset(&sym_dev, 0, sizeof(sym_dev));
        memset(&nvram, 0, sizeof(nvram));
+       sym_dev.pdev = pdev;
+       sym_dev.host_id = SYM_SETUP_HOST_ID;
 
        if (pci_enable_device(pdev))
                goto leave;
@@ -1803,12 +1767,17 @@ static int __devinit sym2_probe(struct pci_dev *pdev,
        if (pci_request_regions(pdev, NAME53C8XX))
                goto disable;
 
-       sym_init_device(pdev, &sym_dev);
        if (sym_check_supported(&sym_dev))
                goto free;
 
-       if (sym_check_raid(&sym_dev))
-               goto leave;     /* Don't disable the device */
+       if (sym_iomap_device(&sym_dev))
+               goto free;
+       do_iounmap = 1;
+
+       if (sym_check_raid(&sym_dev)) {
+               do_disable_device = 0;  /* Don't disable the device */
+               goto free;
+       }
 
        if (sym_set_workarounds(&sym_dev))
                goto free;
@@ -1817,13 +1786,14 @@ static int __devinit sym2_probe(struct pci_dev *pdev,
 
        sym_get_nvram(&sym_dev, &nvram);
 
-       instance = sym_attach(&sym2_template, attach_count, &sym_dev);
-       if (!instance)
+       do_iounmap = 0; /* Don't sym_iounmap_device() after sym_attach(). */
+       shost = sym_attach(&sym2_template, attach_count, &sym_dev);
+       if (!shost)
                goto free;
 
-       if (scsi_add_host(instance, &pdev->dev))
+       if (scsi_add_host(shost, &pdev->dev))
                goto detach;
-       scsi_scan_host(instance);
+       scsi_scan_host(shost);
 
        attach_count++;
 
@@ -1832,23 +1802,22 @@ static int __devinit sym2_probe(struct pci_dev *pdev,
  detach:
        sym_detach(pci_get_drvdata(pdev), pdev);
  free:
+       if (do_iounmap)
+               sym_iounmap_device(&sym_dev);
        pci_release_regions(pdev);
  disable:
-       pci_disable_device(pdev);
+       if (do_disable_device)
+               pci_disable_device(pdev);
  leave:
        return -ENODEV;
 }
 
-static void __devexit sym2_remove(struct pci_dev *pdev)
+static void sym2_remove(struct pci_dev *pdev)
 {
-       struct sym_hcb *np = pci_get_drvdata(pdev);
-       struct Scsi_Host *host = np->s.host;
-
-       scsi_remove_host(host);
-       scsi_host_put(host);
-
-       sym_detach(np, pdev);
+       struct Scsi_Host *shost = pci_get_drvdata(pdev);
 
+       scsi_remove_host(shost);
+       sym_detach(shost, pdev);
        pci_release_regions(pdev);
        pci_disable_device(pdev);
 
@@ -1882,9 +1851,9 @@ static pci_ers_result_t sym2_io_error_detected(struct pci_dev *pdev,
  */
 static pci_ers_result_t sym2_io_slot_dump(struct pci_dev *pdev)
 {
-       struct sym_hcb *np = pci_get_drvdata(pdev);
+       struct Scsi_Host *shost = pci_get_drvdata(pdev);
 
-       sym_dump_registers(np);
+       sym_dump_registers(shost);
 
        /* Request a slot reset. */
        return PCI_ERS_RESULT_NEED_RESET;
@@ -1895,7 +1864,7 @@ static pci_ers_result_t sym2_io_slot_dump(struct pci_dev *pdev)
  *
  * This routine is similar to sym_set_workarounds(), except
  * that, at this point, we already know that the device was
- * succesfully intialized at least once before, and so most
+ * successfully intialized at least once before, and so most
  * of the steps taken there are un-needed here.
  */
 static void sym2_reset_workarounds(struct pci_dev *pdev)
@@ -1924,7 +1893,8 @@ static void sym2_reset_workarounds(struct pci_dev *pdev)
  */
 static pci_ers_result_t sym2_io_slot_reset(struct pci_dev *pdev)
 {
-       struct sym_hcb *np = pci_get_drvdata(pdev);
+       struct Scsi_Host *shost = pci_get_drvdata(pdev);
+       struct sym_hcb *np = sym_get_hcb(shost);
 
        printk(KERN_INFO "%s: recovering from a PCI slot reset\n",
                  sym_name(np));
@@ -1954,7 +1924,7 @@ static pci_ers_result_t sym2_io_slot_reset(struct pci_dev *pdev)
                                sym_name(np));
                        return PCI_ERS_RESULT_DISCONNECT;
                }
-               sym_start_up(np, 1);
+               sym_start_up(shost, 1);
        }
 
        return PCI_ERS_RESULT_RECOVERED;
@@ -1970,14 +1940,12 @@ static pci_ers_result_t sym2_io_slot_reset(struct pci_dev *pdev)
  */
 static void sym2_io_resume(struct pci_dev *pdev)
 {
-       struct sym_hcb *np = pci_get_drvdata(pdev);
-       struct Scsi_Host *shost = np->s.host;
-       struct host_data *hostdata = shost_priv(shost);
+       struct Scsi_Host *shost = pci_get_drvdata(pdev);
+       struct sym_data *sym_data = shost_priv(shost);
 
        spin_lock_irq(shost->host_lock);
-       if (hostdata->io_reset)
-               complete_all(hostdata->io_reset);
-       hostdata->io_reset = NULL;
+       if (sym_data->io_reset)
+               complete_all(sym_data->io_reset);
        spin_unlock_irq(shost->host_lock);
 }
 
@@ -2154,7 +2122,7 @@ static struct pci_driver sym2_driver = {
        .name           = NAME53C8XX,
        .id_table       = sym2_id_table,
        .probe          = sym2_probe,
-       .remove         = __devexit_p(sym2_remove),
+       .remove         = sym2_remove,
        .err_handler    = &sym2_err_handler,
 };