diff options
author | James Smart <James.Smart@Emulex.Com> | 2007-06-17 20:56:39 -0400 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.il.steeleye.com> | 2007-06-17 23:38:11 -0400 |
commit | 858c9f6c19c6f9bf86cbbc64ce0d17c61d6131b8 (patch) | |
tree | 9591b15b4424066023e375ad0aa33fdd37e1c452 /drivers/scsi/lpfc/lpfc_sli.c | |
parent | 92d7f7b0cde3ad2260e7462b40867b57efd49851 (diff) |
[SCSI] lpfc: bug fixes
Following the NPIV support, the following changes have been accumulated
in the testing and qualification of the driver:
- Fix affinity of ELS ring to slow/deferred event processing
- Fix Ring attention masks
- Defer dev_loss_tmo timeout handling to worker thread
- Consolidate link down error classification for better error checking
- Remove unused/deprecated nlp_initiator_tmr timer
- Fix for async scan - move adapter init code back into pci_probe_one
context. Fix async scan interfaces.
- Expand validation of ability to create vports
- Extract VPI resource cnt from firmware
- Tuning of Login/Reject policies to better deal with overwhelmned targets
- Misc ELS and discovery fixes
- Export the npiv_enable attribute to sysfs
- Mailbox handling fix
- Add debugfs support
- A few other small misc fixes:
- wrong return values, double-frees, bad locking
- Added adapter failure heartbeat
Signed-off-by: James Smart <James.Smart@emulex.com>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_sli.c')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_sli.c | 208 |
1 files changed, 153 insertions, 55 deletions
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index a2927dc3161f..f4d5a6b00fde 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c | |||
@@ -38,6 +38,7 @@ | |||
38 | #include "lpfc_crtn.h" | 38 | #include "lpfc_crtn.h" |
39 | #include "lpfc_logmsg.h" | 39 | #include "lpfc_logmsg.h" |
40 | #include "lpfc_compat.h" | 40 | #include "lpfc_compat.h" |
41 | #include "lpfc_debugfs.h" | ||
41 | 42 | ||
42 | /* | 43 | /* |
43 | * Define macro to log: Mailbox command x%x cannot issue Data | 44 | * Define macro to log: Mailbox command x%x cannot issue Data |
@@ -269,20 +270,11 @@ lpfc_sli_ringtxcmpl_put(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | |||
269 | static struct lpfc_iocbq * | 270 | static struct lpfc_iocbq * |
270 | lpfc_sli_ringtx_get(struct lpfc_hba *phba, struct lpfc_sli_ring *pring) | 271 | lpfc_sli_ringtx_get(struct lpfc_hba *phba, struct lpfc_sli_ring *pring) |
271 | { | 272 | { |
272 | struct list_head *dlp; | ||
273 | struct lpfc_iocbq *cmd_iocb; | 273 | struct lpfc_iocbq *cmd_iocb; |
274 | 274 | ||
275 | dlp = &pring->txq; | 275 | list_remove_head((&pring->txq), cmd_iocb, struct lpfc_iocbq, list); |
276 | cmd_iocb = NULL; | 276 | if (cmd_iocb != NULL) |
277 | list_remove_head((&pring->txq), cmd_iocb, | ||
278 | struct lpfc_iocbq, | ||
279 | list); | ||
280 | if (cmd_iocb) { | ||
281 | /* If the first ptr is not equal to the list header, | ||
282 | * deque the IOCBQ_t and return it. | ||
283 | */ | ||
284 | pring->txq_cnt--; | 277 | pring->txq_cnt--; |
285 | } | ||
286 | return cmd_iocb; | 278 | return cmd_iocb; |
287 | } | 279 | } |
288 | 280 | ||
@@ -736,6 +728,7 @@ lpfc_sli_chk_mbx_command(uint8_t mbxCommand) | |||
736 | case MBX_LOAD_EXP_ROM: | 728 | case MBX_LOAD_EXP_ROM: |
737 | case MBX_REG_VPI: | 729 | case MBX_REG_VPI: |
738 | case MBX_UNREG_VPI: | 730 | case MBX_UNREG_VPI: |
731 | case MBX_HEARTBEAT: | ||
739 | ret = mbxCommand; | 732 | ret = mbxCommand; |
740 | break; | 733 | break; |
741 | default: | 734 | default: |
@@ -748,15 +741,18 @@ static void | |||
748 | lpfc_sli_wake_mbox_wait(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq) | 741 | lpfc_sli_wake_mbox_wait(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq) |
749 | { | 742 | { |
750 | wait_queue_head_t *pdone_q; | 743 | wait_queue_head_t *pdone_q; |
744 | unsigned long drvr_flag; | ||
751 | 745 | ||
752 | /* | 746 | /* |
753 | * If pdone_q is empty, the driver thread gave up waiting and | 747 | * If pdone_q is empty, the driver thread gave up waiting and |
754 | * continued running. | 748 | * continued running. |
755 | */ | 749 | */ |
756 | pmboxq->mbox_flag |= LPFC_MBX_WAKE; | 750 | pmboxq->mbox_flag |= LPFC_MBX_WAKE; |
751 | spin_lock_irqsave(&phba->hbalock, drvr_flag); | ||
757 | pdone_q = (wait_queue_head_t *) pmboxq->context1; | 752 | pdone_q = (wait_queue_head_t *) pmboxq->context1; |
758 | if (pdone_q) | 753 | if (pdone_q) |
759 | wake_up_interruptible(pdone_q); | 754 | wake_up_interruptible(pdone_q); |
755 | spin_unlock_irqrestore(&phba->hbalock, drvr_flag); | ||
760 | return; | 756 | return; |
761 | } | 757 | } |
762 | 758 | ||
@@ -817,6 +813,25 @@ lpfc_sli_handle_mb_event(struct lpfc_hba *phba) | |||
817 | 813 | ||
818 | pmbox = &pmb->mb; | 814 | pmbox = &pmb->mb; |
819 | 815 | ||
816 | if (pmbox->mbxCommand != MBX_HEARTBEAT) { | ||
817 | if (pmb->vport) { | ||
818 | lpfc_debugfs_disc_trc(pmb->vport, | ||
819 | LPFC_DISC_TRC_MBOX_VPORT, | ||
820 | "MBOX cmpl vport: cmd:x%x mb:x%x x%x", | ||
821 | (uint32_t)pmbox->mbxCommand, | ||
822 | pmbox->un.varWords[0], | ||
823 | pmbox->un.varWords[1]); | ||
824 | } | ||
825 | else { | ||
826 | lpfc_debugfs_disc_trc(phba->pport, | ||
827 | LPFC_DISC_TRC_MBOX, | ||
828 | "MBOX cmpl: cmd:x%x mb:x%x x%x", | ||
829 | (uint32_t)pmbox->mbxCommand, | ||
830 | pmbox->un.varWords[0], | ||
831 | pmbox->un.varWords[1]); | ||
832 | } | ||
833 | } | ||
834 | |||
820 | /* | 835 | /* |
821 | * It is a fatal error if unknown mbox command completion. | 836 | * It is a fatal error if unknown mbox command completion. |
822 | */ | 837 | */ |
@@ -1309,6 +1324,7 @@ lpfc_sli_handle_fast_ring_event(struct lpfc_hba *phba, | |||
1309 | * network byte order and pci byte orders are different. | 1324 | * network byte order and pci byte orders are different. |
1310 | */ | 1325 | */ |
1311 | entry = lpfc_resp_iocb(phba, pring); | 1326 | entry = lpfc_resp_iocb(phba, pring); |
1327 | phba->last_completion_time = jiffies; | ||
1312 | 1328 | ||
1313 | if (++pring->rspidx >= portRspMax) | 1329 | if (++pring->rspidx >= portRspMax) |
1314 | pring->rspidx = 0; | 1330 | pring->rspidx = 0; |
@@ -1511,6 +1527,7 @@ lpfc_sli_handle_slow_ring_event(struct lpfc_hba *phba, | |||
1511 | */ | 1527 | */ |
1512 | entry = lpfc_resp_iocb(phba, pring); | 1528 | entry = lpfc_resp_iocb(phba, pring); |
1513 | 1529 | ||
1530 | phba->last_completion_time = jiffies; | ||
1514 | rspiocbp = __lpfc_sli_get_iocbq(phba); | 1531 | rspiocbp = __lpfc_sli_get_iocbq(phba); |
1515 | if (rspiocbp == NULL) { | 1532 | if (rspiocbp == NULL) { |
1516 | printk(KERN_ERR "%s: out of buffers! Failing " | 1533 | printk(KERN_ERR "%s: out of buffers! Failing " |
@@ -2304,7 +2321,7 @@ lpfc_sli_hba_setup(struct lpfc_hba *phba) | |||
2304 | 2321 | ||
2305 | switch (lpfc_sli_mode) { | 2322 | switch (lpfc_sli_mode) { |
2306 | case 2: | 2323 | case 2: |
2307 | if (lpfc_npiv_enable) { | 2324 | if (phba->cfg_npiv_enable) { |
2308 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT | LOG_VPORT, | 2325 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT | LOG_VPORT, |
2309 | "%d:1824 NPIV enabled: Override lpfc_sli_mode " | 2326 | "%d:1824 NPIV enabled: Override lpfc_sli_mode " |
2310 | "parameter (%d) to auto (0).\n", | 2327 | "parameter (%d) to auto (0).\n", |
@@ -2573,6 +2590,21 @@ lpfc_sli_issue_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox, uint32_t flag) | |||
2573 | psli->slistat.mbox_busy++; | 2590 | psli->slistat.mbox_busy++; |
2574 | spin_unlock_irqrestore(&phba->hbalock, drvr_flag); | 2591 | spin_unlock_irqrestore(&phba->hbalock, drvr_flag); |
2575 | 2592 | ||
2593 | if (pmbox->vport) { | ||
2594 | lpfc_debugfs_disc_trc(pmbox->vport, | ||
2595 | LPFC_DISC_TRC_MBOX_VPORT, | ||
2596 | "MBOX Bsy vport: cmd:x%x mb:x%x x%x", | ||
2597 | (uint32_t)mb->mbxCommand, | ||
2598 | mb->un.varWords[0], mb->un.varWords[1]); | ||
2599 | } | ||
2600 | else { | ||
2601 | lpfc_debugfs_disc_trc(phba->pport, | ||
2602 | LPFC_DISC_TRC_MBOX, | ||
2603 | "MBOX Bsy: cmd:x%x mb:x%x x%x", | ||
2604 | (uint32_t)mb->mbxCommand, | ||
2605 | mb->un.varWords[0], mb->un.varWords[1]); | ||
2606 | } | ||
2607 | |||
2576 | return MBX_BUSY; | 2608 | return MBX_BUSY; |
2577 | } | 2609 | } |
2578 | 2610 | ||
@@ -2618,6 +2650,23 @@ lpfc_sli_issue_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox, uint32_t flag) | |||
2618 | mb->mbxCommand, phba->pport->port_state, | 2650 | mb->mbxCommand, phba->pport->port_state, |
2619 | psli->sli_flag, flag); | 2651 | psli->sli_flag, flag); |
2620 | 2652 | ||
2653 | if (mb->mbxCommand != MBX_HEARTBEAT) { | ||
2654 | if (pmbox->vport) { | ||
2655 | lpfc_debugfs_disc_trc(pmbox->vport, | ||
2656 | LPFC_DISC_TRC_MBOX_VPORT, | ||
2657 | "MBOX Send vport: cmd:x%x mb:x%x x%x", | ||
2658 | (uint32_t)mb->mbxCommand, | ||
2659 | mb->un.varWords[0], mb->un.varWords[1]); | ||
2660 | } | ||
2661 | else { | ||
2662 | lpfc_debugfs_disc_trc(phba->pport, | ||
2663 | LPFC_DISC_TRC_MBOX, | ||
2664 | "MBOX Send: cmd:x%x mb:x%x x%x", | ||
2665 | (uint32_t)mb->mbxCommand, | ||
2666 | mb->un.varWords[0], mb->un.varWords[1]); | ||
2667 | } | ||
2668 | } | ||
2669 | |||
2621 | psli->slistat.mbox_cmd++; | 2670 | psli->slistat.mbox_cmd++; |
2622 | evtctr = psli->slistat.mbox_event; | 2671 | evtctr = psli->slistat.mbox_event; |
2623 | 2672 | ||
@@ -2760,14 +2809,13 @@ lpfc_sli_issue_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmbox, uint32_t flag) | |||
2760 | /* | 2809 | /* |
2761 | * Caller needs to hold lock. | 2810 | * Caller needs to hold lock. |
2762 | */ | 2811 | */ |
2763 | static int | 2812 | static void |
2764 | __lpfc_sli_ringtx_put(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | 2813 | __lpfc_sli_ringtx_put(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, |
2765 | struct lpfc_iocbq *piocb) | 2814 | struct lpfc_iocbq *piocb) |
2766 | { | 2815 | { |
2767 | /* Insert the caller's iocb in the txq tail for later processing. */ | 2816 | /* Insert the caller's iocb in the txq tail for later processing. */ |
2768 | list_add_tail(&piocb->list, &pring->txq); | 2817 | list_add_tail(&piocb->list, &pring->txq); |
2769 | pring->txq_cnt++; | 2818 | pring->txq_cnt++; |
2770 | return 0; | ||
2771 | } | 2819 | } |
2772 | 2820 | ||
2773 | static struct lpfc_iocbq * | 2821 | static struct lpfc_iocbq * |
@@ -3074,11 +3122,11 @@ lpfc_sli_queue_setup(struct lpfc_hba *phba) | |||
3074 | int | 3122 | int |
3075 | lpfc_sli_host_down(struct lpfc_vport *vport) | 3123 | lpfc_sli_host_down(struct lpfc_vport *vport) |
3076 | { | 3124 | { |
3125 | LIST_HEAD(completions); | ||
3077 | struct lpfc_hba *phba = vport->phba; | 3126 | struct lpfc_hba *phba = vport->phba; |
3078 | struct lpfc_sli *psli = &phba->sli; | 3127 | struct lpfc_sli *psli = &phba->sli; |
3079 | struct lpfc_sli_ring *pring; | 3128 | struct lpfc_sli_ring *pring; |
3080 | struct lpfc_iocbq *iocb, *next_iocb; | 3129 | struct lpfc_iocbq *iocb, *next_iocb; |
3081 | IOCB_t *icmd = NULL; | ||
3082 | int i; | 3130 | int i; |
3083 | unsigned long flags = 0; | 3131 | unsigned long flags = 0; |
3084 | uint16_t prev_pring_flag; | 3132 | uint16_t prev_pring_flag; |
@@ -3086,31 +3134,20 @@ lpfc_sli_host_down(struct lpfc_vport *vport) | |||
3086 | lpfc_cleanup_discovery_resources(vport); | 3134 | lpfc_cleanup_discovery_resources(vport); |
3087 | 3135 | ||
3088 | spin_lock_irqsave(&phba->hbalock, flags); | 3136 | spin_lock_irqsave(&phba->hbalock, flags); |
3089 | |||
3090 | for (i = 0; i < psli->num_rings; i++) { | 3137 | for (i = 0; i < psli->num_rings; i++) { |
3091 | pring = &psli->ring[i]; | 3138 | pring = &psli->ring[i]; |
3092 | prev_pring_flag = pring->flag; | 3139 | prev_pring_flag = pring->flag; |
3093 | pring->flag |= LPFC_DEFERRED_RING_EVENT; | 3140 | if (pring->ringno == LPFC_ELS_RING) /* Only slow rings */ |
3094 | 3141 | pring->flag |= LPFC_DEFERRED_RING_EVENT; | |
3095 | /* | 3142 | /* |
3096 | * Error everything on the txq since these iocbs have not been | 3143 | * Error everything on the txq since these iocbs have not been |
3097 | * given to the FW yet. | 3144 | * given to the FW yet. |
3098 | */ | 3145 | */ |
3099 | |||
3100 | list_for_each_entry_safe(iocb, next_iocb, &pring->txq, list) { | 3146 | list_for_each_entry_safe(iocb, next_iocb, &pring->txq, list) { |
3101 | if (iocb->vport != vport) | 3147 | if (iocb->vport != vport) |
3102 | continue; | 3148 | continue; |
3103 | list_del_init(&iocb->list); | 3149 | list_move_tail(&iocb->list, &completions); |
3104 | pring->txq_cnt--; | 3150 | pring->txq_cnt--; |
3105 | if (iocb->iocb_cmpl) { | ||
3106 | icmd = &iocb->iocb; | ||
3107 | icmd->ulpStatus = IOSTAT_LOCAL_REJECT; | ||
3108 | icmd->un.ulpWord[4] = IOERR_SLI_DOWN; | ||
3109 | spin_unlock_irqrestore(&phba->hbalock, flags); | ||
3110 | (iocb->iocb_cmpl) (phba, iocb, iocb); | ||
3111 | spin_lock_irqsave(&phba->hbalock, flags); | ||
3112 | } else | ||
3113 | lpfc_sli_release_iocbq(phba, iocb); | ||
3114 | } | 3151 | } |
3115 | 3152 | ||
3116 | /* Next issue ABTS for everything on the txcmplq */ | 3153 | /* Next issue ABTS for everything on the txcmplq */ |
@@ -3126,6 +3163,17 @@ lpfc_sli_host_down(struct lpfc_vport *vport) | |||
3126 | 3163 | ||
3127 | spin_unlock_irqrestore(&phba->hbalock, flags); | 3164 | spin_unlock_irqrestore(&phba->hbalock, flags); |
3128 | 3165 | ||
3166 | while (!list_empty(&completions)) { | ||
3167 | list_remove_head(&completions, iocb, struct lpfc_iocbq, list); | ||
3168 | |||
3169 | if (!iocb->iocb_cmpl) | ||
3170 | lpfc_sli_release_iocbq(phba, iocb); | ||
3171 | else { | ||
3172 | iocb->iocb.ulpStatus = IOSTAT_LOCAL_REJECT; | ||
3173 | iocb->iocb.un.ulpWord[4] = IOERR_SLI_DOWN; | ||
3174 | (iocb->iocb_cmpl) (phba, iocb, iocb); | ||
3175 | } | ||
3176 | } | ||
3129 | return 1; | 3177 | return 1; |
3130 | } | 3178 | } |
3131 | 3179 | ||
@@ -3148,7 +3196,8 @@ lpfc_sli_hba_down(struct lpfc_hba *phba) | |||
3148 | spin_lock_irqsave(&phba->hbalock, flags); | 3196 | spin_lock_irqsave(&phba->hbalock, flags); |
3149 | for (i = 0; i < psli->num_rings; i++) { | 3197 | for (i = 0; i < psli->num_rings; i++) { |
3150 | pring = &psli->ring[i]; | 3198 | pring = &psli->ring[i]; |
3151 | pring->flag |= LPFC_DEFERRED_RING_EVENT; | 3199 | if (pring->ringno == LPFC_ELS_RING) /* Only slow rings */ |
3200 | pring->flag |= LPFC_DEFERRED_RING_EVENT; | ||
3152 | 3201 | ||
3153 | /* | 3202 | /* |
3154 | * Error everything on the txq since these iocbs have not been | 3203 | * Error everything on the txq since these iocbs have not been |
@@ -3326,8 +3375,10 @@ lpfc_ignore_els_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
3326 | "x%x x%x x%x\n", | 3375 | "x%x x%x x%x\n", |
3327 | phba->brd_no, irsp->ulpIoTag, irsp->ulpStatus, | 3376 | phba->brd_no, irsp->ulpIoTag, irsp->ulpStatus, |
3328 | irsp->un.ulpWord[4], irsp->ulpTimeout); | 3377 | irsp->un.ulpWord[4], irsp->ulpTimeout); |
3329 | 3378 | if (cmdiocb->iocb.ulpCommand == CMD_GEN_REQUEST64_CR) | |
3330 | lpfc_els_free_iocb(phba, cmdiocb); | 3379 | lpfc_ct_free_iocb(phba, cmdiocb); |
3380 | else | ||
3381 | lpfc_els_free_iocb(phba, cmdiocb); | ||
3331 | return; | 3382 | return; |
3332 | } | 3383 | } |
3333 | 3384 | ||
@@ -3352,10 +3403,11 @@ lpfc_sli_issue_abort_iotag(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | |||
3352 | (cmdiocb->iocb_flag & LPFC_DRIVER_ABORTED) != 0) | 3403 | (cmdiocb->iocb_flag & LPFC_DRIVER_ABORTED) != 0) |
3353 | return 0; | 3404 | return 0; |
3354 | 3405 | ||
3355 | /* If we're unloading, don't abort the iocb, but change the callback so | 3406 | /* If we're unloading, don't abort iocb on the ELS ring, but change the |
3356 | * that nothing happens when it finishes. | 3407 | * callback so that nothing happens when it finishes. |
3357 | */ | 3408 | */ |
3358 | if (vport->load_flag & FC_UNLOADING) { | 3409 | if ((vport->load_flag & FC_UNLOADING) && |
3410 | (pring->ringno == LPFC_ELS_RING)) { | ||
3359 | if (cmdiocb->iocb_flag & LPFC_IO_FABRIC) | 3411 | if (cmdiocb->iocb_flag & LPFC_IO_FABRIC) |
3360 | cmdiocb->fabric_iocb_cmpl = lpfc_ignore_els_cmpl; | 3412 | cmdiocb->fabric_iocb_cmpl = lpfc_ignore_els_cmpl; |
3361 | else | 3413 | else |
@@ -3540,9 +3592,9 @@ lpfc_sli_wake_iocb_wait(struct lpfc_hba *phba, | |||
3540 | &rspiocbq->iocb, sizeof(IOCB_t)); | 3592 | &rspiocbq->iocb, sizeof(IOCB_t)); |
3541 | 3593 | ||
3542 | pdone_q = cmdiocbq->context_un.wait_queue; | 3594 | pdone_q = cmdiocbq->context_un.wait_queue; |
3543 | spin_unlock_irqrestore(&phba->hbalock, iflags); | ||
3544 | if (pdone_q) | 3595 | if (pdone_q) |
3545 | wake_up(pdone_q); | 3596 | wake_up(pdone_q); |
3597 | spin_unlock_irqrestore(&phba->hbalock, iflags); | ||
3546 | return; | 3598 | return; |
3547 | } | 3599 | } |
3548 | 3600 | ||
@@ -3638,6 +3690,7 @@ lpfc_sli_issue_mbox_wait(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq, | |||
3638 | { | 3690 | { |
3639 | DECLARE_WAIT_QUEUE_HEAD_ONSTACK(done_q); | 3691 | DECLARE_WAIT_QUEUE_HEAD_ONSTACK(done_q); |
3640 | int retval; | 3692 | int retval; |
3693 | unsigned long flag; | ||
3641 | 3694 | ||
3642 | /* The caller must leave context1 empty. */ | 3695 | /* The caller must leave context1 empty. */ |
3643 | if (pmboxq->context1 != 0) | 3696 | if (pmboxq->context1 != 0) |
@@ -3656,6 +3709,7 @@ lpfc_sli_issue_mbox_wait(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq, | |||
3656 | pmboxq->mbox_flag & LPFC_MBX_WAKE, | 3709 | pmboxq->mbox_flag & LPFC_MBX_WAKE, |
3657 | timeout * HZ); | 3710 | timeout * HZ); |
3658 | 3711 | ||
3712 | spin_lock_irqsave(&phba->hbalock, flag); | ||
3659 | pmboxq->context1 = NULL; | 3713 | pmboxq->context1 = NULL; |
3660 | /* | 3714 | /* |
3661 | * if LPFC_MBX_WAKE flag is set the mailbox is completed | 3715 | * if LPFC_MBX_WAKE flag is set the mailbox is completed |
@@ -3663,8 +3717,11 @@ lpfc_sli_issue_mbox_wait(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq, | |||
3663 | */ | 3717 | */ |
3664 | if (pmboxq->mbox_flag & LPFC_MBX_WAKE) | 3718 | if (pmboxq->mbox_flag & LPFC_MBX_WAKE) |
3665 | retval = MBX_SUCCESS; | 3719 | retval = MBX_SUCCESS; |
3666 | else | 3720 | else { |
3667 | retval = MBX_TIMEOUT; | 3721 | retval = MBX_TIMEOUT; |
3722 | pmboxq->mbox_cmpl = lpfc_sli_def_mbox_cmpl; | ||
3723 | } | ||
3724 | spin_unlock_irqrestore(&phba->hbalock, flag); | ||
3668 | } | 3725 | } |
3669 | 3726 | ||
3670 | return retval; | 3727 | return retval; |
@@ -3712,6 +3769,9 @@ lpfc_intr_handler(int irq, void *dev_id) | |||
3712 | uint32_t control; | 3769 | uint32_t control; |
3713 | 3770 | ||
3714 | MAILBOX_t *mbox, *pmbox; | 3771 | MAILBOX_t *mbox, *pmbox; |
3772 | struct lpfc_vport *vport; | ||
3773 | struct lpfc_nodelist *ndlp; | ||
3774 | struct lpfc_dmabuf *mp; | ||
3715 | LPFC_MBOXQ_t *pmb; | 3775 | LPFC_MBOXQ_t *pmb; |
3716 | int rc; | 3776 | int rc; |
3717 | 3777 | ||
@@ -3780,18 +3840,23 @@ lpfc_intr_handler(int irq, void *dev_id) | |||
3780 | } | 3840 | } |
3781 | 3841 | ||
3782 | if (work_ha_copy & ~(HA_ERATT|HA_MBATT|HA_LATT)) { | 3842 | if (work_ha_copy & ~(HA_ERATT|HA_MBATT|HA_LATT)) { |
3783 | for (i = 0; i < phba->sli.num_rings; i++) { | 3843 | /* |
3784 | if (work_ha_copy & (HA_RXATT << (4*i))) { | 3844 | * Turn off Slow Rings interrupts, LPFC_ELS_RING is |
3785 | /* | 3845 | * the only slow ring. |
3786 | * Turn off Slow Rings interrupts | 3846 | */ |
3787 | */ | 3847 | status = (work_ha_copy & |
3788 | spin_lock(&phba->hbalock); | 3848 | (HA_RXMASK << (4*LPFC_ELS_RING))); |
3789 | control = readl(phba->HCregaddr); | 3849 | status >>= (4*LPFC_ELS_RING); |
3790 | control &= ~(HC_R0INT_ENA << i); | 3850 | if (status & HA_RXMASK) { |
3851 | spin_lock(&phba->hbalock); | ||
3852 | control = readl(phba->HCregaddr); | ||
3853 | if (control & (HC_R0INT_ENA << LPFC_ELS_RING)) { | ||
3854 | control &= | ||
3855 | ~(HC_R0INT_ENA << LPFC_ELS_RING); | ||
3791 | writel(control, phba->HCregaddr); | 3856 | writel(control, phba->HCregaddr); |
3792 | readl(phba->HCregaddr); /* flush */ | 3857 | readl(phba->HCregaddr); /* flush */ |
3793 | spin_unlock(&phba->hbalock); | ||
3794 | } | 3858 | } |
3859 | spin_unlock(&phba->hbalock); | ||
3795 | } | 3860 | } |
3796 | } | 3861 | } |
3797 | 3862 | ||
@@ -3819,6 +3884,7 @@ lpfc_intr_handler(int irq, void *dev_id) | |||
3819 | pmb = phba->sli.mbox_active; | 3884 | pmb = phba->sli.mbox_active; |
3820 | pmbox = &pmb->mb; | 3885 | pmbox = &pmb->mb; |
3821 | mbox = &phba->slim2p->mbx; | 3886 | mbox = &phba->slim2p->mbx; |
3887 | vport = pmb->vport; | ||
3822 | 3888 | ||
3823 | /* First check out the status word */ | 3889 | /* First check out the status word */ |
3824 | lpfc_sli_pcimem_bcopy(mbox, pmbox, sizeof(uint32_t)); | 3890 | lpfc_sli_pcimem_bcopy(mbox, pmbox, sizeof(uint32_t)); |
@@ -3833,22 +3899,54 @@ lpfc_intr_handler(int irq, void *dev_id) | |||
3833 | "Interrupt mbxCommand x%x " | 3899 | "Interrupt mbxCommand x%x " |
3834 | "mbxStatus x%x\n", | 3900 | "mbxStatus x%x\n", |
3835 | phba->brd_no, | 3901 | phba->brd_no, |
3836 | (pmb->vport | 3902 | (vport |
3837 | ? pmb->vport->vpi | 3903 | ? vport->vpi : 0), |
3838 | : 0), | ||
3839 | pmbox->mbxCommand, | 3904 | pmbox->mbxCommand, |
3840 | pmbox->mbxStatus); | 3905 | pmbox->mbxStatus); |
3841 | } | 3906 | } |
3907 | phba->last_completion_time = jiffies; | ||
3842 | del_timer_sync(&phba->sli.mbox_tmo); | 3908 | del_timer_sync(&phba->sli.mbox_tmo); |
3843 | 3909 | ||
3844 | spin_lock(&phba->pport->work_port_lock); | ||
3845 | phba->pport->work_port_events &= ~WORKER_MBOX_TMO; | ||
3846 | spin_unlock(&phba->pport->work_port_lock); | ||
3847 | phba->sli.mbox_active = NULL; | 3910 | phba->sli.mbox_active = NULL; |
3848 | if (pmb->mbox_cmpl) { | 3911 | if (pmb->mbox_cmpl) { |
3849 | lpfc_sli_pcimem_bcopy(mbox, pmbox, | 3912 | lpfc_sli_pcimem_bcopy(mbox, pmbox, |
3850 | MAILBOX_CMD_SIZE); | 3913 | MAILBOX_CMD_SIZE); |
3851 | } | 3914 | } |
3915 | if (pmb->mbox_flag & LPFC_MBX_IMED_UNREG) { | ||
3916 | pmb->mbox_flag &= ~LPFC_MBX_IMED_UNREG; | ||
3917 | |||
3918 | lpfc_debugfs_disc_trc(vport, | ||
3919 | LPFC_DISC_TRC_MBOX_VPORT, | ||
3920 | "MBOX dflt rpi: : status:x%x rpi:x%x", | ||
3921 | (uint32_t)pmbox->mbxStatus, | ||
3922 | pmbox->un.varWords[0], 0); | ||
3923 | |||
3924 | if ( !pmbox->mbxStatus) { | ||
3925 | mp = (struct lpfc_dmabuf *) | ||
3926 | (pmb->context1); | ||
3927 | ndlp = (struct lpfc_nodelist *) | ||
3928 | pmb->context2; | ||
3929 | |||
3930 | /* Reg_LOGIN of dflt RPI was successful. | ||
3931 | * new lets get rid of the RPI using the | ||
3932 | * same mbox buffer. | ||
3933 | */ | ||
3934 | lpfc_unreg_login(phba, vport->vpi, | ||
3935 | pmbox->un.varWords[0], pmb); | ||
3936 | pmb->mbox_cmpl = lpfc_mbx_cmpl_dflt_rpi; | ||
3937 | pmb->context1 = mp; | ||
3938 | pmb->context2 = ndlp; | ||
3939 | pmb->vport = vport; | ||
3940 | spin_lock(&phba->hbalock); | ||
3941 | phba->sli.sli_flag &= | ||
3942 | ~LPFC_SLI_MBOX_ACTIVE; | ||
3943 | spin_unlock(&phba->hbalock); | ||
3944 | goto send_current_mbox; | ||
3945 | } | ||
3946 | } | ||
3947 | spin_lock(&phba->pport->work_port_lock); | ||
3948 | phba->pport->work_port_events &= ~WORKER_MBOX_TMO; | ||
3949 | spin_unlock(&phba->pport->work_port_lock); | ||
3852 | lpfc_mbox_cmpl_put(phba, pmb); | 3950 | lpfc_mbox_cmpl_put(phba, pmb); |
3853 | } | 3951 | } |
3854 | if ((work_ha_copy & HA_MBATT) && | 3952 | if ((work_ha_copy & HA_MBATT) && |
@@ -3858,7 +3956,7 @@ send_next_mbox: | |||
3858 | phba->sli.sli_flag &= ~LPFC_SLI_MBOX_ACTIVE; | 3956 | phba->sli.sli_flag &= ~LPFC_SLI_MBOX_ACTIVE; |
3859 | pmb = lpfc_mbox_get(phba); | 3957 | pmb = lpfc_mbox_get(phba); |
3860 | spin_unlock(&phba->hbalock); | 3958 | spin_unlock(&phba->hbalock); |
3861 | 3959 | send_current_mbox: | |
3862 | /* Process next mailbox command if there is one */ | 3960 | /* Process next mailbox command if there is one */ |
3863 | if (pmb != NULL) { | 3961 | if (pmb != NULL) { |
3864 | rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT); | 3962 | rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT); |
@@ -3891,7 +3989,7 @@ send_next_mbox: | |||
3891 | */ | 3989 | */ |
3892 | status = (ha_copy & (HA_RXMASK << (4*LPFC_FCP_RING))); | 3990 | status = (ha_copy & (HA_RXMASK << (4*LPFC_FCP_RING))); |
3893 | status >>= (4*LPFC_FCP_RING); | 3991 | status >>= (4*LPFC_FCP_RING); |
3894 | if (status & HA_RXATT) | 3992 | if (status & HA_RXMASK) |
3895 | lpfc_sli_handle_fast_ring_event(phba, | 3993 | lpfc_sli_handle_fast_ring_event(phba, |
3896 | &phba->sli.ring[LPFC_FCP_RING], | 3994 | &phba->sli.ring[LPFC_FCP_RING], |
3897 | status); | 3995 | status); |
@@ -3904,7 +4002,7 @@ send_next_mbox: | |||
3904 | */ | 4002 | */ |
3905 | status = (ha_copy & (HA_RXMASK << (4*LPFC_EXTRA_RING))); | 4003 | status = (ha_copy & (HA_RXMASK << (4*LPFC_EXTRA_RING))); |
3906 | status >>= (4*LPFC_EXTRA_RING); | 4004 | status >>= (4*LPFC_EXTRA_RING); |
3907 | if (status & HA_RXATT) { | 4005 | if (status & HA_RXMASK) { |
3908 | lpfc_sli_handle_fast_ring_event(phba, | 4006 | lpfc_sli_handle_fast_ring_event(phba, |
3909 | &phba->sli.ring[LPFC_EXTRA_RING], | 4007 | &phba->sli.ring[LPFC_EXTRA_RING], |
3910 | status); | 4008 | status); |