diff options
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_els.c')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_els.c | 181 |
1 files changed, 50 insertions, 131 deletions
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 886c5f1b11d2..f54e0f7eaee3 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); |
@@ -1812,11 +1813,11 @@ lpfc_els_retry_delay(unsigned long ptr) | |||
1812 | * count until the queued work is done | 1813 | * count until the queued work is done |
1813 | */ | 1814 | */ |
1814 | evtp->evt_arg1 = lpfc_nlp_get(ndlp); | 1815 | evtp->evt_arg1 = lpfc_nlp_get(ndlp); |
1815 | evtp->evt = LPFC_EVT_ELS_RETRY; | 1816 | if (evtp->evt_arg1) { |
1816 | list_add_tail(&evtp->evt_listp, &phba->work_list); | 1817 | evtp->evt = LPFC_EVT_ELS_RETRY; |
1817 | if (phba->work_wait) | 1818 | list_add_tail(&evtp->evt_listp, &phba->work_list); |
1818 | lpfc_worker_wake_up(phba); | 1819 | lpfc_worker_wake_up(phba); |
1819 | 1820 | } | |
1820 | spin_unlock_irqrestore(&phba->hbalock, flags); | 1821 | spin_unlock_irqrestore(&phba->hbalock, flags); |
1821 | return; | 1822 | return; |
1822 | } | 1823 | } |
@@ -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 | } |
@@ -3875,20 +3802,17 @@ lpfc_els_timeout(unsigned long ptr) | |||
3875 | { | 3802 | { |
3876 | struct lpfc_vport *vport = (struct lpfc_vport *) ptr; | 3803 | struct lpfc_vport *vport = (struct lpfc_vport *) ptr; |
3877 | struct lpfc_hba *phba = vport->phba; | 3804 | struct lpfc_hba *phba = vport->phba; |
3805 | uint32_t tmo_posted; | ||
3878 | unsigned long iflag; | 3806 | unsigned long iflag; |
3879 | 3807 | ||
3880 | spin_lock_irqsave(&vport->work_port_lock, iflag); | 3808 | spin_lock_irqsave(&vport->work_port_lock, iflag); |
3881 | if ((vport->work_port_events & WORKER_ELS_TMO) == 0) { | 3809 | tmo_posted = vport->work_port_events & WORKER_ELS_TMO; |
3810 | if (!tmo_posted) | ||
3882 | vport->work_port_events |= WORKER_ELS_TMO; | 3811 | vport->work_port_events |= WORKER_ELS_TMO; |
3883 | spin_unlock_irqrestore(&vport->work_port_lock, iflag); | 3812 | spin_unlock_irqrestore(&vport->work_port_lock, iflag); |
3884 | 3813 | ||
3885 | spin_lock_irqsave(&phba->hbalock, iflag); | 3814 | if (!tmo_posted) |
3886 | if (phba->work_wait) | 3815 | lpfc_worker_wake_up(phba); |
3887 | lpfc_worker_wake_up(phba); | ||
3888 | spin_unlock_irqrestore(&phba->hbalock, iflag); | ||
3889 | } | ||
3890 | else | ||
3891 | spin_unlock_irqrestore(&vport->work_port_lock, iflag); | ||
3892 | return; | 3816 | return; |
3893 | } | 3817 | } |
3894 | 3818 | ||
@@ -3933,9 +3857,6 @@ lpfc_els_timeout_handler(struct lpfc_vport *vport) | |||
3933 | els_command == ELS_CMD_FDISC) | 3857 | els_command == ELS_CMD_FDISC) |
3934 | continue; | 3858 | continue; |
3935 | 3859 | ||
3936 | if (vport != piocb->vport) | ||
3937 | continue; | ||
3938 | |||
3939 | if (piocb->drvrTimeout > 0) { | 3860 | if (piocb->drvrTimeout > 0) { |
3940 | if (piocb->drvrTimeout >= timeout) | 3861 | if (piocb->drvrTimeout >= timeout) |
3941 | piocb->drvrTimeout -= timeout; | 3862 | piocb->drvrTimeout -= timeout; |
@@ -4089,7 +4010,7 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | |||
4089 | payload = ((struct lpfc_dmabuf *)elsiocb->context2)->virt; | 4010 | payload = ((struct lpfc_dmabuf *)elsiocb->context2)->virt; |
4090 | cmd = *payload; | 4011 | cmd = *payload; |
4091 | if ((phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) == 0) | 4012 | if ((phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) == 0) |
4092 | lpfc_post_buffer(phba, pring, 1, 1); | 4013 | lpfc_post_buffer(phba, pring, 1); |
4093 | 4014 | ||
4094 | did = icmd->un.rcvels.remoteID; | 4015 | did = icmd->un.rcvels.remoteID; |
4095 | if (icmd->ulpStatus) { | 4016 | if (icmd->ulpStatus) { |
@@ -4398,7 +4319,7 @@ lpfc_els_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | |||
4398 | phba->fc_stat.NoRcvBuf++; | 4319 | phba->fc_stat.NoRcvBuf++; |
4399 | /* Not enough posted buffers; Try posting more buffers */ | 4320 | /* Not enough posted buffers; Try posting more buffers */ |
4400 | if (!(phba->sli3_options & LPFC_SLI3_HBQ_ENABLED)) | 4321 | if (!(phba->sli3_options & LPFC_SLI3_HBQ_ENABLED)) |
4401 | lpfc_post_buffer(phba, pring, 0, 1); | 4322 | lpfc_post_buffer(phba, pring, 0); |
4402 | return; | 4323 | return; |
4403 | } | 4324 | } |
4404 | 4325 | ||
@@ -4842,18 +4763,16 @@ lpfc_fabric_block_timeout(unsigned long ptr) | |||
4842 | struct lpfc_hba *phba = (struct lpfc_hba *) ptr; | 4763 | struct lpfc_hba *phba = (struct lpfc_hba *) ptr; |
4843 | unsigned long iflags; | 4764 | unsigned long iflags; |
4844 | uint32_t tmo_posted; | 4765 | uint32_t tmo_posted; |
4766 | |||
4845 | spin_lock_irqsave(&phba->pport->work_port_lock, iflags); | 4767 | spin_lock_irqsave(&phba->pport->work_port_lock, iflags); |
4846 | tmo_posted = phba->pport->work_port_events & WORKER_FABRIC_BLOCK_TMO; | 4768 | tmo_posted = phba->pport->work_port_events & WORKER_FABRIC_BLOCK_TMO; |
4847 | if (!tmo_posted) | 4769 | if (!tmo_posted) |
4848 | phba->pport->work_port_events |= WORKER_FABRIC_BLOCK_TMO; | 4770 | phba->pport->work_port_events |= WORKER_FABRIC_BLOCK_TMO; |
4849 | spin_unlock_irqrestore(&phba->pport->work_port_lock, iflags); | 4771 | spin_unlock_irqrestore(&phba->pport->work_port_lock, iflags); |
4850 | 4772 | ||
4851 | if (!tmo_posted) { | 4773 | if (!tmo_posted) |
4852 | spin_lock_irqsave(&phba->hbalock, iflags); | 4774 | lpfc_worker_wake_up(phba); |
4853 | if (phba->work_wait) | 4775 | return; |
4854 | lpfc_worker_wake_up(phba); | ||
4855 | spin_unlock_irqrestore(&phba->hbalock, iflags); | ||
4856 | } | ||
4857 | } | 4776 | } |
4858 | 4777 | ||
4859 | static void | 4778 | static void |