diff options
author | James Smart <James.Smart@Emulex.Com> | 2009-05-22 14:53:21 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2009-06-08 12:26:19 -0400 |
commit | 21e9a0a5fbd2b7cb3ae29f6d491a30bc0e688422 (patch) | |
tree | d5ae35da0cdec82a78b814d907d630d57b5cc7ae /drivers/scsi/lpfc/lpfc_hbadisc.c | |
parent | f4b4c68f74dcd5da03df851090cad28ad4e8d7cc (diff) |
[SCSI] lpfc 8.3.2 : Persistent Vport Support
Add support for persistent vport definitions at creation at boot time
Also includes a few misc fixes for:
- conversion to vpi name from vport slang name
- couple of small mailbox references
- some additional discovery mods
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_hbadisc.c')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_hbadisc.c | 180 |
1 files changed, 141 insertions, 39 deletions
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index 126323a4dcec..35c41ae75be2 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c | |||
@@ -2079,6 +2079,128 @@ out: | |||
2079 | return; | 2079 | return; |
2080 | } | 2080 | } |
2081 | 2081 | ||
2082 | /** | ||
2083 | * lpfc_create_static_vport - Read HBA config region to create static vports. | ||
2084 | * @phba: pointer to lpfc hba data structure. | ||
2085 | * | ||
2086 | * This routine issue a DUMP mailbox command for config region 22 to get | ||
2087 | * the list of static vports to be created. The function create vports | ||
2088 | * based on the information returned from the HBA. | ||
2089 | **/ | ||
2090 | void | ||
2091 | lpfc_create_static_vport(struct lpfc_hba *phba) | ||
2092 | { | ||
2093 | LPFC_MBOXQ_t *pmb = NULL; | ||
2094 | MAILBOX_t *mb; | ||
2095 | struct static_vport_info *vport_info; | ||
2096 | int rc, i; | ||
2097 | struct fc_vport_identifiers vport_id; | ||
2098 | struct fc_vport *new_fc_vport; | ||
2099 | struct Scsi_Host *shost; | ||
2100 | struct lpfc_vport *vport; | ||
2101 | uint16_t offset = 0; | ||
2102 | uint8_t *vport_buff; | ||
2103 | |||
2104 | pmb = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); | ||
2105 | if (!pmb) { | ||
2106 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | ||
2107 | "0542 lpfc_create_static_vport failed to" | ||
2108 | " allocate mailbox memory\n"); | ||
2109 | return; | ||
2110 | } | ||
2111 | |||
2112 | mb = &pmb->u.mb; | ||
2113 | |||
2114 | vport_info = kzalloc(sizeof(struct static_vport_info), GFP_KERNEL); | ||
2115 | if (!vport_info) { | ||
2116 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | ||
2117 | "0543 lpfc_create_static_vport failed to" | ||
2118 | " allocate vport_info\n"); | ||
2119 | mempool_free(pmb, phba->mbox_mem_pool); | ||
2120 | return; | ||
2121 | } | ||
2122 | |||
2123 | vport_buff = (uint8_t *) vport_info; | ||
2124 | do { | ||
2125 | lpfc_dump_static_vport(phba, pmb, offset); | ||
2126 | pmb->vport = phba->pport; | ||
2127 | rc = lpfc_sli_issue_mbox_wait(phba, pmb, LPFC_MBOX_TMO); | ||
2128 | |||
2129 | if ((rc != MBX_SUCCESS) || mb->mbxStatus) { | ||
2130 | lpfc_printf_log(phba, KERN_WARNING, LOG_INIT, | ||
2131 | "0544 lpfc_create_static_vport failed to" | ||
2132 | " issue dump mailbox command ret 0x%x " | ||
2133 | "status 0x%x\n", | ||
2134 | rc, mb->mbxStatus); | ||
2135 | goto out; | ||
2136 | } | ||
2137 | |||
2138 | if (mb->un.varDmp.word_cnt > | ||
2139 | sizeof(struct static_vport_info) - offset) | ||
2140 | mb->un.varDmp.word_cnt = | ||
2141 | sizeof(struct static_vport_info) - offset; | ||
2142 | |||
2143 | lpfc_sli_pcimem_bcopy(((uint8_t *)mb) + DMP_RSP_OFFSET, | ||
2144 | vport_buff + offset, | ||
2145 | mb->un.varDmp.word_cnt); | ||
2146 | offset += mb->un.varDmp.word_cnt; | ||
2147 | |||
2148 | } while (mb->un.varDmp.word_cnt && | ||
2149 | offset < sizeof(struct static_vport_info)); | ||
2150 | |||
2151 | |||
2152 | if ((le32_to_cpu(vport_info->signature) != VPORT_INFO_SIG) || | ||
2153 | ((le32_to_cpu(vport_info->rev) & VPORT_INFO_REV_MASK) | ||
2154 | != VPORT_INFO_REV)) { | ||
2155 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | ||
2156 | "0545 lpfc_create_static_vport bad" | ||
2157 | " information header 0x%x 0x%x\n", | ||
2158 | le32_to_cpu(vport_info->signature), | ||
2159 | le32_to_cpu(vport_info->rev) & VPORT_INFO_REV_MASK); | ||
2160 | |||
2161 | goto out; | ||
2162 | } | ||
2163 | |||
2164 | shost = lpfc_shost_from_vport(phba->pport); | ||
2165 | |||
2166 | for (i = 0; i < MAX_STATIC_VPORT_COUNT; i++) { | ||
2167 | memset(&vport_id, 0, sizeof(vport_id)); | ||
2168 | vport_id.port_name = wwn_to_u64(vport_info->vport_list[i].wwpn); | ||
2169 | vport_id.node_name = wwn_to_u64(vport_info->vport_list[i].wwnn); | ||
2170 | if (!vport_id.port_name || !vport_id.node_name) | ||
2171 | continue; | ||
2172 | |||
2173 | vport_id.roles = FC_PORT_ROLE_FCP_INITIATOR; | ||
2174 | vport_id.vport_type = FC_PORTTYPE_NPIV; | ||
2175 | vport_id.disable = false; | ||
2176 | new_fc_vport = fc_vport_create(shost, 0, &vport_id); | ||
2177 | |||
2178 | if (!new_fc_vport) { | ||
2179 | lpfc_printf_log(phba, KERN_WARNING, LOG_INIT, | ||
2180 | "0546 lpfc_create_static_vport failed to" | ||
2181 | " create vport \n"); | ||
2182 | continue; | ||
2183 | } | ||
2184 | |||
2185 | vport = *(struct lpfc_vport **)new_fc_vport->dd_data; | ||
2186 | vport->vport_flag |= STATIC_VPORT; | ||
2187 | } | ||
2188 | |||
2189 | out: | ||
2190 | /* | ||
2191 | * If this is timed out command, setting NULL to context2 tell SLI | ||
2192 | * layer not to use this buffer. | ||
2193 | */ | ||
2194 | spin_lock_irq(&phba->hbalock); | ||
2195 | pmb->context2 = NULL; | ||
2196 | spin_unlock_irq(&phba->hbalock); | ||
2197 | kfree(vport_info); | ||
2198 | if (rc != MBX_TIMEOUT) | ||
2199 | mempool_free(pmb, phba->mbox_mem_pool); | ||
2200 | |||
2201 | return; | ||
2202 | } | ||
2203 | |||
2082 | /* | 2204 | /* |
2083 | * This routine handles processing a Fabric REG_LOGIN mailbox | 2205 | * This routine handles processing a Fabric REG_LOGIN mailbox |
2084 | * command upon completion. It is setup in the LPFC_MBOXQ | 2206 | * command upon completion. It is setup in the LPFC_MBOXQ |
@@ -2089,16 +2211,17 @@ void | |||
2089 | lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) | 2211 | lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) |
2090 | { | 2212 | { |
2091 | struct lpfc_vport *vport = pmb->vport; | 2213 | struct lpfc_vport *vport = pmb->vport; |
2092 | MAILBOX_t *mb = &pmb->mb; | 2214 | MAILBOX_t *mb = &pmb->u.mb; |
2093 | struct lpfc_dmabuf *mp = (struct lpfc_dmabuf *) (pmb->context1); | 2215 | struct lpfc_dmabuf *mp = (struct lpfc_dmabuf *) (pmb->context1); |
2094 | struct lpfc_nodelist *ndlp; | 2216 | struct lpfc_nodelist *ndlp; |
2095 | struct lpfc_vport **vports; | ||
2096 | int i; | ||
2097 | 2217 | ||
2098 | ndlp = (struct lpfc_nodelist *) pmb->context2; | 2218 | ndlp = (struct lpfc_nodelist *) pmb->context2; |
2099 | pmb->context1 = NULL; | 2219 | pmb->context1 = NULL; |
2100 | pmb->context2 = NULL; | 2220 | pmb->context2 = NULL; |
2101 | if (mb->mbxStatus) { | 2221 | if (mb->mbxStatus) { |
2222 | lpfc_printf_vlog(vport, KERN_ERR, LOG_MBOX, | ||
2223 | "0258 Register Fabric login error: 0x%x\n", | ||
2224 | mb->mbxStatus); | ||
2102 | lpfc_mbuf_free(phba, mp->virt, mp->phys); | 2225 | lpfc_mbuf_free(phba, mp->virt, mp->phys); |
2103 | kfree(mp); | 2226 | kfree(mp); |
2104 | mempool_free(pmb, phba->mbox_mem_pool); | 2227 | mempool_free(pmb, phba->mbox_mem_pool); |
@@ -2117,9 +2240,6 @@ lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) | |||
2117 | } | 2240 | } |
2118 | 2241 | ||
2119 | lpfc_vport_set_state(vport, FC_VPORT_FAILED); | 2242 | lpfc_vport_set_state(vport, FC_VPORT_FAILED); |
2120 | lpfc_printf_vlog(vport, KERN_ERR, LOG_MBOX, | ||
2121 | "0258 Register Fabric login error: 0x%x\n", | ||
2122 | mb->mbxStatus); | ||
2123 | /* Decrement the reference count to ndlp after the reference | 2243 | /* Decrement the reference count to ndlp after the reference |
2124 | * to the ndlp are done. | 2244 | * to the ndlp are done. |
2125 | */ | 2245 | */ |
@@ -2128,34 +2248,12 @@ lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) | |||
2128 | } | 2248 | } |
2129 | 2249 | ||
2130 | ndlp->nlp_rpi = mb->un.varWords[0]; | 2250 | ndlp->nlp_rpi = mb->un.varWords[0]; |
2251 | ndlp->nlp_flag |= NLP_RPI_VALID; | ||
2131 | ndlp->nlp_type |= NLP_FABRIC; | 2252 | ndlp->nlp_type |= NLP_FABRIC; |
2132 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE); | 2253 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE); |
2133 | 2254 | ||
2134 | if (vport->port_state == LPFC_FABRIC_CFG_LINK) { | 2255 | if (vport->port_state == LPFC_FABRIC_CFG_LINK) { |
2135 | vports = lpfc_create_vport_work_array(phba); | 2256 | lpfc_start_fdiscs(phba); |
2136 | if (vports != NULL) | ||
2137 | for(i = 0; | ||
2138 | i <= phba->max_vpi && vports[i] != NULL; | ||
2139 | i++) { | ||
2140 | if (vports[i]->port_type == LPFC_PHYSICAL_PORT) | ||
2141 | continue; | ||
2142 | if (phba->fc_topology == TOPOLOGY_LOOP) { | ||
2143 | lpfc_vport_set_state(vports[i], | ||
2144 | FC_VPORT_LINKDOWN); | ||
2145 | continue; | ||
2146 | } | ||
2147 | if (phba->link_flag & LS_NPIV_FAB_SUPPORTED) | ||
2148 | lpfc_initial_fdisc(vports[i]); | ||
2149 | else { | ||
2150 | lpfc_vport_set_state(vports[i], | ||
2151 | FC_VPORT_NO_FABRIC_SUPP); | ||
2152 | lpfc_printf_vlog(vport, KERN_ERR, | ||
2153 | LOG_ELS, | ||
2154 | "0259 No NPIV " | ||
2155 | "Fabric support\n"); | ||
2156 | } | ||
2157 | } | ||
2158 | lpfc_destroy_vport_work_array(phba, vports); | ||
2159 | lpfc_do_scr_ns_plogi(phba, vport); | 2257 | lpfc_do_scr_ns_plogi(phba, vport); |
2160 | } | 2258 | } |
2161 | 2259 | ||
@@ -2179,13 +2277,16 @@ lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) | |||
2179 | void | 2277 | void |
2180 | lpfc_mbx_cmpl_ns_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) | 2278 | lpfc_mbx_cmpl_ns_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) |
2181 | { | 2279 | { |
2182 | MAILBOX_t *mb = &pmb->mb; | 2280 | MAILBOX_t *mb = &pmb->u.mb; |
2183 | struct lpfc_dmabuf *mp = (struct lpfc_dmabuf *) (pmb->context1); | 2281 | struct lpfc_dmabuf *mp = (struct lpfc_dmabuf *) (pmb->context1); |
2184 | struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) pmb->context2; | 2282 | struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) pmb->context2; |
2185 | struct lpfc_vport *vport = pmb->vport; | 2283 | struct lpfc_vport *vport = pmb->vport; |
2186 | 2284 | ||
2187 | if (mb->mbxStatus) { | 2285 | if (mb->mbxStatus) { |
2188 | out: | 2286 | out: |
2287 | lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, | ||
2288 | "0260 Register NameServer error: 0x%x\n", | ||
2289 | mb->mbxStatus); | ||
2189 | /* decrement the node reference count held for this | 2290 | /* decrement the node reference count held for this |
2190 | * callback function. | 2291 | * callback function. |
2191 | */ | 2292 | */ |
@@ -2209,15 +2310,13 @@ out: | |||
2209 | return; | 2310 | return; |
2210 | } | 2311 | } |
2211 | lpfc_vport_set_state(vport, FC_VPORT_FAILED); | 2312 | lpfc_vport_set_state(vport, FC_VPORT_FAILED); |
2212 | lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, | ||
2213 | "0260 Register NameServer error: 0x%x\n", | ||
2214 | mb->mbxStatus); | ||
2215 | return; | 2313 | return; |
2216 | } | 2314 | } |
2217 | 2315 | ||
2218 | pmb->context1 = NULL; | 2316 | pmb->context1 = NULL; |
2219 | 2317 | ||
2220 | ndlp->nlp_rpi = mb->un.varWords[0]; | 2318 | ndlp->nlp_rpi = mb->un.varWords[0]; |
2319 | ndlp->nlp_flag |= NLP_RPI_VALID; | ||
2221 | ndlp->nlp_type |= NLP_FABRIC; | 2320 | ndlp->nlp_type |= NLP_FABRIC; |
2222 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE); | 2321 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE); |
2223 | 2322 | ||
@@ -2718,7 +2817,7 @@ lpfc_check_sli_ndlp(struct lpfc_hba *phba, | |||
2718 | if (pring->ringno == LPFC_ELS_RING) { | 2817 | if (pring->ringno == LPFC_ELS_RING) { |
2719 | switch (icmd->ulpCommand) { | 2818 | switch (icmd->ulpCommand) { |
2720 | case CMD_GEN_REQUEST64_CR: | 2819 | case CMD_GEN_REQUEST64_CR: |
2721 | if (icmd->ulpContext == (volatile ushort)ndlp->nlp_rpi) | 2820 | if (iocb->context_un.ndlp == ndlp) |
2722 | return 1; | 2821 | return 1; |
2723 | case CMD_ELS_REQUEST64_CR: | 2822 | case CMD_ELS_REQUEST64_CR: |
2724 | if (icmd->un.elsreq64.remoteID == ndlp->nlp_DID) | 2823 | if (icmd->un.elsreq64.remoteID == ndlp->nlp_DID) |
@@ -2765,7 +2864,7 @@ lpfc_no_rpi(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp) | |||
2765 | */ | 2864 | */ |
2766 | psli = &phba->sli; | 2865 | psli = &phba->sli; |
2767 | rpi = ndlp->nlp_rpi; | 2866 | rpi = ndlp->nlp_rpi; |
2768 | if (rpi) { | 2867 | if (ndlp->nlp_flag & NLP_RPI_VALID) { |
2769 | /* Now process each ring */ | 2868 | /* Now process each ring */ |
2770 | for (i = 0; i < psli->num_rings; i++) { | 2869 | for (i = 0; i < psli->num_rings; i++) { |
2771 | pring = &psli->ring[i]; | 2870 | pring = &psli->ring[i]; |
@@ -2813,7 +2912,7 @@ lpfc_unreg_rpi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) | |||
2813 | LPFC_MBOXQ_t *mbox; | 2912 | LPFC_MBOXQ_t *mbox; |
2814 | int rc; | 2913 | int rc; |
2815 | 2914 | ||
2816 | if (ndlp->nlp_rpi) { | 2915 | if (ndlp->nlp_flag & NLP_RPI_VALID) { |
2817 | mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); | 2916 | mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); |
2818 | if (mbox) { | 2917 | if (mbox) { |
2819 | lpfc_unreg_login(phba, vport->vpi, ndlp->nlp_rpi, mbox); | 2918 | lpfc_unreg_login(phba, vport->vpi, ndlp->nlp_rpi, mbox); |
@@ -2825,6 +2924,7 @@ lpfc_unreg_rpi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) | |||
2825 | } | 2924 | } |
2826 | lpfc_no_rpi(phba, ndlp); | 2925 | lpfc_no_rpi(phba, ndlp); |
2827 | ndlp->nlp_rpi = 0; | 2926 | ndlp->nlp_rpi = 0; |
2927 | ndlp->nlp_flag &= ~NLP_RPI_VALID; | ||
2828 | return 1; | 2928 | return 1; |
2829 | } | 2929 | } |
2830 | return 0; | 2930 | return 0; |
@@ -2972,13 +3072,14 @@ lpfc_nlp_remove(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) | |||
2972 | int rc; | 3072 | int rc; |
2973 | 3073 | ||
2974 | lpfc_cancel_retry_delay_tmo(vport, ndlp); | 3074 | lpfc_cancel_retry_delay_tmo(vport, ndlp); |
2975 | if (ndlp->nlp_flag & NLP_DEFER_RM && !ndlp->nlp_rpi) { | 3075 | if ((ndlp->nlp_flag & NLP_DEFER_RM) && |
3076 | !(ndlp->nlp_flag & NLP_RPI_VALID)) { | ||
2976 | /* For this case we need to cleanup the default rpi | 3077 | /* For this case we need to cleanup the default rpi |
2977 | * allocated by the firmware. | 3078 | * allocated by the firmware. |
2978 | */ | 3079 | */ |
2979 | if ((mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL)) | 3080 | if ((mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL)) |
2980 | != NULL) { | 3081 | != NULL) { |
2981 | rc = lpfc_reg_login(phba, vport->vpi, ndlp->nlp_DID, | 3082 | rc = lpfc_reg_rpi(phba, vport->vpi, ndlp->nlp_DID, |
2982 | (uint8_t *) &vport->fc_sparam, mbox, 0); | 3083 | (uint8_t *) &vport->fc_sparam, mbox, 0); |
2983 | if (rc) { | 3084 | if (rc) { |
2984 | mempool_free(mbox, phba->mbox_mem_pool); | 3085 | mempool_free(mbox, phba->mbox_mem_pool); |
@@ -3713,6 +3814,7 @@ lpfc_mbx_cmpl_fdmi_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) | |||
3713 | pmb->context1 = NULL; | 3814 | pmb->context1 = NULL; |
3714 | 3815 | ||
3715 | ndlp->nlp_rpi = mb->un.varWords[0]; | 3816 | ndlp->nlp_rpi = mb->un.varWords[0]; |
3817 | ndlp->nlp_flag |= NLP_RPI_VALID; | ||
3716 | ndlp->nlp_type |= NLP_FABRIC; | 3818 | ndlp->nlp_type |= NLP_FABRIC; |
3717 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE); | 3819 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE); |
3718 | 3820 | ||