aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/lpfc/lpfc_sli.c
diff options
context:
space:
mode:
authorJames Smart <James.Smart@Emulex.Com>2008-08-24 21:50:30 -0400
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2008-10-13 09:28:55 -0400
commit9399627f340794baebf7e4581470ccb92f019acc (patch)
treec30e656a1c353e2f025bb5ca3daf142128434a34 /drivers/scsi/lpfc/lpfc_sli.c
parent0f1f53a7efd60d7cdd8e82925f0c62dcf64ba092 (diff)
[SCSI] lpfc 8.2.8 : Add MSI-X support
Add support for MSI-X Multi-Message interrupts. We use different vectors for fast-path interrupts (i/o) and slow-patch interrupts (discovery, etc). 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.c401
1 files changed, 308 insertions, 93 deletions
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index 1812e18246d5..2cca39e9b93d 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -1699,6 +1699,36 @@ lpfc_sli_rsp_pointers_error(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
1699} 1699}
1700 1700
1701/** 1701/**
1702 * lpfc_poll_eratt: Error attention polling timer timeout handler.
1703 * @ptr: Pointer to address of HBA context object.
1704 *
1705 * This function is invoked by the Error Attention polling timer when the
1706 * timer times out. It will check the SLI Error Attention register for
1707 * possible attention events. If so, it will post an Error Attention event
1708 * and wake up worker thread to process it. Otherwise, it will set up the
1709 * Error Attention polling timer for the next poll.
1710 **/
1711void lpfc_poll_eratt(unsigned long ptr)
1712{
1713 struct lpfc_hba *phba;
1714 uint32_t eratt = 0;
1715
1716 phba = (struct lpfc_hba *)ptr;
1717
1718 /* Check chip HA register for error event */
1719 eratt = lpfc_sli_check_eratt(phba);
1720
1721 if (eratt)
1722 /* Tell the worker thread there is work to do */
1723 lpfc_worker_wake_up(phba);
1724 else
1725 /* Restart the timer for next eratt poll */
1726 mod_timer(&phba->eratt_poll, jiffies +
1727 HZ * LPFC_ERATT_POLL_INTERVAL);
1728 return;
1729}
1730
1731/**
1702 * lpfc_sli_poll_fcp_ring: Handle FCP ring completion in polling mode. 1732 * lpfc_sli_poll_fcp_ring: Handle FCP ring completion in polling mode.
1703 * @phba: Pointer to HBA context object. 1733 * @phba: Pointer to HBA context object.
1704 * 1734 *
@@ -3011,7 +3041,7 @@ lpfc_sli_hbq_setup(struct lpfc_hba *phba)
3011} 3041}
3012 3042
3013/** 3043/**
3014 * lpfc_do_config_port: Issue config port mailbox command. 3044 * lpfc_sli_config_port: Issue config port mailbox command.
3015 * @phba: Pointer to HBA context object. 3045 * @phba: Pointer to HBA context object.
3016 * @sli_mode: sli mode - 2/3 3046 * @sli_mode: sli mode - 2/3
3017 * 3047 *
@@ -3023,8 +3053,8 @@ lpfc_sli_hbq_setup(struct lpfc_hba *phba)
3023 * The function returns 0 if successful, else returns negative error 3053 * The function returns 0 if successful, else returns negative error
3024 * code. 3054 * code.
3025 **/ 3055 **/
3026static int 3056int
3027lpfc_do_config_port(struct lpfc_hba *phba, int sli_mode) 3057lpfc_sli_config_port(struct lpfc_hba *phba, int sli_mode)
3028{ 3058{
3029 LPFC_MBOXQ_t *pmb; 3059 LPFC_MBOXQ_t *pmb;
3030 uint32_t resetcount = 0, rc = 0, done = 0; 3060 uint32_t resetcount = 0, rc = 0, done = 0;
@@ -3165,13 +3195,14 @@ lpfc_sli_hba_setup(struct lpfc_hba *phba)
3165 break; 3195 break;
3166 } 3196 }
3167 3197
3168 rc = lpfc_do_config_port(phba, mode); 3198 rc = lpfc_sli_config_port(phba, mode);
3199
3169 if (rc && lpfc_sli_mode == 3) 3200 if (rc && lpfc_sli_mode == 3)
3170 lpfc_printf_log(phba, KERN_ERR, LOG_INIT | LOG_VPORT, 3201 lpfc_printf_log(phba, KERN_ERR, LOG_INIT | LOG_VPORT,
3171 "1820 Unable to select SLI-3. " 3202 "1820 Unable to select SLI-3. "
3172 "Not supported by adapter.\n"); 3203 "Not supported by adapter.\n");
3173 if (rc && mode != 2) 3204 if (rc && mode != 2)
3174 rc = lpfc_do_config_port(phba, 2); 3205 rc = lpfc_sli_config_port(phba, 2);
3175 if (rc) 3206 if (rc)
3176 goto lpfc_sli_hba_setup_error; 3207 goto lpfc_sli_hba_setup_error;
3177 3208
@@ -3192,8 +3223,7 @@ lpfc_sli_hba_setup(struct lpfc_hba *phba)
3192 if (rc) 3223 if (rc)
3193 goto lpfc_sli_hba_setup_error; 3224 goto lpfc_sli_hba_setup_error;
3194 3225
3195 /* Init HBQs */ 3226 /* Init HBQs */
3196
3197 if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) { 3227 if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) {
3198 rc = lpfc_sli_hbq_setup(phba); 3228 rc = lpfc_sli_hbq_setup(phba);
3199 if (rc) 3229 if (rc)
@@ -5128,28 +5158,73 @@ lpfc_sli_flush_mbox_queue(struct lpfc_hba * phba)
5128} 5158}
5129 5159
5130/** 5160/**
5131 * lpfc_intr_handler: The interrupt handler of lpfc driver. 5161 * lpfc_sli_check_eratt: check error attention events
5162 * @phba: Pointer to HBA context.
5163 *
5164 * This function is called form timer soft interrupt context to check HBA's
5165 * error attention register bit for error attention events.
5166 *
5167 * This fucntion returns 1 when there is Error Attention in the Host Attention
5168 * Register and returns 0 otherwise.
5169 **/
5170int
5171lpfc_sli_check_eratt(struct lpfc_hba *phba)
5172{
5173 uint32_t ha_copy;
5174
5175 /* If somebody is waiting to handle an eratt, don't process it
5176 * here. The brdkill function will do this.
5177 */
5178 if (phba->link_flag & LS_IGNORE_ERATT)
5179 return 0;
5180
5181 /* Check if interrupt handler handles this ERATT */
5182 spin_lock_irq(&phba->hbalock);
5183 if (phba->hba_flag & HBA_ERATT_HANDLED) {
5184 /* Interrupt handler has handled ERATT */
5185 spin_unlock_irq(&phba->hbalock);
5186 return 0;
5187 }
5188
5189 /* Read chip Host Attention (HA) register */
5190 ha_copy = readl(phba->HAregaddr);
5191 if (ha_copy & HA_ERATT) {
5192 /* Read host status register to retrieve error event */
5193 lpfc_sli_read_hs(phba);
5194 /* Set the driver HA work bitmap */
5195 phba->work_ha |= HA_ERATT;
5196 /* Indicate polling handles this ERATT */
5197 phba->hba_flag |= HBA_ERATT_HANDLED;
5198 spin_unlock_irq(&phba->hbalock);
5199 return 1;
5200 }
5201 spin_unlock_irq(&phba->hbalock);
5202 return 0;
5203}
5204
5205/**
5206 * lpfc_sp_intr_handler: The slow-path interrupt handler of lpfc driver.
5132 * @irq: Interrupt number. 5207 * @irq: Interrupt number.
5133 * @dev_id: The device context pointer. 5208 * @dev_id: The device context pointer.
5134 * 5209 *
5135 * This function is called from the PCI layer when there is 5210 * This function is directly called from the PCI layer as an interrupt
5136 * an event in the HBA which requires driver attention. When 5211 * service routine when the device is enabled with MSI-X multi-message
5137 * the PCI slot is in error recovery or the HBA is undergoing 5212 * interrupt mode and there are slow-path events in the HBA. However,
5138 * initialization the interrupt handler will not process the 5213 * when the device is enabled with either MSI or Pin-IRQ interrupt mode,
5139 * interrupt. 5214 * this function is called as part of the device-level interrupt handler.
5140 * The error attention, link attention and els ring attention 5215 * When the PCI slot is in error recovery or the HBA is undergoing
5141 * events are handled by the worker thread. The interrupt 5216 * initialization, the interrupt handler will not process the interrupt.
5142 * handler signals the worker thread and returns for these 5217 * The link attention and ELS ring attention events are handled by the
5143 * events. 5218 * worker thread. The interrupt handler signals the worker thread and
5144 * The SCSI ring event and mailbox events are handled in the 5219 * and returns for these events. This function is called without any
5145 * interrupt context. 5220 * lock held. It gets the hbalock to access and update SLI data
5146 * This function is called without any lock held. It gets the 5221 * structures.
5147 * hbalock to access and update SLI data structures. 5222 *
5148 * This function returns IRQ_HANDLED when interrupt is handled 5223 * This function returns IRQ_HANDLED when interrupt is handled else it
5149 * else it returns IRQ_NONE. 5224 * returns IRQ_NONE.
5150 **/ 5225 **/
5151irqreturn_t 5226irqreturn_t
5152lpfc_intr_handler(int irq, void *dev_id) 5227lpfc_sp_intr_handler(int irq, void *dev_id)
5153{ 5228{
5154 struct lpfc_hba *phba; 5229 struct lpfc_hba *phba;
5155 uint32_t ha_copy; 5230 uint32_t ha_copy;
@@ -5168,54 +5243,52 @@ lpfc_intr_handler(int irq, void *dev_id)
5168 * Get the driver's phba structure from the dev_id and 5243 * Get the driver's phba structure from the dev_id and
5169 * assume the HBA is not interrupting. 5244 * assume the HBA is not interrupting.
5170 */ 5245 */
5171 phba = (struct lpfc_hba *) dev_id; 5246 phba = (struct lpfc_hba *)dev_id;
5172 5247
5173 if (unlikely(!phba)) 5248 if (unlikely(!phba))
5174 return IRQ_NONE; 5249 return IRQ_NONE;
5175 5250
5176 /* If the pci channel is offline, ignore all the interrupts. */
5177 if (unlikely(pci_channel_offline(phba->pcidev)))
5178 return IRQ_NONE;
5179
5180 phba->sli.slistat.sli_intr++;
5181
5182 /* 5251 /*
5183 * Call the HBA to see if it is interrupting. If not, don't claim 5252 * Stuff needs to be attented to when this function is invoked as an
5184 * the interrupt 5253 * individual interrupt handler in MSI-X multi-message interrupt mode
5185 */ 5254 */
5186 5255 if (phba->intr_type == MSIX) {
5187 /* Ignore all interrupts during initialization. */ 5256 /* If the pci channel is offline, ignore all the interrupts */
5188 if (unlikely(phba->link_state < LPFC_LINK_DOWN)) 5257 if (unlikely(pci_channel_offline(phba->pcidev)))
5189 return IRQ_NONE; 5258 return IRQ_NONE;
5190 5259 /* Update device-level interrupt statistics */
5191 /* 5260 phba->sli.slistat.sli_intr++;
5192 * Read host attention register to determine interrupt source 5261 /* Ignore all interrupts during initialization. */
5193 * Clear Attention Sources, except Error Attention (to 5262 if (unlikely(phba->link_state < LPFC_LINK_DOWN))
5194 * preserve status) and Link Attention 5263 return IRQ_NONE;
5195 */ 5264 /* Need to read HA REG for slow-path events */
5196 spin_lock(&phba->hbalock); 5265 spin_lock(&phba->hbalock);
5197 if (phba->sli3_options & LPFC_SLI3_INB_ENABLED &&
5198 (phba->inb_last_counter != *phba->inb_counter)) {
5199 phba->inb_last_counter = *phba->inb_counter;
5200 ha_copy = le32_to_cpu(*phba->inb_ha_copy);
5201 } else
5202 ha_copy = readl(phba->HAregaddr); 5266 ha_copy = readl(phba->HAregaddr);
5203 if (unlikely(!ha_copy)) { 5267 /* If somebody is waiting to handle an eratt don't process it
5268 * here. The brdkill function will do this.
5269 */
5270 if (phba->link_flag & LS_IGNORE_ERATT)
5271 ha_copy &= ~HA_ERATT;
5272 /* Check the need for handling ERATT in interrupt handler */
5273 if (ha_copy & HA_ERATT) {
5274 if (phba->hba_flag & HBA_ERATT_HANDLED)
5275 /* ERATT polling has handled ERATT */
5276 ha_copy &= ~HA_ERATT;
5277 else
5278 /* Indicate interrupt handler handles ERATT */
5279 phba->hba_flag |= HBA_ERATT_HANDLED;
5280 }
5281 /* Clear up only attention source related to slow-path */
5282 writel((ha_copy & (HA_MBATT | HA_R2_CLR_MSK)),
5283 phba->HAregaddr);
5284 readl(phba->HAregaddr); /* flush */
5204 spin_unlock(&phba->hbalock); 5285 spin_unlock(&phba->hbalock);
5205 return IRQ_NONE; 5286 } else
5206 } 5287 ha_copy = phba->ha_copy;
5207 /* If somebody is waiting to handle an eratt don't process it
5208 * here. The brdkill function will do this.
5209 */
5210 if (phba->link_flag & LS_IGNORE_ERATT)
5211 ha_copy &= ~HA_ERATT;
5212 writel((ha_copy & ~(HA_LATT | HA_ERATT)), phba->HAregaddr);
5213 readl(phba->HAregaddr); /* flush */
5214 spin_unlock(&phba->hbalock);
5215 5288
5216 work_ha_copy = ha_copy & phba->work_ha_mask; 5289 work_ha_copy = ha_copy & phba->work_ha_mask;
5217 5290
5218 if (unlikely(work_ha_copy)) { 5291 if (work_ha_copy) {
5219 if (work_ha_copy & HA_LATT) { 5292 if (work_ha_copy & HA_LATT) {
5220 if (phba->sli.sli_flag & LPFC_PROCESS_LA) { 5293 if (phba->sli.sli_flag & LPFC_PROCESS_LA) {
5221 /* 5294 /*
@@ -5234,7 +5307,7 @@ lpfc_intr_handler(int irq, void *dev_id)
5234 work_ha_copy &= ~HA_LATT; 5307 work_ha_copy &= ~HA_LATT;
5235 } 5308 }
5236 5309
5237 if (work_ha_copy & ~(HA_ERATT|HA_MBATT|HA_LATT)) { 5310 if (work_ha_copy & ~(HA_ERATT | HA_MBATT | HA_LATT)) {
5238 /* 5311 /*
5239 * Turn off Slow Rings interrupts, LPFC_ELS_RING is 5312 * Turn off Slow Rings interrupts, LPFC_ELS_RING is
5240 * the only slow ring. 5313 * the only slow ring.
@@ -5275,28 +5348,10 @@ lpfc_intr_handler(int irq, void *dev_id)
5275 spin_unlock(&phba->hbalock); 5348 spin_unlock(&phba->hbalock);
5276 } 5349 }
5277 } 5350 }
5278
5279 if (work_ha_copy & HA_ERATT) {
5280 /*
5281 * There was a link/board error. Read the
5282 * status register to retrieve the error event
5283 * and process it.
5284 */
5285 phba->sli.slistat.err_attn_event++;
5286 /* Save status info */
5287 phba->work_hs = readl(phba->HSregaddr);
5288 phba->work_status[0] = readl(phba->MBslimaddr + 0xa8);
5289 phba->work_status[1] = readl(phba->MBslimaddr + 0xac);
5290
5291 /* Clear Chip error bit */
5292 writel(HA_ERATT, phba->HAregaddr);
5293 readl(phba->HAregaddr); /* flush */
5294 phba->pport->stopped = 1;
5295 }
5296
5297 spin_lock(&phba->hbalock); 5351 spin_lock(&phba->hbalock);
5298 if ((work_ha_copy & HA_MBATT) && 5352 if (work_ha_copy & HA_ERATT)
5299 (phba->sli.mbox_active)) { 5353 lpfc_sli_read_hs(phba);
5354 if ((work_ha_copy & HA_MBATT) && (phba->sli.mbox_active)) {
5300 pmb = phba->sli.mbox_active; 5355 pmb = phba->sli.mbox_active;
5301 pmbox = &pmb->mb; 5356 pmbox = &pmb->mb;
5302 mbox = phba->mbox; 5357 mbox = phba->mbox;
@@ -5379,6 +5434,7 @@ lpfc_intr_handler(int irq, void *dev_id)
5379 } 5434 }
5380 } else 5435 } else
5381 spin_unlock(&phba->hbalock); 5436 spin_unlock(&phba->hbalock);
5437
5382 if ((work_ha_copy & HA_MBATT) && 5438 if ((work_ha_copy & HA_MBATT) &&
5383 (phba->sli.mbox_active == NULL)) { 5439 (phba->sli.mbox_active == NULL)) {
5384send_current_mbox: 5440send_current_mbox:
@@ -5398,15 +5454,74 @@ send_current_mbox:
5398 spin_unlock(&phba->hbalock); 5454 spin_unlock(&phba->hbalock);
5399 lpfc_worker_wake_up(phba); 5455 lpfc_worker_wake_up(phba);
5400 } 5456 }
5457 return IRQ_HANDLED;
5401 5458
5402 ha_copy &= ~(phba->work_ha_mask); 5459} /* lpfc_sp_intr_handler */
5460
5461/**
5462 * lpfc_fp_intr_handler: The fast-path interrupt handler of lpfc driver.
5463 * @irq: Interrupt number.
5464 * @dev_id: The device context pointer.
5465 *
5466 * This function is directly called from the PCI layer as an interrupt
5467 * service routine when the device is enabled with MSI-X multi-message
5468 * interrupt mode and there is a fast-path FCP IOCB ring event in the
5469 * HBA. However, when the device is enabled with either MSI or Pin-IRQ
5470 * interrupt mode, this function is called as part of the device-level
5471 * interrupt handler. When the PCI slot is in error recovery or the HBA
5472 * is undergoing initialization, the interrupt handler will not process
5473 * the interrupt. The SCSI FCP fast-path ring event are handled in the
5474 * intrrupt context. This function is called without any lock held. It
5475 * gets the hbalock to access and update SLI data structures.
5476 *
5477 * This function returns IRQ_HANDLED when interrupt is handled else it
5478 * returns IRQ_NONE.
5479 **/
5480irqreturn_t
5481lpfc_fp_intr_handler(int irq, void *dev_id)
5482{
5483 struct lpfc_hba *phba;
5484 uint32_t ha_copy;
5485 unsigned long status;
5486
5487 /* Get the driver's phba structure from the dev_id and
5488 * assume the HBA is not interrupting.
5489 */
5490 phba = (struct lpfc_hba *) dev_id;
5491
5492 if (unlikely(!phba))
5493 return IRQ_NONE;
5494
5495 /*
5496 * Stuff needs to be attented to when this function is invoked as an
5497 * individual interrupt handler in MSI-X multi-message interrupt mode
5498 */
5499 if (phba->intr_type == MSIX) {
5500 /* If pci channel is offline, ignore all the interrupts */
5501 if (unlikely(pci_channel_offline(phba->pcidev)))
5502 return IRQ_NONE;
5503 /* Update device-level interrupt statistics */
5504 phba->sli.slistat.sli_intr++;
5505 /* Ignore all interrupts during initialization. */
5506 if (unlikely(phba->link_state < LPFC_LINK_DOWN))
5507 return IRQ_NONE;
5508 /* Need to read HA REG for FCP ring and other ring events */
5509 ha_copy = readl(phba->HAregaddr);
5510 /* Clear up only attention source related to fast-path */
5511 spin_lock(&phba->hbalock);
5512 writel((ha_copy & (HA_R0_CLR_MSK | HA_R1_CLR_MSK)),
5513 phba->HAregaddr);
5514 readl(phba->HAregaddr); /* flush */
5515 spin_unlock(&phba->hbalock);
5516 } else
5517 ha_copy = phba->ha_copy;
5403 5518
5404 /* 5519 /*
5405 * Process all events on FCP ring. Take the optimized path for 5520 * Process all events on FCP ring. Take the optimized path for FCP IO.
5406 * FCP IO. Any other IO is slow path and is handled by
5407 * the worker thread.
5408 */ 5521 */
5409 status = (ha_copy & (HA_RXMASK << (4*LPFC_FCP_RING))); 5522 ha_copy &= ~(phba->work_ha_mask);
5523
5524 status = (ha_copy & (HA_RXMASK << (4*LPFC_FCP_RING)));
5410 status >>= (4*LPFC_FCP_RING); 5525 status >>= (4*LPFC_FCP_RING);
5411 if (status & HA_RXMASK) 5526 if (status & HA_RXMASK)
5412 lpfc_sli_handle_fast_ring_event(phba, 5527 lpfc_sli_handle_fast_ring_event(phba,
@@ -5415,11 +5530,10 @@ send_current_mbox:
5415 5530
5416 if (phba->cfg_multi_ring_support == 2) { 5531 if (phba->cfg_multi_ring_support == 2) {
5417 /* 5532 /*
5418 * Process all events on extra ring. Take the optimized path 5533 * Process all events on extra ring. Take the optimized path
5419 * for extra ring IO. Any other IO is slow path and is handled 5534 * for extra ring IO.
5420 * by the worker thread.
5421 */ 5535 */
5422 status = (ha_copy & (HA_RXMASK << (4*LPFC_EXTRA_RING))); 5536 status = (ha_copy & (HA_RXMASK << (4*LPFC_EXTRA_RING)));
5423 status >>= (4*LPFC_EXTRA_RING); 5537 status >>= (4*LPFC_EXTRA_RING);
5424 if (status & HA_RXMASK) { 5538 if (status & HA_RXMASK) {
5425 lpfc_sli_handle_fast_ring_event(phba, 5539 lpfc_sli_handle_fast_ring_event(phba,
@@ -5428,5 +5542,106 @@ send_current_mbox:
5428 } 5542 }
5429 } 5543 }
5430 return IRQ_HANDLED; 5544 return IRQ_HANDLED;
5545} /* lpfc_fp_intr_handler */
5546
5547/**
5548 * lpfc_intr_handler: The device-level interrupt handler of lpfc driver.
5549 * @irq: Interrupt number.
5550 * @dev_id: The device context pointer.
5551 *
5552 * This function is the device-level interrupt handler called from the PCI
5553 * layer when either MSI or Pin-IRQ interrupt mode is enabled and there is
5554 * an event in the HBA which requires driver attention. This function
5555 * invokes the slow-path interrupt attention handling function and fast-path
5556 * interrupt attention handling function in turn to process the relevant
5557 * HBA attention events. This function is called without any lock held. It
5558 * gets the hbalock to access and update SLI data structures.
5559 *
5560 * This function returns IRQ_HANDLED when interrupt is handled, else it
5561 * returns IRQ_NONE.
5562 **/
5563irqreturn_t
5564lpfc_intr_handler(int irq, void *dev_id)
5565{
5566 struct lpfc_hba *phba;
5567 irqreturn_t sp_irq_rc, fp_irq_rc;
5568 unsigned long status1, status2;
5569
5570 /*
5571 * Get the driver's phba structure from the dev_id and
5572 * assume the HBA is not interrupting.
5573 */
5574 phba = (struct lpfc_hba *) dev_id;
5575
5576 if (unlikely(!phba))
5577 return IRQ_NONE;
5578
5579 /* If the pci channel is offline, ignore all the interrupts. */
5580 if (unlikely(pci_channel_offline(phba->pcidev)))
5581 return IRQ_NONE;
5582
5583 /* Update device level interrupt statistics */
5584 phba->sli.slistat.sli_intr++;
5585
5586 /* Ignore all interrupts during initialization. */
5587 if (unlikely(phba->link_state < LPFC_LINK_DOWN))
5588 return IRQ_NONE;
5589
5590 spin_lock(&phba->hbalock);
5591 phba->ha_copy = readl(phba->HAregaddr);
5592 if (unlikely(!phba->ha_copy)) {
5593 spin_unlock(&phba->hbalock);
5594 return IRQ_NONE;
5595 } else if (phba->ha_copy & HA_ERATT) {
5596 if (phba->hba_flag & HBA_ERATT_HANDLED)
5597 /* ERATT polling has handled ERATT */
5598 phba->ha_copy &= ~HA_ERATT;
5599 else
5600 /* Indicate interrupt handler handles ERATT */
5601 phba->hba_flag |= HBA_ERATT_HANDLED;
5602 }
5603
5604 /* Clear attention sources except link and error attentions */
5605 writel((phba->ha_copy & ~(HA_LATT | HA_ERATT)), phba->HAregaddr);
5606 readl(phba->HAregaddr); /* flush */
5607 spin_unlock(&phba->hbalock);
5608
5609 /*
5610 * Invokes slow-path host attention interrupt handling as appropriate.
5611 */
5612
5613 /* status of events with mailbox and link attention */
5614 status1 = phba->ha_copy & (HA_MBATT | HA_LATT | HA_ERATT);
5615
5616 /* status of events with ELS ring */
5617 status2 = (phba->ha_copy & (HA_RXMASK << (4*LPFC_ELS_RING)));
5618 status2 >>= (4*LPFC_ELS_RING);
5619
5620 if (status1 || (status2 & HA_RXMASK))
5621 sp_irq_rc = lpfc_sp_intr_handler(irq, dev_id);
5622 else
5623 sp_irq_rc = IRQ_NONE;
5624
5625 /*
5626 * Invoke fast-path host attention interrupt handling as appropriate.
5627 */
5628
5629 /* status of events with FCP ring */
5630 status1 = (phba->ha_copy & (HA_RXMASK << (4*LPFC_FCP_RING)));
5631 status1 >>= (4*LPFC_FCP_RING);
5632
5633 /* status of events with extra ring */
5634 if (phba->cfg_multi_ring_support == 2) {
5635 status2 = (phba->ha_copy & (HA_RXMASK << (4*LPFC_EXTRA_RING)));
5636 status2 >>= (4*LPFC_EXTRA_RING);
5637 } else
5638 status2 = 0;
5639
5640 if ((status1 & HA_RXMASK) || (status2 & HA_RXMASK))
5641 fp_irq_rc = lpfc_fp_intr_handler(irq, dev_id);
5642 else
5643 fp_irq_rc = IRQ_NONE;
5431 5644
5432} /* lpfc_intr_handler */ 5645 /* Return device-level interrupt handling status */
5646 return (sp_irq_rc == IRQ_HANDLED) ? sp_irq_rc : fp_irq_rc;
5647} /* lpfc_intr_handler */