summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDan Williams <dan.j.williams@intel.com>2011-04-19 12:32:51 -0700
committerDan Williams <dan.j.williams@intel.com>2011-07-03 04:00:37 -0700
commit31e824ed0d8c84c5232405167b2338ffc071ae8a (patch)
treed63462e4a808ef9992632e9261a65be4a51ba471
parente2023b8735956bb78f167d0fdc575364e69b02c4 (diff)
downloadblackbird-op-linux-31e824ed0d8c84c5232405167b2338ffc071ae8a.tar.gz
blackbird-op-linux-31e824ed0d8c84c5232405167b2338ffc071ae8a.zip
isci: rely on irq core for intx multiplexing, and silence screaming intx
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>
-rw-r--r--drivers/scsi/isci/host.c26
-rw-r--r--drivers/scsi/isci/init.c17
2 files changed, 22 insertions, 21 deletions
diff --git a/drivers/scsi/isci/host.c b/drivers/scsi/isci/host.c
index 927f08892ad6..0d706b2ce25e 100644
--- a/drivers/scsi/isci/host.c
+++ b/drivers/scsi/isci/host.c
@@ -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;
diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c
index 015ce94453bb..5a9cd5fbeab9 100644
--- a/drivers/scsi/isci/init.c
+++ b/drivers/scsi/isci/init.c
@@ -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;
}
OpenPOWER on IntegriCloud