]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/scsi/gdth.c
[SCSI] gdth: fix Error: Driver 'gdth' is already registered, aborting...
[linux-2.6-omap-h63xx.git] / drivers / scsi / gdth.c
index 27ebd336409b6fbd922c17360438a7c0ec79babe..46771d4c81bdcd8abeb8bad9b81bdd6430f5dfff 100644 (file)
 
 /* The meaning of the Scsi_Pointer members in this driver is as follows:
  * ptr:                     Chaining
- * this_residual:           gdth_bufflen
- * buffer:                  gdth_sglist
+ * this_residual:           unused
+ * buffer:                  unused
  * dma_handle:              unused
- * buffers_residual:        gdth_sg_count
+ * buffers_residual:        unused
  * Status:                  unused
  * Message:                 unused
  * have_data_in:            unused
@@ -372,47 +372,6 @@ static const struct file_operations gdth_fops = {
     .release = gdth_close,
 };
 
-/*
- * gdth scsi_command access wrappers.
- *   below 6 functions are used throughout the driver to access scsi_command's
- *   io parameters. The reason we do not use the regular accessors from
- *   scsi_cmnd.h is because of gdth_execute(). Since it is unrecommended for
- *   llds to directly set scsi_cmnd's IO members. This driver will use SCp
- *   members for IO parameters, and will copy scsi_cmnd's members to Scp
- *   members in queuecommand. For internal commands through gdth_execute()
- *   SCp's members will be set directly.
- */
-static inline unsigned gdth_bufflen(struct scsi_cmnd *cmd)
-{
-       return (unsigned)cmd->SCp.this_residual;
-}
-
-static inline void gdth_set_bufflen(struct scsi_cmnd *cmd, unsigned bufflen)
-{
-       cmd->SCp.this_residual = bufflen;
-}
-
-static inline unsigned gdth_sg_count(struct scsi_cmnd *cmd)
-{
-       return (unsigned)cmd->SCp.buffers_residual;
-}
-
-static inline void gdth_set_sg_count(struct scsi_cmnd *cmd, unsigned sg_count)
-{
-       cmd->SCp.buffers_residual = sg_count;
-}
-
-static inline struct scatterlist *gdth_sglist(struct scsi_cmnd *cmd)
-{
-       return cmd->SCp.buffer;
-}
-
-static inline void gdth_set_sglist(struct scsi_cmnd *cmd,
-                                   struct scatterlist *sglist)
-{
-       cmd->SCp.buffer = sglist;
-}
-
 #include "gdth_proc.h"
 #include "gdth_proc.c"
 
@@ -493,6 +452,12 @@ int __gdth_execute(struct scsi_device *sdev, gdth_cmd_str *gdtcmd, char *cmnd,
     if (!scp)
         return -ENOMEM;
 
+    scp->sense_buffer = kzalloc(SCSI_SENSE_BUFFERSIZE, GFP_KERNEL);
+    if (!scp->sense_buffer) {
+       kfree(scp);
+       return -ENOMEM;
+    }
+
     scp->device = sdev;
     memset(&cmndinfo, 0, sizeof(cmndinfo));
 
@@ -500,7 +465,7 @@ int __gdth_execute(struct scsi_device *sdev, gdth_cmd_str *gdtcmd, char *cmnd,
     scp->request = (struct request *)&wait;
     scp->timeout_per_command = timeout*HZ;
     scp->cmd_len = 12;
-    memcpy(scp->cmnd, cmnd, 12);
+    scp->cmnd = cmnd;
     cmndinfo.priority = IOCTL_PRI;
     cmndinfo.internal_cmd_str = gdtcmd;
     cmndinfo.internal_command = 1;
@@ -513,6 +478,7 @@ int __gdth_execute(struct scsi_device *sdev, gdth_cmd_str *gdtcmd, char *cmnd,
     rval = cmndinfo.status;
     if (info)
         *info = cmndinfo.info;
+    kfree(scp->sense_buffer);
     kfree(scp);
     return rval;
 }
@@ -584,125 +550,110 @@ static int __init gdth_search_isa(ulong32 bios_adr)
 #endif /* CONFIG_ISA */
 
 #ifdef CONFIG_PCI
-static void gdth_search_dev(gdth_pci_str *pcistr, ushort *cnt,
-                            ushort vendor, ushort dev);
 
-static int __init gdth_search_pci(gdth_pci_str *pcistr)
+static bool gdth_search_vortex(ushort device)
 {
-    ushort device, cnt;
-    
-    TRACE(("gdth_search_pci()\n"));
-
-    cnt = 0;
-    for (device = 0; device <= PCI_DEVICE_ID_VORTEX_GDT6555; ++device)
-        gdth_search_dev(pcistr, &cnt, PCI_VENDOR_ID_VORTEX, device);
-    for (device = PCI_DEVICE_ID_VORTEX_GDT6x17RP; 
-         device <= PCI_DEVICE_ID_VORTEX_GDTMAXRP; ++device)
-        gdth_search_dev(pcistr, &cnt, PCI_VENDOR_ID_VORTEX, device);
-    gdth_search_dev(pcistr, &cnt, PCI_VENDOR_ID_VORTEX, 
-                    PCI_DEVICE_ID_VORTEX_GDTNEWRX);
-    gdth_search_dev(pcistr, &cnt, PCI_VENDOR_ID_VORTEX, 
-                    PCI_DEVICE_ID_VORTEX_GDTNEWRX2);
-    gdth_search_dev(pcistr, &cnt, PCI_VENDOR_ID_INTEL,
-                    PCI_DEVICE_ID_INTEL_SRC);
-    gdth_search_dev(pcistr, &cnt, PCI_VENDOR_ID_INTEL,
-                    PCI_DEVICE_ID_INTEL_SRC_XSCALE);
-    return cnt;
+       if (device <= PCI_DEVICE_ID_VORTEX_GDT6555)
+               return true;
+       if (device >= PCI_DEVICE_ID_VORTEX_GDT6x17RP &&
+           device <= PCI_DEVICE_ID_VORTEX_GDTMAXRP)
+               return true;
+       if (device == PCI_DEVICE_ID_VORTEX_GDTNEWRX ||
+           device == PCI_DEVICE_ID_VORTEX_GDTNEWRX2)
+               return true;
+       return false;
 }
 
+static int gdth_pci_probe_one(gdth_pci_str *pcistr, gdth_ha_str **ha_out);
+static int gdth_pci_init_one(struct pci_dev *pdev,
+                            const struct pci_device_id *ent);
+static void gdth_pci_remove_one(struct pci_dev *pdev);
+static void gdth_remove_one(gdth_ha_str *ha);
+
 /* Vortex only makes RAID controllers.
  * We do not really want to specify all 550 ids here, so wildcard match.
  */
-static struct pci_device_id gdthtable[] __maybe_unused = {
-    {PCI_VENDOR_ID_VORTEX,PCI_ANY_ID,PCI_ANY_ID, PCI_ANY_ID},
-    {PCI_VENDOR_ID_INTEL,PCI_DEVICE_ID_INTEL_SRC,PCI_ANY_ID,PCI_ANY_ID}, 
-    {PCI_VENDOR_ID_INTEL,PCI_DEVICE_ID_INTEL_SRC_XSCALE,PCI_ANY_ID,PCI_ANY_ID}, 
-    {0}
+static const struct pci_device_id gdthtable[] = {
+       { PCI_VDEVICE(VORTEX, PCI_ANY_ID) },
+       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_SRC) },
+       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_SRC_XSCALE) },
+       { }     /* terminate list */
+};
+MODULE_DEVICE_TABLE(pci, gdthtable);
+
+static struct pci_driver gdth_pci_driver = {
+       .name           = "gdth",
+       .id_table       = gdthtable,
+       .probe          = gdth_pci_init_one,
+       .remove         = gdth_pci_remove_one,
 };
-MODULE_DEVICE_TABLE(pci,gdthtable);
 
-static void __init gdth_search_dev(gdth_pci_str *pcistr, ushort *cnt,
-                                   ushort vendor, ushort device)
+static void gdth_pci_remove_one(struct pci_dev *pdev)
+{
+       gdth_ha_str *ha = pci_get_drvdata(pdev);
+
+       pci_set_drvdata(pdev, NULL);
+
+       list_del(&ha->list);
+       gdth_remove_one(ha);
+
+       pci_disable_device(pdev);
+}
+
+static int gdth_pci_init_one(struct pci_dev *pdev,
+                                      const struct pci_device_id *ent)
 {
-    ulong base0, base1, base2;
-    struct pci_dev *pdev;
+       ushort vendor = pdev->vendor;
+       ushort device = pdev->device;
+       ulong base0, base1, base2;
+       int rc;
+       gdth_pci_str gdth_pcistr;
+       gdth_ha_str *ha = NULL;
     
-    TRACE(("gdth_search_dev() cnt %d vendor %x device %x\n",
-          *cnt, vendor, device));
+       TRACE(("gdth_search_dev() cnt %d vendor %x device %x\n",
+              gdth_ctr_count, vendor, device));
 
-    pdev = NULL;
-    while ((pdev = pci_get_device(vendor, device, pdev))
-           != NULL) {
-        if (pci_enable_device(pdev))
-            continue;
-        if (*cnt >= MAXHA) {
-            pci_dev_put(pdev);
-            return;
-        }
+       memset(&gdth_pcistr, 0, sizeof(gdth_pcistr));
+
+       if (vendor == PCI_VENDOR_ID_VORTEX && !gdth_search_vortex(device))
+               return -ENODEV;
+
+       rc = pci_enable_device(pdev);
+       if (rc)
+               return rc;
+
+       if (gdth_ctr_count >= MAXHA)
+               return -EBUSY;
 
         /* GDT PCI controller found, resources are already in pdev */
-        pcistr[*cnt].pdev = pdev;
-        pcistr[*cnt].irq = pdev->irq;
+       gdth_pcistr.pdev = pdev;
         base0 = pci_resource_flags(pdev, 0);
         base1 = pci_resource_flags(pdev, 1);
         base2 = pci_resource_flags(pdev, 2);
         if (device <= PCI_DEVICE_ID_VORTEX_GDT6000B ||   /* GDT6000/B */
             device >= PCI_DEVICE_ID_VORTEX_GDT6x17RP) {  /* MPR */
             if (!(base0 & IORESOURCE_MEM)) 
-                continue;
-            pcistr[*cnt].dpmem = pci_resource_start(pdev, 0);
+               return -ENODEV;
+           gdth_pcistr.dpmem = pci_resource_start(pdev, 0);
         } else {                                  /* GDT6110, GDT6120, .. */
             if (!(base0 & IORESOURCE_MEM) ||
                 !(base2 & IORESOURCE_MEM) ||
                 !(base1 & IORESOURCE_IO)) 
-                continue;
-            pcistr[*cnt].dpmem = pci_resource_start(pdev, 2);
-            pcistr[*cnt].io_mm = pci_resource_start(pdev, 0);
-            pcistr[*cnt].io    = pci_resource_start(pdev, 1);
+               return -ENODEV;
+           gdth_pcistr.dpmem = pci_resource_start(pdev, 2);
+           gdth_pcistr.io    = pci_resource_start(pdev, 1);
         }
         TRACE2(("Controller found at %d/%d, irq %d, dpmem 0x%lx\n",
-                pcistr[*cnt].pdev->bus->number,
-               PCI_SLOT(pcistr[*cnt].pdev->devfn),
-                pcistr[*cnt].irq, pcistr[*cnt].dpmem));
-        (*cnt)++;
-    }       
-}   
+               gdth_pcistr.pdev->bus->number,
+               PCI_SLOT(gdth_pcistr.pdev->devfn),
+               gdth_pcistr.irq,
+               gdth_pcistr.dpmem));
 
-static void __init gdth_sort_pci(gdth_pci_str *pcistr, int cnt)
-{    
-    gdth_pci_str temp;
-    int i, changed;
-    
-    TRACE(("gdth_sort_pci() cnt %d\n",cnt));
-    if (cnt == 0)
-        return;
+       rc = gdth_pci_probe_one(&gdth_pcistr, &ha);
+       if (rc)
+               return rc;
 
-    do {
-        changed = FALSE;
-        for (i = 0; i < cnt-1; ++i) {
-            if (!reverse_scan) {
-                if ((pcistr[i].pdev->bus->number > pcistr[i+1].pdev->bus->number) ||
-                    (pcistr[i].pdev->bus->number == pcistr[i+1].pdev->bus->number &&
-                     PCI_SLOT(pcistr[i].pdev->devfn) >
-                     PCI_SLOT(pcistr[i+1].pdev->devfn))) {
-                    temp = pcistr[i];
-                    pcistr[i] = pcistr[i+1];
-                    pcistr[i+1] = temp;
-                    changed = TRUE;
-                }
-            } else {
-                if ((pcistr[i].pdev->bus->number < pcistr[i+1].pdev->bus->number) ||
-                    (pcistr[i].pdev->bus->number == pcistr[i+1].pdev->bus->number &&
-                     PCI_SLOT(pcistr[i].pdev->devfn) <
-                     PCI_SLOT(pcistr[i+1].pdev->devfn))) {
-                    temp = pcistr[i];
-                    pcistr[i] = pcistr[i+1];
-                    pcistr[i+1] = temp;
-                    changed = TRUE;
-                }
-            }
-        }
-    } while (changed);
+       return 0;
 }
 #endif /* CONFIG_PCI */
 
@@ -902,7 +853,8 @@ static int __init gdth_init_isa(ulong32 bios_adr,gdth_ha_str *ha)
 #endif /* CONFIG_ISA */
 
 #ifdef CONFIG_PCI
-static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)
+static int gdth_init_pci(struct pci_dev *pdev, gdth_pci_str *pcistr,
+                                  gdth_ha_str *ha)
 {
     register gdt6_dpram_str __iomem *dp6_ptr;
     register gdt6c_dpram_str __iomem *dp6c_ptr;
@@ -914,14 +866,14 @@ static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)
 
     TRACE(("gdth_init_pci()\n"));
 
-    if (pcistr->pdev->vendor == PCI_VENDOR_ID_INTEL)
+    if (pdev->vendor == PCI_VENDOR_ID_INTEL)
         ha->oem_id = OEM_ID_INTEL;
     else
         ha->oem_id = OEM_ID_ICP;
-    ha->brd_phys = (pcistr->pdev->bus->number << 8) | (pcistr->pdev->devfn & 0xf8);
-    ha->stype = (ulong32)pcistr->pdev->device;
-    ha->irq = pcistr->irq;
-    ha->pdev = pcistr->pdev;
+    ha->brd_phys = (pdev->bus->number << 8) | (pdev->devfn & 0xf8);
+    ha->stype = (ulong32)pdev->device;
+    ha->irq = pdev->irq;
+    ha->pdev = pdev;
     
     if (ha->pdev->device <= PCI_DEVICE_ID_VORTEX_GDT6000B) {  /* GDT6000/B */
         TRACE2(("init_pci() dpmem %lx irq %d\n",pcistr->dpmem,ha->irq));
@@ -949,8 +901,7 @@ static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)
                     continue;
                 }
                 iounmap(ha->brd);
-                pci_write_config_dword(pcistr->pdev, 
-                                       PCI_BASE_ADDRESS_0, i);
+               pci_write_config_dword(pdev, PCI_BASE_ADDRESS_0, i);
                 ha->brd = ioremap(i, sizeof(gdt6_dpram_str)); 
                 if (ha->brd == NULL) {
                     printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
@@ -1059,8 +1010,7 @@ static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)
                     continue;
                 }
                 iounmap(ha->brd);
-                pci_write_config_dword(pcistr->pdev, 
-                                       PCI_BASE_ADDRESS_2, i);
+               pci_write_config_dword(pdev, PCI_BASE_ADDRESS_2, i);
                 ha->brd = ioremap(i, sizeof(gdt6c_dpram_str)); 
                 if (ha->brd == NULL) {
                     printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
@@ -1152,16 +1102,16 @@ static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)
         }
 
         /* manipulate config. space to enable DPMEM, start RP controller */
-        pci_read_config_word(pcistr->pdev, PCI_COMMAND, &command);
+       pci_read_config_word(pdev, PCI_COMMAND, &command);
         command |= 6;
-        pci_write_config_word(pcistr->pdev, PCI_COMMAND, command);
-        if (pci_resource_start(pcistr->pdev, 8) == 1UL)
-            pci_resource_start(pcistr->pdev, 8) = 0UL;
+       pci_write_config_word(pdev, PCI_COMMAND, command);
+       if (pci_resource_start(pdev, 8) == 1UL)
+           pci_resource_start(pdev, 8) = 0UL;
         i = 0xFEFF0001UL;
-        pci_write_config_dword(pcistr->pdev, PCI_ROM_ADDRESS, i);
+       pci_write_config_dword(pdev, PCI_ROM_ADDRESS, i);
         gdth_delay(1);
-        pci_write_config_dword(pcistr->pdev, PCI_ROM_ADDRESS,
-                               pci_resource_start(pcistr->pdev, 8));
+       pci_write_config_dword(pdev, PCI_ROM_ADDRESS,
+                              pci_resource_start(pdev, 8));
         
         dp6m_ptr = ha->brd;
 
@@ -1188,8 +1138,7 @@ static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)
                     continue;
                 }
                 iounmap(ha->brd);
-                pci_write_config_dword(pcistr->pdev, 
-                                       PCI_BASE_ADDRESS_0, i);
+               pci_write_config_dword(pdev, PCI_BASE_ADDRESS_0, i);
                 ha->brd = ioremap(i, sizeof(gdt6m_dpram_str)); 
                 if (ha->brd == NULL) {
                     printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
@@ -2346,12 +2295,12 @@ static void gdth_next(gdth_ha_str *ha)
 static void gdth_copy_internal_data(gdth_ha_str *ha, Scsi_Cmnd *scp,
                                     char *buffer, ushort count)
 {
-    ushort cpcount,i, max_sg = gdth_sg_count(scp);
+    ushort cpcount,i, max_sg = scsi_sg_count(scp);
     ushort cpsum,cpnow;
     struct scatterlist *sl;
     char *address;
 
-    cpcount = min_t(ushort, count, gdth_bufflen(scp));
+    cpcount = min_t(ushort, count, scsi_bufflen(scp));
 
     if (cpcount) {
         cpsum=0;
@@ -2359,7 +2308,7 @@ static void gdth_copy_internal_data(gdth_ha_str *ha, Scsi_Cmnd *scp,
             unsigned long flags;
             cpnow = (ushort)sl->length;
             TRACE(("copy_internal() now %d sum %d count %d %d\n",
-                          cpnow, cpsum, cpcount, gdth_bufflen(scp)));
+                          cpnow, cpsum, cpcount, scsi_bufflen(scp)));
             if (cpsum+cpnow > cpcount) 
                 cpnow = cpcount - cpsum;
             cpsum += cpnow;
@@ -2582,10 +2531,10 @@ static int gdth_fill_cache_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp, ushort hdrive)
             cmdp->u.cache.BlockCnt = blockcnt;
         }
 
-        if (gdth_bufflen(scp)) {
+        if (scsi_bufflen(scp)) {
             cmndinfo->dma_dir = (read_write == 1 ?
                 PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE);   
-            sgcnt = pci_map_sg(ha->pdev, gdth_sglist(scp), gdth_sg_count(scp),
+            sgcnt = pci_map_sg(ha->pdev, scsi_sglist(scp), scsi_sg_count(scp),
                                cmndinfo->dma_dir);
             if (mode64) {
                 struct scatterlist *sl;
@@ -2732,7 +2681,7 @@ static int gdth_fill_raw_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp, unchar b)
             cmdp->u.raw64.lun        = l;
             cmdp->u.raw64.bus        = b;
             cmdp->u.raw64.priority   = 0;
-            cmdp->u.raw64.sdlen      = gdth_bufflen(scp);
+            cmdp->u.raw64.sdlen      = scsi_bufflen(scp);
             cmdp->u.raw64.sense_len  = 16;
             cmdp->u.raw64.sense_data = sense_paddr;
             cmdp->u.raw64.direction  = 
@@ -2749,7 +2698,7 @@ static int gdth_fill_raw_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp, unchar b)
             cmdp->u.raw.bus        = b;
             cmdp->u.raw.priority   = 0;
             cmdp->u.raw.link_p     = 0;
-            cmdp->u.raw.sdlen      = gdth_bufflen(scp);
+            cmdp->u.raw.sdlen      = scsi_bufflen(scp);
             cmdp->u.raw.sense_len  = 16;
             cmdp->u.raw.sense_data = sense_paddr;
             cmdp->u.raw.direction  = 
@@ -2758,9 +2707,9 @@ static int gdth_fill_raw_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp, unchar b)
             cmdp->u.raw.sg_ranz    = 0;
         }
 
-        if (gdth_bufflen(scp)) {
+        if (scsi_bufflen(scp)) {
             cmndinfo->dma_dir = PCI_DMA_BIDIRECTIONAL;
-            sgcnt = pci_map_sg(ha->pdev, gdth_sglist(scp), gdth_sg_count(scp),
+            sgcnt = pci_map_sg(ha->pdev, scsi_sglist(scp), scsi_sg_count(scp),
                                cmndinfo->dma_dir);
             if (mode64) {
                 struct scatterlist *sl;
@@ -3381,8 +3330,8 @@ static int gdth_sync_event(gdth_ha_str *ha, int service, unchar index,
             /* retry */
             return 2;
         }
-        if (gdth_bufflen(scp))
-            pci_unmap_sg(ha->pdev, gdth_sglist(scp), gdth_sg_count(scp),
+        if (scsi_bufflen(scp))
+            pci_unmap_sg(ha->pdev, scsi_sglist(scp), scsi_sg_count(scp),
                          cmndinfo->dma_dir);
 
         if (cmndinfo->sense_paddr)
@@ -3774,6 +3723,8 @@ static void gdth_log_event(gdth_evt_data *dvr, char *buffer)
 }
 
 #ifdef GDTH_STATISTICS
+static unchar  gdth_timer_running;
+
 static void gdth_timeout(ulong data)
 {
     ulong32 i;
@@ -3781,7 +3732,10 @@ static void gdth_timeout(ulong data)
     gdth_ha_str *ha;
     ulong flags;
 
-    BUG_ON(list_empty(&gdth_instances));
+    if(unlikely(list_empty(&gdth_instances))) {
+           gdth_timer_running = 0;
+           return;
+    }
 
     ha = list_first_entry(&gdth_instances, gdth_ha_str, list);
     spin_lock_irqsave(&ha->smp_lock, flags);
@@ -3801,6 +3755,22 @@ static void gdth_timeout(ulong data)
     add_timer(&gdth_timer);
     spin_unlock_irqrestore(&ha->smp_lock, flags);
 }
+
+static void gdth_timer_init(void)
+{
+       if (gdth_timer_running)
+               return;
+       gdth_timer_running = 1;
+       TRACE2(("gdth_detect(): Initializing timer !\n"));
+       gdth_timer.expires = jiffies + HZ;
+       gdth_timer.data = 0L;
+       gdth_timer.function = gdth_timeout;
+       add_timer(&gdth_timer);
+}
+#else
+static inline void gdth_timer_init(void)
+{
+}
 #endif
 
 static void __init internal_setup(char *str,int *ints)
@@ -4024,10 +3994,6 @@ static int gdth_queuecommand(struct scsi_cmnd *scp,
     gdth_update_timeout(scp, scp->timeout_per_command * 6);
     cmndinfo->priority = DEFAULT_PRI;
 
-    gdth_set_bufflen(scp, scsi_bufflen(scp));
-    gdth_set_sg_count(scp, scsi_sg_count(scp));
-    gdth_set_sglist(scp, scsi_sglist(scp));
-
     return __gdth_queuecommand(ha, scp, cmndinfo);
 }
 
@@ -4789,6 +4755,7 @@ static int __init gdth_isa_probe_one(ulong32 isa_bios)
        if (error)
                goto out_free_coal_stat;
        list_add_tail(&ha->list, &gdth_instances);
+       gdth_timer_init();
 
        scsi_scan_host(shp);
 
@@ -4919,6 +4886,7 @@ static int __init gdth_eisa_probe_one(ushort eisa_slot)
        if (error)
                goto out_free_coal_stat;
        list_add_tail(&ha->list, &gdth_instances);
+       gdth_timer_init();
 
        scsi_scan_host(shp);
 
@@ -4948,12 +4916,16 @@ static int __init gdth_eisa_probe_one(ushort eisa_slot)
 #endif /* CONFIG_EISA */
 
 #ifdef CONFIG_PCI
-static int __init gdth_pci_probe_one(gdth_pci_str *pcistr, int ctr)
+static int gdth_pci_probe_one(gdth_pci_str *pcistr,
+                            gdth_ha_str **ha_out)
 {
        struct Scsi_Host *shp;
        gdth_ha_str *ha;
        dma_addr_t scratch_dma_handle = 0;
        int error, i;
+       struct pci_dev *pdev = pcistr->pdev;
+
+       *ha_out = NULL;
 
        shp = scsi_host_alloc(&gdth_template, sizeof(gdth_ha_str));
        if (!shp)
@@ -4961,13 +4933,13 @@ static int __init gdth_pci_probe_one(gdth_pci_str *pcistr, int ctr)
        ha = shost_priv(shp);
 
        error = -ENODEV;
-       if (!gdth_init_pci(&pcistr[ctr],ha))
+       if (!gdth_init_pci(pdev, pcistr, ha))
                goto out_host_put;
 
        /* controller found and initialized */
        printk("Configuring GDT-PCI HA at %d/%d IRQ %u\n",
-               pcistr[ctr].pdev->bus->number,
-               PCI_SLOT(pcistr[ctr].pdev->devfn),
+               pdev->bus->number,
+               PCI_SLOT(pdev->devfn),
                ha->irq);
 
        error = request_irq(ha->irq, gdth_interrupt,
@@ -5012,7 +4984,7 @@ static int __init gdth_pci_probe_one(gdth_pci_str *pcistr, int ctr)
 
        ha->scratch_busy = FALSE;
        ha->req_first = NULL;
-       ha->tid_cnt = pcistr[ctr].pdev->device >= 0x200 ? MAXID : MAX_HDRIVES;
+       ha->tid_cnt = pdev->device >= 0x200 ? MAXID : MAX_HDRIVES;
        if (max_ids > 0 && max_ids < ha->tid_cnt)
                ha->tid_cnt = max_ids;
        for (i = 0; i < GDTH_MAXCMDS; ++i)
@@ -5032,16 +5004,16 @@ static int __init gdth_pci_probe_one(gdth_pci_str *pcistr, int ctr)
        /* 64-bit DMA only supported from FW >= x.43 */
        if (!(ha->cache_feat & ha->raw_feat & ha->screen_feat & GDT_64BIT) ||
            !ha->dma64_support) {
-               if (pci_set_dma_mask(pcistr[ctr].pdev, DMA_32BIT_MASK)) {
+               if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) {
                        printk(KERN_WARNING "GDT-PCI %d: "
                                "Unable to set 32-bit DMA\n", ha->hanum);
                                goto out_free_coal_stat;
                }
        } else {
                shp->max_cmd_len = 16;
-               if (!pci_set_dma_mask(pcistr[ctr].pdev, DMA_64BIT_MASK)) {
+               if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)) {
                        printk("GDT-PCI %d: 64-bit DMA enabled\n", ha->hanum);
-               } else if (pci_set_dma_mask(pcistr[ctr].pdev, DMA_32BIT_MASK)) {
+               } else if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) {
                        printk(KERN_WARNING "GDT-PCI %d: "
                                "Unable to set 64/32-bit DMA\n", ha->hanum);
                        goto out_free_coal_stat;
@@ -5055,13 +5027,18 @@ static int __init gdth_pci_probe_one(gdth_pci_str *pcistr, int ctr)
        spin_lock_init(&ha->smp_lock);
        gdth_enable_int(ha);
 
-       error = scsi_add_host(shp, &pcistr[ctr].pdev->dev);
+       error = scsi_add_host(shp, &pdev->dev);
        if (error)
                goto out_free_coal_stat;
        list_add_tail(&ha->list, &gdth_instances);
 
+       pci_set_drvdata(ha->pdev, ha);
+       gdth_timer_init();
+
        scsi_scan_host(shp);
 
+       *ha_out = ha;
+
        return 0;
 
  out_free_coal_stat:
@@ -5156,6 +5133,7 @@ static int __init gdth_init(void)
        /* initializations */
        gdth_polling = TRUE;
        gdth_clear_events();
+       init_timer(&gdth_timer);
 
        /* As default we do not probe for EISA or ISA controllers */
        if (probe_eisa_isa) {
@@ -5178,31 +5156,17 @@ static int __init gdth_init(void)
 
 #ifdef CONFIG_PCI
        /* scanning for PCI controllers */
-       {
-               gdth_pci_str pcistr[MAXHA];
-               int cnt,ctr;
-
-               cnt = gdth_search_pci(pcistr);
-               printk("GDT-HA: Found %d PCI Storage RAID Controllers\n", cnt);
-               gdth_sort_pci(pcistr,cnt);
-               for (ctr = 0; ctr < cnt; ++ctr)
-                       gdth_pci_probe_one(pcistr, ctr);
+       if (pci_register_driver(&gdth_pci_driver)) {
+               gdth_ha_str *ha;
+
+               list_for_each_entry(ha, &gdth_instances, list)
+                       gdth_remove_one(ha);
+               return -ENODEV;
        }
 #endif /* CONFIG_PCI */
 
        TRACE2(("gdth_detect() %d controller detected\n", gdth_ctr_count));
 
-       if (list_empty(&gdth_instances))
-               return -ENODEV;
-
-#ifdef GDTH_STATISTICS
-       TRACE2(("gdth_detect(): Initializing timer !\n"));
-       init_timer(&gdth_timer);
-       gdth_timer.expires = jiffies + HZ;
-       gdth_timer.data = 0L;
-       gdth_timer.function = gdth_timeout;
-       add_timer(&gdth_timer);
-#endif
        major = register_chrdev(0,"gdth", &gdth_fops);
        register_reboot_notifier(&gdth_notifier);
        gdth_polling = FALSE;
@@ -5220,6 +5184,10 @@ static void __exit gdth_exit(void)
        del_timer_sync(&gdth_timer);
 #endif
 
+#ifdef CONFIG_PCI
+       pci_unregister_driver(&gdth_pci_driver);
+#endif
+
        list_for_each_entry(ha, &gdth_instances, list)
                gdth_remove_one(ha);
 }