isci: rely on irq core for intx multiplexing, and silence screaming intx
authorDan Williams <dan.j.williams@intel.com>
Tue, 19 Apr 2011 19:32:51 +0000 (12:32 -0700)
committerDan Williams <dan.j.williams@intel.com>
Sun, 3 Jul 2011 11:00:37 +0000 (04:00 -0700)
Remove the extra logic to poll each controller for interrupts, that's
the core's job for shared interrupts.

While testing noticed that a number of interrupts fire while waiting for
the completion tasklet to run, so added an irq-ack.

Reported-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
drivers/scsi/isci/host.c
drivers/scsi/isci/init.c

index 927f088..0d706b2 100644 (file)
@@ -77,23 +77,19 @@ irqreturn_t isci_msix_isr(int vec, void *data)
 
 irqreturn_t isci_intx_isr(int vec, void *data)
 {
-       struct pci_dev *pdev = data;
-       struct isci_host *ihost;
        irqreturn_t ret = IRQ_NONE;
-       int i;
+       struct isci_host *ihost = data;
+       struct scic_sds_controller *scic = ihost->core_controller;
 
-       for_each_isci_host(i, ihost, pdev) {
-               struct scic_sds_controller *scic = ihost->core_controller;
-
-               if (scic_sds_controller_isr(scic)) {
-                       tasklet_schedule(&ihost->completion_tasklet);
-                       ret = IRQ_HANDLED;
-               } else if (scic_sds_controller_error_isr(scic)) {
-                       spin_lock(&ihost->scic_lock);
-                       scic_sds_controller_error_handler(scic);
-                       spin_unlock(&ihost->scic_lock);
-                       ret = IRQ_HANDLED;
-               }
+       if (scic_sds_controller_isr(scic)) {
+               writel(SMU_ISR_COMPLETION, &scic->smu_registers->interrupt_status);
+               tasklet_schedule(&ihost->completion_tasklet);
+               ret = IRQ_HANDLED;
+       } else if (scic_sds_controller_error_isr(scic)) {
+               spin_lock(&ihost->scic_lock);
+               scic_sds_controller_error_handler(scic);
+               spin_unlock(&ihost->scic_lock);
+               ret = IRQ_HANDLED;
        }
 
        return ret;
index 015ce94..5a9cd5f 100644 (file)
@@ -335,6 +335,7 @@ static int num_controllers(struct pci_dev *pdev)
 static int isci_setup_interrupts(struct pci_dev *pdev)
 {
        int err, i, num_msix;
+       struct isci_host *ihost;
        struct isci_pci_info *pci_info = to_pci_info(pdev);
 
        /*
@@ -353,9 +354,9 @@ static int isci_setup_interrupts(struct pci_dev *pdev)
        for (i = 0; i < num_msix; i++) {
                int id = i / SCI_NUM_MSI_X_INT;
                struct msix_entry *msix = &pci_info->msix_entries[i];
-               struct isci_host *isci_host = pci_info->hosts[id];
                irq_handler_t isr;
 
+               ihost = pci_info->hosts[id];
                /* odd numbered vectors are error interrupts */
                if (i & 1)
                        isr = isci_error_isr;
@@ -363,16 +364,16 @@ static int isci_setup_interrupts(struct pci_dev *pdev)
                        isr = isci_msix_isr;
 
                err = devm_request_irq(&pdev->dev, msix->vector, isr, 0,
-                                      DRV_NAME"-msix", isci_host);
+                                      DRV_NAME"-msix", ihost);
                if (!err)
                        continue;
 
                dev_info(&pdev->dev, "msix setup failed falling back to intx\n");
                while (i--) {
                        id = i / SCI_NUM_MSI_X_INT;
-                       isci_host = pci_info->hosts[id];
+                       ihost = pci_info->hosts[id];
                        msix = &pci_info->msix_entries[i];
-                       devm_free_irq(&pdev->dev, msix->vector, isci_host);
+                       devm_free_irq(&pdev->dev, msix->vector, ihost);
                }
                pci_disable_msix(pdev);
                goto intx;
@@ -380,8 +381,12 @@ static int isci_setup_interrupts(struct pci_dev *pdev)
        return 0;
 
  intx:
-       err = devm_request_irq(&pdev->dev, pdev->irq, isci_intx_isr,
-                              IRQF_SHARED, DRV_NAME"-intx", pdev);
+       for_each_isci_host(i, ihost, pdev) {
+               err = devm_request_irq(&pdev->dev, pdev->irq, isci_intx_isr,
+                                      IRQF_SHARED, DRV_NAME"-intx", ihost);
+               if (err)
+                       break;
+       }
        return err;
 }