diff options
author | James Smart <James.Smart@Emulex.Com> | 2007-06-17 20:56:38 -0400 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.il.steeleye.com> | 2007-06-17 23:27:39 -0400 |
commit | 92d7f7b0cde3ad2260e7462b40867b57efd49851 (patch) | |
tree | fadb1d8f1a817c2f85937b5e9c3b830bdecb5555 /drivers/scsi/lpfc/lpfc_ct.c | |
parent | ed957684294618602b48f1950b0c9bbcb036583f (diff) |
[SCSI] lpfc: NPIV: add NPIV support on top of SLI-3
NPIV support is added to the driver. It utilizes the interfaces of
the fc transport for the creation and deletion of vports. Within the
driver, a new Scsi_Host is created for each NPIV instance, and is
paired with a new instance of a FC port. This allows N FC Port
elements to share a single Adapter.
Signed-off-by: James Smart <James.Smart@emulex.com>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_ct.c')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_ct.c | 520 |
1 files changed, 386 insertions, 134 deletions
diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c index e8ed5d7ccf9f..5584f395314c 100644 --- a/drivers/scsi/lpfc/lpfc_ct.c +++ b/drivers/scsi/lpfc/lpfc_ct.c | |||
@@ -40,6 +40,7 @@ | |||
40 | #include "lpfc_logmsg.h" | 40 | #include "lpfc_logmsg.h" |
41 | #include "lpfc_crtn.h" | 41 | #include "lpfc_crtn.h" |
42 | #include "lpfc_version.h" | 42 | #include "lpfc_version.h" |
43 | #include "lpfc_vport.h" | ||
43 | 44 | ||
44 | #define HBA_PORTSPEED_UNKNOWN 0 /* Unknown - transceiver | 45 | #define HBA_PORTSPEED_UNKNOWN 0 /* Unknown - transceiver |
45 | * incapable of reporting */ | 46 | * incapable of reporting */ |
@@ -74,15 +75,13 @@ lpfc_ct_unsol_buffer(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq, | |||
74 | __FUNCTION__, __LINE__, | 75 | __FUNCTION__, __LINE__, |
75 | piocbq, mp, size, | 76 | piocbq, mp, size, |
76 | piocbq->iocb.ulpStatus); | 77 | piocbq->iocb.ulpStatus); |
78 | |||
77 | } | 79 | } |
78 | 80 | ||
79 | static void | 81 | static void |
80 | lpfc_ct_ignore_hbq_buffer(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq, | 82 | lpfc_ct_ignore_hbq_buffer(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq, |
81 | struct hbq_dmabuf *sp, uint32_t size) | 83 | struct lpfc_dmabuf *mp, uint32_t size) |
82 | { | 84 | { |
83 | struct lpfc_dmabuf *mp = NULL; | ||
84 | |||
85 | mp = sp ? &sp->dbuf : NULL; | ||
86 | if (!mp) { | 85 | if (!mp) { |
87 | printk(KERN_ERR "%s (%d): Unsolited CT, no " | 86 | printk(KERN_ERR "%s (%d): Unsolited CT, no " |
88 | "HBQ buffer, piocbq = %p, status = x%x\n", | 87 | "HBQ buffer, piocbq = %p, status = x%x\n", |
@@ -102,21 +101,26 @@ void | |||
102 | lpfc_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | 101 | lpfc_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, |
103 | struct lpfc_iocbq *piocbq) | 102 | struct lpfc_iocbq *piocbq) |
104 | { | 103 | { |
104 | |||
105 | struct lpfc_dmabuf *mp = NULL; | 105 | struct lpfc_dmabuf *mp = NULL; |
106 | struct hbq_dmabuf *sp = NULL; | ||
107 | IOCB_t *icmd = &piocbq->iocb; | 106 | IOCB_t *icmd = &piocbq->iocb; |
108 | int i; | 107 | int i; |
109 | struct lpfc_iocbq *iocbq; | 108 | struct lpfc_iocbq *iocbq; |
110 | dma_addr_t paddr; | 109 | dma_addr_t paddr; |
111 | uint32_t size; | 110 | uint32_t size; |
111 | struct lpfc_dmabuf *bdeBuf1 = piocbq->context2; | ||
112 | struct lpfc_dmabuf *bdeBuf2 = piocbq->context3; | ||
113 | |||
114 | piocbq->context2 = NULL; | ||
115 | piocbq->context3 = NULL; | ||
112 | 116 | ||
113 | if ((icmd->ulpStatus == IOSTAT_LOCAL_REJECT) && | 117 | if (unlikely(icmd->ulpStatus == IOSTAT_NEED_BUFFER)) { |
114 | ((icmd->un.ulpWord[4] & 0xff) == IOERR_RCV_BUFFER_WAITING)) { | 118 | lpfc_sli_hbqbuf_add_hbqs(phba, LPFC_ELS_HBQ); |
119 | } else if ((icmd->ulpStatus == IOSTAT_LOCAL_REJECT) && | ||
120 | ((icmd->un.ulpWord[4] & 0xff) == IOERR_RCV_BUFFER_WAITING)) { | ||
115 | /* Not enough posted buffers; Try posting more buffers */ | 121 | /* Not enough posted buffers; Try posting more buffers */ |
116 | phba->fc_stat.NoRcvBuf++; | 122 | phba->fc_stat.NoRcvBuf++; |
117 | if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) | 123 | if (!(phba->sli3_options & LPFC_SLI3_HBQ_ENABLED)) |
118 | lpfc_sli_hbqbuf_fill_hbq(phba); | ||
119 | else | ||
120 | lpfc_post_buffer(phba, pring, 0, 1); | 124 | lpfc_post_buffer(phba, pring, 0, 1); |
121 | return; | 125 | return; |
122 | } | 126 | } |
@@ -139,23 +143,14 @@ lpfc_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | |||
139 | } | 143 | } |
140 | 144 | ||
141 | size = icmd->un.cont64[0].tus.f.bdeSize; | 145 | size = icmd->un.cont64[0].tus.f.bdeSize; |
142 | sp = lpfc_sli_hbqbuf_find(phba, icmd->un.ulpWord[3]); | 146 | lpfc_ct_ignore_hbq_buffer(phba, piocbq, bdeBuf1, size); |
143 | if (sp) | 147 | lpfc_in_buf_free(phba, bdeBuf1); |
144 | phba->hbq_buff_count--; | ||
145 | lpfc_ct_ignore_hbq_buffer(phba, iocbq, sp, size); | ||
146 | lpfc_sli_free_hbq(phba, sp); | ||
147 | if (icmd->ulpBdeCount == 2) { | 148 | if (icmd->ulpBdeCount == 2) { |
148 | sp = lpfc_sli_hbqbuf_find(phba, | 149 | lpfc_ct_ignore_hbq_buffer(phba, piocbq, bdeBuf2, |
149 | icmd->un.ulpWord[15]); | ||
150 | if (sp) | ||
151 | phba->hbq_buff_count--; | ||
152 | lpfc_ct_ignore_hbq_buffer(phba, iocbq, sp, | ||
153 | size); | 150 | size); |
154 | lpfc_sli_free_hbq(phba, sp); | 151 | lpfc_in_buf_free(phba, bdeBuf2); |
155 | } | 152 | } |
156 | |||
157 | } | 153 | } |
158 | lpfc_sli_hbqbuf_fill_hbq(phba); | ||
159 | } else { | 154 | } else { |
160 | struct lpfc_iocbq *next; | 155 | struct lpfc_iocbq *next; |
161 | 156 | ||
@@ -176,8 +171,7 @@ lpfc_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, | |||
176 | paddr); | 171 | paddr); |
177 | size = icmd->un.cont64[i].tus.f.bdeSize; | 172 | size = icmd->un.cont64[i].tus.f.bdeSize; |
178 | lpfc_ct_unsol_buffer(phba, piocbq, mp, size); | 173 | lpfc_ct_unsol_buffer(phba, piocbq, mp, size); |
179 | lpfc_mbuf_free(phba, mp->virt, mp->phys); | 174 | lpfc_in_buf_free(phba, mp); |
180 | kfree(mp); | ||
181 | } | 175 | } |
182 | list_del(&iocbq->list); | 176 | list_del(&iocbq->list); |
183 | lpfc_sli_release_iocbq(phba, iocbq); | 177 | lpfc_sli_release_iocbq(phba, iocbq); |
@@ -222,7 +216,8 @@ lpfc_alloc_ct_rsp(struct lpfc_hba *phba, int cmdcode, struct ulp_bde64 *bpl, | |||
222 | 216 | ||
223 | INIT_LIST_HEAD(&mp->list); | 217 | INIT_LIST_HEAD(&mp->list); |
224 | 218 | ||
225 | if (cmdcode == be16_to_cpu(SLI_CTNS_GID_FT)) | 219 | if (cmdcode == be16_to_cpu(SLI_CTNS_GID_FT) || |
220 | cmdcode == be16_to_cpu(SLI_CTNS_GFF_ID)) | ||
226 | mp->virt = lpfc_mbuf_alloc(phba, MEM_PRI, &(mp->phys)); | 221 | mp->virt = lpfc_mbuf_alloc(phba, MEM_PRI, &(mp->phys)); |
227 | else | 222 | else |
228 | mp->virt = lpfc_mbuf_alloc(phba, 0, &(mp->phys)); | 223 | mp->virt = lpfc_mbuf_alloc(phba, 0, &(mp->phys)); |
@@ -242,8 +237,8 @@ lpfc_alloc_ct_rsp(struct lpfc_hba *phba, int cmdcode, struct ulp_bde64 *bpl, | |||
242 | 237 | ||
243 | bpl->tus.f.bdeFlags = BUFF_USE_RCV; | 238 | bpl->tus.f.bdeFlags = BUFF_USE_RCV; |
244 | /* build buffer ptr list for IOCB */ | 239 | /* build buffer ptr list for IOCB */ |
245 | bpl->addrLow = le32_to_cpu( putPaddrLow(mp->phys) ); | 240 | bpl->addrLow = le32_to_cpu(putPaddrLow(mp->phys) ); |
246 | bpl->addrHigh = le32_to_cpu( putPaddrHigh(mp->phys) ); | 241 | bpl->addrHigh = le32_to_cpu(putPaddrHigh(mp->phys) ); |
247 | bpl->tus.f.bdeSize = (uint16_t) cnt; | 242 | bpl->tus.f.bdeSize = (uint16_t) cnt; |
248 | bpl->tus.w = le32_to_cpu(bpl->tus.w); | 243 | bpl->tus.w = le32_to_cpu(bpl->tus.w); |
249 | bpl++; | 244 | bpl++; |
@@ -262,13 +257,14 @@ lpfc_gen_req(struct lpfc_vport *vport, struct lpfc_dmabuf *bmp, | |||
262 | void (*cmpl) (struct lpfc_hba *, struct lpfc_iocbq *, | 257 | void (*cmpl) (struct lpfc_hba *, struct lpfc_iocbq *, |
263 | struct lpfc_iocbq *), | 258 | struct lpfc_iocbq *), |
264 | struct lpfc_nodelist *ndlp, uint32_t usr_flg, uint32_t num_entry, | 259 | struct lpfc_nodelist *ndlp, uint32_t usr_flg, uint32_t num_entry, |
265 | uint32_t tmo) | 260 | uint32_t tmo, uint8_t retry) |
266 | { | 261 | { |
267 | struct lpfc_hba *phba = vport->phba; | 262 | struct lpfc_hba *phba = vport->phba; |
268 | struct lpfc_sli *psli = &phba->sli; | 263 | struct lpfc_sli *psli = &phba->sli; |
269 | struct lpfc_sli_ring *pring = &psli->ring[LPFC_ELS_RING]; | 264 | struct lpfc_sli_ring *pring = &psli->ring[LPFC_ELS_RING]; |
270 | IOCB_t *icmd; | 265 | IOCB_t *icmd; |
271 | struct lpfc_iocbq *geniocb; | 266 | struct lpfc_iocbq *geniocb; |
267 | int rc; | ||
272 | 268 | ||
273 | /* Allocate buffer for command iocb */ | 269 | /* Allocate buffer for command iocb */ |
274 | geniocb = lpfc_sli_get_iocbq(phba); | 270 | geniocb = lpfc_sli_get_iocbq(phba); |
@@ -311,15 +307,25 @@ lpfc_gen_req(struct lpfc_vport *vport, struct lpfc_dmabuf *bmp, | |||
311 | icmd->ulpClass = CLASS3; | 307 | icmd->ulpClass = CLASS3; |
312 | icmd->ulpContext = ndlp->nlp_rpi; | 308 | icmd->ulpContext = ndlp->nlp_rpi; |
313 | 309 | ||
310 | if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) { | ||
311 | /* For GEN_REQUEST64_CR, use the RPI */ | ||
312 | icmd->ulpCt_h = 0; | ||
313 | icmd->ulpCt_l = 0; | ||
314 | } | ||
315 | |||
314 | /* Issue GEN REQ IOCB for NPORT <did> */ | 316 | /* Issue GEN REQ IOCB for NPORT <did> */ |
315 | lpfc_printf_log(phba, KERN_INFO, LOG_ELS, | 317 | lpfc_printf_log(phba, KERN_INFO, LOG_ELS, |
316 | "%d:0119 Issue GEN REQ IOCB for NPORT x%x " | 318 | "%d (%d):0119 Issue GEN REQ IOCB to NPORT x%x " |
317 | "Data: x%x x%x\n", phba->brd_no, icmd->un.ulpWord[5], | 319 | "Data: x%x x%x\n", phba->brd_no, vport->vpi, |
318 | icmd->ulpIoTag, vport->port_state); | 320 | ndlp->nlp_DID, icmd->ulpIoTag, |
321 | vport->port_state); | ||
319 | geniocb->iocb_cmpl = cmpl; | 322 | geniocb->iocb_cmpl = cmpl; |
320 | geniocb->drvrTimeout = icmd->ulpTimeout + LPFC_DRVR_TIMEOUT; | 323 | geniocb->drvrTimeout = icmd->ulpTimeout + LPFC_DRVR_TIMEOUT; |
321 | geniocb->vport = vport; | 324 | geniocb->vport = vport; |
322 | if (lpfc_sli_issue_iocb(phba, pring, geniocb, 0) == IOCB_ERROR) { | 325 | geniocb->retry = retry; |
326 | rc = lpfc_sli_issue_iocb(phba, pring, geniocb, 0); | ||
327 | |||
328 | if (rc == IOCB_ERROR) { | ||
323 | lpfc_sli_release_iocbq(phba, geniocb); | 329 | lpfc_sli_release_iocbq(phba, geniocb); |
324 | return 1; | 330 | return 1; |
325 | } | 331 | } |
@@ -332,7 +338,7 @@ lpfc_ct_cmd(struct lpfc_vport *vport, struct lpfc_dmabuf *inmp, | |||
332 | struct lpfc_dmabuf *bmp, struct lpfc_nodelist *ndlp, | 338 | struct lpfc_dmabuf *bmp, struct lpfc_nodelist *ndlp, |
333 | void (*cmpl) (struct lpfc_hba *, struct lpfc_iocbq *, | 339 | void (*cmpl) (struct lpfc_hba *, struct lpfc_iocbq *, |
334 | struct lpfc_iocbq *), | 340 | struct lpfc_iocbq *), |
335 | uint32_t rsp_size) | 341 | uint32_t rsp_size, uint8_t retry) |
336 | { | 342 | { |
337 | struct lpfc_hba *phba = vport->phba; | 343 | struct lpfc_hba *phba = vport->phba; |
338 | struct ulp_bde64 *bpl = (struct ulp_bde64 *) bmp->virt; | 344 | struct ulp_bde64 *bpl = (struct ulp_bde64 *) bmp->virt; |
@@ -349,7 +355,7 @@ lpfc_ct_cmd(struct lpfc_vport *vport, struct lpfc_dmabuf *inmp, | |||
349 | return -ENOMEM; | 355 | return -ENOMEM; |
350 | 356 | ||
351 | status = lpfc_gen_req(vport, bmp, inmp, outmp, cmpl, ndlp, 0, | 357 | status = lpfc_gen_req(vport, bmp, inmp, outmp, cmpl, ndlp, 0, |
352 | cnt+1, 0); | 358 | cnt+1, 0, retry); |
353 | if (status) { | 359 | if (status) { |
354 | lpfc_free_ct_rsp(phba, outmp); | 360 | lpfc_free_ct_rsp(phba, outmp); |
355 | return -ENOMEM; | 361 | return -ENOMEM; |
@@ -357,10 +363,23 @@ lpfc_ct_cmd(struct lpfc_vport *vport, struct lpfc_dmabuf *inmp, | |||
357 | return 0; | 363 | return 0; |
358 | } | 364 | } |
359 | 365 | ||
366 | static struct lpfc_vport * | ||
367 | lpfc_find_vport_by_did(struct lpfc_hba *phba, uint32_t did) { | ||
368 | |||
369 | struct lpfc_vport *vport_curr; | ||
370 | |||
371 | list_for_each_entry(vport_curr, &phba->port_list, listentry) { | ||
372 | if ((vport_curr->fc_myDID) && | ||
373 | (vport_curr->fc_myDID == did)) | ||
374 | return vport_curr; | ||
375 | } | ||
376 | |||
377 | return NULL; | ||
378 | } | ||
379 | |||
360 | static int | 380 | static int |
361 | lpfc_ns_rsp(struct lpfc_vport *vport, struct lpfc_dmabuf *mp, uint32_t Size) | 381 | lpfc_ns_rsp(struct lpfc_vport *vport, struct lpfc_dmabuf *mp, uint32_t Size) |
362 | { | 382 | { |
363 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); | ||
364 | struct lpfc_hba *phba = vport->phba; | 383 | struct lpfc_hba *phba = vport->phba; |
365 | struct lpfc_sli_ct_request *Response = | 384 | struct lpfc_sli_ct_request *Response = |
366 | (struct lpfc_sli_ct_request *) mp->virt; | 385 | (struct lpfc_sli_ct_request *) mp->virt; |
@@ -372,6 +391,7 @@ lpfc_ns_rsp(struct lpfc_vport *vport, struct lpfc_dmabuf *mp, uint32_t Size) | |||
372 | struct list_head head; | 391 | struct list_head head; |
373 | 392 | ||
374 | lpfc_set_disctmo(vport); | 393 | lpfc_set_disctmo(vport); |
394 | vport->num_disc_nodes = 0; | ||
375 | 395 | ||
376 | 396 | ||
377 | list_add_tail(&head, &mp->list); | 397 | list_add_tail(&head, &mp->list); |
@@ -392,25 +412,64 @@ lpfc_ns_rsp(struct lpfc_vport *vport, struct lpfc_dmabuf *mp, uint32_t Size) | |||
392 | /* Get next DID from NameServer List */ | 412 | /* Get next DID from NameServer List */ |
393 | CTentry = *ctptr++; | 413 | CTentry = *ctptr++; |
394 | Did = ((be32_to_cpu(CTentry)) & Mask_DID); | 414 | Did = ((be32_to_cpu(CTentry)) & Mask_DID); |
415 | |||
395 | ndlp = NULL; | 416 | ndlp = NULL; |
396 | /* Check for rscn processing or not */ | 417 | |
397 | if (Did != vport->fc_myDID) | 418 | /* |
398 | ndlp = lpfc_setup_disc_node(vport, Did); | 419 | * Check for rscn processing or not |
399 | if (ndlp) { | 420 | * To conserve rpi's, filter out addresses for other |
400 | lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, | 421 | * vports on the same physical HBAs. |
401 | "%d:0238 Process x%x NameServer" | 422 | */ |
402 | " Rsp Data: x%x x%x x%x\n", | 423 | if ((Did != vport->fc_myDID) && |
403 | phba->brd_no, | 424 | ((lpfc_find_vport_by_did(phba, Did) == NULL) || |
404 | Did, ndlp->nlp_flag, | 425 | phba->cfg_peer_port_login)) { |
405 | vport->fc_flag, | 426 | if ((vport->port_type != LPFC_NPIV_PORT) || |
406 | vport->fc_rscn_id_cnt); | 427 | (vport->fc_flag & FC_RFF_NOT_SUPPORTED) || |
407 | } else { | 428 | (!phba->cfg_vport_restrict_login)) { |
408 | lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, | 429 | ndlp = lpfc_setup_disc_node(vport, Did); |
409 | "%d:0239 Skip x%x NameServer " | 430 | if (ndlp) { |
410 | "Rsp Data: x%x x%x x%x\n", | 431 | lpfc_printf_log(phba, KERN_INFO, |
411 | phba->brd_no, | 432 | LOG_DISCOVERY, |
412 | Did, Size, vport->fc_flag, | 433 | "%d (%d):0238 Process " |
413 | vport->fc_rscn_id_cnt); | 434 | "x%x NameServer Rsp" |
435 | "Data: x%x x%x x%x\n", | ||
436 | phba->brd_no, | ||
437 | vport->vpi, Did, | ||
438 | ndlp->nlp_flag, | ||
439 | vport->fc_flag, | ||
440 | vport->fc_rscn_id_cnt); | ||
441 | } else { | ||
442 | lpfc_printf_log(phba, KERN_INFO, | ||
443 | LOG_DISCOVERY, | ||
444 | "%d (%d):0239 Skip x%x " | ||
445 | "NameServer Rsp Data: " | ||
446 | "x%x x%x\n", | ||
447 | phba->brd_no, | ||
448 | vport->vpi, Did, | ||
449 | vport->fc_flag, | ||
450 | vport->fc_rscn_id_cnt); | ||
451 | } | ||
452 | |||
453 | } else { | ||
454 | if (!(vport->fc_flag & FC_RSCN_MODE) || | ||
455 | (lpfc_rscn_payload_check(vport, Did))) { | ||
456 | if (lpfc_ns_cmd(vport, | ||
457 | SLI_CTNS_GFF_ID, | ||
458 | 0, Did) == 0) | ||
459 | vport->num_disc_nodes++; | ||
460 | } | ||
461 | else { | ||
462 | lpfc_printf_log(phba, KERN_INFO, | ||
463 | LOG_DISCOVERY, | ||
464 | "%d (%d):0245 Skip x%x " | ||
465 | "NameServer Rsp Data: " | ||
466 | "x%x x%x\n", | ||
467 | phba->brd_no, | ||
468 | vport->vpi, Did, | ||
469 | vport->fc_flag, | ||
470 | vport->fc_rscn_id_cnt); | ||
471 | } | ||
472 | } | ||
414 | } | 473 | } |
415 | if (CTentry & (be32_to_cpu(SLI_CT_LAST_ENTRY))) | 474 | if (CTentry & (be32_to_cpu(SLI_CT_LAST_ENTRY))) |
416 | goto nsout1; | 475 | goto nsout1; |
@@ -422,34 +481,19 @@ lpfc_ns_rsp(struct lpfc_vport *vport, struct lpfc_dmabuf *mp, uint32_t Size) | |||
422 | 481 | ||
423 | nsout1: | 482 | nsout1: |
424 | list_del(&head); | 483 | list_del(&head); |
425 | |||
426 | /* | ||
427 | * The driver has cycled through all Nports in the RSCN payload. | ||
428 | * Complete the handling by cleaning up and marking the | ||
429 | * current driver state. | ||
430 | */ | ||
431 | if (vport->port_state == LPFC_VPORT_READY) { | ||
432 | lpfc_els_flush_rscn(vport); | ||
433 | spin_lock_irq(shost->host_lock); | ||
434 | vport->fc_flag |= FC_RSCN_MODE; /* we are still in RSCN mode */ | ||
435 | spin_unlock_irq(shost->host_lock); | ||
436 | } | ||
437 | return 0; | 484 | return 0; |
438 | } | 485 | } |
439 | 486 | ||
440 | |||
441 | |||
442 | |||
443 | static void | 487 | static void |
444 | lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | 488 | lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, |
445 | struct lpfc_iocbq *rspiocb) | 489 | struct lpfc_iocbq *rspiocb) |
446 | { | 490 | { |
447 | struct lpfc_vport *vport = cmdiocb->vport; | 491 | struct lpfc_vport *vport = cmdiocb->vport; |
492 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); | ||
448 | IOCB_t *irsp; | 493 | IOCB_t *irsp; |
449 | struct lpfc_dmabuf *bmp; | 494 | struct lpfc_dmabuf *bmp; |
450 | struct lpfc_dmabuf *inp; | 495 | struct lpfc_dmabuf *inp; |
451 | struct lpfc_dmabuf *outp; | 496 | struct lpfc_dmabuf *outp; |
452 | struct lpfc_nodelist *ndlp; | ||
453 | struct lpfc_sli_ct_request *CTrsp; | 497 | struct lpfc_sli_ct_request *CTrsp; |
454 | int rc; | 498 | int rc; |
455 | 499 | ||
@@ -460,33 +504,41 @@ lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
460 | outp = (struct lpfc_dmabuf *) cmdiocb->context2; | 504 | outp = (struct lpfc_dmabuf *) cmdiocb->context2; |
461 | bmp = (struct lpfc_dmabuf *) cmdiocb->context3; | 505 | bmp = (struct lpfc_dmabuf *) cmdiocb->context3; |
462 | 506 | ||
507 | /* Don't bother processing response if vport is being torn down. */ | ||
508 | if (vport->load_flag & FC_UNLOADING) | ||
509 | goto out; | ||
510 | |||
463 | irsp = &rspiocb->iocb; | 511 | irsp = &rspiocb->iocb; |
464 | if (irsp->ulpStatus) { | 512 | if (irsp->ulpStatus) { |
465 | if ((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) && | 513 | if ((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) && |
466 | ((irsp->un.ulpWord[4] == IOERR_SLI_DOWN) || | 514 | ((irsp->un.ulpWord[4] == IOERR_SLI_DOWN) || |
467 | (irsp->un.ulpWord[4] == IOERR_SLI_ABORTED))) | 515 | (irsp->un.ulpWord[4] == IOERR_SLI_ABORTED))) |
468 | goto out; | 516 | goto err1; |
469 | 517 | ||
470 | /* Check for retry */ | 518 | /* Check for retry */ |
471 | if (vport->fc_ns_retry < LPFC_MAX_NS_RETRY) { | 519 | if (vport->fc_ns_retry < LPFC_MAX_NS_RETRY) { |
472 | vport->fc_ns_retry++; | 520 | vport->fc_ns_retry++; |
473 | /* CT command is being retried */ | 521 | /* CT command is being retried */ |
474 | ndlp = lpfc_findnode_did(vport, NameServer_DID); | 522 | rc = lpfc_ns_cmd(vport, SLI_CTNS_GID_FT, |
475 | if (ndlp && ndlp->nlp_state == NLP_STE_UNMAPPED_NODE) { | 523 | vport->fc_ns_retry, 0); |
476 | rc = lpfc_ns_cmd(vport, ndlp, SLI_CTNS_GID_FT); | 524 | if (rc == 0) |
477 | if (rc == 0) | 525 | goto out; |
478 | goto out; | 526 | } |
479 | } | 527 | err1: |
480 | } | 528 | lpfc_vport_set_state(vport, FC_VPORT_FAILED); |
529 | lpfc_printf_log(phba, KERN_ERR, LOG_ELS, | ||
530 | "%d (%d):0257 GID_FT Query error: 0x%x 0x%x\n", | ||
531 | phba->brd_no, vport->vpi, irsp->ulpStatus, | ||
532 | vport->fc_ns_retry); | ||
481 | } else { | 533 | } else { |
482 | /* Good status, continue checking */ | 534 | /* Good status, continue checking */ |
483 | CTrsp = (struct lpfc_sli_ct_request *) outp->virt; | 535 | CTrsp = (struct lpfc_sli_ct_request *) outp->virt; |
484 | if (CTrsp->CommandResponse.bits.CmdRsp == | 536 | if (CTrsp->CommandResponse.bits.CmdRsp == |
485 | be16_to_cpu(SLI_CT_RESPONSE_FS_ACC)) { | 537 | be16_to_cpu(SLI_CT_RESPONSE_FS_ACC)) { |
486 | lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, | 538 | lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, |
487 | "%d:0208 NameServer Rsp " | 539 | "%d (%d):0208 NameServer Rsp " |
488 | "Data: x%x\n", | 540 | "Data: x%x\n", |
489 | phba->brd_no, | 541 | phba->brd_no, vport->vpi, |
490 | vport->fc_flag); | 542 | vport->fc_flag); |
491 | lpfc_ns_rsp(vport, outp, | 543 | lpfc_ns_rsp(vport, outp, |
492 | (uint32_t) (irsp->un.genreq64.bdl.bdeSize)); | 544 | (uint32_t) (irsp->un.genreq64.bdl.bdeSize)); |
@@ -494,21 +546,19 @@ lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
494 | be16_to_cpu(SLI_CT_RESPONSE_FS_RJT)) { | 546 | be16_to_cpu(SLI_CT_RESPONSE_FS_RJT)) { |
495 | /* NameServer Rsp Error */ | 547 | /* NameServer Rsp Error */ |
496 | lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, | 548 | lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, |
497 | "%d:0240 NameServer Rsp Error " | 549 | "%d (%d):0240 NameServer Rsp Error " |
498 | "Data: x%x x%x x%x x%x\n", | 550 | "Data: x%x x%x x%x x%x\n", |
499 | phba->brd_no, | 551 | phba->brd_no, vport->vpi, |
500 | CTrsp->CommandResponse.bits.CmdRsp, | 552 | CTrsp->CommandResponse.bits.CmdRsp, |
501 | (uint32_t) CTrsp->ReasonCode, | 553 | (uint32_t) CTrsp->ReasonCode, |
502 | (uint32_t) CTrsp->Explanation, | 554 | (uint32_t) CTrsp->Explanation, |
503 | vport->fc_flag); | 555 | vport->fc_flag); |
504 | } else { | 556 | } else { |
505 | /* NameServer Rsp Error */ | 557 | /* NameServer Rsp Error */ |
506 | lpfc_printf_log(phba, | 558 | lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY, |
507 | KERN_INFO, | 559 | "%d (%d):0241 NameServer Rsp Error " |
508 | LOG_DISCOVERY, | ||
509 | "%d:0241 NameServer Rsp Error " | ||
510 | "Data: x%x x%x x%x x%x\n", | 560 | "Data: x%x x%x x%x x%x\n", |
511 | phba->brd_no, | 561 | phba->brd_no, vport->vpi, |
512 | CTrsp->CommandResponse.bits.CmdRsp, | 562 | CTrsp->CommandResponse.bits.CmdRsp, |
513 | (uint32_t) CTrsp->ReasonCode, | 563 | (uint32_t) CTrsp->ReasonCode, |
514 | (uint32_t) CTrsp->Explanation, | 564 | (uint32_t) CTrsp->Explanation, |
@@ -516,8 +566,111 @@ lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
516 | } | 566 | } |
517 | } | 567 | } |
518 | /* Link up / RSCN discovery */ | 568 | /* Link up / RSCN discovery */ |
519 | lpfc_disc_start(vport); | 569 | if (vport->num_disc_nodes == 0) { |
570 | /* | ||
571 | * The driver has cycled through all Nports in the RSCN payload. | ||
572 | * Complete the handling by cleaning up and marking the | ||
573 | * current driver state. | ||
574 | */ | ||
575 | if (vport->port_state >= LPFC_DISC_AUTH) { | ||
576 | if (vport->fc_flag & FC_RSCN_MODE) { | ||
577 | lpfc_els_flush_rscn(vport); | ||
578 | spin_lock_irq(shost->host_lock); | ||
579 | vport->fc_flag |= FC_RSCN_MODE; /* RSCN still */ | ||
580 | spin_unlock_irq(shost->host_lock); | ||
581 | } | ||
582 | else | ||
583 | lpfc_els_flush_rscn(vport); | ||
584 | } | ||
585 | |||
586 | lpfc_disc_start(vport); | ||
587 | } | ||
588 | out: | ||
589 | lpfc_free_ct_rsp(phba, outp); | ||
590 | lpfc_mbuf_free(phba, inp->virt, inp->phys); | ||
591 | lpfc_mbuf_free(phba, bmp->virt, bmp->phys); | ||
592 | kfree(inp); | ||
593 | kfree(bmp); | ||
594 | lpfc_sli_release_iocbq(phba, cmdiocb); | ||
595 | return; | ||
596 | } | ||
597 | |||
598 | void | ||
599 | lpfc_cmpl_ct_cmd_gff_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | ||
600 | struct lpfc_iocbq *rspiocb) | ||
601 | { | ||
602 | struct lpfc_vport *vport = cmdiocb->vport; | ||
603 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); | ||
604 | IOCB_t *irsp = &rspiocb->iocb; | ||
605 | struct lpfc_dmabuf *bmp = (struct lpfc_dmabuf *) cmdiocb->context3; | ||
606 | struct lpfc_dmabuf *inp = (struct lpfc_dmabuf *) cmdiocb->context1; | ||
607 | struct lpfc_dmabuf *outp = (struct lpfc_dmabuf *) cmdiocb->context2; | ||
608 | struct lpfc_sli_ct_request *CTrsp; | ||
609 | int did; | ||
610 | uint8_t fbits; | ||
611 | struct lpfc_nodelist *ndlp; | ||
612 | |||
613 | did = ((struct lpfc_sli_ct_request *) inp->virt)->un.gff.PortId; | ||
614 | did = be32_to_cpu(did); | ||
615 | |||
616 | if (irsp->ulpStatus == IOSTAT_SUCCESS) { | ||
617 | /* Good status, continue checking */ | ||
618 | CTrsp = (struct lpfc_sli_ct_request *) outp->virt; | ||
619 | fbits = CTrsp->un.gff_acc.fbits[FCP_TYPE_FEATURE_OFFSET]; | ||
620 | |||
621 | if (CTrsp->CommandResponse.bits.CmdRsp == | ||
622 | be16_to_cpu(SLI_CT_RESPONSE_FS_ACC)) { | ||
623 | if ((fbits & FC4_FEATURE_INIT) && | ||
624 | !(fbits & FC4_FEATURE_TARGET)) { | ||
625 | lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, | ||
626 | "%d (%d):0245 Skip x%x GFF " | ||
627 | "NameServer Rsp Data: (init) " | ||
628 | "x%x x%x\n", phba->brd_no, | ||
629 | vport->vpi, did, fbits, | ||
630 | vport->fc_rscn_id_cnt); | ||
631 | goto out; | ||
632 | } | ||
633 | } | ||
634 | } | ||
635 | /* This is a target port, unregistered port, or the GFF_ID failed */ | ||
636 | ndlp = lpfc_setup_disc_node(vport, did); | ||
637 | if (ndlp) { | ||
638 | lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, | ||
639 | "%d (%d):0242 Process x%x GFF " | ||
640 | "NameServer Rsp Data: x%x x%x x%x\n", | ||
641 | phba->brd_no, vport->vpi, | ||
642 | did, ndlp->nlp_flag, vport->fc_flag, | ||
643 | vport->fc_rscn_id_cnt); | ||
644 | } else { | ||
645 | lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, | ||
646 | "%d (%d):0243 Skip x%x GFF " | ||
647 | "NameServer Rsp Data: x%x x%x\n", | ||
648 | phba->brd_no, vport->vpi, did, | ||
649 | vport->fc_flag, vport->fc_rscn_id_cnt); | ||
650 | } | ||
520 | out: | 651 | out: |
652 | /* Link up / RSCN discovery */ | ||
653 | if (vport->num_disc_nodes) | ||
654 | vport->num_disc_nodes--; | ||
655 | if (vport->num_disc_nodes == 0) { | ||
656 | /* | ||
657 | * The driver has cycled through all Nports in the RSCN payload. | ||
658 | * Complete the handling by cleaning up and marking the | ||
659 | * current driver state. | ||
660 | */ | ||
661 | if (vport->port_state >= LPFC_DISC_AUTH) { | ||
662 | if (vport->fc_flag & FC_RSCN_MODE) { | ||
663 | lpfc_els_flush_rscn(vport); | ||
664 | spin_lock_irq(shost->host_lock); | ||
665 | vport->fc_flag |= FC_RSCN_MODE; /* RSCN still */ | ||
666 | spin_unlock_irq(shost->host_lock); | ||
667 | } | ||
668 | else | ||
669 | lpfc_els_flush_rscn(vport); | ||
670 | } | ||
671 | lpfc_disc_start(vport); | ||
672 | } | ||
673 | |||
521 | lpfc_free_ct_rsp(phba, outp); | 674 | lpfc_free_ct_rsp(phba, outp); |
522 | lpfc_mbuf_free(phba, inp->virt, inp->phys); | 675 | lpfc_mbuf_free(phba, inp->virt, inp->phys); |
523 | lpfc_mbuf_free(phba, bmp->virt, bmp->phys); | 676 | lpfc_mbuf_free(phba, bmp->virt, bmp->phys); |
@@ -527,15 +680,19 @@ out: | |||
527 | return; | 680 | return; |
528 | } | 681 | } |
529 | 682 | ||
683 | |||
530 | static void | 684 | static void |
531 | lpfc_cmpl_ct_cmd_rft_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | 685 | lpfc_cmpl_ct_cmd_rft_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, |
532 | struct lpfc_iocbq *rspiocb) | 686 | struct lpfc_iocbq *rspiocb) |
533 | { | 687 | { |
688 | struct lpfc_vport *vport = cmdiocb->vport; | ||
534 | struct lpfc_dmabuf *bmp; | 689 | struct lpfc_dmabuf *bmp; |
535 | struct lpfc_dmabuf *inp; | 690 | struct lpfc_dmabuf *inp; |
536 | struct lpfc_dmabuf *outp; | 691 | struct lpfc_dmabuf *outp; |
537 | IOCB_t *irsp; | 692 | IOCB_t *irsp; |
538 | struct lpfc_sli_ct_request *CTrsp; | 693 | struct lpfc_sli_ct_request *CTrsp; |
694 | int cmdcode, rc; | ||
695 | uint8_t retry; | ||
539 | 696 | ||
540 | /* we pass cmdiocb to state machine which needs rspiocb as well */ | 697 | /* we pass cmdiocb to state machine which needs rspiocb as well */ |
541 | cmdiocb->context_un.rsp_iocb = rspiocb; | 698 | cmdiocb->context_un.rsp_iocb = rspiocb; |
@@ -545,16 +702,40 @@ lpfc_cmpl_ct_cmd_rft_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
545 | bmp = (struct lpfc_dmabuf *) cmdiocb->context3; | 702 | bmp = (struct lpfc_dmabuf *) cmdiocb->context3; |
546 | irsp = &rspiocb->iocb; | 703 | irsp = &rspiocb->iocb; |
547 | 704 | ||
705 | cmdcode = be16_to_cpu(((struct lpfc_sli_ct_request *) inp->virt)-> | ||
706 | CommandResponse.bits.CmdRsp); | ||
548 | CTrsp = (struct lpfc_sli_ct_request *) outp->virt; | 707 | CTrsp = (struct lpfc_sli_ct_request *) outp->virt; |
549 | 708 | ||
550 | /* RFT request completes status <ulpStatus> CmdRsp <CmdRsp> */ | 709 | /* NS request completes status <ulpStatus> CmdRsp <CmdRsp> */ |
551 | lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, | 710 | lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, |
552 | "%d:0209 RFT request completes ulpStatus x%x " | 711 | "%d (%d):0209 NS request %x completes " |
712 | "ulpStatus x%x / x%x " | ||
553 | "CmdRsp x%x, Context x%x, Tag x%x\n", | 713 | "CmdRsp x%x, Context x%x, Tag x%x\n", |
554 | phba->brd_no, irsp->ulpStatus, | 714 | phba->brd_no, vport->vpi, |
715 | cmdcode, irsp->ulpStatus, irsp->un.ulpWord[4], | ||
555 | CTrsp->CommandResponse.bits.CmdRsp, | 716 | CTrsp->CommandResponse.bits.CmdRsp, |
556 | cmdiocb->iocb.ulpContext, cmdiocb->iocb.ulpIoTag); | 717 | cmdiocb->iocb.ulpContext, cmdiocb->iocb.ulpIoTag); |
557 | 718 | ||
719 | if (irsp->ulpStatus) { | ||
720 | if ((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) && | ||
721 | ((irsp->un.ulpWord[4] == IOERR_SLI_DOWN) || | ||
722 | (irsp->un.ulpWord[4] == IOERR_SLI_ABORTED))) | ||
723 | goto out; | ||
724 | |||
725 | retry = cmdiocb->retry; | ||
726 | if (retry >= LPFC_MAX_NS_RETRY) | ||
727 | goto out; | ||
728 | |||
729 | retry++; | ||
730 | lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, | ||
731 | "%d (%d):0216 Retrying NS cmd %x\n", | ||
732 | phba->brd_no, vport->vpi, cmdcode); | ||
733 | rc = lpfc_ns_cmd(vport, cmdcode, retry, 0); | ||
734 | if (rc == 0) | ||
735 | goto out; | ||
736 | } | ||
737 | |||
738 | out: | ||
558 | lpfc_free_ct_rsp(phba, outp); | 739 | lpfc_free_ct_rsp(phba, outp); |
559 | lpfc_mbuf_free(phba, inp->virt, inp->phys); | 740 | lpfc_mbuf_free(phba, inp->virt, inp->phys); |
560 | lpfc_mbuf_free(phba, bmp->virt, bmp->phys); | 741 | lpfc_mbuf_free(phba, bmp->virt, bmp->phys); |
@@ -573,6 +754,14 @@ lpfc_cmpl_ct_cmd_rnn_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
573 | } | 754 | } |
574 | 755 | ||
575 | static void | 756 | static void |
757 | lpfc_cmpl_ct_cmd_rspn_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | ||
758 | struct lpfc_iocbq *rspiocb) | ||
759 | { | ||
760 | lpfc_cmpl_ct_cmd_rft_id(phba, cmdiocb, rspiocb); | ||
761 | return; | ||
762 | } | ||
763 | |||
764 | static void | ||
576 | lpfc_cmpl_ct_cmd_rsnn_nn(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | 765 | lpfc_cmpl_ct_cmd_rsnn_nn(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, |
577 | struct lpfc_iocbq *rspiocb) | 766 | struct lpfc_iocbq *rspiocb) |
578 | { | 767 | { |
@@ -581,23 +770,54 @@ lpfc_cmpl_ct_cmd_rsnn_nn(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
581 | } | 770 | } |
582 | 771 | ||
583 | static void | 772 | static void |
584 | lpfc_cmpl_ct_cmd_rff_id(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb, | 773 | lpfc_cmpl_ct_cmd_rff_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, |
585 | struct lpfc_iocbq * rspiocb) | 774 | struct lpfc_iocbq *rspiocb) |
586 | { | 775 | { |
776 | IOCB_t *irsp = &rspiocb->iocb; | ||
777 | struct lpfc_vport *vport = cmdiocb->vport; | ||
778 | |||
779 | if (irsp->ulpStatus != IOSTAT_SUCCESS) | ||
780 | vport->fc_flag |= FC_RFF_NOT_SUPPORTED; | ||
781 | |||
587 | lpfc_cmpl_ct_cmd_rft_id(phba, cmdiocb, rspiocb); | 782 | lpfc_cmpl_ct_cmd_rft_id(phba, cmdiocb, rspiocb); |
588 | return; | 783 | return; |
589 | } | 784 | } |
590 | 785 | ||
591 | void | 786 | int |
592 | lpfc_get_hba_sym_node_name(struct lpfc_hba *phba, uint8_t *symbp) | 787 | lpfc_vport_symbolic_port_name(struct lpfc_vport *vport, char *symbol, |
788 | size_t size) | ||
789 | { | ||
790 | int n; | ||
791 | uint8_t *wwn = vport->phba->wwpn; | ||
792 | |||
793 | n = snprintf(symbol, size, | ||
794 | "Emulex PPN-%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", | ||
795 | wwn[0], wwn[1], wwn[2], wwn[3], | ||
796 | wwn[4], wwn[5], wwn[6], wwn[7]); | ||
797 | |||
798 | if (vport->port_type == LPFC_PHYSICAL_PORT) | ||
799 | return n; | ||
800 | |||
801 | if (n < size) | ||
802 | n += snprintf(symbol + n, size - n, " VPort-%d", vport->vpi); | ||
803 | |||
804 | if (n < size && vport->vname) | ||
805 | n += snprintf(symbol + n, size - n, " VName-%s", vport->vname); | ||
806 | return n; | ||
807 | } | ||
808 | |||
809 | int | ||
810 | lpfc_vport_symbolic_node_name(struct lpfc_vport *vport, char *symbol, | ||
811 | size_t size) | ||
593 | { | 812 | { |
594 | char fwrev[16]; | 813 | char fwrev[16]; |
814 | int n; | ||
595 | 815 | ||
596 | lpfc_decode_firmware_rev(phba, fwrev, 0); | 816 | lpfc_decode_firmware_rev(vport->phba, fwrev, 0); |
597 | 817 | ||
598 | sprintf(symbp, "Emulex %s FV%s DV%s", phba->ModelName, | 818 | n = snprintf(symbol, size, "Emulex %s FV%s DV%s", |
599 | fwrev, lpfc_release_version); | 819 | vport->phba->ModelName, fwrev, lpfc_release_version); |
600 | return; | 820 | return n; |
601 | } | 821 | } |
602 | 822 | ||
603 | /* | 823 | /* |
@@ -608,8 +828,10 @@ lpfc_get_hba_sym_node_name(struct lpfc_hba *phba, uint8_t *symbp) | |||
608 | * LI_CTNS_RFT_ID | 828 | * LI_CTNS_RFT_ID |
609 | */ | 829 | */ |
610 | int | 830 | int |
611 | lpfc_ns_cmd(struct lpfc_vport *vport, struct lpfc_nodelist * ndlp, int cmdcode) | 831 | lpfc_ns_cmd(struct lpfc_vport *vport, int cmdcode, |
832 | uint8_t retry, uint32_t context) | ||
612 | { | 833 | { |
834 | struct lpfc_nodelist * ndlp; | ||
613 | struct lpfc_hba *phba = vport->phba; | 835 | struct lpfc_hba *phba = vport->phba; |
614 | struct lpfc_dmabuf *mp, *bmp; | 836 | struct lpfc_dmabuf *mp, *bmp; |
615 | struct lpfc_sli_ct_request *CtReq; | 837 | struct lpfc_sli_ct_request *CtReq; |
@@ -617,6 +839,11 @@ lpfc_ns_cmd(struct lpfc_vport *vport, struct lpfc_nodelist * ndlp, int cmdcode) | |||
617 | void (*cmpl) (struct lpfc_hba *, struct lpfc_iocbq *, | 839 | void (*cmpl) (struct lpfc_hba *, struct lpfc_iocbq *, |
618 | struct lpfc_iocbq *) = NULL; | 840 | struct lpfc_iocbq *) = NULL; |
619 | uint32_t rsp_size = 1024; | 841 | uint32_t rsp_size = 1024; |
842 | size_t size; | ||
843 | |||
844 | ndlp = lpfc_findnode_did(vport, NameServer_DID); | ||
845 | if (ndlp == NULL || ndlp->nlp_state != NLP_STE_UNMAPPED_NODE) | ||
846 | return 1; | ||
620 | 847 | ||
621 | /* fill in BDEs for command */ | 848 | /* fill in BDEs for command */ |
622 | /* Allocate buffer for command payload */ | 849 | /* Allocate buffer for command payload */ |
@@ -640,24 +867,26 @@ lpfc_ns_cmd(struct lpfc_vport *vport, struct lpfc_nodelist * ndlp, int cmdcode) | |||
640 | goto ns_cmd_free_bmp; | 867 | goto ns_cmd_free_bmp; |
641 | 868 | ||
642 | /* NameServer Req */ | 869 | /* NameServer Req */ |
643 | lpfc_printf_log(phba, | 870 | lpfc_printf_log(phba, KERN_INFO ,LOG_DISCOVERY, |
644 | KERN_INFO, | 871 | "%d (%d):0236 NameServer Req Data: x%x x%x x%x\n", |
645 | LOG_DISCOVERY, | 872 | phba->brd_no, vport->vpi, cmdcode, vport->fc_flag, |
646 | "%d:0236 NameServer Req Data: x%x x%x x%x\n", | ||
647 | phba->brd_no, cmdcode, vport->fc_flag, | ||
648 | vport->fc_rscn_id_cnt); | 873 | vport->fc_rscn_id_cnt); |
649 | 874 | ||
650 | bpl = (struct ulp_bde64 *) bmp->virt; | 875 | bpl = (struct ulp_bde64 *) bmp->virt; |
651 | memset(bpl, 0, sizeof(struct ulp_bde64)); | 876 | memset(bpl, 0, sizeof(struct ulp_bde64)); |
652 | bpl->addrHigh = le32_to_cpu( putPaddrHigh(mp->phys) ); | 877 | bpl->addrHigh = le32_to_cpu(putPaddrHigh(mp->phys) ); |
653 | bpl->addrLow = le32_to_cpu( putPaddrLow(mp->phys) ); | 878 | bpl->addrLow = le32_to_cpu(putPaddrLow(mp->phys) ); |
654 | bpl->tus.f.bdeFlags = 0; | 879 | bpl->tus.f.bdeFlags = 0; |
655 | if (cmdcode == SLI_CTNS_GID_FT) | 880 | if (cmdcode == SLI_CTNS_GID_FT) |
656 | bpl->tus.f.bdeSize = GID_REQUEST_SZ; | 881 | bpl->tus.f.bdeSize = GID_REQUEST_SZ; |
882 | else if (cmdcode == SLI_CTNS_GFF_ID) | ||
883 | bpl->tus.f.bdeSize = GFF_REQUEST_SZ; | ||
657 | else if (cmdcode == SLI_CTNS_RFT_ID) | 884 | else if (cmdcode == SLI_CTNS_RFT_ID) |
658 | bpl->tus.f.bdeSize = RFT_REQUEST_SZ; | 885 | bpl->tus.f.bdeSize = RFT_REQUEST_SZ; |
659 | else if (cmdcode == SLI_CTNS_RNN_ID) | 886 | else if (cmdcode == SLI_CTNS_RNN_ID) |
660 | bpl->tus.f.bdeSize = RNN_REQUEST_SZ; | 887 | bpl->tus.f.bdeSize = RNN_REQUEST_SZ; |
888 | else if (cmdcode == SLI_CTNS_RSPN_ID) | ||
889 | bpl->tus.f.bdeSize = RSPN_REQUEST_SZ; | ||
661 | else if (cmdcode == SLI_CTNS_RSNN_NN) | 890 | else if (cmdcode == SLI_CTNS_RSNN_NN) |
662 | bpl->tus.f.bdeSize = RSNN_REQUEST_SZ; | 891 | bpl->tus.f.bdeSize = RSNN_REQUEST_SZ; |
663 | else if (cmdcode == SLI_CTNS_RFF_ID) | 892 | else if (cmdcode == SLI_CTNS_RFF_ID) |
@@ -678,13 +907,20 @@ lpfc_ns_cmd(struct lpfc_vport *vport, struct lpfc_nodelist * ndlp, int cmdcode) | |||
678 | CtReq->CommandResponse.bits.CmdRsp = | 907 | CtReq->CommandResponse.bits.CmdRsp = |
679 | be16_to_cpu(SLI_CTNS_GID_FT); | 908 | be16_to_cpu(SLI_CTNS_GID_FT); |
680 | CtReq->un.gid.Fc4Type = SLI_CTPT_FCP; | 909 | CtReq->un.gid.Fc4Type = SLI_CTPT_FCP; |
681 | if (vport->port_state < LPFC_VPORT_READY) | 910 | if (vport->port_state < LPFC_NS_QRY) |
682 | vport->port_state = LPFC_NS_QRY; | 911 | vport->port_state = LPFC_NS_QRY; |
683 | lpfc_set_disctmo(vport); | 912 | lpfc_set_disctmo(vport); |
684 | cmpl = lpfc_cmpl_ct_cmd_gid_ft; | 913 | cmpl = lpfc_cmpl_ct_cmd_gid_ft; |
685 | rsp_size = FC_MAX_NS_RSP; | 914 | rsp_size = FC_MAX_NS_RSP; |
686 | break; | 915 | break; |
687 | 916 | ||
917 | case SLI_CTNS_GFF_ID: | ||
918 | CtReq->CommandResponse.bits.CmdRsp = | ||
919 | be16_to_cpu(SLI_CTNS_GFF_ID); | ||
920 | CtReq->un.gff.PortId = be32_to_cpu(context); | ||
921 | cmpl = lpfc_cmpl_ct_cmd_gff_id; | ||
922 | break; | ||
923 | |||
688 | case SLI_CTNS_RFT_ID: | 924 | case SLI_CTNS_RFT_ID: |
689 | CtReq->CommandResponse.bits.CmdRsp = | 925 | CtReq->CommandResponse.bits.CmdRsp = |
690 | be16_to_cpu(SLI_CTNS_RFT_ID); | 926 | be16_to_cpu(SLI_CTNS_RFT_ID); |
@@ -693,17 +929,6 @@ lpfc_ns_cmd(struct lpfc_vport *vport, struct lpfc_nodelist * ndlp, int cmdcode) | |||
693 | cmpl = lpfc_cmpl_ct_cmd_rft_id; | 929 | cmpl = lpfc_cmpl_ct_cmd_rft_id; |
694 | break; | 930 | break; |
695 | 931 | ||
696 | case SLI_CTNS_RFF_ID: | ||
697 | CtReq->CommandResponse.bits.CmdRsp = | ||
698 | be16_to_cpu(SLI_CTNS_RFF_ID); | ||
699 | CtReq->un.rff.PortId = be32_to_cpu(vport->fc_myDID); | ||
700 | CtReq->un.rff.feature_res = 0; | ||
701 | CtReq->un.rff.feature_tgt = 0; | ||
702 | CtReq->un.rff.type_code = FC_FCP_DATA; | ||
703 | CtReq->un.rff.feature_init = 1; | ||
704 | cmpl = lpfc_cmpl_ct_cmd_rff_id; | ||
705 | break; | ||
706 | |||
707 | case SLI_CTNS_RNN_ID: | 932 | case SLI_CTNS_RNN_ID: |
708 | CtReq->CommandResponse.bits.CmdRsp = | 933 | CtReq->CommandResponse.bits.CmdRsp = |
709 | be16_to_cpu(SLI_CTNS_RNN_ID); | 934 | be16_to_cpu(SLI_CTNS_RNN_ID); |
@@ -713,18 +938,39 @@ lpfc_ns_cmd(struct lpfc_vport *vport, struct lpfc_nodelist * ndlp, int cmdcode) | |||
713 | cmpl = lpfc_cmpl_ct_cmd_rnn_id; | 938 | cmpl = lpfc_cmpl_ct_cmd_rnn_id; |
714 | break; | 939 | break; |
715 | 940 | ||
941 | case SLI_CTNS_RSPN_ID: | ||
942 | CtReq->CommandResponse.bits.CmdRsp = | ||
943 | be16_to_cpu(SLI_CTNS_RSPN_ID); | ||
944 | CtReq->un.rspn.PortId = be32_to_cpu(vport->fc_myDID); | ||
945 | size = sizeof(CtReq->un.rspn.symbname); | ||
946 | CtReq->un.rspn.len = | ||
947 | lpfc_vport_symbolic_port_name(vport, | ||
948 | CtReq->un.rspn.symbname, size); | ||
949 | cmpl = lpfc_cmpl_ct_cmd_rspn_id; | ||
950 | break; | ||
716 | case SLI_CTNS_RSNN_NN: | 951 | case SLI_CTNS_RSNN_NN: |
717 | CtReq->CommandResponse.bits.CmdRsp = | 952 | CtReq->CommandResponse.bits.CmdRsp = |
718 | be16_to_cpu(SLI_CTNS_RSNN_NN); | 953 | be16_to_cpu(SLI_CTNS_RSNN_NN); |
719 | memcpy(CtReq->un.rsnn.wwnn, &vport->fc_nodename, | 954 | memcpy(CtReq->un.rsnn.wwnn, &vport->fc_nodename, |
720 | sizeof (struct lpfc_name)); | 955 | sizeof (struct lpfc_name)); |
721 | lpfc_get_hba_sym_node_name(phba, CtReq->un.rsnn.symbname); | 956 | size = sizeof(CtReq->un.rsnn.symbname); |
722 | CtReq->un.rsnn.len = strlen(CtReq->un.rsnn.symbname); | 957 | CtReq->un.rsnn.len = |
958 | lpfc_vport_symbolic_node_name(vport, | ||
959 | CtReq->un.rsnn.symbname, size); | ||
723 | cmpl = lpfc_cmpl_ct_cmd_rsnn_nn; | 960 | cmpl = lpfc_cmpl_ct_cmd_rsnn_nn; |
724 | break; | 961 | break; |
962 | case SLI_CTNS_RFF_ID: | ||
963 | vport->fc_flag &= ~FC_RFF_NOT_SUPPORTED; | ||
964 | CtReq->CommandResponse.bits.CmdRsp = | ||
965 | be16_to_cpu(SLI_CTNS_RFF_ID); | ||
966 | CtReq->un.rff.PortId = be32_to_cpu(vport->fc_myDID);; | ||
967 | CtReq->un.rff.fbits = FC4_FEATURE_INIT; | ||
968 | CtReq->un.rff.type_code = FC_FCP_DATA; | ||
969 | cmpl = lpfc_cmpl_ct_cmd_rff_id; | ||
970 | break; | ||
725 | } | 971 | } |
726 | 972 | ||
727 | if (!lpfc_ct_cmd(vport, mp, bmp, ndlp, cmpl, rsp_size)) | 973 | if (!lpfc_ct_cmd(vport, mp, bmp, ndlp, cmpl, rsp_size, retry)) |
728 | /* On success, The cmpl function will free the buffers */ | 974 | /* On success, The cmpl function will free the buffers */ |
729 | return 0; | 975 | return 0; |
730 | 976 | ||
@@ -757,8 +1003,9 @@ lpfc_cmpl_ct_cmd_fdmi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
757 | if (fdmi_rsp == be16_to_cpu(SLI_CT_RESPONSE_FS_RJT)) { | 1003 | if (fdmi_rsp == be16_to_cpu(SLI_CT_RESPONSE_FS_RJT)) { |
758 | /* FDMI rsp failed */ | 1004 | /* FDMI rsp failed */ |
759 | lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, | 1005 | lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, |
760 | "%d:0220 FDMI rsp failed Data: x%x\n", | 1006 | "%d (%d):0220 FDMI rsp failed Data: x%x\n", |
761 | phba->brd_no, be16_to_cpu(fdmi_cmd)); | 1007 | phba->brd_no, vport->vpi, |
1008 | be16_to_cpu(fdmi_cmd)); | ||
762 | } | 1009 | } |
763 | 1010 | ||
764 | switch (be16_to_cpu(fdmi_cmd)) { | 1011 | switch (be16_to_cpu(fdmi_cmd)) { |
@@ -828,9 +1075,9 @@ lpfc_fdmi_cmd(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, int cmdcode) | |||
828 | 1075 | ||
829 | /* FDMI request */ | 1076 | /* FDMI request */ |
830 | lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, | 1077 | lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, |
831 | "%d:0218 FDMI Request Data: x%x x%x x%x\n", | 1078 | "%d (%d):0218 FDMI Request Data: x%x x%x x%x\n", |
832 | phba->brd_no, | 1079 | phba->brd_no, vport->vpi, vport->fc_flag, |
833 | vport->fc_flag, vport->port_state, cmdcode); | 1080 | vport->port_state, cmdcode); |
834 | 1081 | ||
835 | CtReq = (struct lpfc_sli_ct_request *) mp->virt; | 1082 | CtReq = (struct lpfc_sli_ct_request *) mp->virt; |
836 | 1083 | ||
@@ -1134,15 +1381,15 @@ lpfc_fdmi_cmd(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, int cmdcode) | |||
1134 | } | 1381 | } |
1135 | 1382 | ||
1136 | bpl = (struct ulp_bde64 *) bmp->virt; | 1383 | bpl = (struct ulp_bde64 *) bmp->virt; |
1137 | bpl->addrHigh = le32_to_cpu( putPaddrHigh(mp->phys) ); | 1384 | bpl->addrHigh = le32_to_cpu(putPaddrHigh(mp->phys) ); |
1138 | bpl->addrLow = le32_to_cpu( putPaddrLow(mp->phys) ); | 1385 | bpl->addrLow = le32_to_cpu(putPaddrLow(mp->phys) ); |
1139 | bpl->tus.f.bdeFlags = 0; | 1386 | bpl->tus.f.bdeFlags = 0; |
1140 | bpl->tus.f.bdeSize = size; | 1387 | bpl->tus.f.bdeSize = size; |
1141 | bpl->tus.w = le32_to_cpu(bpl->tus.w); | 1388 | bpl->tus.w = le32_to_cpu(bpl->tus.w); |
1142 | 1389 | ||
1143 | cmpl = lpfc_cmpl_ct_cmd_fdmi; | 1390 | cmpl = lpfc_cmpl_ct_cmd_fdmi; |
1144 | 1391 | ||
1145 | if (!lpfc_ct_cmd(vport, mp, bmp, ndlp, cmpl, FC_MAX_NS_RSP)) | 1392 | if (!lpfc_ct_cmd(vport, mp, bmp, ndlp, cmpl, FC_MAX_NS_RSP, 0)) |
1146 | return 0; | 1393 | return 0; |
1147 | 1394 | ||
1148 | lpfc_mbuf_free(phba, bmp->virt, bmp->phys); | 1395 | lpfc_mbuf_free(phba, bmp->virt, bmp->phys); |
@@ -1155,8 +1402,8 @@ fdmi_cmd_free_mp: | |||
1155 | fdmi_cmd_exit: | 1402 | fdmi_cmd_exit: |
1156 | /* Issue FDMI request failed */ | 1403 | /* Issue FDMI request failed */ |
1157 | lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, | 1404 | lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY, |
1158 | "%d:0244 Issue FDMI request failed Data: x%x\n", | 1405 | "%d (%d):0244 Issue FDMI request failed Data: x%x\n", |
1159 | phba->brd_no, cmdcode); | 1406 | phba->brd_no, vport->vpi, cmdcode); |
1160 | return 1; | 1407 | return 1; |
1161 | } | 1408 | } |
1162 | 1409 | ||
@@ -1170,10 +1417,15 @@ lpfc_fdmi_tmo(unsigned long ptr) | |||
1170 | spin_lock_irqsave(&vport->work_port_lock, iflag); | 1417 | spin_lock_irqsave(&vport->work_port_lock, iflag); |
1171 | if (!(vport->work_port_events & WORKER_FDMI_TMO)) { | 1418 | if (!(vport->work_port_events & WORKER_FDMI_TMO)) { |
1172 | vport->work_port_events |= WORKER_FDMI_TMO; | 1419 | vport->work_port_events |= WORKER_FDMI_TMO; |
1420 | spin_unlock_irqrestore(&vport->work_port_lock, iflag); | ||
1421 | |||
1422 | spin_lock_irqsave(&phba->hbalock, iflag); | ||
1173 | if (phba->work_wait) | 1423 | if (phba->work_wait) |
1174 | wake_up(phba->work_wait); | 1424 | lpfc_worker_wake_up(phba); |
1425 | spin_unlock_irqrestore(&phba->hbalock, iflag); | ||
1175 | } | 1426 | } |
1176 | spin_unlock_irqrestore(&vport->work_port_lock, iflag); | 1427 | else |
1428 | spin_unlock_irqrestore(&vport->work_port_lock, iflag); | ||
1177 | } | 1429 | } |
1178 | 1430 | ||
1179 | void | 1431 | void |