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 | |
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>
-rw-r--r-- | drivers/scsi/lpfc/lpfc_attr.c | 31 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_hbadisc.c | 180 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_init.c | 1 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_mbox.c | 38 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_scsi.c | 6 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_vport.c | 37 |
6 files changed, 236 insertions, 57 deletions
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index 46e032aa0bea..d73e677201f8 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c | |||
@@ -2277,6 +2277,36 @@ lpfc_param_init(topology, 0, 0, 6) | |||
2277 | static DEVICE_ATTR(lpfc_topology, S_IRUGO | S_IWUSR, | 2277 | static DEVICE_ATTR(lpfc_topology, S_IRUGO | S_IWUSR, |
2278 | lpfc_topology_show, lpfc_topology_store); | 2278 | lpfc_topology_show, lpfc_topology_store); |
2279 | 2279 | ||
2280 | /** | ||
2281 | * lpfc_static_vport_show: Read callback function for | ||
2282 | * lpfc_static_vport sysfs file. | ||
2283 | * @dev: Pointer to class device object. | ||
2284 | * @attr: device attribute structure. | ||
2285 | * @buf: Data buffer. | ||
2286 | * | ||
2287 | * This function is the read call back function for | ||
2288 | * lpfc_static_vport sysfs file. The lpfc_static_vport | ||
2289 | * sysfs file report the mageability of the vport. | ||
2290 | **/ | ||
2291 | static ssize_t | ||
2292 | lpfc_static_vport_show(struct device *dev, struct device_attribute *attr, | ||
2293 | char *buf) | ||
2294 | { | ||
2295 | struct Scsi_Host *shost = class_to_shost(dev); | ||
2296 | struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; | ||
2297 | if (vport->vport_flag & STATIC_VPORT) | ||
2298 | sprintf(buf, "1\n"); | ||
2299 | else | ||
2300 | sprintf(buf, "0\n"); | ||
2301 | |||
2302 | return strlen(buf); | ||
2303 | } | ||
2304 | |||
2305 | /* | ||
2306 | * Sysfs attribute to control the statistical data collection. | ||
2307 | */ | ||
2308 | static DEVICE_ATTR(lpfc_static_vport, S_IRUGO, | ||
2309 | lpfc_static_vport_show, NULL); | ||
2280 | 2310 | ||
2281 | /** | 2311 | /** |
2282 | * lpfc_stat_data_ctrl_store - write call back for lpfc_stat_data_ctrl sysfs file | 2312 | * lpfc_stat_data_ctrl_store - write call back for lpfc_stat_data_ctrl sysfs file |
@@ -3051,6 +3081,7 @@ struct device_attribute *lpfc_vport_attrs[] = { | |||
3051 | &dev_attr_lpfc_enable_da_id, | 3081 | &dev_attr_lpfc_enable_da_id, |
3052 | &dev_attr_lpfc_max_scsicmpl_time, | 3082 | &dev_attr_lpfc_max_scsicmpl_time, |
3053 | &dev_attr_lpfc_stat_data_ctrl, | 3083 | &dev_attr_lpfc_stat_data_ctrl, |
3084 | &dev_attr_lpfc_static_vport, | ||
3054 | NULL, | 3085 | NULL, |
3055 | }; | 3086 | }; |
3056 | 3087 | ||
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 | ||
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 65cd3fe62200..2f5907f92eea 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c | |||
@@ -385,6 +385,7 @@ lpfc_config_port_post(struct lpfc_hba *phba) | |||
385 | /* Update the fc_host data structures with new wwn. */ | 385 | /* Update the fc_host data structures with new wwn. */ |
386 | fc_host_node_name(shost) = wwn_to_u64(vport->fc_nodename.u.wwn); | 386 | fc_host_node_name(shost) = wwn_to_u64(vport->fc_nodename.u.wwn); |
387 | fc_host_port_name(shost) = wwn_to_u64(vport->fc_portname.u.wwn); | 387 | fc_host_port_name(shost) = wwn_to_u64(vport->fc_portname.u.wwn); |
388 | fc_host_max_npiv_vports(shost) = phba->max_vpi; | ||
388 | 389 | ||
389 | /* If no serial number in VPD data, use low 6 bytes of WWNN */ | 390 | /* If no serial number in VPD data, use low 6 bytes of WWNN */ |
390 | /* This should be consolidated into parse_vpd ? - mr */ | 391 | /* This should be consolidated into parse_vpd ? - mr */ |
diff --git a/drivers/scsi/lpfc/lpfc_mbox.c b/drivers/scsi/lpfc/lpfc_mbox.c index 29fe5c17f4e8..b9b451c09010 100644 --- a/drivers/scsi/lpfc/lpfc_mbox.c +++ b/drivers/scsi/lpfc/lpfc_mbox.c | |||
@@ -41,6 +41,44 @@ | |||
41 | #include "lpfc_compat.h" | 41 | #include "lpfc_compat.h" |
42 | 42 | ||
43 | /** | 43 | /** |
44 | * lpfc_dump_static_vport - Dump HBA's static vport information. | ||
45 | * @phba: pointer to lpfc hba data structure. | ||
46 | * @pmb: pointer to the driver internal queue element for mailbox command. | ||
47 | * @offset: offset for dumping vport info. | ||
48 | * | ||
49 | * The dump mailbox command provides a method for the device driver to obtain | ||
50 | * various types of information from the HBA device. | ||
51 | * | ||
52 | * This routine prepares the mailbox command for dumping list of static | ||
53 | * vports to be created. | ||
54 | **/ | ||
55 | void | ||
56 | lpfc_dump_static_vport(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb, | ||
57 | uint16_t offset) | ||
58 | { | ||
59 | MAILBOX_t *mb; | ||
60 | void *ctx; | ||
61 | |||
62 | mb = &pmb->u.mb; | ||
63 | ctx = pmb->context2; | ||
64 | |||
65 | /* Setup to dump vport info region */ | ||
66 | memset(pmb, 0, sizeof(LPFC_MBOXQ_t)); | ||
67 | mb->mbxCommand = MBX_DUMP_MEMORY; | ||
68 | mb->un.varDmp.cv = 1; | ||
69 | mb->un.varDmp.type = DMP_NV_PARAMS; | ||
70 | mb->un.varDmp.entry_index = offset; | ||
71 | mb->un.varDmp.region_id = DMP_REGION_VPORT; | ||
72 | mb->un.varDmp.word_cnt = DMP_RSP_SIZE/sizeof(uint32_t); | ||
73 | mb->un.varDmp.co = 0; | ||
74 | mb->un.varDmp.resp_offset = 0; | ||
75 | pmb->context2 = ctx; | ||
76 | mb->mbxOwner = OWN_HOST; | ||
77 | |||
78 | return; | ||
79 | } | ||
80 | |||
81 | /** | ||
44 | * lpfc_dump_mem - Prepare a mailbox command for retrieving HBA's VPD memory | 82 | * lpfc_dump_mem - Prepare a mailbox command for retrieving HBA's VPD memory |
45 | * @phba: pointer to lpfc hba data structure. | 83 | * @phba: pointer to lpfc hba data structure. |
46 | * @pmb: pointer to the driver internal queue element for mailbox command. | 84 | * @pmb: pointer to the driver internal queue element for mailbox command. |
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index 1a7659c8f388..ccbde41c1539 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c | |||
@@ -329,7 +329,7 @@ lpfc_ramp_down_queue_handler(struct lpfc_hba *phba) | |||
329 | 329 | ||
330 | vports = lpfc_create_vport_work_array(phba); | 330 | vports = lpfc_create_vport_work_array(phba); |
331 | if (vports != NULL) | 331 | if (vports != NULL) |
332 | for(i = 0; i <= phba->max_vpi && vports[i] != NULL; i++) { | 332 | for (i = 0; i <= phba->max_vports && vports[i] != NULL; i++) { |
333 | shost = lpfc_shost_from_vport(vports[i]); | 333 | shost = lpfc_shost_from_vport(vports[i]); |
334 | shost_for_each_device(sdev, shost) { | 334 | shost_for_each_device(sdev, shost) { |
335 | new_queue_depth = | 335 | new_queue_depth = |
@@ -383,7 +383,7 @@ lpfc_ramp_up_queue_handler(struct lpfc_hba *phba) | |||
383 | 383 | ||
384 | vports = lpfc_create_vport_work_array(phba); | 384 | vports = lpfc_create_vport_work_array(phba); |
385 | if (vports != NULL) | 385 | if (vports != NULL) |
386 | for(i = 0; i <= phba->max_vpi && vports[i] != NULL; i++) { | 386 | for (i = 0; i <= phba->max_vports && vports[i] != NULL; i++) { |
387 | shost = lpfc_shost_from_vport(vports[i]); | 387 | shost = lpfc_shost_from_vport(vports[i]); |
388 | shost_for_each_device(sdev, shost) { | 388 | shost_for_each_device(sdev, shost) { |
389 | if (vports[i]->cfg_lun_queue_depth <= | 389 | if (vports[i]->cfg_lun_queue_depth <= |
@@ -431,7 +431,7 @@ lpfc_scsi_dev_block(struct lpfc_hba *phba) | |||
431 | 431 | ||
432 | vports = lpfc_create_vport_work_array(phba); | 432 | vports = lpfc_create_vport_work_array(phba); |
433 | if (vports != NULL) | 433 | if (vports != NULL) |
434 | for (i = 0; i <= phba->max_vpi && vports[i] != NULL; i++) { | 434 | for (i = 0; i <= phba->max_vports && vports[i] != NULL; i++) { |
435 | shost = lpfc_shost_from_vport(vports[i]); | 435 | shost = lpfc_shost_from_vport(vports[i]); |
436 | shost_for_each_device(sdev, shost) { | 436 | shost_for_each_device(sdev, shost) { |
437 | rport = starget_to_rport(scsi_target(sdev)); | 437 | rport = starget_to_rport(scsi_target(sdev)); |
diff --git a/drivers/scsi/lpfc/lpfc_vport.c b/drivers/scsi/lpfc/lpfc_vport.c index a415ec0b9a86..a6313ee84ac5 100644 --- a/drivers/scsi/lpfc/lpfc_vport.c +++ b/drivers/scsi/lpfc/lpfc_vport.c | |||
@@ -251,23 +251,22 @@ static void lpfc_discovery_wait(struct lpfc_vport *vport) | |||
251 | (vport->fc_flag & wait_flags) || | 251 | (vport->fc_flag & wait_flags) || |
252 | ((vport->port_state > LPFC_VPORT_FAILED) && | 252 | ((vport->port_state > LPFC_VPORT_FAILED) && |
253 | (vport->port_state < LPFC_VPORT_READY))) { | 253 | (vport->port_state < LPFC_VPORT_READY))) { |
254 | lpfc_printf_log(phba, KERN_INFO, LOG_VPORT, | 254 | lpfc_printf_vlog(vport, KERN_INFO, LOG_VPORT, |
255 | "1833 Vport discovery quiesce Wait:" | 255 | "1833 Vport discovery quiesce Wait:" |
256 | " vpi x%x state x%x fc_flags x%x" | 256 | " state x%x fc_flags x%x" |
257 | " num_nodes x%x, waiting 1000 msecs" | 257 | " num_nodes x%x, waiting 1000 msecs" |
258 | " total wait msecs x%x\n", | 258 | " total wait msecs x%x\n", |
259 | vport->vpi, vport->port_state, | 259 | vport->port_state, vport->fc_flag, |
260 | vport->fc_flag, vport->num_disc_nodes, | 260 | vport->num_disc_nodes, |
261 | jiffies_to_msecs(jiffies - start_time)); | 261 | jiffies_to_msecs(jiffies - start_time)); |
262 | msleep(1000); | 262 | msleep(1000); |
263 | } else { | 263 | } else { |
264 | /* Base case. Wait variants satisfied. Break out */ | 264 | /* Base case. Wait variants satisfied. Break out */ |
265 | lpfc_printf_log(phba, KERN_INFO, LOG_VPORT, | 265 | lpfc_printf_vlog(vport, KERN_INFO, LOG_VPORT, |
266 | "1834 Vport discovery quiesced:" | 266 | "1834 Vport discovery quiesced:" |
267 | " vpi x%x state x%x fc_flags x%x" | 267 | " state x%x fc_flags x%x" |
268 | " wait msecs x%x\n", | 268 | " wait msecs x%x\n", |
269 | vport->vpi, vport->port_state, | 269 | vport->port_state, vport->fc_flag, |
270 | vport->fc_flag, | ||
271 | jiffies_to_msecs(jiffies | 270 | jiffies_to_msecs(jiffies |
272 | - start_time)); | 271 | - start_time)); |
273 | break; | 272 | break; |
@@ -275,12 +274,10 @@ static void lpfc_discovery_wait(struct lpfc_vport *vport) | |||
275 | } | 274 | } |
276 | 275 | ||
277 | if (time_after(jiffies, wait_time_max)) | 276 | if (time_after(jiffies, wait_time_max)) |
278 | lpfc_printf_log(phba, KERN_ERR, LOG_VPORT, | 277 | lpfc_printf_vlog(vport, KERN_ERR, LOG_VPORT, |
279 | "1835 Vport discovery quiesce failed:" | 278 | "1835 Vport discovery quiesce failed:" |
280 | " vpi x%x state x%x fc_flags x%x" | 279 | " state x%x fc_flags x%x wait msecs x%x\n", |
281 | " wait msecs x%x\n", | 280 | vport->port_state, vport->fc_flag, |
282 | vport->vpi, vport->port_state, | ||
283 | vport->fc_flag, | ||
284 | jiffies_to_msecs(jiffies - start_time)); | 281 | jiffies_to_msecs(jiffies - start_time)); |
285 | } | 282 | } |
286 | 283 | ||
@@ -558,6 +555,16 @@ lpfc_vport_delete(struct fc_vport *fc_vport) | |||
558 | "physical host\n"); | 555 | "physical host\n"); |
559 | return VPORT_ERROR; | 556 | return VPORT_ERROR; |
560 | } | 557 | } |
558 | |||
559 | /* If the vport is a static vport fail the deletion. */ | ||
560 | if ((vport->vport_flag & STATIC_VPORT) && | ||
561 | !(phba->pport->load_flag & FC_UNLOADING)) { | ||
562 | lpfc_printf_vlog(vport, KERN_ERR, LOG_VPORT, | ||
563 | "1837 vport_delete failed: Cannot delete " | ||
564 | "static vport.\n"); | ||
565 | return VPORT_ERROR; | ||
566 | } | ||
567 | |||
561 | /* | 568 | /* |
562 | * If we are not unloading the driver then prevent the vport_delete | 569 | * If we are not unloading the driver then prevent the vport_delete |
563 | * from happening until after this vport's discovery is finished. | 570 | * from happening until after this vport's discovery is finished. |
@@ -733,7 +740,7 @@ lpfc_create_vport_work_array(struct lpfc_hba *phba) | |||
733 | struct lpfc_vport *port_iterator; | 740 | struct lpfc_vport *port_iterator; |
734 | struct lpfc_vport **vports; | 741 | struct lpfc_vport **vports; |
735 | int index = 0; | 742 | int index = 0; |
736 | vports = kzalloc((phba->max_vpi + 1) * sizeof(struct lpfc_vport *), | 743 | vports = kzalloc((phba->max_vports + 1) * sizeof(struct lpfc_vport *), |
737 | GFP_KERNEL); | 744 | GFP_KERNEL); |
738 | if (vports == NULL) | 745 | if (vports == NULL) |
739 | return NULL; | 746 | return NULL; |
@@ -757,7 +764,7 @@ lpfc_destroy_vport_work_array(struct lpfc_hba *phba, struct lpfc_vport **vports) | |||
757 | int i; | 764 | int i; |
758 | if (vports == NULL) | 765 | if (vports == NULL) |
759 | return; | 766 | return; |
760 | for (i=0; vports[i] != NULL && i <= phba->max_vpi; i++) | 767 | for (i = 0; vports[i] != NULL && i <= phba->max_vports; i++) |
761 | scsi_host_put(lpfc_shost_from_vport(vports[i])); | 768 | scsi_host_put(lpfc_shost_from_vport(vports[i])); |
762 | kfree(vports); | 769 | kfree(vports); |
763 | } | 770 | } |