rk_fiq_debugger: map signal irq for fiq mode
[firefly-linux-kernel-4.4.55.git] / drivers / scsi / aacraid / commsup.c
index 4da574925284454cdba9cd6d6cc036bffc3dcdea..8c758c36fc709b931dd43df173c3cca09d0abf7e 100644 (file)
@@ -83,13 +83,38 @@ static int fib_map_alloc(struct aac_dev *dev)
 
 void aac_fib_map_free(struct aac_dev *dev)
 {
-       pci_free_consistent(dev->pdev,
-         dev->max_fib_size * (dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB),
-         dev->hw_fib_va, dev->hw_fib_pa);
+       if (dev->hw_fib_va && dev->max_fib_size) {
+               pci_free_consistent(dev->pdev,
+               (dev->max_fib_size *
+               (dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB)),
+               dev->hw_fib_va, dev->hw_fib_pa);
+       }
        dev->hw_fib_va = NULL;
        dev->hw_fib_pa = 0;
 }
 
+void aac_fib_vector_assign(struct aac_dev *dev)
+{
+       u32 i = 0;
+       u32 vector = 1;
+       struct fib *fibptr = NULL;
+
+       for (i = 0, fibptr = &dev->fibs[i];
+               i < (dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB);
+               i++, fibptr++) {
+               if ((dev->max_msix == 1) ||
+                 (i > ((dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB - 1)
+                       - dev->vector_cap))) {
+                       fibptr->vector_no = 0;
+               } else {
+                       fibptr->vector_no = vector;
+                       vector++;
+                       if (vector == dev->max_msix)
+                               vector = 1;
+               }
+       }
+}
+
 /**
  *     aac_fib_setup   -       setup the fibs
  *     @dev: Adapter to set up
@@ -151,6 +176,12 @@ int aac_fib_setup(struct aac_dev * dev)
                hw_fib_pa = hw_fib_pa +
                        dev->max_fib_size + sizeof(struct aac_fib_xporthdr);
        }
+
+       /*
+        *Assign vector numbers to fibs
+        */
+       aac_fib_vector_assign(dev);
+
        /*
         *      Add the fib chain to the free list
         */
@@ -580,10 +611,10 @@ int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size,
                                        }
                                        return -EFAULT;
                                }
-                               /* We used to udelay() here but that absorbed
-                                * a CPU when a timeout occured. Not very
-                                * useful. */
-                               cpu_relax();
+                               /*
+                                * Allow other processes / CPUS to use core
+                                */
+                               schedule();
                        }
                } else if (down_interruptible(&fibptr->event_wait)) {
                        /* Do nothing ... satisfy
@@ -1270,13 +1301,12 @@ retry_next:
 static int _aac_reset_adapter(struct aac_dev *aac, int forced)
 {
        int index, quirks;
-       int retval, i;
+       int retval;
        struct Scsi_Host *host;
        struct scsi_device *dev;
        struct scsi_cmnd *command;
        struct scsi_cmnd *command_list;
        int jafo = 0;
-       int cpu;
 
        /*
         * Assumptions:
@@ -1339,35 +1369,7 @@ static int _aac_reset_adapter(struct aac_dev *aac, int forced)
        aac->comm_phys = 0;
        kfree(aac->queues);
        aac->queues = NULL;
-       cpu = cpumask_first(cpu_online_mask);
-       if (aac->pdev->device == PMC_DEVICE_S6 ||
-           aac->pdev->device == PMC_DEVICE_S7 ||
-           aac->pdev->device == PMC_DEVICE_S8 ||
-           aac->pdev->device == PMC_DEVICE_S9) {
-               if (aac->max_msix > 1) {
-                       for (i = 0; i < aac->max_msix; i++) {
-                               if (irq_set_affinity_hint(
-                                   aac->msixentry[i].vector,
-                                   NULL)) {
-                                       printk(KERN_ERR "%s%d: Failed to reset IRQ affinity for cpu %d\n",
-                                               aac->name,
-                                               aac->id,
-                                               cpu);
-                               }
-                               cpu = cpumask_next(cpu,
-                                               cpu_online_mask);
-                               free_irq(aac->msixentry[i].vector,
-                                        &(aac->aac_msix[i]));
-                       }
-                       pci_disable_msix(aac->pdev);
-               } else {
-                       free_irq(aac->pdev->irq, &(aac->aac_msix[0]));
-               }
-       } else {
-               free_irq(aac->pdev->irq, aac);
-       }
-       if (aac->msi)
-               pci_disable_msi(aac->pdev);
+       aac_free_irq(aac);
        kfree(aac->fsa_dev);
        aac->fsa_dev = NULL;
        quirks = aac_get_driver_ident(index)->quirks;
@@ -1968,6 +1970,10 @@ int aac_command_thread(void *data)
                if (difference <= 0)
                        difference = 1;
                set_current_state(TASK_INTERRUPTIBLE);
+
+               if (kthread_should_stop())
+                       break;
+
                schedule_timeout(difference);
 
                if (kthread_should_stop())
@@ -1978,3 +1984,83 @@ int aac_command_thread(void *data)
        dev->aif_thread = 0;
        return 0;
 }
+
+int aac_acquire_irq(struct aac_dev *dev)
+{
+       int i;
+       int j;
+       int ret = 0;
+       int cpu;
+
+       cpu = cpumask_first(cpu_online_mask);
+       if (!dev->sync_mode && dev->msi_enabled && dev->max_msix > 1) {
+               for (i = 0; i < dev->max_msix; i++) {
+                       dev->aac_msix[i].vector_no = i;
+                       dev->aac_msix[i].dev = dev;
+                       if (request_irq(dev->msixentry[i].vector,
+                                       dev->a_ops.adapter_intr,
+                                       0, "aacraid", &(dev->aac_msix[i]))) {
+                               printk(KERN_ERR "%s%d: Failed to register IRQ for vector %d.\n",
+                                               dev->name, dev->id, i);
+                               for (j = 0 ; j < i ; j++)
+                                       free_irq(dev->msixentry[j].vector,
+                                                &(dev->aac_msix[j]));
+                               pci_disable_msix(dev->pdev);
+                               ret = -1;
+                       }
+                       if (irq_set_affinity_hint(dev->msixentry[i].vector,
+                                                       get_cpu_mask(cpu))) {
+                               printk(KERN_ERR "%s%d: Failed to set IRQ affinity for cpu %d\n",
+                                           dev->name, dev->id, cpu);
+                       }
+                       cpu = cpumask_next(cpu, cpu_online_mask);
+               }
+       } else {
+               dev->aac_msix[0].vector_no = 0;
+               dev->aac_msix[0].dev = dev;
+
+               if (request_irq(dev->pdev->irq, dev->a_ops.adapter_intr,
+                       IRQF_SHARED, "aacraid",
+                       &(dev->aac_msix[0])) < 0) {
+                       if (dev->msi)
+                               pci_disable_msi(dev->pdev);
+                       printk(KERN_ERR "%s%d: Interrupt unavailable.\n",
+                                       dev->name, dev->id);
+                       ret = -1;
+               }
+       }
+       return ret;
+}
+
+void aac_free_irq(struct aac_dev *dev)
+{
+       int i;
+       int cpu;
+
+       cpu = cpumask_first(cpu_online_mask);
+       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) {
+               if (dev->max_msix > 1) {
+                       for (i = 0; i < dev->max_msix; i++) {
+                               if (irq_set_affinity_hint(
+                                       dev->msixentry[i].vector, NULL)) {
+                                       printk(KERN_ERR "%s%d: Failed to reset IRQ affinity for cpu %d\n",
+                                           dev->name, dev->id, cpu);
+                               }
+                               cpu = cpumask_next(cpu, cpu_online_mask);
+                               free_irq(dev->msixentry[i].vector,
+                                               &(dev->aac_msix[i]));
+                       }
+               } else {
+                       free_irq(dev->pdev->irq, &(dev->aac_msix[0]));
+               }
+       } else {
+               free_irq(dev->pdev->irq, dev);
+       }
+       if (dev->msi)
+               pci_disable_msi(dev->pdev);
+       else if (dev->max_msix > 1)
+               pci_disable_msix(dev->pdev);
+}