aacraid: IOP RESET command handling changes
[deliverable/linux.git] / drivers / scsi / aacraid / comminit.c
index 177b094c7792133d25b550ff7522b54f92dc1950..284b1c54be7fc37b54f85dc32340a609dae8b9ba 100644 (file)
@@ -43,6 +43,8 @@
 
 #include "aacraid.h"
 
+static void aac_define_int_mode(struct aac_dev *dev);
+
 struct aac_common aac_config = {
        .irq_mod = 1
 };
@@ -91,7 +93,7 @@ static int aac_alloc_comm(struct aac_dev *dev, void **commaddr, unsigned long co
        init->InitStructRevision = cpu_to_le32(ADAPTER_INIT_STRUCT_REVISION);
        if (dev->max_fib_size != sizeof(struct hw_fib))
                init->InitStructRevision = cpu_to_le32(ADAPTER_INIT_STRUCT_REVISION_4);
-       init->MiniPortRevision = cpu_to_le32(Sa_MINIPORT_REVISION);
+       init->Sa_MSIXVectors = cpu_to_le32(Sa_MINIPORT_REVISION);
        init->fsrev = cpu_to_le32(dev->fsrev);
 
        /*
@@ -140,7 +142,8 @@ static int aac_alloc_comm(struct aac_dev *dev, void **commaddr, unsigned long co
                        INITFLAGS_NEW_COMM_TYPE2_SUPPORTED | INITFLAGS_FAST_JBOD_SUPPORTED);
                init->HostRRQ_AddrHigh = cpu_to_le32((u32)((u64)dev->host_rrq_pa >> 32));
                init->HostRRQ_AddrLow = cpu_to_le32((u32)(dev->host_rrq_pa & 0xffffffff));
-               init->MiniPortRevision = cpu_to_le32(0L);               /* number of MSI-X */
+               /* number of MSI-X */
+               init->Sa_MSIXVectors = cpu_to_le32(dev->max_msix);
                dprintk((KERN_WARNING"aacraid: New Comm Interface type2 enabled\n"));
        }
 
@@ -228,6 +231,11 @@ int aac_send_shutdown(struct aac_dev * dev)
        /* FIB should be freed only after getting the response from the F/W */
        if (status != -ERESTARTSYS)
                aac_fib_free(fibctx);
+       if ((dev->pdev->device == PMC_DEVICE_S7 ||
+            dev->pdev->device == PMC_DEVICE_S8 ||
+            dev->pdev->device == PMC_DEVICE_S9) &&
+            dev->msi_enabled)
+               aac_src_access_devreg(dev, AAC_ENABLE_INTX);
        return status;
 }
 
@@ -350,8 +358,10 @@ struct aac_dev *aac_init_adapter(struct aac_dev *dev)
        dev->raw_io_interface = dev->raw_io_64 = 0;
 
        if ((!aac_adapter_sync_cmd(dev, GET_ADAPTER_PROPERTIES,
-               0, 0, 0, 0, 0, 0, status+0, status+1, status+2, NULL, NULL)) &&
+               0, 0, 0, 0, 0, 0,
+               status+0, status+1, status+2, status+3, NULL)) &&
                        (status[0] == 0x00000001)) {
+               dev->doorbell_mask = status[3];
                if (status[1] & le32_to_cpu(AAC_OPT_NEW_COMM_64))
                        dev->raw_io_64 = 1;
                dev->sync_mode = aac_sync_mode;
@@ -388,6 +398,8 @@ struct aac_dev *aac_init_adapter(struct aac_dev *dev)
                        }
                }
        }
+       dev->max_msix = 0;
+       dev->msi_enabled = 0;
        if ((!aac_adapter_sync_cmd(dev, GET_COMM_PREFERRED_SETTINGS,
          0, 0, 0, 0, 0, 0,
          status+0, status+1, status+2, status+3, status+4))
@@ -461,6 +473,11 @@ struct aac_dev *aac_init_adapter(struct aac_dev *dev)
        if (host->can_queue > AAC_NUM_IO_FIB)
                host->can_queue = AAC_NUM_IO_FIB;
 
+       if (dev->pdev->device == PMC_DEVICE_S6 ||
+           dev->pdev->device == PMC_DEVICE_S7 ||
+           dev->pdev->device == PMC_DEVICE_S8 ||
+           dev->pdev->device == PMC_DEVICE_S9)
+               aac_define_int_mode(dev);
        /*
         *      Ok now init the communication subsystem
         */
@@ -489,4 +506,78 @@ struct aac_dev *aac_init_adapter(struct aac_dev *dev)
        return dev;
 }
 
-    
+static void aac_define_int_mode(struct aac_dev *dev)
+{
+
+       int i, msi_count;
+
+       /* max. vectors from GET_COMM_PREFERRED_SETTINGS */
+       if (dev->max_msix == 0 ||
+           dev->pdev->device == PMC_DEVICE_S6 ||
+           dev->sync_mode) {
+               dev->max_msix = 1;
+               dev->vector_cap =
+                       dev->scsi_host_ptr->can_queue +
+                       AAC_NUM_MGT_FIB;
+               return;
+       }
+
+       msi_count = min(dev->max_msix,
+               (unsigned int)num_online_cpus());
+
+       dev->max_msix = msi_count;
+
+       if (msi_count > AAC_MAX_MSIX)
+               msi_count = AAC_MAX_MSIX;
+
+       for (i = 0; i < msi_count; i++)
+               dev->msixentry[i].entry = i;
+
+       if (msi_count > 1 &&
+           pci_find_capability(dev->pdev, PCI_CAP_ID_MSIX)) {
+               i = pci_enable_msix(dev->pdev,
+                                   dev->msixentry,
+                                   msi_count);
+                /* Check how many MSIX vectors are allocated */
+               if (i >= 0) {
+                       dev->msi_enabled = 1;
+                       if (i) {
+                               msi_count = i;
+                               if (pci_enable_msix(dev->pdev,
+                                   dev->msixentry,
+                                   msi_count)) {
+                                       dev->msi_enabled = 0;
+                                       printk(KERN_ERR "%s%d: MSIX not supported!! Will try MSI 0x%x.\n",
+                                                       dev->name, dev->id, i);
+                               }
+                       }
+               } else {
+                       dev->msi_enabled = 0;
+                       printk(KERN_ERR "%s%d: MSIX not supported!! Will try MSI 0x%x.\n",
+                                       dev->name, dev->id, i);
+               }
+       }
+
+       if (!dev->msi_enabled) {
+               msi_count = 1;
+               i = pci_enable_msi(dev->pdev);
+
+               if (!i) {
+                       dev->msi_enabled = 1;
+                       dev->msi = 1;
+               } else {
+                       printk(KERN_ERR "%s%d: MSI not supported!! Will try INTx 0x%x.\n",
+                                       dev->name, dev->id, i);
+               }
+       }
+
+       if (!dev->msi_enabled)
+               dev->max_msix = msi_count = 1;
+       else {
+               if (dev->max_msix > msi_count)
+                       dev->max_msix = msi_count;
+       }
+       dev->vector_cap =
+               (dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB) /
+               msi_count;
+}
This page took 0.039836 seconds and 5 git commands to generate.