aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/lpfc/lpfc_sli.c
diff options
context:
space:
mode:
authorJames Smart <James.Smart@Emulex.Com>2008-12-04 22:39:35 -0500
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2008-12-29 12:24:27 -0500
commit5b75da2fa2c9570c3c3dbb2f63cae5b4183e0ca3 (patch)
tree618f67c4fd9cda1d60aa24d04262e4fb3ee2911f /drivers/scsi/lpfc/lpfc_sli.c
parenteaf15d5b5605e1a403f631489de30a49fd66905d (diff)
[SCSI] lpfc 8.3.0 : Add active interrupt test for enabling MSI/MSI-X/INTx
Per the recent discussions at the Linux Plumbers Conference, when enabling MSI or MSI-X, generate a test interrupt to verify the interrupt routing is working properly. If the test interrupt fails, fall back to MSI first, and if that fails as well, to INTx. If the interrupt test fails with INTx, log an error and fail the PCI probe. Also changed the use of spin_(lock|unlock) to the _irq(save|restore) variants in the interrupt handlers because with multi-message MSI-X, both interrupt handlers can now run in parallel. Signed-off-by: James Smart <James.Smart@emulex.com> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_sli.c')
-rw-r--r--drivers/scsi/lpfc/lpfc_sli.c38
1 files changed, 22 insertions, 16 deletions
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index eadc19346408..4e5b4ee121f1 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -5238,6 +5238,7 @@ lpfc_sp_intr_handler(int irq, void *dev_id)
5238 uint32_t ha_copy; 5238 uint32_t ha_copy;
5239 uint32_t work_ha_copy; 5239 uint32_t work_ha_copy;
5240 unsigned long status; 5240 unsigned long status;
5241 unsigned long iflag;
5241 uint32_t control; 5242 uint32_t control;
5242 5243
5243 MAILBOX_t *mbox, *pmbox; 5244 MAILBOX_t *mbox, *pmbox;
@@ -5270,7 +5271,7 @@ lpfc_sp_intr_handler(int irq, void *dev_id)
5270 if (unlikely(phba->link_state < LPFC_LINK_DOWN)) 5271 if (unlikely(phba->link_state < LPFC_LINK_DOWN))
5271 return IRQ_NONE; 5272 return IRQ_NONE;
5272 /* Need to read HA REG for slow-path events */ 5273 /* Need to read HA REG for slow-path events */
5273 spin_lock(&phba->hbalock); 5274 spin_lock_irqsave(&phba->hbalock, iflag);
5274 ha_copy = readl(phba->HAregaddr); 5275 ha_copy = readl(phba->HAregaddr);
5275 /* If somebody is waiting to handle an eratt don't process it 5276 /* If somebody is waiting to handle an eratt don't process it
5276 * here. The brdkill function will do this. 5277 * here. The brdkill function will do this.
@@ -5290,7 +5291,7 @@ lpfc_sp_intr_handler(int irq, void *dev_id)
5290 writel((ha_copy & (HA_MBATT | HA_R2_CLR_MSK)), 5291 writel((ha_copy & (HA_MBATT | HA_R2_CLR_MSK)),
5291 phba->HAregaddr); 5292 phba->HAregaddr);
5292 readl(phba->HAregaddr); /* flush */ 5293 readl(phba->HAregaddr); /* flush */
5293 spin_unlock(&phba->hbalock); 5294 spin_unlock_irqrestore(&phba->hbalock, iflag);
5294 } else 5295 } else
5295 ha_copy = phba->ha_copy; 5296 ha_copy = phba->ha_copy;
5296 5297
@@ -5303,13 +5304,13 @@ lpfc_sp_intr_handler(int irq, void *dev_id)
5303 * Turn off Link Attention interrupts 5304 * Turn off Link Attention interrupts
5304 * until CLEAR_LA done 5305 * until CLEAR_LA done
5305 */ 5306 */
5306 spin_lock(&phba->hbalock); 5307 spin_lock_irqsave(&phba->hbalock, iflag);
5307 phba->sli.sli_flag &= ~LPFC_PROCESS_LA; 5308 phba->sli.sli_flag &= ~LPFC_PROCESS_LA;
5308 control = readl(phba->HCregaddr); 5309 control = readl(phba->HCregaddr);
5309 control &= ~HC_LAINT_ENA; 5310 control &= ~HC_LAINT_ENA;
5310 writel(control, phba->HCregaddr); 5311 writel(control, phba->HCregaddr);
5311 readl(phba->HCregaddr); /* flush */ 5312 readl(phba->HCregaddr); /* flush */
5312 spin_unlock(&phba->hbalock); 5313 spin_unlock_irqrestore(&phba->hbalock, iflag);
5313 } 5314 }
5314 else 5315 else
5315 work_ha_copy &= ~HA_LATT; 5316 work_ha_copy &= ~HA_LATT;
@@ -5324,7 +5325,7 @@ lpfc_sp_intr_handler(int irq, void *dev_id)
5324 (HA_RXMASK << (4*LPFC_ELS_RING))); 5325 (HA_RXMASK << (4*LPFC_ELS_RING)));
5325 status >>= (4*LPFC_ELS_RING); 5326 status >>= (4*LPFC_ELS_RING);
5326 if (status & HA_RXMASK) { 5327 if (status & HA_RXMASK) {
5327 spin_lock(&phba->hbalock); 5328 spin_lock_irqsave(&phba->hbalock, iflag);
5328 control = readl(phba->HCregaddr); 5329 control = readl(phba->HCregaddr);
5329 5330
5330 lpfc_debugfs_slow_ring_trc(phba, 5331 lpfc_debugfs_slow_ring_trc(phba,
@@ -5353,10 +5354,10 @@ lpfc_sp_intr_handler(int irq, void *dev_id)
5353 (uint32_t)((unsigned long) 5354 (uint32_t)((unsigned long)
5354 &phba->work_waitq)); 5355 &phba->work_waitq));
5355 } 5356 }
5356 spin_unlock(&phba->hbalock); 5357 spin_unlock_irqrestore(&phba->hbalock, iflag);
5357 } 5358 }
5358 } 5359 }
5359 spin_lock(&phba->hbalock); 5360 spin_lock_irqsave(&phba->hbalock, iflag);
5360 if (work_ha_copy & HA_ERATT) 5361 if (work_ha_copy & HA_ERATT)
5361 lpfc_sli_read_hs(phba); 5362 lpfc_sli_read_hs(phba);
5362 if ((work_ha_copy & HA_MBATT) && (phba->sli.mbox_active)) { 5363 if ((work_ha_copy & HA_MBATT) && (phba->sli.mbox_active)) {
@@ -5368,7 +5369,7 @@ lpfc_sp_intr_handler(int irq, void *dev_id)
5368 /* First check out the status word */ 5369 /* First check out the status word */
5369 lpfc_sli_pcimem_bcopy(mbox, pmbox, sizeof(uint32_t)); 5370 lpfc_sli_pcimem_bcopy(mbox, pmbox, sizeof(uint32_t));
5370 if (pmbox->mbxOwner != OWN_HOST) { 5371 if (pmbox->mbxOwner != OWN_HOST) {
5371 spin_unlock(&phba->hbalock); 5372 spin_unlock_irqrestore(&phba->hbalock, iflag);
5372 /* 5373 /*
5373 * Stray Mailbox Interrupt, mbxCommand <cmd> 5374 * Stray Mailbox Interrupt, mbxCommand <cmd>
5374 * mbxStatus <status> 5375 * mbxStatus <status>
@@ -5385,7 +5386,7 @@ lpfc_sp_intr_handler(int irq, void *dev_id)
5385 work_ha_copy &= ~HA_MBATT; 5386 work_ha_copy &= ~HA_MBATT;
5386 } else { 5387 } else {
5387 phba->sli.mbox_active = NULL; 5388 phba->sli.mbox_active = NULL;
5388 spin_unlock(&phba->hbalock); 5389 spin_unlock_irqrestore(&phba->hbalock, iflag);
5389 phba->last_completion_time = jiffies; 5390 phba->last_completion_time = jiffies;
5390 del_timer(&phba->sli.mbox_tmo); 5391 del_timer(&phba->sli.mbox_tmo);
5391 if (pmb->mbox_cmpl) { 5392 if (pmb->mbox_cmpl) {
@@ -5434,14 +5435,18 @@ lpfc_sp_intr_handler(int irq, void *dev_id)
5434 goto send_current_mbox; 5435 goto send_current_mbox;
5435 } 5436 }
5436 } 5437 }
5437 spin_lock(&phba->pport->work_port_lock); 5438 spin_lock_irqsave(
5439 &phba->pport->work_port_lock,
5440 iflag);
5438 phba->pport->work_port_events &= 5441 phba->pport->work_port_events &=
5439 ~WORKER_MBOX_TMO; 5442 ~WORKER_MBOX_TMO;
5440 spin_unlock(&phba->pport->work_port_lock); 5443 spin_unlock_irqrestore(
5444 &phba->pport->work_port_lock,
5445 iflag);
5441 lpfc_mbox_cmpl_put(phba, pmb); 5446 lpfc_mbox_cmpl_put(phba, pmb);
5442 } 5447 }
5443 } else 5448 } else
5444 spin_unlock(&phba->hbalock); 5449 spin_unlock_irqrestore(&phba->hbalock, iflag);
5445 5450
5446 if ((work_ha_copy & HA_MBATT) && 5451 if ((work_ha_copy & HA_MBATT) &&
5447 (phba->sli.mbox_active == NULL)) { 5452 (phba->sli.mbox_active == NULL)) {
@@ -5457,9 +5462,9 @@ send_current_mbox:
5457 "MBX_SUCCESS"); 5462 "MBX_SUCCESS");
5458 } 5463 }
5459 5464
5460 spin_lock(&phba->hbalock); 5465 spin_lock_irqsave(&phba->hbalock, iflag);
5461 phba->work_ha |= work_ha_copy; 5466 phba->work_ha |= work_ha_copy;
5462 spin_unlock(&phba->hbalock); 5467 spin_unlock_irqrestore(&phba->hbalock, iflag);
5463 lpfc_worker_wake_up(phba); 5468 lpfc_worker_wake_up(phba);
5464 } 5469 }
5465 return IRQ_HANDLED; 5470 return IRQ_HANDLED;
@@ -5491,6 +5496,7 @@ lpfc_fp_intr_handler(int irq, void *dev_id)
5491 struct lpfc_hba *phba; 5496 struct lpfc_hba *phba;
5492 uint32_t ha_copy; 5497 uint32_t ha_copy;
5493 unsigned long status; 5498 unsigned long status;
5499 unsigned long iflag;
5494 5500
5495 /* Get the driver's phba structure from the dev_id and 5501 /* Get the driver's phba structure from the dev_id and
5496 * assume the HBA is not interrupting. 5502 * assume the HBA is not interrupting.
@@ -5516,11 +5522,11 @@ lpfc_fp_intr_handler(int irq, void *dev_id)
5516 /* Need to read HA REG for FCP ring and other ring events */ 5522 /* Need to read HA REG for FCP ring and other ring events */
5517 ha_copy = readl(phba->HAregaddr); 5523 ha_copy = readl(phba->HAregaddr);
5518 /* Clear up only attention source related to fast-path */ 5524 /* Clear up only attention source related to fast-path */
5519 spin_lock(&phba->hbalock); 5525 spin_lock_irqsave(&phba->hbalock, iflag);
5520 writel((ha_copy & (HA_R0_CLR_MSK | HA_R1_CLR_MSK)), 5526 writel((ha_copy & (HA_R0_CLR_MSK | HA_R1_CLR_MSK)),
5521 phba->HAregaddr); 5527 phba->HAregaddr);
5522 readl(phba->HAregaddr); /* flush */ 5528 readl(phba->HAregaddr); /* flush */
5523 spin_unlock(&phba->hbalock); 5529 spin_unlock_irqrestore(&phba->hbalock, iflag);
5524 } else 5530 } else
5525 ha_copy = phba->ha_copy; 5531 ha_copy = phba->ha_copy;
5526 5532