aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/lpfc/lpfc_els.c
diff options
context:
space:
mode:
authorJames Smart <James.Smart@Emulex.Com>2008-06-14 22:52:47 -0400
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2008-07-12 09:22:27 -0400
commit0d2b6b83030d6a88cbf7db57f84f2daf0e0b251b (patch)
tree7523cdfa622916864ccd1cecef6f407a482e35e6 /drivers/scsi/lpfc/lpfc_els.c
parent915caaaf622172bd3451e7b76ba9cfcea80e87c7 (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/lpfc_els.c')
-rw-r--r--drivers/scsi/lpfc/lpfc_els.c141
1 files changed, 34 insertions, 107 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
3781lpfc_els_rcv_fan(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, 3772lpfc_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}