diff options
author | James Smart <James.Smart@Emulex.Com> | 2008-06-14 22:52:47 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2008-07-12 09:22:27 -0400 |
commit | 0d2b6b83030d6a88cbf7db57f84f2daf0e0b251b (patch) | |
tree | 7523cdfa622916864ccd1cecef6f407a482e35e6 /drivers/scsi/lpfc | |
parent | 915caaaf622172bd3451e7b76ba9cfcea80e87c7 (diff) |
[SCSI] lpfc 8.2.7 : Discovery Fixes
- Fix ADISC timeout on initiators causing devloss timeout on targets
- Correct FAN processing : port state vs unreg rpi's wasn't consistent
- Correct mismatches between ASICs and PLOGI that would skip PLOGI
Signed-off-by: James Smart <james.smart@emulex.com>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers/scsi/lpfc')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_els.c | 141 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_hbadisc.c | 23 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_init.c | 3 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_nportdisc.c | 145 |
4 files changed, 99 insertions, 213 deletions
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 886c5f1b11d2..d418c7c1251e 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c | |||
@@ -1754,29 +1754,34 @@ lpfc_cancel_retry_delay_tmo(struct lpfc_vport *vport, struct lpfc_nodelist *nlp) | |||
1754 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); | 1754 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); |
1755 | struct lpfc_work_evt *evtp; | 1755 | struct lpfc_work_evt *evtp; |
1756 | 1756 | ||
1757 | if (!(nlp->nlp_flag & NLP_DELAY_TMO)) | ||
1758 | return; | ||
1757 | spin_lock_irq(shost->host_lock); | 1759 | spin_lock_irq(shost->host_lock); |
1758 | nlp->nlp_flag &= ~NLP_DELAY_TMO; | 1760 | nlp->nlp_flag &= ~NLP_DELAY_TMO; |
1759 | spin_unlock_irq(shost->host_lock); | 1761 | spin_unlock_irq(shost->host_lock); |
1760 | del_timer_sync(&nlp->nlp_delayfunc); | 1762 | del_timer_sync(&nlp->nlp_delayfunc); |
1761 | nlp->nlp_last_elscmd = 0; | 1763 | nlp->nlp_last_elscmd = 0; |
1762 | |||
1763 | if (!list_empty(&nlp->els_retry_evt.evt_listp)) { | 1764 | if (!list_empty(&nlp->els_retry_evt.evt_listp)) { |
1764 | list_del_init(&nlp->els_retry_evt.evt_listp); | 1765 | list_del_init(&nlp->els_retry_evt.evt_listp); |
1765 | /* Decrement nlp reference count held for the delayed retry */ | 1766 | /* Decrement nlp reference count held for the delayed retry */ |
1766 | evtp = &nlp->els_retry_evt; | 1767 | evtp = &nlp->els_retry_evt; |
1767 | lpfc_nlp_put((struct lpfc_nodelist *)evtp->evt_arg1); | 1768 | lpfc_nlp_put((struct lpfc_nodelist *)evtp->evt_arg1); |
1768 | } | 1769 | } |
1769 | |||
1770 | if (nlp->nlp_flag & NLP_NPR_2B_DISC) { | 1770 | if (nlp->nlp_flag & NLP_NPR_2B_DISC) { |
1771 | spin_lock_irq(shost->host_lock); | 1771 | spin_lock_irq(shost->host_lock); |
1772 | nlp->nlp_flag &= ~NLP_NPR_2B_DISC; | 1772 | nlp->nlp_flag &= ~NLP_NPR_2B_DISC; |
1773 | spin_unlock_irq(shost->host_lock); | 1773 | spin_unlock_irq(shost->host_lock); |
1774 | if (vport->num_disc_nodes) { | 1774 | if (vport->num_disc_nodes) { |
1775 | /* Check to see if there are more | 1775 | if (vport->port_state < LPFC_VPORT_READY) { |
1776 | * PLOGIs to be sent | 1776 | /* Check if there are more ADISCs to be sent */ |
1777 | */ | 1777 | lpfc_more_adisc(vport); |
1778 | lpfc_more_plogi(vport); | 1778 | if ((vport->num_disc_nodes == 0) && |
1779 | 1779 | (vport->fc_npr_cnt)) | |
1780 | lpfc_els_disc_plogi(vport); | ||
1781 | } else { | ||
1782 | /* Check if there are more PLOGIs to be sent */ | ||
1783 | lpfc_more_plogi(vport); | ||
1784 | } | ||
1780 | if (vport->num_disc_nodes == 0) { | 1785 | if (vport->num_disc_nodes == 0) { |
1781 | spin_lock_irq(shost->host_lock); | 1786 | spin_lock_irq(shost->host_lock); |
1782 | vport->fc_flag &= ~FC_NDISC_ACTIVE; | 1787 | vport->fc_flag &= ~FC_NDISC_ACTIVE; |
@@ -1798,10 +1803,6 @@ lpfc_els_retry_delay(unsigned long ptr) | |||
1798 | unsigned long flags; | 1803 | unsigned long flags; |
1799 | struct lpfc_work_evt *evtp = &ndlp->els_retry_evt; | 1804 | struct lpfc_work_evt *evtp = &ndlp->els_retry_evt; |
1800 | 1805 | ||
1801 | ndlp = (struct lpfc_nodelist *) ptr; | ||
1802 | phba = ndlp->vport->phba; | ||
1803 | evtp = &ndlp->els_retry_evt; | ||
1804 | |||
1805 | spin_lock_irqsave(&phba->hbalock, flags); | 1806 | spin_lock_irqsave(&phba->hbalock, flags); |
1806 | if (!list_empty(&evtp->evt_listp)) { | 1807 | if (!list_empty(&evtp->evt_listp)) { |
1807 | spin_unlock_irqrestore(&phba->hbalock, flags); | 1808 | spin_unlock_irqrestore(&phba->hbalock, flags); |
@@ -2761,10 +2762,11 @@ lpfc_els_rsp_prli_acc(struct lpfc_vport *vport, struct lpfc_iocbq *oldiocb, | |||
2761 | npr = (PRLI *) pcmd; | 2762 | npr = (PRLI *) pcmd; |
2762 | vpd = &phba->vpd; | 2763 | vpd = &phba->vpd; |
2763 | /* | 2764 | /* |
2764 | * If our firmware version is 3.20 or later, | 2765 | * If the remote port is a target and our firmware version is 3.20 or |
2765 | * set the following bits for FC-TAPE support. | 2766 | * later, set the following bits for FC-TAPE support. |
2766 | */ | 2767 | */ |
2767 | if (vpd->rev.feaLevelHigh >= 0x02) { | 2768 | if ((ndlp->nlp_type & NLP_FCP_TARGET) && |
2769 | (vpd->rev.feaLevelHigh >= 0x02)) { | ||
2768 | npr->ConfmComplAllowed = 1; | 2770 | npr->ConfmComplAllowed = 1; |
2769 | npr->Retry = 1; | 2771 | npr->Retry = 1; |
2770 | npr->TaskRetryIdReq = 1; | 2772 | npr->TaskRetryIdReq = 1; |
@@ -3056,27 +3058,16 @@ lpfc_rscn_recovery_check(struct lpfc_vport *vport) | |||
3056 | { | 3058 | { |
3057 | struct lpfc_nodelist *ndlp = NULL; | 3059 | struct lpfc_nodelist *ndlp = NULL; |
3058 | 3060 | ||
3059 | /* Look at all nodes effected by pending RSCNs and move | 3061 | /* Move all affected nodes by pending RSCNs to NPR state. */ |
3060 | * them to NPR state. | ||
3061 | */ | ||
3062 | |||
3063 | list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) { | 3062 | list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) { |
3064 | if (!NLP_CHK_NODE_ACT(ndlp) || | 3063 | if (!NLP_CHK_NODE_ACT(ndlp) || |
3065 | ndlp->nlp_state == NLP_STE_UNUSED_NODE || | 3064 | (ndlp->nlp_state == NLP_STE_UNUSED_NODE) || |
3066 | lpfc_rscn_payload_check(vport, ndlp->nlp_DID) == 0) | 3065 | !lpfc_rscn_payload_check(vport, ndlp->nlp_DID)) |
3067 | continue; | 3066 | continue; |
3068 | |||
3069 | lpfc_disc_state_machine(vport, ndlp, NULL, | 3067 | lpfc_disc_state_machine(vport, ndlp, NULL, |
3070 | NLP_EVT_DEVICE_RECOVERY); | 3068 | NLP_EVT_DEVICE_RECOVERY); |
3071 | 3069 | lpfc_cancel_retry_delay_tmo(vport, ndlp); | |
3072 | /* | ||
3073 | * Make sure NLP_DELAY_TMO is NOT running after a device | ||
3074 | * recovery event. | ||
3075 | */ | ||
3076 | if (ndlp->nlp_flag & NLP_DELAY_TMO) | ||
3077 | lpfc_cancel_retry_delay_tmo(vport, ndlp); | ||
3078 | } | 3070 | } |
3079 | |||
3080 | return 0; | 3071 | return 0; |
3081 | } | 3072 | } |
3082 | 3073 | ||
@@ -3781,91 +3772,27 @@ static int | |||
3781 | lpfc_els_rcv_fan(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, | 3772 | lpfc_els_rcv_fan(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, |
3782 | struct lpfc_nodelist *fan_ndlp) | 3773 | struct lpfc_nodelist *fan_ndlp) |
3783 | { | 3774 | { |
3784 | struct lpfc_dmabuf *pcmd; | 3775 | struct lpfc_hba *phba = vport->phba; |
3785 | uint32_t *lp; | 3776 | uint32_t *lp; |
3786 | IOCB_t *icmd; | ||
3787 | uint32_t cmd, did; | ||
3788 | FAN *fp; | 3777 | FAN *fp; |
3789 | struct lpfc_nodelist *ndlp, *next_ndlp; | ||
3790 | struct lpfc_hba *phba = vport->phba; | ||
3791 | |||
3792 | /* FAN received */ | ||
3793 | lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, | ||
3794 | "0265 FAN received\n"); | ||
3795 | icmd = &cmdiocb->iocb; | ||
3796 | did = icmd->un.elsreq64.remoteID; | ||
3797 | pcmd = (struct lpfc_dmabuf *)cmdiocb->context2; | ||
3798 | lp = (uint32_t *)pcmd->virt; | ||
3799 | |||
3800 | cmd = *lp++; | ||
3801 | fp = (FAN *) lp; | ||
3802 | 3778 | ||
3779 | lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, "0265 FAN received\n"); | ||
3780 | lp = (uint32_t *)((struct lpfc_dmabuf *)cmdiocb->context2)->virt; | ||
3781 | fp = (FAN *) ++lp; | ||
3803 | /* FAN received; Fan does not have a reply sequence */ | 3782 | /* FAN received; Fan does not have a reply sequence */ |
3804 | 3783 | if ((vport == phba->pport) && | |
3805 | if (phba->pport->port_state == LPFC_LOCAL_CFG_LINK) { | 3784 | (vport->port_state == LPFC_LOCAL_CFG_LINK)) { |
3806 | if ((memcmp(&phba->fc_fabparam.nodeName, &fp->FnodeName, | 3785 | if ((memcmp(&phba->fc_fabparam.nodeName, &fp->FnodeName, |
3807 | sizeof(struct lpfc_name)) != 0) || | 3786 | sizeof(struct lpfc_name))) || |
3808 | (memcmp(&phba->fc_fabparam.portName, &fp->FportName, | 3787 | (memcmp(&phba->fc_fabparam.portName, &fp->FportName, |
3809 | sizeof(struct lpfc_name)) != 0)) { | 3788 | sizeof(struct lpfc_name)))) { |
3810 | /* | 3789 | /* This port has switched fabrics. FLOGI is required */ |
3811 | * This node has switched fabrics. FLOGI is required | ||
3812 | * Clean up the old rpi's | ||
3813 | */ | ||
3814 | |||
3815 | list_for_each_entry_safe(ndlp, next_ndlp, | ||
3816 | &vport->fc_nodes, nlp_listp) { | ||
3817 | if (!NLP_CHK_NODE_ACT(ndlp)) | ||
3818 | continue; | ||
3819 | if (ndlp->nlp_state != NLP_STE_NPR_NODE) | ||
3820 | continue; | ||
3821 | if (ndlp->nlp_type & NLP_FABRIC) { | ||
3822 | /* | ||
3823 | * Clean up old Fabric, Nameserver and | ||
3824 | * other NLP_FABRIC logins | ||
3825 | */ | ||
3826 | lpfc_drop_node(vport, ndlp); | ||
3827 | |||
3828 | } else if (!(ndlp->nlp_flag & NLP_NPR_ADISC)) { | ||
3829 | /* Fail outstanding I/O now since this | ||
3830 | * device is marked for PLOGI | ||
3831 | */ | ||
3832 | lpfc_unreg_rpi(vport, ndlp); | ||
3833 | } | ||
3834 | } | ||
3835 | |||
3836 | lpfc_initial_flogi(vport); | 3790 | lpfc_initial_flogi(vport); |
3837 | return 0; | 3791 | } else { |
3838 | } | 3792 | /* FAN verified - skip FLOGI */ |
3839 | /* Discovery not needed, | 3793 | vport->fc_myDID = vport->fc_prevDID; |
3840 | * move the nodes to their original state. | 3794 | lpfc_issue_fabric_reglogin(vport); |
3841 | */ | ||
3842 | list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, | ||
3843 | nlp_listp) { | ||
3844 | if (!NLP_CHK_NODE_ACT(ndlp)) | ||
3845 | continue; | ||
3846 | if (ndlp->nlp_state != NLP_STE_NPR_NODE) | ||
3847 | continue; | ||
3848 | |||
3849 | switch (ndlp->nlp_prev_state) { | ||
3850 | case NLP_STE_UNMAPPED_NODE: | ||
3851 | ndlp->nlp_prev_state = NLP_STE_NPR_NODE; | ||
3852 | lpfc_nlp_set_state(vport, ndlp, | ||
3853 | NLP_STE_UNMAPPED_NODE); | ||
3854 | break; | ||
3855 | |||
3856 | case NLP_STE_MAPPED_NODE: | ||
3857 | ndlp->nlp_prev_state = NLP_STE_NPR_NODE; | ||
3858 | lpfc_nlp_set_state(vport, ndlp, | ||
3859 | NLP_STE_MAPPED_NODE); | ||
3860 | break; | ||
3861 | |||
3862 | default: | ||
3863 | break; | ||
3864 | } | ||
3865 | } | 3795 | } |
3866 | |||
3867 | /* Start discovery - this should just do CLEAR_LA */ | ||
3868 | lpfc_disc_start(vport); | ||
3869 | } | 3796 | } |
3870 | return 0; | 3797 | return 0; |
3871 | } | 3798 | } |
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index 7cb68feb04fd..f3dc19dfac5b 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c | |||
@@ -1087,6 +1087,8 @@ lpfc_mbx_cmpl_read_la(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) | |||
1087 | MAILBOX_t *mb = &pmb->mb; | 1087 | MAILBOX_t *mb = &pmb->mb; |
1088 | struct lpfc_dmabuf *mp = (struct lpfc_dmabuf *) (pmb->context1); | 1088 | struct lpfc_dmabuf *mp = (struct lpfc_dmabuf *) (pmb->context1); |
1089 | 1089 | ||
1090 | /* Unblock ELS traffic */ | ||
1091 | phba->sli.ring[LPFC_ELS_RING].flag &= ~LPFC_STOP_IOCB_EVENT; | ||
1090 | /* Check for error */ | 1092 | /* Check for error */ |
1091 | if (mb->mbxStatus) { | 1093 | if (mb->mbxStatus) { |
1092 | lpfc_printf_log(phba, KERN_INFO, LOG_LINK_EVENT, | 1094 | lpfc_printf_log(phba, KERN_INFO, LOG_LINK_EVENT, |
@@ -1650,7 +1652,6 @@ lpfc_nlp_set_state(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
1650 | ndlp->nlp_DID, old_state, state); | 1652 | ndlp->nlp_DID, old_state, state); |
1651 | 1653 | ||
1652 | if (old_state == NLP_STE_NPR_NODE && | 1654 | if (old_state == NLP_STE_NPR_NODE && |
1653 | (ndlp->nlp_flag & NLP_DELAY_TMO) != 0 && | ||
1654 | state != NLP_STE_NPR_NODE) | 1655 | state != NLP_STE_NPR_NODE) |
1655 | lpfc_cancel_retry_delay_tmo(vport, ndlp); | 1656 | lpfc_cancel_retry_delay_tmo(vport, ndlp); |
1656 | if (old_state == NLP_STE_UNMAPPED_NODE) { | 1657 | if (old_state == NLP_STE_UNMAPPED_NODE) { |
@@ -1687,8 +1688,7 @@ lpfc_dequeue_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) | |||
1687 | { | 1688 | { |
1688 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); | 1689 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); |
1689 | 1690 | ||
1690 | if ((ndlp->nlp_flag & NLP_DELAY_TMO) != 0) | 1691 | lpfc_cancel_retry_delay_tmo(vport, ndlp); |
1691 | lpfc_cancel_retry_delay_tmo(vport, ndlp); | ||
1692 | if (ndlp->nlp_state && !list_empty(&ndlp->nlp_listp)) | 1692 | if (ndlp->nlp_state && !list_empty(&ndlp->nlp_listp)) |
1693 | lpfc_nlp_counters(vport, ndlp->nlp_state, -1); | 1693 | lpfc_nlp_counters(vport, ndlp->nlp_state, -1); |
1694 | spin_lock_irq(shost->host_lock); | 1694 | spin_lock_irq(shost->host_lock); |
@@ -1701,8 +1701,7 @@ lpfc_dequeue_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) | |||
1701 | static void | 1701 | static void |
1702 | lpfc_disable_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) | 1702 | lpfc_disable_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) |
1703 | { | 1703 | { |
1704 | if ((ndlp->nlp_flag & NLP_DELAY_TMO) != 0) | 1704 | lpfc_cancel_retry_delay_tmo(vport, ndlp); |
1705 | lpfc_cancel_retry_delay_tmo(vport, ndlp); | ||
1706 | if (ndlp->nlp_state && !list_empty(&ndlp->nlp_listp)) | 1705 | if (ndlp->nlp_state && !list_empty(&ndlp->nlp_listp)) |
1707 | lpfc_nlp_counters(vport, ndlp->nlp_state, -1); | 1706 | lpfc_nlp_counters(vport, ndlp->nlp_state, -1); |
1708 | lpfc_nlp_state_cleanup(vport, ndlp, ndlp->nlp_state, | 1707 | lpfc_nlp_state_cleanup(vport, ndlp, ndlp->nlp_state, |
@@ -2121,10 +2120,8 @@ lpfc_cleanup_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) | |||
2121 | ndlp->nlp_last_elscmd = 0; | 2120 | ndlp->nlp_last_elscmd = 0; |
2122 | del_timer_sync(&ndlp->nlp_delayfunc); | 2121 | del_timer_sync(&ndlp->nlp_delayfunc); |
2123 | 2122 | ||
2124 | if (!list_empty(&ndlp->els_retry_evt.evt_listp)) | 2123 | list_del_init(&ndlp->els_retry_evt.evt_listp); |
2125 | list_del_init(&ndlp->els_retry_evt.evt_listp); | 2124 | list_del_init(&ndlp->dev_loss_evt.evt_listp); |
2126 | if (!list_empty(&ndlp->dev_loss_evt.evt_listp)) | ||
2127 | list_del_init(&ndlp->dev_loss_evt.evt_listp); | ||
2128 | 2125 | ||
2129 | lpfc_unreg_rpi(vport, ndlp); | 2126 | lpfc_unreg_rpi(vport, ndlp); |
2130 | 2127 | ||
@@ -2144,10 +2141,7 @@ lpfc_nlp_remove(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) | |||
2144 | LPFC_MBOXQ_t *mbox; | 2141 | LPFC_MBOXQ_t *mbox; |
2145 | int rc; | 2142 | int rc; |
2146 | 2143 | ||
2147 | if (ndlp->nlp_flag & NLP_DELAY_TMO) { | 2144 | lpfc_cancel_retry_delay_tmo(vport, ndlp); |
2148 | lpfc_cancel_retry_delay_tmo(vport, ndlp); | ||
2149 | } | ||
2150 | |||
2151 | if (ndlp->nlp_flag & NLP_DEFER_RM && !ndlp->nlp_rpi) { | 2145 | if (ndlp->nlp_flag & NLP_DEFER_RM && !ndlp->nlp_rpi) { |
2152 | /* For this case we need to cleanup the default rpi | 2146 | /* For this case we need to cleanup the default rpi |
2153 | * allocated by the firmware. | 2147 | * allocated by the firmware. |
@@ -2317,8 +2311,7 @@ lpfc_setup_disc_node(struct lpfc_vport *vport, uint32_t did) | |||
2317 | /* Since this node is marked for discovery, | 2311 | /* Since this node is marked for discovery, |
2318 | * delay timeout is not needed. | 2312 | * delay timeout is not needed. |
2319 | */ | 2313 | */ |
2320 | if (ndlp->nlp_flag & NLP_DELAY_TMO) | 2314 | lpfc_cancel_retry_delay_tmo(vport, ndlp); |
2321 | lpfc_cancel_retry_delay_tmo(vport, ndlp); | ||
2322 | } else | 2315 | } else |
2323 | ndlp = NULL; | 2316 | ndlp = NULL; |
2324 | } else { | 2317 | } else { |
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index fa757b251f82..6fcddda58512 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c | |||
@@ -851,6 +851,8 @@ lpfc_handle_latt(struct lpfc_hba *phba) | |||
851 | lpfc_read_la(phba, pmb, mp); | 851 | lpfc_read_la(phba, pmb, mp); |
852 | pmb->mbox_cmpl = lpfc_mbx_cmpl_read_la; | 852 | pmb->mbox_cmpl = lpfc_mbx_cmpl_read_la; |
853 | pmb->vport = vport; | 853 | pmb->vport = vport; |
854 | /* Block ELS IOCBs until we have processed this mbox command */ | ||
855 | phba->sli.ring[LPFC_ELS_RING].flag |= LPFC_STOP_IOCB_EVENT; | ||
854 | rc = lpfc_sli_issue_mbox (phba, pmb, MBX_NOWAIT); | 856 | rc = lpfc_sli_issue_mbox (phba, pmb, MBX_NOWAIT); |
855 | if (rc == MBX_NOT_FINISHED) { | 857 | if (rc == MBX_NOT_FINISHED) { |
856 | rc = 4; | 858 | rc = 4; |
@@ -866,6 +868,7 @@ lpfc_handle_latt(struct lpfc_hba *phba) | |||
866 | return; | 868 | return; |
867 | 869 | ||
868 | lpfc_handle_latt_free_mbuf: | 870 | lpfc_handle_latt_free_mbuf: |
871 | phba->sli.ring[LPFC_ELS_RING].flag &= ~LPFC_STOP_IOCB_EVENT; | ||
869 | lpfc_mbuf_free(phba, mp->virt, mp->phys); | 872 | lpfc_mbuf_free(phba, mp->virt, mp->phys); |
870 | lpfc_handle_latt_free_mp: | 873 | lpfc_handle_latt_free_mp: |
871 | kfree(mp); | 874 | kfree(mp); |
diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c index d08c4c890744..6688a8689b56 100644 --- a/drivers/scsi/lpfc/lpfc_nportdisc.c +++ b/drivers/scsi/lpfc/lpfc_nportdisc.c | |||
@@ -235,10 +235,7 @@ lpfc_els_abort(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp) | |||
235 | (iocb->iocb_cmpl) (phba, iocb, iocb); | 235 | (iocb->iocb_cmpl) (phba, iocb, iocb); |
236 | } | 236 | } |
237 | } | 237 | } |
238 | 238 | lpfc_cancel_retry_delay_tmo(phba->pport, ndlp); | |
239 | /* If we are delaying issuing an ELS command, cancel it */ | ||
240 | if (ndlp->nlp_flag & NLP_DELAY_TMO) | ||
241 | lpfc_cancel_retry_delay_tmo(phba->pport, ndlp); | ||
242 | return 0; | 239 | return 0; |
243 | } | 240 | } |
244 | 241 | ||
@@ -249,7 +246,6 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
249 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); | 246 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); |
250 | struct lpfc_hba *phba = vport->phba; | 247 | struct lpfc_hba *phba = vport->phba; |
251 | struct lpfc_dmabuf *pcmd; | 248 | struct lpfc_dmabuf *pcmd; |
252 | struct lpfc_work_evt *evtp; | ||
253 | uint32_t *lp; | 249 | uint32_t *lp; |
254 | IOCB_t *icmd; | 250 | IOCB_t *icmd; |
255 | struct serv_parm *sp; | 251 | struct serv_parm *sp; |
@@ -425,73 +421,8 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
425 | ndlp, mbox); | 421 | ndlp, mbox); |
426 | return 1; | 422 | return 1; |
427 | } | 423 | } |
428 | |||
429 | /* If the remote NPort logs into us, before we can initiate | ||
430 | * discovery to them, cleanup the NPort from discovery accordingly. | ||
431 | */ | ||
432 | if (ndlp->nlp_state == NLP_STE_NPR_NODE) { | ||
433 | spin_lock_irq(shost->host_lock); | ||
434 | ndlp->nlp_flag &= ~NLP_DELAY_TMO; | ||
435 | spin_unlock_irq(shost->host_lock); | ||
436 | del_timer_sync(&ndlp->nlp_delayfunc); | ||
437 | ndlp->nlp_last_elscmd = 0; | ||
438 | |||
439 | if (!list_empty(&ndlp->els_retry_evt.evt_listp)) { | ||
440 | list_del_init(&ndlp->els_retry_evt.evt_listp); | ||
441 | /* Decrement ndlp reference count held for the | ||
442 | * delayed retry | ||
443 | */ | ||
444 | evtp = &ndlp->els_retry_evt; | ||
445 | lpfc_nlp_put((struct lpfc_nodelist *)evtp->evt_arg1); | ||
446 | } | ||
447 | |||
448 | if (ndlp->nlp_flag & NLP_NPR_2B_DISC) { | ||
449 | spin_lock_irq(shost->host_lock); | ||
450 | ndlp->nlp_flag &= ~NLP_NPR_2B_DISC; | ||
451 | spin_unlock_irq(shost->host_lock); | ||
452 | |||
453 | if ((ndlp->nlp_flag & NLP_ADISC_SND) && | ||
454 | (vport->num_disc_nodes)) { | ||
455 | /* Check to see if there are more | ||
456 | * ADISCs to be sent | ||
457 | */ | ||
458 | lpfc_more_adisc(vport); | ||
459 | |||
460 | if ((vport->num_disc_nodes == 0) && | ||
461 | (vport->fc_npr_cnt)) | ||
462 | lpfc_els_disc_plogi(vport); | ||
463 | |||
464 | if (vport->num_disc_nodes == 0) { | ||
465 | spin_lock_irq(shost->host_lock); | ||
466 | vport->fc_flag &= ~FC_NDISC_ACTIVE; | ||
467 | spin_unlock_irq(shost->host_lock); | ||
468 | lpfc_can_disctmo(vport); | ||
469 | lpfc_end_rscn(vport); | ||
470 | } | ||
471 | } | ||
472 | } | ||
473 | } else if ((ndlp->nlp_state == NLP_STE_PLOGI_ISSUE) && | ||
474 | (ndlp->nlp_flag & NLP_NPR_2B_DISC) && | ||
475 | (vport->num_disc_nodes)) { | ||
476 | spin_lock_irq(shost->host_lock); | ||
477 | ndlp->nlp_flag &= ~NLP_NPR_2B_DISC; | ||
478 | spin_unlock_irq(shost->host_lock); | ||
479 | /* Check to see if there are more | ||
480 | * PLOGIs to be sent | ||
481 | */ | ||
482 | lpfc_more_plogi(vport); | ||
483 | if (vport->num_disc_nodes == 0) { | ||
484 | spin_lock_irq(shost->host_lock); | ||
485 | vport->fc_flag &= ~FC_NDISC_ACTIVE; | ||
486 | spin_unlock_irq(shost->host_lock); | ||
487 | lpfc_can_disctmo(vport); | ||
488 | lpfc_end_rscn(vport); | ||
489 | } | ||
490 | } | ||
491 | |||
492 | lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb, ndlp, mbox); | 424 | lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb, ndlp, mbox); |
493 | return 1; | 425 | return 1; |
494 | |||
495 | out: | 426 | out: |
496 | stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; | 427 | stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; |
497 | stat.un.b.lsRjtRsnCodeExp = LSEXP_OUT_OF_RESOURCE; | 428 | stat.un.b.lsRjtRsnCodeExp = LSEXP_OUT_OF_RESOURCE; |
@@ -574,7 +505,9 @@ lpfc_rcv_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
574 | else | 505 | else |
575 | lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL); | 506 | lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL); |
576 | 507 | ||
577 | if (!(ndlp->nlp_type & NLP_FABRIC) || | 508 | if ((!(ndlp->nlp_type & NLP_FABRIC) && |
509 | ((ndlp->nlp_type & NLP_FCP_TARGET) || | ||
510 | !(ndlp->nlp_type & NLP_FCP_INITIATOR))) || | ||
578 | (ndlp->nlp_state == NLP_STE_ADISC_ISSUE)) { | 511 | (ndlp->nlp_state == NLP_STE_ADISC_ISSUE)) { |
579 | /* Only try to re-login if this is NOT a Fabric Node */ | 512 | /* Only try to re-login if this is NOT a Fabric Node */ |
580 | mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ * 1); | 513 | mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ * 1); |
@@ -751,6 +684,7 @@ static uint32_t | |||
751 | lpfc_rcv_plogi_plogi_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | 684 | lpfc_rcv_plogi_plogi_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, |
752 | void *arg, uint32_t evt) | 685 | void *arg, uint32_t evt) |
753 | { | 686 | { |
687 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); | ||
754 | struct lpfc_hba *phba = vport->phba; | 688 | struct lpfc_hba *phba = vport->phba; |
755 | struct lpfc_iocbq *cmdiocb = arg; | 689 | struct lpfc_iocbq *cmdiocb = arg; |
756 | struct lpfc_dmabuf *pcmd = (struct lpfc_dmabuf *) cmdiocb->context2; | 690 | struct lpfc_dmabuf *pcmd = (struct lpfc_dmabuf *) cmdiocb->context2; |
@@ -776,7 +710,22 @@ lpfc_rcv_plogi_plogi_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
776 | lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, | 710 | lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, |
777 | NULL); | 711 | NULL); |
778 | } else { | 712 | } else { |
779 | lpfc_rcv_plogi(vport, ndlp, cmdiocb); | 713 | if (lpfc_rcv_plogi(vport, ndlp, cmdiocb) && |
714 | (ndlp->nlp_flag & NLP_NPR_2B_DISC) && | ||
715 | (vport->num_disc_nodes)) { | ||
716 | spin_lock_irq(shost->host_lock); | ||
717 | ndlp->nlp_flag &= ~NLP_NPR_2B_DISC; | ||
718 | spin_unlock_irq(shost->host_lock); | ||
719 | /* Check if there are more PLOGIs to be sent */ | ||
720 | lpfc_more_plogi(vport); | ||
721 | if (vport->num_disc_nodes == 0) { | ||
722 | spin_lock_irq(shost->host_lock); | ||
723 | vport->fc_flag &= ~FC_NDISC_ACTIVE; | ||
724 | spin_unlock_irq(shost->host_lock); | ||
725 | lpfc_can_disctmo(vport); | ||
726 | lpfc_end_rscn(vport); | ||
727 | } | ||
728 | } | ||
780 | } /* If our portname was less */ | 729 | } /* If our portname was less */ |
781 | 730 | ||
782 | return ndlp->nlp_state; | 731 | return ndlp->nlp_state; |
@@ -1040,6 +989,7 @@ static uint32_t | |||
1040 | lpfc_rcv_plogi_adisc_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | 989 | lpfc_rcv_plogi_adisc_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, |
1041 | void *arg, uint32_t evt) | 990 | void *arg, uint32_t evt) |
1042 | { | 991 | { |
992 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); | ||
1043 | struct lpfc_hba *phba = vport->phba; | 993 | struct lpfc_hba *phba = vport->phba; |
1044 | struct lpfc_iocbq *cmdiocb; | 994 | struct lpfc_iocbq *cmdiocb; |
1045 | 995 | ||
@@ -1048,9 +998,28 @@ lpfc_rcv_plogi_adisc_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
1048 | 998 | ||
1049 | cmdiocb = (struct lpfc_iocbq *) arg; | 999 | cmdiocb = (struct lpfc_iocbq *) arg; |
1050 | 1000 | ||
1051 | if (lpfc_rcv_plogi(vport, ndlp, cmdiocb)) | 1001 | if (lpfc_rcv_plogi(vport, ndlp, cmdiocb)) { |
1052 | return ndlp->nlp_state; | 1002 | if (ndlp->nlp_flag & NLP_NPR_2B_DISC) { |
1003 | spin_lock_irq(shost->host_lock); | ||
1004 | ndlp->nlp_flag &= ~NLP_NPR_2B_DISC; | ||
1005 | spin_unlock_irq(shost->host_lock); | ||
1053 | 1006 | ||
1007 | if (vport->num_disc_nodes) { | ||
1008 | lpfc_more_adisc(vport); | ||
1009 | if ((vport->num_disc_nodes == 0) && | ||
1010 | (vport->fc_npr_cnt)) | ||
1011 | lpfc_els_disc_plogi(vport); | ||
1012 | if (vport->num_disc_nodes == 0) { | ||
1013 | spin_lock_irq(shost->host_lock); | ||
1014 | vport->fc_flag &= ~FC_NDISC_ACTIVE; | ||
1015 | spin_unlock_irq(shost->host_lock); | ||
1016 | lpfc_can_disctmo(vport); | ||
1017 | lpfc_end_rscn(vport); | ||
1018 | } | ||
1019 | } | ||
1020 | } | ||
1021 | return ndlp->nlp_state; | ||
1022 | } | ||
1054 | ndlp->nlp_prev_state = NLP_STE_ADISC_ISSUE; | 1023 | ndlp->nlp_prev_state = NLP_STE_ADISC_ISSUE; |
1055 | lpfc_issue_els_plogi(vport, ndlp->nlp_DID, 0); | 1024 | lpfc_issue_els_plogi(vport, ndlp->nlp_DID, 0); |
1056 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_PLOGI_ISSUE); | 1025 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_PLOGI_ISSUE); |
@@ -1742,24 +1711,21 @@ lpfc_rcv_plogi_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
1742 | struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg; | 1711 | struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg; |
1743 | 1712 | ||
1744 | /* Ignore PLOGI if we have an outstanding LOGO */ | 1713 | /* Ignore PLOGI if we have an outstanding LOGO */ |
1745 | if (ndlp->nlp_flag & (NLP_LOGO_SND | NLP_LOGO_ACC)) { | 1714 | if (ndlp->nlp_flag & (NLP_LOGO_SND | NLP_LOGO_ACC)) |
1746 | return ndlp->nlp_state; | 1715 | return ndlp->nlp_state; |
1747 | } | ||
1748 | |||
1749 | if (lpfc_rcv_plogi(vport, ndlp, cmdiocb)) { | 1716 | if (lpfc_rcv_plogi(vport, ndlp, cmdiocb)) { |
1717 | lpfc_cancel_retry_delay_tmo(vport, ndlp); | ||
1750 | spin_lock_irq(shost->host_lock); | 1718 | spin_lock_irq(shost->host_lock); |
1751 | ndlp->nlp_flag &= ~NLP_NPR_ADISC; | 1719 | ndlp->nlp_flag &= ~(NLP_NPR_ADISC | NLP_NPR_2B_DISC); |
1752 | spin_unlock_irq(shost->host_lock); | 1720 | spin_unlock_irq(shost->host_lock); |
1753 | return ndlp->nlp_state; | 1721 | } else if (!(ndlp->nlp_flag & NLP_NPR_2B_DISC)) { |
1754 | } | 1722 | /* send PLOGI immediately, move to PLOGI issue state */ |
1755 | 1723 | if (!(ndlp->nlp_flag & NLP_DELAY_TMO)) { | |
1756 | /* send PLOGI immediately, move to PLOGI issue state */ | 1724 | ndlp->nlp_prev_state = NLP_STE_NPR_NODE; |
1757 | if (!(ndlp->nlp_flag & NLP_DELAY_TMO)) { | 1725 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_PLOGI_ISSUE); |
1758 | ndlp->nlp_prev_state = NLP_STE_NPR_NODE; | 1726 | lpfc_issue_els_plogi(vport, ndlp->nlp_DID, 0); |
1759 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_PLOGI_ISSUE); | 1727 | } |
1760 | lpfc_issue_els_plogi(vport, ndlp->nlp_DID, 0); | ||
1761 | } | 1728 | } |
1762 | |||
1763 | return ndlp->nlp_state; | 1729 | return ndlp->nlp_state; |
1764 | } | 1730 | } |
1765 | 1731 | ||
@@ -1810,7 +1776,6 @@ lpfc_rcv_padisc_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
1810 | struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg; | 1776 | struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg; |
1811 | 1777 | ||
1812 | lpfc_rcv_padisc(vport, ndlp, cmdiocb); | 1778 | lpfc_rcv_padisc(vport, ndlp, cmdiocb); |
1813 | |||
1814 | /* | 1779 | /* |
1815 | * Do not start discovery if discovery is about to start | 1780 | * Do not start discovery if discovery is about to start |
1816 | * or discovery in progress for this node. Starting discovery | 1781 | * or discovery in progress for this node. Starting discovery |
@@ -1973,9 +1938,7 @@ lpfc_device_recov_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
1973 | spin_lock_irq(shost->host_lock); | 1938 | spin_lock_irq(shost->host_lock); |
1974 | ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC); | 1939 | ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC); |
1975 | spin_unlock_irq(shost->host_lock); | 1940 | spin_unlock_irq(shost->host_lock); |
1976 | if (ndlp->nlp_flag & NLP_DELAY_TMO) { | 1941 | lpfc_cancel_retry_delay_tmo(vport, ndlp); |
1977 | lpfc_cancel_retry_delay_tmo(vport, ndlp); | ||
1978 | } | ||
1979 | return ndlp->nlp_state; | 1942 | return ndlp->nlp_state; |
1980 | } | 1943 | } |
1981 | 1944 | ||