Merge mulgrave-w:git/scsi-misc-2.6
[powerpc.git] / drivers / scsi / aacraid / linit.c
index c259633..d67058f 100644 (file)
  * Abstract: Linux Driver entry module for Adaptec RAID Array Controller
  */
 
-#define AAC_DRIVER_VERSION             "1.1-4"
-#ifndef AAC_DRIVER_BRANCH
-#define AAC_DRIVER_BRANCH              ""
-#endif
-#define AAC_DRIVER_BUILD_DATE          __DATE__ " " __TIME__
-#define AAC_DRIVERNAME                 "aacraid"
 
 #include <linux/compat.h>
 #include <linux/blkdev.h>
@@ -45,6 +39,7 @@
 #include <linux/pci.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
+#include <linux/dma-mapping.h>
 #include <linux/syscalls.h>
 #include <linux/delay.h>
 #include <linux/smp_lock.h>
 
 #include "aacraid.h"
 
+#define AAC_DRIVER_VERSION             "1.1-5"
+#ifndef AAC_DRIVER_BRANCH
+#define AAC_DRIVER_BRANCH              ""
+#endif
+#define AAC_DRIVER_BUILD_DATE          __DATE__ " " __TIME__
+#define AAC_DRIVERNAME                 "aacraid"
+
 #ifdef AAC_DRIVER_BUILD
 #define _str(x) #x
 #define str(x) _str(x)
@@ -72,7 +74,7 @@
 MODULE_AUTHOR("Red Hat Inc and Adaptec");
 MODULE_DESCRIPTION("Dell PERC2, 2/Si, 3/Si, 3/Di, "
                   "Adaptec Advanced Raid Products, "
-                  "and HP NetRAID-4M SCSI driver");
+                  "HP NetRAID-4M, IBM ServeRAID & ICP SCSI driver");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(AAC_DRIVER_FULL_VERSION);
 
@@ -117,7 +119,7 @@ static struct pci_device_id aac_pci_tbl[] = {
        { 0x9005, 0x0286, 0x9005, 0x029f, 0, 0, 26 }, /* ICP9014R0 (Lancer) */
        { 0x9005, 0x0286, 0x9005, 0x02a0, 0, 0, 27 }, /* ICP9047MA (Lancer) */
        { 0x9005, 0x0286, 0x9005, 0x02a1, 0, 0, 28 }, /* ICP9087MA (Lancer) */
-       { 0x9005, 0x0286, 0x9005, 0x02a3, 0, 0, 29 }, /* ICP5085AU (Hurricane) */
+       { 0x9005, 0x0286, 0x9005, 0x02a3, 0, 0, 29 }, /* ICP5445AU (Hurricane44) */
        { 0x9005, 0x0285, 0x9005, 0x02a4, 0, 0, 30 }, /* ICP9085LI (Marauder-X) */
        { 0x9005, 0x0285, 0x9005, 0x02a5, 0, 0, 31 }, /* ICP5085BR (Marauder-E) */
        { 0x9005, 0x0286, 0x9005, 0x02a6, 0, 0, 32 }, /* ICP9067MA (Intruder-6) */
@@ -141,7 +143,7 @@ static struct pci_device_id aac_pci_tbl[] = {
        { 0x9005, 0x0285, 0x9005, 0x0298, 0, 0, 48 }, /* ASR-4000SAS (BlackBird) */
        { 0x9005, 0x0285, 0x9005, 0x0299, 0, 0, 49 }, /* ASR-4800SAS (Marauder-X) */
        { 0x9005, 0x0285, 0x9005, 0x029a, 0, 0, 50 }, /* ASR-4805SAS (Marauder-E) */
-       { 0x9005, 0x0286, 0x9005, 0x02a2, 0, 0, 51 }, /* ASR-4810SAS (Hurricane */
+       { 0x9005, 0x0286, 0x9005, 0x02a2, 0, 0, 51 }, /* ASR-3800SAS (Hurricane44) */
 
        { 0x9005, 0x0285, 0x1028, 0x0287, 0, 0, 52 }, /* Perc 320/DC*/
        { 0x1011, 0x0046, 0x9005, 0x0365, 0, 0, 53 }, /* Adaptec 5400S (Mustang)*/
@@ -193,7 +195,7 @@ static struct aac_driver_ident aac_drivers[] = {
        { aac_rkt_init, "aacraid",  "ICP     ", "ICP9014R0       ", 1 }, /* ICP9014R0 (Lancer) */
        { aac_rkt_init, "aacraid",  "ICP     ", "ICP9047MA       ", 1 }, /* ICP9047MA (Lancer) */
        { aac_rkt_init, "aacraid",  "ICP     ", "ICP9087MA       ", 1 }, /* ICP9087MA (Lancer) */
-       { aac_rkt_init, "aacraid",  "ICP     ", "ICP5085AU       ", 1 }, /* ICP5085AU (Hurricane) */
+       { aac_rkt_init, "aacraid",  "ICP     ", "ICP5445AU       ", 1 }, /* ICP5445AU (Hurricane44) */
        { aac_rx_init, "aacraid",  "ICP     ", "ICP9085LI       ", 1 }, /* ICP9085LI (Marauder-X) */
        { aac_rx_init, "aacraid",  "ICP     ", "ICP5085BR       ", 1 }, /* ICP5085BR (Marauder-E) */
        { aac_rkt_init, "aacraid",  "ICP     ", "ICP9067MA       ", 1 }, /* ICP9067MA (Intruder-6) */
@@ -215,7 +217,7 @@ static struct aac_driver_ident aac_drivers[] = {
        { aac_rx_init, "aacraid",  "ADAPTEC ", "ASR-4000SAS     ", 1 }, /* ASR-4000SAS (BlackBird & AvonPark) */
        { aac_rx_init, "aacraid",  "ADAPTEC ", "ASR-4800SAS     ", 1 }, /* ASR-4800SAS (Marauder-X) */
        { aac_rx_init, "aacraid",  "ADAPTEC ", "ASR-4805SAS     ", 1 }, /* ASR-4805SAS (Marauder-E) */
-       { aac_rkt_init, "aacraid",  "ADAPTEC ", "ASR-4810SAS     ", 1 }, /* ASR-4810SAS (Hurricane) */
+       { aac_rkt_init, "aacraid",  "ADAPTEC ", "ASR-3800SAS     ", 1 }, /* ASR-3800SAS (Hurricane44) */
 
        { aac_rx_init, "percraid", "DELL    ", "PERC 320/DC     ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG }, /* Perc 320/DC*/
        { aac_sa_init, "aacraid",  "ADAPTEC ", "Adaptec 5400S   ", 4, AAC_QUIRK_34SG }, /* Adaptec 5400S (Mustang)*/
@@ -242,6 +244,7 @@ static struct aac_driver_ident aac_drivers[] = {
 static int aac_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
 {
        cmd->scsi_done = done;
+       cmd->SCp.phase = AAC_OWNER_LOWLEVEL;
        return (aac_scsi_cmd(cmd) ? FAILED : 0);
 } 
 
@@ -450,27 +453,23 @@ static int aac_eh_reset(struct scsi_cmnd* cmd)
 
        printk(KERN_ERR "%s: Host adapter reset request. SCSI hang ?\n", 
                                        AAC_DRIVERNAME);
-
-
-       spin_lock_irq(host->host_lock);
-
        aac = (struct aac_dev *)host->hostdata;
-       if (aac_adapter_check_health(aac)) {
-               printk(KERN_ERR "%s: Host adapter appears dead\n", 
-                               AAC_DRIVERNAME);
-               spin_unlock_irq(host->host_lock);
-               return -ENODEV;
-       }
+
+       if ((count = aac_check_health(aac)))
+               return count;
        /*
         * Wait for all commands to complete to this specific
         * target (block maximum 60 seconds).
         */
        for (count = 60; count; --count) {
-               int active = 0;
+               int active = aac->in_reset;
+
+               if (active == 0)
                __shost_for_each_device(dev, host) {
                        spin_lock_irqsave(&dev->list_lock, flags);
                        list_for_each_entry(command, &dev->cmd_list, list) {
-                               if (command->serial_number) {
+                               if ((command != cmd) &&
+                                   (command->SCp.phase == AAC_OWNER_FIRMWARE)) {
                                        active++;
                                        break;
                                }
@@ -483,13 +482,10 @@ static int aac_eh_reset(struct scsi_cmnd* cmd)
                /*
                 * We can exit If all the commands are complete
                 */
-               spin_unlock_irq(host->host_lock);
                if (active == 0)
                        return SUCCESS;
                ssleep(1);
-               spin_lock_irq(host->host_lock);
        }
-       spin_unlock_irq(host->host_lock);
        printk(KERN_ERR "%s: SCSI bus appears hung\n", AAC_DRIVERNAME);
        return -ETIMEDOUT;
 }
@@ -568,12 +564,12 @@ static long aac_compat_do_ioctl(struct aac_dev *dev, unsigned cmd, unsigned long
                
                f = compat_alloc_user_space(sizeof(*f));
                ret = 0;
-               if (clear_user(f, sizeof(*f) != sizeof(*f)))
+               if (clear_user(f, sizeof(*f)))
                        ret = -EFAULT;
                if (copy_in_user(f, (void __user *)arg, sizeof(struct fib_ioctl) - sizeof(u32)))
                        ret = -EFAULT;
                if (!ret)
-                       ret = aac_do_ioctl(dev, cmd, (void __user *)arg);
+                       ret = aac_do_ioctl(dev, cmd, f);
                break;
        }
 
@@ -686,6 +682,18 @@ static ssize_t aac_show_serial_number(struct class_device *class_dev,
        return len;
 }
 
+static ssize_t aac_show_max_channel(struct class_device *class_dev, char *buf)
+{
+       return snprintf(buf, PAGE_SIZE, "%d\n",
+         class_to_shost(class_dev)->max_channel);
+}
+
+static ssize_t aac_show_max_id(struct class_device *class_dev, char *buf)
+{
+       return snprintf(buf, PAGE_SIZE, "%d\n",
+         class_to_shost(class_dev)->max_id);
+}
+
 
 static struct class_device_attribute aac_model = {
        .attr = {
@@ -729,6 +737,20 @@ static struct class_device_attribute aac_serial_number = {
        },
        .show = aac_show_serial_number,
 };
+static struct class_device_attribute aac_max_channel = {
+       .attr = {
+               .name = "max_channel",
+               .mode = S_IRUGO,
+       },
+       .show = aac_show_max_channel,
+};
+static struct class_device_attribute aac_max_id = {
+       .attr = {
+               .name = "max_id",
+               .mode = S_IRUGO,
+       },
+       .show = aac_show_max_id,
+};
 
 static struct class_device_attribute *aac_attrs[] = {
        &aac_model,
@@ -737,6 +759,8 @@ static struct class_device_attribute *aac_attrs[] = {
        &aac_monitor_version,
        &aac_bios_version,
        &aac_serial_number,
+       &aac_max_channel,
+       &aac_max_id,
        NULL
 };
 
@@ -774,6 +798,7 @@ static struct scsi_host_template aac_driver_template = {
        .cmd_per_lun                    = AAC_NUM_IO_FIB, 
 #endif 
        .use_clustering                 = ENABLE_CLUSTERING,
+       .emulated                       = 1,
 };
 
 
@@ -797,18 +822,19 @@ static int __devinit aac_probe_one(struct pci_dev *pdev,
        error = pci_enable_device(pdev);
        if (error)
                goto out;
+       error = -ENODEV;
 
        if (pci_set_dma_mask(pdev, DMA_32BIT_MASK) || 
                        pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK))
-               goto out;
+               goto out_disable_pdev;
        /*
         * If the quirk31 bit is set, the adapter needs adapter
         * to driver communication memory to be allocated below 2gig
         */
        if (aac_drivers[index].quirks & AAC_QUIRK_31BIT) 
-               if (pci_set_dma_mask(pdev, 0x7FFFFFFFULL) ||
-                               pci_set_consistent_dma_mask(pdev, 0x7FFFFFFFULL))
-                       goto out;
+               if (pci_set_dma_mask(pdev, DMA_31BIT_MASK) ||
+                               pci_set_consistent_dma_mask(pdev, DMA_31BIT_MASK))
+                       goto out_disable_pdev;
        
        pci_set_master(pdev);
 
@@ -903,11 +929,11 @@ static int __devinit aac_probe_one(struct pci_dev *pdev,
         * physical channels are address by their actual physical number+1
         */
        if (aac->nondasd_support == 1)
-               shost->max_channel = aac->maximum_num_channels + 1;
+               shost->max_channel = aac->maximum_num_channels;
        else
-               shost->max_channel = 1;
+               shost->max_channel = 0;
 
-       aac_get_config_status(aac);
+       aac_get_config_status(aac, 0);
        aac_get_containers(aac);
        list_add(&aac->entry, insert);
 
@@ -987,6 +1013,10 @@ static void __devexit aac_remove_one(struct pci_dev *pdev)
        list_del(&aac->entry);
        scsi_host_put(shost);
        pci_disable_device(pdev);
+       if (list_empty(&aac_devices)) {
+               unregister_chrdev(aac_cfg_major, "aac");
+               aac_cfg_major = -1;
+       }
 }
 
 static struct pci_driver aac_pci_driver = {
@@ -1019,7 +1049,8 @@ static int __init aac_init(void)
 
 static void __exit aac_exit(void)
 {
-       unregister_chrdev(aac_cfg_major, "aac");
+       if (aac_cfg_major > -1)
+               unregister_chrdev(aac_cfg_major, "aac");
        pci_unregister_driver(&aac_pci_driver);
 }