diff options
author | James Smart <James.Smart@Emulex.Com> | 2009-04-06 18:48:10 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2009-04-27 10:42:47 -0400 |
commit | a257bf905efd22fd2c055580b0ab2e8e7ed1b6a1 (patch) | |
tree | e0f2ef6b9627d86456c92d56fa2c088c6d6544bf /drivers/scsi/lpfc/lpfc_sli.c | |
parent | 3621a710a7dbb2d22a8e95d94bcf0c2d13ef57fc (diff) |
[SCSI] lpfc 8.3.1: misc fixes/changes
8.3.1 Fixes/Changes :
- Fix incorrect byte-swapping on word 4 of IOCB (data length) which
caused LUNs to not be discovered on big-endian (e.g. PPC)
- Remove a bad cast of MBslimaddr which loses the __iomem (sparse)
- Make lpfc_debugfs_mask_disc_trc static (sparse)
- Correct misspelled word BlockGuard in lpfc_logmsg.h comment
- Replaced repeated code segment for canceling IOCBs from a list with
a function call, lpfc_sli_cancel_iocbs().
- Increased HBQ buffers to support 40KB SSC sequences.
- Added sysfs interface to update speed and topology parameter without
link bounce.
- Fixed bug with sysfs fc_host WWNs not being updated after changing
the WWNs.
- Check if the active mailbox is NULL in the beginning of the mailbox
timeout handler - fixes panic in the mailbox timeout handler while
running IO stress test
- Fixed system panic in lpfc_pci_remove_one() due to ndlp indirect
reference to phba through vport
- Removed de-reference of scsi device after call to scsi_done() to fix
panic in scsi completion path while accessing scsi device after
scsi_done is called.
- Fixed "Nodelist not empty" message when unloading the driver after
target reboot test
- Added LP2105 HBA model description
- Added code to print all 16 words of unrecognized ASYNC events
- Fixed memory leak in vport create + delete loop
- Added support for handling dual error bit from HBA
- Fixed a driver NULL pointer dereference in lpfc_sli_process_sol_iocb
- Fixed a discovery bug with FC switch reboot in lpfc_setup_disc_node
- Take NULL termintator into account when calculating available buffer space
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.c | 221 |
1 files changed, 148 insertions, 73 deletions
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 74cfa963dfc5..eb5c75c45ba4 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c | |||
@@ -185,6 +185,38 @@ lpfc_sli_release_iocbq(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq) | |||
185 | } | 185 | } |
186 | 186 | ||
187 | /** | 187 | /** |
188 | * lpfc_sli_cancel_iocbs - Cancel all iocbs from a list. | ||
189 | * @phba: Pointer to HBA context object. | ||
190 | * @iocblist: List of IOCBs. | ||
191 | * @ulpstatus: ULP status in IOCB command field. | ||
192 | * @ulpWord4: ULP word-4 in IOCB command field. | ||
193 | * | ||
194 | * This function is called with a list of IOCBs to cancel. It cancels the IOCB | ||
195 | * on the list by invoking the complete callback function associated with the | ||
196 | * IOCB with the provided @ulpstatus and @ulpword4 set to the IOCB commond | ||
197 | * fields. | ||
198 | **/ | ||
199 | void | ||
200 | lpfc_sli_cancel_iocbs(struct lpfc_hba *phba, struct list_head *iocblist, | ||
201 | uint32_t ulpstatus, uint32_t ulpWord4) | ||
202 | { | ||
203 | struct lpfc_iocbq *piocb; | ||
204 | |||
205 | while (!list_empty(iocblist)) { | ||
206 | list_remove_head(iocblist, piocb, struct lpfc_iocbq, list); | ||
207 | |||
208 | if (!piocb->iocb_cmpl) | ||
209 | lpfc_sli_release_iocbq(phba, piocb); | ||
210 | else { | ||
211 | piocb->iocb.ulpStatus = ulpstatus; | ||
212 | piocb->iocb.un.ulpWord[4] = ulpWord4; | ||
213 | (piocb->iocb_cmpl) (phba, piocb, piocb); | ||
214 | } | ||
215 | } | ||
216 | return; | ||
217 | } | ||
218 | |||
219 | /** | ||
188 | * lpfc_sli_iocb_cmd_type - Get the iocb type | 220 | * lpfc_sli_iocb_cmd_type - Get the iocb type |
189 | * @iocb_cmnd: iocb command code. | 221 | * @iocb_cmnd: iocb command code. |
190 | * | 222 | * |
@@ -818,8 +850,8 @@ static struct lpfc_hbq_init lpfc_els_hbq = { | |||
818 | .profile = 0, | 850 | .profile = 0, |
819 | .ring_mask = (1 << LPFC_ELS_RING), | 851 | .ring_mask = (1 << LPFC_ELS_RING), |
820 | .buffer_count = 0, | 852 | .buffer_count = 0, |
821 | .init_count = 20, | 853 | .init_count = 40, |
822 | .add_count = 5, | 854 | .add_count = 40, |
823 | }; | 855 | }; |
824 | 856 | ||
825 | /* HBQ for the extra ring if needed */ | 857 | /* HBQ for the extra ring if needed */ |
@@ -1596,7 +1628,7 @@ lpfc_sli_process_sol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | |||
1596 | * Ring <ringno> handler: unexpected completion IoTag | 1628 | * Ring <ringno> handler: unexpected completion IoTag |
1597 | * <IoTag> | 1629 | * <IoTag> |
1598 | */ | 1630 | */ |
1599 | lpfc_printf_vlog(cmdiocbp->vport, KERN_WARNING, LOG_SLI, | 1631 | lpfc_printf_log(phba, KERN_WARNING, LOG_SLI, |
1600 | "0322 Ring %d handler: " | 1632 | "0322 Ring %d handler: " |
1601 | "unexpected completion IoTag x%x " | 1633 | "unexpected completion IoTag x%x " |
1602 | "Data: x%x x%x x%x x%x\n", | 1634 | "Data: x%x x%x x%x x%x\n", |
@@ -2324,7 +2356,6 @@ lpfc_sli_abort_iocb_ring(struct lpfc_hba *phba, struct lpfc_sli_ring *pring) | |||
2324 | { | 2356 | { |
2325 | LIST_HEAD(completions); | 2357 | LIST_HEAD(completions); |
2326 | struct lpfc_iocbq *iocb, *next_iocb; | 2358 | struct lpfc_iocbq *iocb, *next_iocb; |
2327 | IOCB_t *cmd = NULL; | ||
2328 | 2359 | ||
2329 | if (pring->ringno == LPFC_ELS_RING) { | 2360 | if (pring->ringno == LPFC_ELS_RING) { |
2330 | lpfc_fabric_abort_hba(phba); | 2361 | lpfc_fabric_abort_hba(phba); |
@@ -2343,19 +2374,9 @@ lpfc_sli_abort_iocb_ring(struct lpfc_hba *phba, struct lpfc_sli_ring *pring) | |||
2343 | 2374 | ||
2344 | spin_unlock_irq(&phba->hbalock); | 2375 | spin_unlock_irq(&phba->hbalock); |
2345 | 2376 | ||
2346 | while (!list_empty(&completions)) { | 2377 | /* Cancel all the IOCBs from the completions list */ |
2347 | iocb = list_get_first(&completions, struct lpfc_iocbq, list); | 2378 | lpfc_sli_cancel_iocbs(phba, &completions, IOSTAT_LOCAL_REJECT, |
2348 | cmd = &iocb->iocb; | 2379 | IOERR_SLI_ABORTED); |
2349 | list_del_init(&iocb->list); | ||
2350 | |||
2351 | if (!iocb->iocb_cmpl) | ||
2352 | lpfc_sli_release_iocbq(phba, iocb); | ||
2353 | else { | ||
2354 | cmd->ulpStatus = IOSTAT_LOCAL_REJECT; | ||
2355 | cmd->un.ulpWord[4] = IOERR_SLI_ABORTED; | ||
2356 | (iocb->iocb_cmpl) (phba, iocb, iocb); | ||
2357 | } | ||
2358 | } | ||
2359 | } | 2380 | } |
2360 | 2381 | ||
2361 | /** | 2382 | /** |
@@ -2373,8 +2394,6 @@ lpfc_sli_flush_fcp_rings(struct lpfc_hba *phba) | |||
2373 | { | 2394 | { |
2374 | LIST_HEAD(txq); | 2395 | LIST_HEAD(txq); |
2375 | LIST_HEAD(txcmplq); | 2396 | LIST_HEAD(txcmplq); |
2376 | struct lpfc_iocbq *iocb; | ||
2377 | IOCB_t *cmd = NULL; | ||
2378 | struct lpfc_sli *psli = &phba->sli; | 2397 | struct lpfc_sli *psli = &phba->sli; |
2379 | struct lpfc_sli_ring *pring; | 2398 | struct lpfc_sli_ring *pring; |
2380 | 2399 | ||
@@ -2392,34 +2411,12 @@ lpfc_sli_flush_fcp_rings(struct lpfc_hba *phba) | |||
2392 | spin_unlock_irq(&phba->hbalock); | 2411 | spin_unlock_irq(&phba->hbalock); |
2393 | 2412 | ||
2394 | /* Flush the txq */ | 2413 | /* Flush the txq */ |
2395 | while (!list_empty(&txq)) { | 2414 | lpfc_sli_cancel_iocbs(phba, &txq, IOSTAT_LOCAL_REJECT, |
2396 | iocb = list_get_first(&txq, struct lpfc_iocbq, list); | 2415 | IOERR_SLI_DOWN); |
2397 | cmd = &iocb->iocb; | ||
2398 | list_del_init(&iocb->list); | ||
2399 | |||
2400 | if (!iocb->iocb_cmpl) | ||
2401 | lpfc_sli_release_iocbq(phba, iocb); | ||
2402 | else { | ||
2403 | cmd->ulpStatus = IOSTAT_LOCAL_REJECT; | ||
2404 | cmd->un.ulpWord[4] = IOERR_SLI_DOWN; | ||
2405 | (iocb->iocb_cmpl) (phba, iocb, iocb); | ||
2406 | } | ||
2407 | } | ||
2408 | 2416 | ||
2409 | /* Flush the txcmpq */ | 2417 | /* Flush the txcmpq */ |
2410 | while (!list_empty(&txcmplq)) { | 2418 | lpfc_sli_cancel_iocbs(phba, &txcmplq, IOSTAT_LOCAL_REJECT, |
2411 | iocb = list_get_first(&txcmplq, struct lpfc_iocbq, list); | 2419 | IOERR_SLI_DOWN); |
2412 | cmd = &iocb->iocb; | ||
2413 | list_del_init(&iocb->list); | ||
2414 | |||
2415 | if (!iocb->iocb_cmpl) | ||
2416 | lpfc_sli_release_iocbq(phba, iocb); | ||
2417 | else { | ||
2418 | cmd->ulpStatus = IOSTAT_LOCAL_REJECT; | ||
2419 | cmd->un.ulpWord[4] = IOERR_SLI_DOWN; | ||
2420 | (iocb->iocb_cmpl) (phba, iocb, iocb); | ||
2421 | } | ||
2422 | } | ||
2423 | } | 2420 | } |
2424 | 2421 | ||
2425 | /** | 2422 | /** |
@@ -3251,6 +3248,21 @@ lpfc_mbox_timeout_handler(struct lpfc_hba *phba) | |||
3251 | struct lpfc_sli *psli = &phba->sli; | 3248 | struct lpfc_sli *psli = &phba->sli; |
3252 | struct lpfc_sli_ring *pring; | 3249 | struct lpfc_sli_ring *pring; |
3253 | 3250 | ||
3251 | /* Check the pmbox pointer first. There is a race condition | ||
3252 | * between the mbox timeout handler getting executed in the | ||
3253 | * worklist and the mailbox actually completing. When this | ||
3254 | * race condition occurs, the mbox_active will be NULL. | ||
3255 | */ | ||
3256 | spin_lock_irq(&phba->hbalock); | ||
3257 | if (pmbox == NULL) { | ||
3258 | lpfc_printf_log(phba, KERN_WARNING, | ||
3259 | LOG_MBOX | LOG_SLI, | ||
3260 | "0353 Active Mailbox cleared - mailbox timeout " | ||
3261 | "exiting\n"); | ||
3262 | spin_unlock_irq(&phba->hbalock); | ||
3263 | return; | ||
3264 | } | ||
3265 | |||
3254 | /* Mbox cmd <mbxCommand> timeout */ | 3266 | /* Mbox cmd <mbxCommand> timeout */ |
3255 | lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI, | 3267 | lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI, |
3256 | "0310 Mailbox command x%x timeout Data: x%x x%x x%p\n", | 3268 | "0310 Mailbox command x%x timeout Data: x%x x%x x%p\n", |
@@ -3258,6 +3270,7 @@ lpfc_mbox_timeout_handler(struct lpfc_hba *phba) | |||
3258 | phba->pport->port_state, | 3270 | phba->pport->port_state, |
3259 | phba->sli.sli_flag, | 3271 | phba->sli.sli_flag, |
3260 | phba->sli.mbox_active); | 3272 | phba->sli.mbox_active); |
3273 | spin_unlock_irq(&phba->hbalock); | ||
3261 | 3274 | ||
3262 | /* Setting state unknown so lpfc_sli_abort_iocb_ring | 3275 | /* Setting state unknown so lpfc_sli_abort_iocb_ring |
3263 | * would get IOCB_ERROR from lpfc_sli_issue_iocb, allowing | 3276 | * would get IOCB_ERROR from lpfc_sli_issue_iocb, allowing |
@@ -3364,6 +3377,12 @@ lpfc_sli_issue_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox, uint32_t flag) | |||
3364 | goto out_not_finished; | 3377 | goto out_not_finished; |
3365 | } | 3378 | } |
3366 | 3379 | ||
3380 | /* If HBA has a deferred error attention, fail the iocb. */ | ||
3381 | if (unlikely(phba->hba_flag & DEFER_ERATT)) { | ||
3382 | spin_unlock_irqrestore(&phba->hbalock, drvr_flag); | ||
3383 | goto out_not_finished; | ||
3384 | } | ||
3385 | |||
3367 | psli = &phba->sli; | 3386 | psli = &phba->sli; |
3368 | 3387 | ||
3369 | mb = &pmbox->mb; | 3388 | mb = &pmbox->mb; |
@@ -3728,6 +3747,10 @@ __lpfc_sli_issue_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | |||
3728 | if (unlikely(pci_channel_offline(phba->pcidev))) | 3747 | if (unlikely(pci_channel_offline(phba->pcidev))) |
3729 | return IOCB_ERROR; | 3748 | return IOCB_ERROR; |
3730 | 3749 | ||
3750 | /* If HBA has a deferred error attention, fail the iocb. */ | ||
3751 | if (unlikely(phba->hba_flag & DEFER_ERATT)) | ||
3752 | return IOCB_ERROR; | ||
3753 | |||
3731 | /* | 3754 | /* |
3732 | * We should never get an IOCB if we are in a < LINK_DOWN state | 3755 | * We should never get an IOCB if we are in a < LINK_DOWN state |
3733 | */ | 3756 | */ |
@@ -3906,6 +3929,7 @@ lpfc_sli_async_event_handler(struct lpfc_hba * phba, | |||
3906 | uint16_t temp; | 3929 | uint16_t temp; |
3907 | struct temp_event temp_event_data; | 3930 | struct temp_event temp_event_data; |
3908 | struct Scsi_Host *shost; | 3931 | struct Scsi_Host *shost; |
3932 | uint32_t *iocb_w; | ||
3909 | 3933 | ||
3910 | icmd = &iocbq->iocb; | 3934 | icmd = &iocbq->iocb; |
3911 | evt_code = icmd->un.asyncstat.evt_code; | 3935 | evt_code = icmd->un.asyncstat.evt_code; |
@@ -3913,13 +3937,23 @@ lpfc_sli_async_event_handler(struct lpfc_hba * phba, | |||
3913 | 3937 | ||
3914 | if ((evt_code != ASYNC_TEMP_WARN) && | 3938 | if ((evt_code != ASYNC_TEMP_WARN) && |
3915 | (evt_code != ASYNC_TEMP_SAFE)) { | 3939 | (evt_code != ASYNC_TEMP_SAFE)) { |
3940 | iocb_w = (uint32_t *) icmd; | ||
3916 | lpfc_printf_log(phba, | 3941 | lpfc_printf_log(phba, |
3917 | KERN_ERR, | 3942 | KERN_ERR, |
3918 | LOG_SLI, | 3943 | LOG_SLI, |
3919 | "0346 Ring %d handler: unexpected ASYNC_STATUS" | 3944 | "0346 Ring %d handler: unexpected ASYNC_STATUS" |
3920 | " evt_code 0x%x\n", | 3945 | " evt_code 0x%x \n" |
3946 | "W0 0x%08x W1 0x%08x W2 0x%08x W3 0x%08x\n" | ||
3947 | "W4 0x%08x W5 0x%08x W6 0x%08x W7 0x%08x\n" | ||
3948 | "W8 0x%08x W9 0x%08x W10 0x%08x W11 0x%08x\n" | ||
3949 | "W12 0x%08x W13 0x%08x W14 0x%08x W15 0x%08x\n", | ||
3921 | pring->ringno, | 3950 | pring->ringno, |
3922 | icmd->un.asyncstat.evt_code); | 3951 | icmd->un.asyncstat.evt_code, |
3952 | iocb_w[0], iocb_w[1], iocb_w[2], iocb_w[3], | ||
3953 | iocb_w[4], iocb_w[5], iocb_w[6], iocb_w[7], | ||
3954 | iocb_w[8], iocb_w[9], iocb_w[10], iocb_w[11], | ||
3955 | iocb_w[12], iocb_w[13], iocb_w[14], iocb_w[15]); | ||
3956 | |||
3923 | return; | 3957 | return; |
3924 | } | 3958 | } |
3925 | temp_event_data.data = (uint32_t)temp; | 3959 | temp_event_data.data = (uint32_t)temp; |
@@ -4178,17 +4212,9 @@ lpfc_sli_host_down(struct lpfc_vport *vport) | |||
4178 | 4212 | ||
4179 | spin_unlock_irqrestore(&phba->hbalock, flags); | 4213 | spin_unlock_irqrestore(&phba->hbalock, flags); |
4180 | 4214 | ||
4181 | while (!list_empty(&completions)) { | 4215 | /* Cancel all the IOCBs from the completions list */ |
4182 | list_remove_head(&completions, iocb, struct lpfc_iocbq, list); | 4216 | lpfc_sli_cancel_iocbs(phba, &completions, IOSTAT_LOCAL_REJECT, |
4183 | 4217 | IOERR_SLI_DOWN); | |
4184 | if (!iocb->iocb_cmpl) | ||
4185 | lpfc_sli_release_iocbq(phba, iocb); | ||
4186 | else { | ||
4187 | iocb->iocb.ulpStatus = IOSTAT_LOCAL_REJECT; | ||
4188 | iocb->iocb.un.ulpWord[4] = IOERR_SLI_DOWN; | ||
4189 | (iocb->iocb_cmpl) (phba, iocb, iocb); | ||
4190 | } | ||
4191 | } | ||
4192 | return 1; | 4218 | return 1; |
4193 | } | 4219 | } |
4194 | 4220 | ||
@@ -4215,8 +4241,6 @@ lpfc_sli_hba_down(struct lpfc_hba *phba) | |||
4215 | struct lpfc_sli_ring *pring; | 4241 | struct lpfc_sli_ring *pring; |
4216 | struct lpfc_dmabuf *buf_ptr; | 4242 | struct lpfc_dmabuf *buf_ptr; |
4217 | LPFC_MBOXQ_t *pmb; | 4243 | LPFC_MBOXQ_t *pmb; |
4218 | struct lpfc_iocbq *iocb; | ||
4219 | IOCB_t *cmd = NULL; | ||
4220 | int i; | 4244 | int i; |
4221 | unsigned long flags = 0; | 4245 | unsigned long flags = 0; |
4222 | 4246 | ||
@@ -4244,18 +4268,9 @@ lpfc_sli_hba_down(struct lpfc_hba *phba) | |||
4244 | } | 4268 | } |
4245 | spin_unlock_irqrestore(&phba->hbalock, flags); | 4269 | spin_unlock_irqrestore(&phba->hbalock, flags); |
4246 | 4270 | ||
4247 | while (!list_empty(&completions)) { | 4271 | /* Cancel all the IOCBs from the completions list */ |
4248 | list_remove_head(&completions, iocb, struct lpfc_iocbq, list); | 4272 | lpfc_sli_cancel_iocbs(phba, &completions, IOSTAT_LOCAL_REJECT, |
4249 | cmd = &iocb->iocb; | 4273 | IOERR_SLI_DOWN); |
4250 | |||
4251 | if (!iocb->iocb_cmpl) | ||
4252 | lpfc_sli_release_iocbq(phba, iocb); | ||
4253 | else { | ||
4254 | cmd->ulpStatus = IOSTAT_LOCAL_REJECT; | ||
4255 | cmd->un.ulpWord[4] = IOERR_SLI_DOWN; | ||
4256 | (iocb->iocb_cmpl) (phba, iocb, iocb); | ||
4257 | } | ||
4258 | } | ||
4259 | 4274 | ||
4260 | spin_lock_irqsave(&phba->hbalock, flags); | 4275 | spin_lock_irqsave(&phba->hbalock, flags); |
4261 | list_splice_init(&phba->elsbuf, &completions); | 4276 | list_splice_init(&phba->elsbuf, &completions); |
@@ -5137,11 +5152,31 @@ lpfc_sli_check_eratt(struct lpfc_hba *phba) | |||
5137 | return 0; | 5152 | return 0; |
5138 | } | 5153 | } |
5139 | 5154 | ||
5155 | /* | ||
5156 | * If there is deferred error attention, do not check for error | ||
5157 | * attention | ||
5158 | */ | ||
5159 | if (unlikely(phba->hba_flag & DEFER_ERATT)) { | ||
5160 | spin_unlock_irq(&phba->hbalock); | ||
5161 | return 0; | ||
5162 | } | ||
5163 | |||
5140 | /* Read chip Host Attention (HA) register */ | 5164 | /* Read chip Host Attention (HA) register */ |
5141 | ha_copy = readl(phba->HAregaddr); | 5165 | ha_copy = readl(phba->HAregaddr); |
5142 | if (ha_copy & HA_ERATT) { | 5166 | if (ha_copy & HA_ERATT) { |
5143 | /* Read host status register to retrieve error event */ | 5167 | /* Read host status register to retrieve error event */ |
5144 | lpfc_sli_read_hs(phba); | 5168 | lpfc_sli_read_hs(phba); |
5169 | |||
5170 | /* Check if there is a deferred error condition is active */ | ||
5171 | if ((HS_FFER1 & phba->work_hs) && | ||
5172 | ((HS_FFER2 | HS_FFER3 | HS_FFER4 | HS_FFER5 | | ||
5173 | HS_FFER6 | HS_FFER7) & phba->work_hs)) { | ||
5174 | phba->hba_flag |= DEFER_ERATT; | ||
5175 | /* Clear all interrupt enable conditions */ | ||
5176 | writel(0, phba->HCregaddr); | ||
5177 | readl(phba->HCregaddr); | ||
5178 | } | ||
5179 | |||
5145 | /* Set the driver HA work bitmap */ | 5180 | /* Set the driver HA work bitmap */ |
5146 | phba->work_ha |= HA_ERATT; | 5181 | phba->work_ha |= HA_ERATT; |
5147 | /* Indicate polling handles this ERATT */ | 5182 | /* Indicate polling handles this ERATT */ |
@@ -5230,6 +5265,16 @@ lpfc_sp_intr_handler(int irq, void *dev_id) | |||
5230 | /* Indicate interrupt handler handles ERATT */ | 5265 | /* Indicate interrupt handler handles ERATT */ |
5231 | phba->hba_flag |= HBA_ERATT_HANDLED; | 5266 | phba->hba_flag |= HBA_ERATT_HANDLED; |
5232 | } | 5267 | } |
5268 | |||
5269 | /* | ||
5270 | * If there is deferred error attention, do not check for any | ||
5271 | * interrupt. | ||
5272 | */ | ||
5273 | if (unlikely(phba->hba_flag & DEFER_ERATT)) { | ||
5274 | spin_unlock_irq(&phba->hbalock); | ||
5275 | return IRQ_NONE; | ||
5276 | } | ||
5277 | |||
5233 | /* Clear up only attention source related to slow-path */ | 5278 | /* Clear up only attention source related to slow-path */ |
5234 | writel((ha_copy & (HA_MBATT | HA_R2_CLR_MSK)), | 5279 | writel((ha_copy & (HA_MBATT | HA_R2_CLR_MSK)), |
5235 | phba->HAregaddr); | 5280 | phba->HAregaddr); |
@@ -5301,8 +5346,22 @@ lpfc_sp_intr_handler(int irq, void *dev_id) | |||
5301 | } | 5346 | } |
5302 | } | 5347 | } |
5303 | spin_lock_irqsave(&phba->hbalock, iflag); | 5348 | spin_lock_irqsave(&phba->hbalock, iflag); |
5304 | if (work_ha_copy & HA_ERATT) | 5349 | if (work_ha_copy & HA_ERATT) { |
5305 | lpfc_sli_read_hs(phba); | 5350 | lpfc_sli_read_hs(phba); |
5351 | /* | ||
5352 | * Check if there is a deferred error condition | ||
5353 | * is active | ||
5354 | */ | ||
5355 | if ((HS_FFER1 & phba->work_hs) && | ||
5356 | ((HS_FFER2 | HS_FFER3 | HS_FFER4 | HS_FFER5 | | ||
5357 | HS_FFER6 | HS_FFER7) & phba->work_hs)) { | ||
5358 | phba->hba_flag |= DEFER_ERATT; | ||
5359 | /* Clear all interrupt enable conditions */ | ||
5360 | writel(0, phba->HCregaddr); | ||
5361 | readl(phba->HCregaddr); | ||
5362 | } | ||
5363 | } | ||
5364 | |||
5306 | if ((work_ha_copy & HA_MBATT) && (phba->sli.mbox_active)) { | 5365 | if ((work_ha_copy & HA_MBATT) && (phba->sli.mbox_active)) { |
5307 | pmb = phba->sli.mbox_active; | 5366 | pmb = phba->sli.mbox_active; |
5308 | pmbox = &pmb->mb; | 5367 | pmbox = &pmb->mb; |
@@ -5466,6 +5525,14 @@ lpfc_fp_intr_handler(int irq, void *dev_id) | |||
5466 | ha_copy = readl(phba->HAregaddr); | 5525 | ha_copy = readl(phba->HAregaddr); |
5467 | /* Clear up only attention source related to fast-path */ | 5526 | /* Clear up only attention source related to fast-path */ |
5468 | spin_lock_irqsave(&phba->hbalock, iflag); | 5527 | spin_lock_irqsave(&phba->hbalock, iflag); |
5528 | /* | ||
5529 | * If there is deferred error attention, do not check for | ||
5530 | * any interrupt. | ||
5531 | */ | ||
5532 | if (unlikely(phba->hba_flag & DEFER_ERATT)) { | ||
5533 | spin_unlock_irq(&phba->hbalock); | ||
5534 | return IRQ_NONE; | ||
5535 | } | ||
5469 | writel((ha_copy & (HA_R0_CLR_MSK | HA_R1_CLR_MSK)), | 5536 | writel((ha_copy & (HA_R0_CLR_MSK | HA_R1_CLR_MSK)), |
5470 | phba->HAregaddr); | 5537 | phba->HAregaddr); |
5471 | readl(phba->HAregaddr); /* flush */ | 5538 | readl(phba->HAregaddr); /* flush */ |
@@ -5558,6 +5625,14 @@ lpfc_intr_handler(int irq, void *dev_id) | |||
5558 | phba->hba_flag |= HBA_ERATT_HANDLED; | 5625 | phba->hba_flag |= HBA_ERATT_HANDLED; |
5559 | } | 5626 | } |
5560 | 5627 | ||
5628 | /* | ||
5629 | * If there is deferred error attention, do not check for any interrupt. | ||
5630 | */ | ||
5631 | if (unlikely(phba->hba_flag & DEFER_ERATT)) { | ||
5632 | spin_unlock_irq(&phba->hbalock); | ||
5633 | return IRQ_NONE; | ||
5634 | } | ||
5635 | |||
5561 | /* Clear attention sources except link and error attentions */ | 5636 | /* Clear attention sources except link and error attentions */ |
5562 | writel((phba->ha_copy & ~(HA_LATT | HA_ERATT)), phba->HAregaddr); | 5637 | writel((phba->ha_copy & ~(HA_LATT | HA_ERATT)), phba->HAregaddr); |
5563 | readl(phba->HAregaddr); /* flush */ | 5638 | readl(phba->HAregaddr); /* flush */ |