| .. | .. |
|---|
| 1 | 1 | /******************************************************************* |
|---|
| 2 | 2 | * This file is part of the Emulex Linux Device Driver for * |
|---|
| 3 | 3 | * Fibre Channel Host Bus Adapters. * |
|---|
| 4 | | - * Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term * |
|---|
| 4 | + * Copyright (C) 2017-2020 Broadcom. All Rights Reserved. The term * |
|---|
| 5 | 5 | * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. * |
|---|
| 6 | 6 | * Copyright (C) 2004-2016 Emulex. All rights reserved. * |
|---|
| 7 | 7 | * EMULEX and SLI are trademarks of Emulex. * |
|---|
| .. | .. |
|---|
| 30 | 30 | #include <scsi/scsi_device.h> |
|---|
| 31 | 31 | #include <scsi/scsi_host.h> |
|---|
| 32 | 32 | #include <scsi/scsi_transport_fc.h> |
|---|
| 33 | +#include <uapi/scsi/fc/fc_fs.h> |
|---|
| 34 | +#include <uapi/scsi/fc/fc_els.h> |
|---|
| 33 | 35 | |
|---|
| 34 | 36 | #include "lpfc_hw4.h" |
|---|
| 35 | 37 | #include "lpfc_hw.h" |
|---|
| .. | .. |
|---|
| 98 | 100 | return 0; |
|---|
| 99 | 101 | |
|---|
| 100 | 102 | /* Pending Link Event during Discovery */ |
|---|
| 101 | | - lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY, |
|---|
| 103 | + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, |
|---|
| 102 | 104 | "0237 Pending Link Event during " |
|---|
| 103 | 105 | "Discovery: State x%x\n", |
|---|
| 104 | 106 | phba->pport->port_state); |
|---|
| .. | .. |
|---|
| 315 | 317 | /* Xmit ELS command <elsCmd> to remote NPORT <did> */ |
|---|
| 316 | 318 | lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, |
|---|
| 317 | 319 | "0116 Xmit ELS command x%x to remote " |
|---|
| 318 | | - "NPORT x%x I/O tag: x%x, port state:x%x" |
|---|
| 319 | | - " fc_flag:x%x\n", |
|---|
| 320 | + "NPORT x%x I/O tag: x%x, port state:x%x " |
|---|
| 321 | + "rpi x%x fc_flag:x%x\n", |
|---|
| 320 | 322 | elscmd, did, elsiocb->iotag, |
|---|
| 321 | | - vport->port_state, |
|---|
| 323 | + vport->port_state, ndlp->nlp_rpi, |
|---|
| 322 | 324 | vport->fc_flag); |
|---|
| 323 | 325 | } else { |
|---|
| 324 | 326 | /* Xmit ELS response <elsCmd> to remote NPORT <did> */ |
|---|
| 325 | 327 | lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, |
|---|
| 326 | 328 | "0117 Xmit ELS response x%x to remote " |
|---|
| 327 | 329 | "NPORT x%x I/O tag: x%x, size: x%x " |
|---|
| 328 | | - "port_state x%x fc_flag x%x\n", |
|---|
| 330 | + "port_state x%x rpi x%x fc_flag x%x\n", |
|---|
| 329 | 331 | elscmd, ndlp->nlp_DID, elsiocb->iotag, |
|---|
| 330 | 332 | cmdSize, vport->port_state, |
|---|
| 331 | | - vport->fc_flag); |
|---|
| 333 | + ndlp->nlp_rpi, vport->fc_flag); |
|---|
| 332 | 334 | } |
|---|
| 333 | 335 | return elsiocb; |
|---|
| 334 | 336 | |
|---|
| .. | .. |
|---|
| 415 | 417 | /* increment the reference count on ndlp to hold reference |
|---|
| 416 | 418 | * for the callback routine. |
|---|
| 417 | 419 | */ |
|---|
| 418 | | - mbox->context2 = lpfc_nlp_get(ndlp); |
|---|
| 420 | + mbox->ctx_ndlp = lpfc_nlp_get(ndlp); |
|---|
| 419 | 421 | |
|---|
| 420 | 422 | rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT); |
|---|
| 421 | 423 | if (rc == MBX_NOT_FINISHED) { |
|---|
| .. | .. |
|---|
| 430 | 432 | * for the failed mbox command. |
|---|
| 431 | 433 | */ |
|---|
| 432 | 434 | lpfc_nlp_put(ndlp); |
|---|
| 433 | | - mp = (struct lpfc_dmabuf *) mbox->context1; |
|---|
| 435 | + mp = (struct lpfc_dmabuf *)mbox->ctx_buf; |
|---|
| 434 | 436 | lpfc_mbuf_free(phba, mp->virt, mp->phys); |
|---|
| 435 | 437 | kfree(mp); |
|---|
| 436 | 438 | fail_free_mbox: |
|---|
| .. | .. |
|---|
| 438 | 440 | |
|---|
| 439 | 441 | fail: |
|---|
| 440 | 442 | lpfc_vport_set_state(vport, FC_VPORT_FAILED); |
|---|
| 441 | | - lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, |
|---|
| 442 | | - "0249 Cannot issue Register Fabric login: Err %d\n", err); |
|---|
| 443 | + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, |
|---|
| 444 | + "0249 Cannot issue Register Fabric login: Err %d\n", |
|---|
| 445 | + err); |
|---|
| 443 | 446 | return -ENXIO; |
|---|
| 444 | 447 | } |
|---|
| 445 | 448 | |
|---|
| .. | .. |
|---|
| 504 | 507 | |
|---|
| 505 | 508 | mboxq->mbox_cmpl = lpfc_mbx_cmpl_reg_vfi; |
|---|
| 506 | 509 | mboxq->vport = vport; |
|---|
| 507 | | - mboxq->context1 = dmabuf; |
|---|
| 510 | + mboxq->ctx_buf = dmabuf; |
|---|
| 508 | 511 | rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_NOWAIT); |
|---|
| 509 | 512 | if (rc == MBX_NOT_FINISHED) { |
|---|
| 510 | 513 | rc = -ENXIO; |
|---|
| .. | .. |
|---|
| 522 | 525 | } |
|---|
| 523 | 526 | |
|---|
| 524 | 527 | lpfc_vport_set_state(vport, FC_VPORT_FAILED); |
|---|
| 525 | | - lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, |
|---|
| 526 | | - "0289 Issue Register VFI failed: Err %d\n", rc); |
|---|
| 528 | + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, |
|---|
| 529 | + "0289 Issue Register VFI failed: Err %d\n", rc); |
|---|
| 527 | 530 | return rc; |
|---|
| 528 | 531 | } |
|---|
| 529 | 532 | |
|---|
| .. | .. |
|---|
| 548 | 551 | |
|---|
| 549 | 552 | mboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); |
|---|
| 550 | 553 | if (!mboxq) { |
|---|
| 551 | | - lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY|LOG_MBOX, |
|---|
| 554 | + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, |
|---|
| 552 | 555 | "2556 UNREG_VFI mbox allocation failed" |
|---|
| 553 | 556 | "HBA state x%x\n", phba->pport->port_state); |
|---|
| 554 | 557 | return -ENOMEM; |
|---|
| .. | .. |
|---|
| 560 | 563 | |
|---|
| 561 | 564 | rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_NOWAIT); |
|---|
| 562 | 565 | if (rc == MBX_NOT_FINISHED) { |
|---|
| 563 | | - lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY|LOG_MBOX, |
|---|
| 566 | + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, |
|---|
| 564 | 567 | "2557 UNREG_VFI issue mbox failed rc x%x " |
|---|
| 565 | 568 | "HBA state x%x\n", |
|---|
| 566 | 569 | rc, phba->pport->port_state); |
|---|
| .. | .. |
|---|
| 1039 | 1042 | if (!(irsp->ulpStatus == IOSTAT_LOCAL_REJECT && |
|---|
| 1040 | 1043 | ((irsp->un.ulpWord[4] & IOERR_PARAM_MASK) == |
|---|
| 1041 | 1044 | IOERR_LOOP_OPEN_FAILURE))) |
|---|
| 1042 | | - lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, |
|---|
| 1043 | | - "2858 FLOGI failure Status:x%x/x%x " |
|---|
| 1044 | | - "TMO:x%x Data x%x x%x\n", |
|---|
| 1045 | | - irsp->ulpStatus, irsp->un.ulpWord[4], |
|---|
| 1046 | | - irsp->ulpTimeout, phba->hba_flag, |
|---|
| 1047 | | - phba->fcf.fcf_flag); |
|---|
| 1045 | + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, |
|---|
| 1046 | + "2858 FLOGI failure Status:x%x/x%x TMO" |
|---|
| 1047 | + ":x%x Data x%x x%x\n", |
|---|
| 1048 | + irsp->ulpStatus, irsp->un.ulpWord[4], |
|---|
| 1049 | + irsp->ulpTimeout, phba->hba_flag, |
|---|
| 1050 | + phba->fcf.fcf_flag); |
|---|
| 1048 | 1051 | |
|---|
| 1049 | 1052 | /* Check for retry */ |
|---|
| 1050 | 1053 | if (lpfc_els_retry(phba, cmdiocb, rspiocb)) |
|---|
| 1051 | 1054 | goto out; |
|---|
| 1055 | + |
|---|
| 1056 | + lpfc_printf_vlog(vport, KERN_WARNING, LOG_TRACE_EVENT, |
|---|
| 1057 | + "0150 FLOGI failure Status:x%x/x%x " |
|---|
| 1058 | + "xri x%x TMO:x%x\n", |
|---|
| 1059 | + irsp->ulpStatus, irsp->un.ulpWord[4], |
|---|
| 1060 | + cmdiocb->sli4_xritag, irsp->ulpTimeout); |
|---|
| 1052 | 1061 | |
|---|
| 1053 | 1062 | /* If this is not a loop open failure, bail out */ |
|---|
| 1054 | 1063 | if (!(irsp->ulpStatus == IOSTAT_LOCAL_REJECT && |
|---|
| .. | .. |
|---|
| 1056 | 1065 | IOERR_LOOP_OPEN_FAILURE))) |
|---|
| 1057 | 1066 | goto flogifail; |
|---|
| 1058 | 1067 | |
|---|
| 1059 | | - lpfc_printf_vlog(vport, KERN_WARNING, LOG_ELS, |
|---|
| 1060 | | - "0150 FLOGI failure Status:x%x/x%x xri x%x TMO:x%x\n", |
|---|
| 1061 | | - irsp->ulpStatus, irsp->un.ulpWord[4], |
|---|
| 1062 | | - cmdiocb->sli4_xritag, irsp->ulpTimeout); |
|---|
| 1063 | | - |
|---|
| 1064 | 1068 | /* FLOGI failed, so there is no fabric */ |
|---|
| 1065 | 1069 | spin_lock_irq(shost->host_lock); |
|---|
| 1066 | | - vport->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP); |
|---|
| 1070 | + vport->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP | |
|---|
| 1071 | + FC_PT2PT_NO_NVME); |
|---|
| 1067 | 1072 | spin_unlock_irq(shost->host_lock); |
|---|
| 1068 | 1073 | |
|---|
| 1069 | 1074 | /* If private loop, then allow max outstanding els to be |
|---|
| .. | .. |
|---|
| 1129 | 1134 | else if (!(phba->hba_flag & HBA_FCOE_MODE)) |
|---|
| 1130 | 1135 | rc = lpfc_cmpl_els_flogi_nport(vport, ndlp, sp); |
|---|
| 1131 | 1136 | else { |
|---|
| 1132 | | - lpfc_printf_vlog(vport, KERN_ERR, |
|---|
| 1133 | | - LOG_FIP | LOG_ELS, |
|---|
| 1137 | + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, |
|---|
| 1134 | 1138 | "2831 FLOGI response with cleared Fabric " |
|---|
| 1135 | 1139 | "bit fcf_index 0x%x " |
|---|
| 1136 | 1140 | "Switch Name %02x%02x%02x%02x%02x%02x%02x%02x " |
|---|
| .. | .. |
|---|
| 1214 | 1218 | } |
|---|
| 1215 | 1219 | |
|---|
| 1216 | 1220 | /** |
|---|
| 1221 | + * lpfc_cmpl_els_link_down - Completion callback function for ELS command |
|---|
| 1222 | + * aborted during a link down |
|---|
| 1223 | + * @phba: pointer to lpfc hba data structure. |
|---|
| 1224 | + * @cmdiocb: pointer to lpfc command iocb data structure. |
|---|
| 1225 | + * @rspiocb: pointer to lpfc response iocb data structure. |
|---|
| 1226 | + * |
|---|
| 1227 | + */ |
|---|
| 1228 | +static void |
|---|
| 1229 | +lpfc_cmpl_els_link_down(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, |
|---|
| 1230 | + struct lpfc_iocbq *rspiocb) |
|---|
| 1231 | +{ |
|---|
| 1232 | + IOCB_t *irsp; |
|---|
| 1233 | + uint32_t *pcmd; |
|---|
| 1234 | + uint32_t cmd; |
|---|
| 1235 | + |
|---|
| 1236 | + pcmd = (uint32_t *)(((struct lpfc_dmabuf *)cmdiocb->context2)->virt); |
|---|
| 1237 | + cmd = *pcmd; |
|---|
| 1238 | + irsp = &rspiocb->iocb; |
|---|
| 1239 | + |
|---|
| 1240 | + lpfc_printf_log(phba, KERN_INFO, LOG_ELS, |
|---|
| 1241 | + "6445 ELS completes after LINK_DOWN: " |
|---|
| 1242 | + " Status %x/%x cmd x%x flg x%x\n", |
|---|
| 1243 | + irsp->ulpStatus, irsp->un.ulpWord[4], cmd, |
|---|
| 1244 | + cmdiocb->iocb_flag); |
|---|
| 1245 | + |
|---|
| 1246 | + if (cmdiocb->iocb_flag & LPFC_IO_FABRIC) { |
|---|
| 1247 | + cmdiocb->iocb_flag &= ~LPFC_IO_FABRIC; |
|---|
| 1248 | + atomic_dec(&phba->fabric_iocb_count); |
|---|
| 1249 | + } |
|---|
| 1250 | + lpfc_els_free_iocb(phba, cmdiocb); |
|---|
| 1251 | +} |
|---|
| 1252 | + |
|---|
| 1253 | +/** |
|---|
| 1217 | 1254 | * lpfc_issue_els_flogi - Issue an flogi iocb command for a vport |
|---|
| 1218 | 1255 | * @vport: pointer to a host virtual N_Port data structure. |
|---|
| 1219 | 1256 | * @ndlp: pointer to a node-list data structure. |
|---|
| .. | .. |
|---|
| 1243 | 1280 | struct serv_parm *sp; |
|---|
| 1244 | 1281 | IOCB_t *icmd; |
|---|
| 1245 | 1282 | struct lpfc_iocbq *elsiocb; |
|---|
| 1283 | + struct lpfc_iocbq defer_flogi_acc; |
|---|
| 1246 | 1284 | uint8_t *pcmd; |
|---|
| 1247 | 1285 | uint16_t cmdsize; |
|---|
| 1248 | | - uint32_t tmo; |
|---|
| 1286 | + uint32_t tmo, did; |
|---|
| 1249 | 1287 | int rc; |
|---|
| 1250 | 1288 | |
|---|
| 1251 | 1289 | cmdsize = (sizeof(uint32_t) + sizeof(struct serv_parm)); |
|---|
| .. | .. |
|---|
| 1317 | 1355 | phba->sli3_options, 0, 0); |
|---|
| 1318 | 1356 | |
|---|
| 1319 | 1357 | rc = lpfc_issue_fabric_iocb(phba, elsiocb); |
|---|
| 1358 | + |
|---|
| 1359 | + phba->hba_flag |= HBA_FLOGI_ISSUED; |
|---|
| 1360 | + |
|---|
| 1361 | + /* Check for a deferred FLOGI ACC condition */ |
|---|
| 1362 | + if (phba->defer_flogi_acc_flag) { |
|---|
| 1363 | + did = vport->fc_myDID; |
|---|
| 1364 | + vport->fc_myDID = Fabric_DID; |
|---|
| 1365 | + |
|---|
| 1366 | + memset(&defer_flogi_acc, 0, sizeof(struct lpfc_iocbq)); |
|---|
| 1367 | + |
|---|
| 1368 | + defer_flogi_acc.iocb.ulpContext = phba->defer_flogi_acc_rx_id; |
|---|
| 1369 | + defer_flogi_acc.iocb.unsli3.rcvsli3.ox_id = |
|---|
| 1370 | + phba->defer_flogi_acc_ox_id; |
|---|
| 1371 | + |
|---|
| 1372 | + lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, |
|---|
| 1373 | + "3354 Xmit deferred FLOGI ACC: rx_id: x%x," |
|---|
| 1374 | + " ox_id: x%x, hba_flag x%x\n", |
|---|
| 1375 | + phba->defer_flogi_acc_rx_id, |
|---|
| 1376 | + phba->defer_flogi_acc_ox_id, phba->hba_flag); |
|---|
| 1377 | + |
|---|
| 1378 | + /* Send deferred FLOGI ACC */ |
|---|
| 1379 | + lpfc_els_rsp_acc(vport, ELS_CMD_FLOGI, &defer_flogi_acc, |
|---|
| 1380 | + ndlp, NULL); |
|---|
| 1381 | + |
|---|
| 1382 | + phba->defer_flogi_acc_flag = false; |
|---|
| 1383 | + |
|---|
| 1384 | + vport->fc_myDID = did; |
|---|
| 1385 | + } |
|---|
| 1386 | + |
|---|
| 1320 | 1387 | if (rc == IOCB_ERROR) { |
|---|
| 1321 | 1388 | lpfc_els_free_iocb(phba, elsiocb); |
|---|
| 1322 | 1389 | return 1; |
|---|
| .. | .. |
|---|
| 1547 | 1614 | struct serv_parm *sp; |
|---|
| 1548 | 1615 | uint8_t name[sizeof(struct lpfc_name)]; |
|---|
| 1549 | 1616 | uint32_t rc, keepDID = 0, keep_nlp_flag = 0; |
|---|
| 1617 | + uint32_t keep_new_nlp_flag = 0; |
|---|
| 1550 | 1618 | uint16_t keep_nlp_state; |
|---|
| 1619 | + u32 keep_nlp_fc4_type = 0; |
|---|
| 1551 | 1620 | struct lpfc_nvme_rport *keep_nrport = NULL; |
|---|
| 1552 | 1621 | int put_node; |
|---|
| 1553 | 1622 | int put_rport; |
|---|
| .. | .. |
|---|
| 1639 | 1708 | * would have updated nlp_fc4_type in ndlp, so we must ensure |
|---|
| 1640 | 1709 | * new_ndlp has the right value. |
|---|
| 1641 | 1710 | */ |
|---|
| 1642 | | - if (vport->fc_flag & FC_FABRIC) |
|---|
| 1711 | + if (vport->fc_flag & FC_FABRIC) { |
|---|
| 1712 | + keep_nlp_fc4_type = new_ndlp->nlp_fc4_type; |
|---|
| 1643 | 1713 | new_ndlp->nlp_fc4_type = ndlp->nlp_fc4_type; |
|---|
| 1714 | + } |
|---|
| 1644 | 1715 | |
|---|
| 1645 | 1716 | lpfc_unreg_rpi(vport, new_ndlp); |
|---|
| 1646 | 1717 | new_ndlp->nlp_DID = ndlp->nlp_DID; |
|---|
| .. | .. |
|---|
| 1651 | 1722 | phba->cfg_rrq_xri_bitmap_sz); |
|---|
| 1652 | 1723 | |
|---|
| 1653 | 1724 | spin_lock_irq(shost->host_lock); |
|---|
| 1654 | | - keep_nlp_flag = new_ndlp->nlp_flag; |
|---|
| 1725 | + keep_new_nlp_flag = new_ndlp->nlp_flag; |
|---|
| 1726 | + keep_nlp_flag = ndlp->nlp_flag; |
|---|
| 1655 | 1727 | new_ndlp->nlp_flag = ndlp->nlp_flag; |
|---|
| 1656 | | - ndlp->nlp_flag = keep_nlp_flag; |
|---|
| 1728 | + |
|---|
| 1729 | + /* if new_ndlp had NLP_UNREG_INP set, keep it */ |
|---|
| 1730 | + if (keep_new_nlp_flag & NLP_UNREG_INP) |
|---|
| 1731 | + new_ndlp->nlp_flag |= NLP_UNREG_INP; |
|---|
| 1732 | + else |
|---|
| 1733 | + new_ndlp->nlp_flag &= ~NLP_UNREG_INP; |
|---|
| 1734 | + |
|---|
| 1735 | + /* if new_ndlp had NLP_RPI_REGISTERED set, keep it */ |
|---|
| 1736 | + if (keep_new_nlp_flag & NLP_RPI_REGISTERED) |
|---|
| 1737 | + new_ndlp->nlp_flag |= NLP_RPI_REGISTERED; |
|---|
| 1738 | + else |
|---|
| 1739 | + new_ndlp->nlp_flag &= ~NLP_RPI_REGISTERED; |
|---|
| 1740 | + |
|---|
| 1741 | + ndlp->nlp_flag = keep_new_nlp_flag; |
|---|
| 1742 | + |
|---|
| 1743 | + /* if ndlp had NLP_UNREG_INP set, keep it */ |
|---|
| 1744 | + if (keep_nlp_flag & NLP_UNREG_INP) |
|---|
| 1745 | + ndlp->nlp_flag |= NLP_UNREG_INP; |
|---|
| 1746 | + else |
|---|
| 1747 | + ndlp->nlp_flag &= ~NLP_UNREG_INP; |
|---|
| 1748 | + |
|---|
| 1749 | + /* if ndlp had NLP_RPI_REGISTERED set, keep it */ |
|---|
| 1750 | + if (keep_nlp_flag & NLP_RPI_REGISTERED) |
|---|
| 1751 | + ndlp->nlp_flag |= NLP_RPI_REGISTERED; |
|---|
| 1752 | + else |
|---|
| 1753 | + ndlp->nlp_flag &= ~NLP_RPI_REGISTERED; |
|---|
| 1754 | + |
|---|
| 1657 | 1755 | spin_unlock_irq(shost->host_lock); |
|---|
| 1658 | 1756 | |
|---|
| 1659 | 1757 | /* Set nlp_states accordingly */ |
|---|
| .. | .. |
|---|
| 1703 | 1801 | spin_unlock_irq(&phba->ndlp_lock); |
|---|
| 1704 | 1802 | } |
|---|
| 1705 | 1803 | |
|---|
| 1706 | | - /* Two ndlps cannot have the same did on the nodelist */ |
|---|
| 1804 | + /* Two ndlps cannot have the same did on the nodelist. |
|---|
| 1805 | + * Note: for this case, ndlp has a NULL WWPN so setting |
|---|
| 1806 | + * the nlp_fc4_type isn't required. |
|---|
| 1807 | + */ |
|---|
| 1707 | 1808 | ndlp->nlp_DID = keepDID; |
|---|
| 1708 | 1809 | lpfc_nlp_set_state(vport, ndlp, keep_nlp_state); |
|---|
| 1709 | 1810 | if (phba->sli_rev == LPFC_SLI_REV4 && |
|---|
| .. | .. |
|---|
| 1722 | 1823 | |
|---|
| 1723 | 1824 | lpfc_unreg_rpi(vport, ndlp); |
|---|
| 1724 | 1825 | |
|---|
| 1725 | | - /* Two ndlps cannot have the same did */ |
|---|
| 1826 | + /* Two ndlps cannot have the same did and the fc4 |
|---|
| 1827 | + * type must be transferred because the ndlp is in |
|---|
| 1828 | + * flight. |
|---|
| 1829 | + */ |
|---|
| 1726 | 1830 | ndlp->nlp_DID = keepDID; |
|---|
| 1831 | + ndlp->nlp_fc4_type = keep_nlp_fc4_type; |
|---|
| 1832 | + |
|---|
| 1727 | 1833 | if (phba->sli_rev == LPFC_SLI_REV4 && |
|---|
| 1728 | 1834 | active_rrqs_xri_bitmap) |
|---|
| 1729 | 1835 | memcpy(ndlp->active_rrqs_xri_bitmap, |
|---|
| .. | .. |
|---|
| 1838 | 1944 | |
|---|
| 1839 | 1945 | ndlp = lpfc_findnode_did(vport, irsp->un.elsreq64.remoteID); |
|---|
| 1840 | 1946 | if (!ndlp || !NLP_CHK_NODE_ACT(ndlp) || ndlp != rrq->ndlp) { |
|---|
| 1841 | | - lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, |
|---|
| 1947 | + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, |
|---|
| 1842 | 1948 | "2882 RRQ completes to NPort x%x " |
|---|
| 1843 | 1949 | "with no ndlp. Data: x%x x%x x%x\n", |
|---|
| 1844 | 1950 | irsp->un.elsreq64.remoteID, |
|---|
| .. | .. |
|---|
| 1861 | 1967 | (((irsp->un.ulpWord[4]) >> 16 != LSRJT_INVALID_CMD) && |
|---|
| 1862 | 1968 | ((irsp->un.ulpWord[4]) >> 16 != LSRJT_UNABLE_TPC)) || |
|---|
| 1863 | 1969 | (phba)->pport->cfg_log_verbose & LOG_ELS) |
|---|
| 1864 | | - lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, |
|---|
| 1865 | | - "2881 RRQ failure DID:%06X Status:x%x/x%x\n", |
|---|
| 1866 | | - ndlp->nlp_DID, irsp->ulpStatus, |
|---|
| 1867 | | - irsp->un.ulpWord[4]); |
|---|
| 1970 | + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, |
|---|
| 1971 | + "2881 RRQ failure DID:%06X Status:" |
|---|
| 1972 | + "x%x/x%x\n", |
|---|
| 1973 | + ndlp->nlp_DID, irsp->ulpStatus, |
|---|
| 1974 | + irsp->un.ulpWord[4]); |
|---|
| 1868 | 1975 | } |
|---|
| 1869 | 1976 | out: |
|---|
| 1870 | 1977 | if (rrq) |
|---|
| .. | .. |
|---|
| 1901 | 2008 | IOCB_t *irsp; |
|---|
| 1902 | 2009 | struct lpfc_nodelist *ndlp; |
|---|
| 1903 | 2010 | struct lpfc_dmabuf *prsp; |
|---|
| 1904 | | - int disc, rc; |
|---|
| 2011 | + int disc; |
|---|
| 1905 | 2012 | |
|---|
| 1906 | 2013 | /* we pass cmdiocb to state machine which needs rspiocb as well */ |
|---|
| 1907 | 2014 | cmdiocb->context_un.rsp_iocb = rspiocb; |
|---|
| .. | .. |
|---|
| 1914 | 2021 | |
|---|
| 1915 | 2022 | ndlp = lpfc_findnode_did(vport, irsp->un.elsreq64.remoteID); |
|---|
| 1916 | 2023 | if (!ndlp || !NLP_CHK_NODE_ACT(ndlp)) { |
|---|
| 1917 | | - lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, |
|---|
| 2024 | + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, |
|---|
| 1918 | 2025 | "0136 PLOGI completes to NPort x%x " |
|---|
| 1919 | 2026 | "with no ndlp. Data: x%x x%x x%x\n", |
|---|
| 1920 | 2027 | irsp->un.elsreq64.remoteID, |
|---|
| .. | .. |
|---|
| 1930 | 2037 | disc = (ndlp->nlp_flag & NLP_NPR_2B_DISC); |
|---|
| 1931 | 2038 | ndlp->nlp_flag &= ~NLP_NPR_2B_DISC; |
|---|
| 1932 | 2039 | spin_unlock_irq(shost->host_lock); |
|---|
| 1933 | | - rc = 0; |
|---|
| 1934 | 2040 | |
|---|
| 1935 | 2041 | /* PLOGI completes to NPort <nlp_DID> */ |
|---|
| 1936 | 2042 | lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, |
|---|
| .. | .. |
|---|
| 1964 | 2070 | (((irsp->un.ulpWord[4]) >> 16 != LSRJT_INVALID_CMD) && |
|---|
| 1965 | 2071 | ((irsp->un.ulpWord[4]) >> 16 != LSRJT_UNABLE_TPC)) || |
|---|
| 1966 | 2072 | (phba)->pport->cfg_log_verbose & LOG_ELS) |
|---|
| 1967 | | - lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, |
|---|
| 2073 | + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, |
|---|
| 1968 | 2074 | "2753 PLOGI failure DID:%06X Status:x%x/x%x\n", |
|---|
| 1969 | 2075 | ndlp->nlp_DID, irsp->ulpStatus, |
|---|
| 1970 | 2076 | irsp->un.ulpWord[4]); |
|---|
| 1971 | 2077 | /* Do not call DSM for lpfc_els_abort'ed ELS cmds */ |
|---|
| 1972 | | - if (lpfc_error_lost_link(irsp)) |
|---|
| 1973 | | - rc = NLP_STE_FREED_NODE; |
|---|
| 1974 | | - else |
|---|
| 1975 | | - rc = lpfc_disc_state_machine(vport, ndlp, cmdiocb, |
|---|
| 1976 | | - NLP_EVT_CMPL_PLOGI); |
|---|
| 2078 | + if (!lpfc_error_lost_link(irsp)) |
|---|
| 2079 | + lpfc_disc_state_machine(vport, ndlp, cmdiocb, |
|---|
| 2080 | + NLP_EVT_CMPL_PLOGI); |
|---|
| 1977 | 2081 | } else { |
|---|
| 1978 | 2082 | /* Good status, call state machine */ |
|---|
| 1979 | 2083 | prsp = list_entry(((struct lpfc_dmabuf *) |
|---|
| 1980 | 2084 | cmdiocb->context2)->list.next, |
|---|
| 1981 | 2085 | struct lpfc_dmabuf, list); |
|---|
| 1982 | 2086 | ndlp = lpfc_plogi_confirm_nport(phba, prsp->virt, ndlp); |
|---|
| 1983 | | - rc = lpfc_disc_state_machine(vport, ndlp, cmdiocb, |
|---|
| 2087 | + lpfc_disc_state_machine(vport, ndlp, cmdiocb, |
|---|
| 1984 | 2088 | NLP_EVT_CMPL_PLOGI); |
|---|
| 1985 | 2089 | } |
|---|
| 1986 | 2090 | |
|---|
| .. | .. |
|---|
| 2037 | 2141 | int ret; |
|---|
| 2038 | 2142 | |
|---|
| 2039 | 2143 | ndlp = lpfc_findnode_did(vport, did); |
|---|
| 2040 | | - if (ndlp && !NLP_CHK_NODE_ACT(ndlp)) |
|---|
| 2041 | | - ndlp = NULL; |
|---|
| 2144 | + |
|---|
| 2145 | + if (ndlp) { |
|---|
| 2146 | + /* Defer the processing of the issue PLOGI until after the |
|---|
| 2147 | + * outstanding UNREG_RPI mbox command completes, unless we |
|---|
| 2148 | + * are going offline. This logic does not apply for Fabric DIDs |
|---|
| 2149 | + */ |
|---|
| 2150 | + if ((ndlp->nlp_flag & NLP_UNREG_INP) && |
|---|
| 2151 | + ((ndlp->nlp_DID & Fabric_DID_MASK) != Fabric_DID_MASK) && |
|---|
| 2152 | + !(vport->fc_flag & FC_OFFLINE_MODE)) { |
|---|
| 2153 | + lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY, |
|---|
| 2154 | + "4110 Issue PLOGI x%x deferred " |
|---|
| 2155 | + "on NPort x%x rpi x%x Data: x%px\n", |
|---|
| 2156 | + ndlp->nlp_defer_did, ndlp->nlp_DID, |
|---|
| 2157 | + ndlp->nlp_rpi, ndlp); |
|---|
| 2158 | + |
|---|
| 2159 | + /* We can only defer 1st PLOGI */ |
|---|
| 2160 | + if (ndlp->nlp_defer_did == NLP_EVT_NOTHING_PENDING) |
|---|
| 2161 | + ndlp->nlp_defer_did = did; |
|---|
| 2162 | + return 0; |
|---|
| 2163 | + } |
|---|
| 2164 | + if (!NLP_CHK_NODE_ACT(ndlp)) |
|---|
| 2165 | + ndlp = NULL; |
|---|
| 2166 | + } |
|---|
| 2042 | 2167 | |
|---|
| 2043 | 2168 | /* If ndlp is not NULL, we will bump the reference count on it */ |
|---|
| 2044 | 2169 | cmdsize = (sizeof(uint32_t) + sizeof(struct serv_parm)); |
|---|
| .. | .. |
|---|
| 2122 | 2247 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); |
|---|
| 2123 | 2248 | IOCB_t *irsp; |
|---|
| 2124 | 2249 | struct lpfc_nodelist *ndlp; |
|---|
| 2250 | + char *mode; |
|---|
| 2251 | + u32 loglevel; |
|---|
| 2125 | 2252 | |
|---|
| 2126 | 2253 | /* we pass cmdiocb to state machine which needs rspiocb as well */ |
|---|
| 2127 | 2254 | cmdiocb->context_un.rsp_iocb = rspiocb; |
|---|
| .. | .. |
|---|
| 2159 | 2286 | goto out; |
|---|
| 2160 | 2287 | } |
|---|
| 2161 | 2288 | |
|---|
| 2289 | + /* If we don't send GFT_ID to Fabric, a PRLI error |
|---|
| 2290 | + * could be expected. |
|---|
| 2291 | + */ |
|---|
| 2292 | + if ((vport->fc_flag & FC_FABRIC) || |
|---|
| 2293 | + (vport->cfg_enable_fc4_type != LPFC_ENABLE_BOTH)) { |
|---|
| 2294 | + mode = KERN_ERR; |
|---|
| 2295 | + loglevel = LOG_TRACE_EVENT; |
|---|
| 2296 | + } else { |
|---|
| 2297 | + mode = KERN_INFO; |
|---|
| 2298 | + loglevel = LOG_ELS; |
|---|
| 2299 | + } |
|---|
| 2300 | + |
|---|
| 2162 | 2301 | /* PRLI failed */ |
|---|
| 2163 | | - lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, |
|---|
| 2302 | + lpfc_printf_vlog(vport, mode, loglevel, |
|---|
| 2164 | 2303 | "2754 PRLI failure DID:%06X Status:x%x/x%x, " |
|---|
| 2165 | 2304 | "data: x%x\n", |
|---|
| 2166 | 2305 | ndlp->nlp_DID, irsp->ulpStatus, |
|---|
| .. | .. |
|---|
| 2172 | 2311 | else |
|---|
| 2173 | 2312 | lpfc_disc_state_machine(vport, ndlp, cmdiocb, |
|---|
| 2174 | 2313 | NLP_EVT_CMPL_PRLI); |
|---|
| 2175 | | - } else |
|---|
| 2314 | + } else { |
|---|
| 2176 | 2315 | /* Good status, call state machine. However, if another |
|---|
| 2177 | 2316 | * PRLI is outstanding, don't call the state machine |
|---|
| 2178 | 2317 | * because final disposition to Mapped or Unmapped is |
|---|
| .. | .. |
|---|
| 2180 | 2319 | */ |
|---|
| 2181 | 2320 | lpfc_disc_state_machine(vport, ndlp, cmdiocb, |
|---|
| 2182 | 2321 | NLP_EVT_CMPL_PRLI); |
|---|
| 2322 | + } |
|---|
| 2183 | 2323 | |
|---|
| 2184 | 2324 | out: |
|---|
| 2185 | 2325 | lpfc_els_free_iocb(phba, cmdiocb); |
|---|
| .. | .. |
|---|
| 2238 | 2378 | ndlp->nlp_type &= ~(NLP_FCP_TARGET | NLP_FCP_INITIATOR); |
|---|
| 2239 | 2379 | ndlp->nlp_type &= ~(NLP_NVME_TARGET | NLP_NVME_INITIATOR); |
|---|
| 2240 | 2380 | ndlp->nlp_fcp_info &= ~NLP_FCP_2_DEVICE; |
|---|
| 2241 | | - ndlp->nlp_flag &= ~NLP_FIRSTBURST; |
|---|
| 2381 | + ndlp->nlp_flag &= ~(NLP_FIRSTBURST | NLP_NPR_2B_DISC); |
|---|
| 2242 | 2382 | ndlp->nvme_fb_size = 0; |
|---|
| 2243 | 2383 | |
|---|
| 2244 | 2384 | send_next_prli: |
|---|
| .. | .. |
|---|
| 2320 | 2460 | npr_nvme = (struct lpfc_nvme_prli *)pcmd; |
|---|
| 2321 | 2461 | bf_set(prli_type_code, npr_nvme, PRLI_NVME_TYPE); |
|---|
| 2322 | 2462 | bf_set(prli_estabImagePair, npr_nvme, 0); /* Should be 0 */ |
|---|
| 2463 | + if (phba->nsler) { |
|---|
| 2464 | + bf_set(prli_nsler, npr_nvme, 1); |
|---|
| 2465 | + bf_set(prli_conf, npr_nvme, 1); |
|---|
| 2466 | + } |
|---|
| 2323 | 2467 | |
|---|
| 2324 | 2468 | /* Only initiators request first burst. */ |
|---|
| 2325 | 2469 | if ((phba->cfg_nvme_enable_fb) && |
|---|
| .. | .. |
|---|
| 2566 | 2710 | goto out; |
|---|
| 2567 | 2711 | } |
|---|
| 2568 | 2712 | /* ADISC failed */ |
|---|
| 2569 | | - lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, |
|---|
| 2713 | + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, |
|---|
| 2570 | 2714 | "2755 ADISC failure DID:%06X Status:x%x/x%x\n", |
|---|
| 2571 | 2715 | ndlp->nlp_DID, irsp->ulpStatus, |
|---|
| 2572 | 2716 | irsp->un.ulpWord[4]); |
|---|
| .. | .. |
|---|
| 2724 | 2868 | */ |
|---|
| 2725 | 2869 | if (irsp->ulpStatus) { |
|---|
| 2726 | 2870 | /* LOGO failed */ |
|---|
| 2727 | | - lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, |
|---|
| 2871 | + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, |
|---|
| 2728 | 2872 | "2756 LOGO failure, No Retry DID:%06X Status:x%x/x%x\n", |
|---|
| 2729 | 2873 | ndlp->nlp_DID, irsp->ulpStatus, |
|---|
| 2730 | 2874 | irsp->un.ulpWord[4]); |
|---|
| .. | .. |
|---|
| 2745 | 2889 | !(vport->fc_flag & FC_PT2PT_PLOGI)) { |
|---|
| 2746 | 2890 | phba->pport->fc_myDID = 0; |
|---|
| 2747 | 2891 | |
|---|
| 2748 | | - if ((phba->cfg_enable_fc4_type == LPFC_ENABLE_BOTH) || |
|---|
| 2749 | | - (phba->cfg_enable_fc4_type == LPFC_ENABLE_NVME)) { |
|---|
| 2892 | + if ((vport->cfg_enable_fc4_type == LPFC_ENABLE_BOTH) || |
|---|
| 2893 | + (vport->cfg_enable_fc4_type == LPFC_ENABLE_NVME)) { |
|---|
| 2750 | 2894 | if (phba->nvmet_support) |
|---|
| 2751 | 2895 | lpfc_nvmet_update_targetport(phba); |
|---|
| 2752 | 2896 | else |
|---|
| .. | .. |
|---|
| 2879 | 3023 | * This routine is a generic completion callback function for ELS commands. |
|---|
| 2880 | 3024 | * Specifically, it is the callback function which does not need to perform |
|---|
| 2881 | 3025 | * any command specific operations. It is currently used by the ELS command |
|---|
| 2882 | | - * issuing routines for the ELS State Change Request (SCR), |
|---|
| 2883 | | - * lpfc_issue_els_scr(), and the ELS Fibre Channel Address Resolution |
|---|
| 2884 | | - * Protocol Response (FARPR) routine, lpfc_issue_els_farpr(). Other than |
|---|
| 2885 | | - * certain debug loggings, this callback function simply invokes the |
|---|
| 3026 | + * issuing routines for RSCN, lpfc_issue_els_rscn, and the ELS Fibre Channel |
|---|
| 3027 | + * Address Resolution Protocol Response (FARPR) routine, lpfc_issue_els_farpr(). |
|---|
| 3028 | + * Other than certain debug loggings, this callback function simply invokes the |
|---|
| 2886 | 3029 | * lpfc_els_chk_latt() routine to check whether link went down during the |
|---|
| 2887 | 3030 | * discovery process. |
|---|
| 2888 | 3031 | **/ |
|---|
| .. | .. |
|---|
| 2896 | 3039 | irsp = &rspiocb->iocb; |
|---|
| 2897 | 3040 | |
|---|
| 2898 | 3041 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, |
|---|
| 2899 | | - "ELS cmd cmpl: status:x%x/x%x did:x%x", |
|---|
| 2900 | | - irsp->ulpStatus, irsp->un.ulpWord[4], |
|---|
| 2901 | | - irsp->un.elsreq64.remoteID); |
|---|
| 3042 | + "ELS cmd cmpl: status:x%x/x%x did:x%x", |
|---|
| 3043 | + irsp->ulpStatus, irsp->un.ulpWord[4], |
|---|
| 3044 | + irsp->un.elsreq64.remoteID); |
|---|
| 3045 | + |
|---|
| 2902 | 3046 | /* ELS cmd tag <ulpIoTag> completes */ |
|---|
| 2903 | 3047 | lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, |
|---|
| 2904 | 3048 | "0106 ELS cmd tag x%x completes Data: x%x x%x x%x\n", |
|---|
| 2905 | 3049 | irsp->ulpIoTag, irsp->ulpStatus, |
|---|
| 2906 | 3050 | irsp->un.ulpWord[4], irsp->ulpTimeout); |
|---|
| 3051 | + |
|---|
| 3052 | + /* Check to see if link went down during discovery */ |
|---|
| 3053 | + lpfc_els_chk_latt(vport); |
|---|
| 3054 | + lpfc_els_free_iocb(phba, cmdiocb); |
|---|
| 3055 | +} |
|---|
| 3056 | + |
|---|
| 3057 | +/** |
|---|
| 3058 | + * lpfc_cmpl_els_disc_cmd - Completion callback function for Discovery ELS cmd |
|---|
| 3059 | + * @phba: pointer to lpfc hba data structure. |
|---|
| 3060 | + * @cmdiocb: pointer to lpfc command iocb data structure. |
|---|
| 3061 | + * @rspiocb: pointer to lpfc response iocb data structure. |
|---|
| 3062 | + * |
|---|
| 3063 | + * This routine is a generic completion callback function for Discovery ELS cmd. |
|---|
| 3064 | + * Currently used by the ELS command issuing routines for the ELS State Change |
|---|
| 3065 | + * Request (SCR), lpfc_issue_els_scr() and the ELS RDF, lpfc_issue_els_rdf(). |
|---|
| 3066 | + * These commands will be retried once only for ELS timeout errors. |
|---|
| 3067 | + **/ |
|---|
| 3068 | +static void |
|---|
| 3069 | +lpfc_cmpl_els_disc_cmd(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, |
|---|
| 3070 | + struct lpfc_iocbq *rspiocb) |
|---|
| 3071 | +{ |
|---|
| 3072 | + struct lpfc_vport *vport = cmdiocb->vport; |
|---|
| 3073 | + IOCB_t *irsp; |
|---|
| 3074 | + struct lpfc_els_rdf_rsp *prdf; |
|---|
| 3075 | + struct lpfc_dmabuf *pcmd, *prsp; |
|---|
| 3076 | + u32 *pdata; |
|---|
| 3077 | + u32 cmd; |
|---|
| 3078 | + |
|---|
| 3079 | + irsp = &rspiocb->iocb; |
|---|
| 3080 | + |
|---|
| 3081 | + lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, |
|---|
| 3082 | + "ELS cmd cmpl: status:x%x/x%x did:x%x", |
|---|
| 3083 | + irsp->ulpStatus, irsp->un.ulpWord[4], |
|---|
| 3084 | + irsp->un.elsreq64.remoteID); |
|---|
| 3085 | + /* ELS cmd tag <ulpIoTag> completes */ |
|---|
| 3086 | + lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, |
|---|
| 3087 | + "0217 ELS cmd tag x%x completes Data: x%x x%x x%x " |
|---|
| 3088 | + "x%x\n", |
|---|
| 3089 | + irsp->ulpIoTag, irsp->ulpStatus, |
|---|
| 3090 | + irsp->un.ulpWord[4], irsp->ulpTimeout, |
|---|
| 3091 | + cmdiocb->retry); |
|---|
| 3092 | + |
|---|
| 3093 | + pcmd = (struct lpfc_dmabuf *)cmdiocb->context2; |
|---|
| 3094 | + if (!pcmd) |
|---|
| 3095 | + goto out; |
|---|
| 3096 | + |
|---|
| 3097 | + pdata = (u32 *)pcmd->virt; |
|---|
| 3098 | + if (!pdata) |
|---|
| 3099 | + goto out; |
|---|
| 3100 | + cmd = *pdata; |
|---|
| 3101 | + |
|---|
| 3102 | + /* Only 1 retry for ELS Timeout only */ |
|---|
| 3103 | + if (irsp->ulpStatus == IOSTAT_LOCAL_REJECT && |
|---|
| 3104 | + ((irsp->un.ulpWord[4] & IOERR_PARAM_MASK) == |
|---|
| 3105 | + IOERR_SEQUENCE_TIMEOUT)) { |
|---|
| 3106 | + cmdiocb->retry++; |
|---|
| 3107 | + if (cmdiocb->retry <= 1) { |
|---|
| 3108 | + switch (cmd) { |
|---|
| 3109 | + case ELS_CMD_SCR: |
|---|
| 3110 | + lpfc_issue_els_scr(vport, cmdiocb->retry); |
|---|
| 3111 | + break; |
|---|
| 3112 | + case ELS_CMD_RDF: |
|---|
| 3113 | + cmdiocb->context1 = NULL; /* save ndlp refcnt */ |
|---|
| 3114 | + lpfc_issue_els_rdf(vport, cmdiocb->retry); |
|---|
| 3115 | + break; |
|---|
| 3116 | + } |
|---|
| 3117 | + goto out; |
|---|
| 3118 | + } |
|---|
| 3119 | + phba->fc_stat.elsRetryExceeded++; |
|---|
| 3120 | + } |
|---|
| 3121 | + if (irsp->ulpStatus) { |
|---|
| 3122 | + /* ELS discovery cmd completes with error */ |
|---|
| 3123 | + lpfc_printf_vlog(vport, KERN_WARNING, LOG_ELS, |
|---|
| 3124 | + "4203 ELS cmd x%x error: x%x x%X\n", cmd, |
|---|
| 3125 | + irsp->ulpStatus, irsp->un.ulpWord[4]); |
|---|
| 3126 | + goto out; |
|---|
| 3127 | + } |
|---|
| 3128 | + |
|---|
| 3129 | + /* The RDF response doesn't have any impact on the running driver |
|---|
| 3130 | + * but the notification descriptors are dumped here for support. |
|---|
| 3131 | + */ |
|---|
| 3132 | + if (cmd == ELS_CMD_RDF) { |
|---|
| 3133 | + int i; |
|---|
| 3134 | + |
|---|
| 3135 | + prsp = list_get_first(&pcmd->list, struct lpfc_dmabuf, list); |
|---|
| 3136 | + if (!prsp) |
|---|
| 3137 | + goto out; |
|---|
| 3138 | + |
|---|
| 3139 | + prdf = (struct lpfc_els_rdf_rsp *)prsp->virt; |
|---|
| 3140 | + if (!prdf) |
|---|
| 3141 | + goto out; |
|---|
| 3142 | + |
|---|
| 3143 | + for (i = 0; i < ELS_RDF_REG_TAG_CNT && |
|---|
| 3144 | + i < be32_to_cpu(prdf->reg_d1.reg_desc.count); i++) |
|---|
| 3145 | + lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, |
|---|
| 3146 | + "4677 Fabric RDF Notification Grant Data: " |
|---|
| 3147 | + "0x%08x\n", |
|---|
| 3148 | + be32_to_cpu( |
|---|
| 3149 | + prdf->reg_d1.desc_tags[i])); |
|---|
| 3150 | + } |
|---|
| 3151 | + |
|---|
| 3152 | +out: |
|---|
| 2907 | 3153 | /* Check to see if link went down during discovery */ |
|---|
| 2908 | 3154 | lpfc_els_chk_latt(vport); |
|---|
| 2909 | 3155 | lpfc_els_free_iocb(phba, cmdiocb); |
|---|
| .. | .. |
|---|
| 2913 | 3159 | /** |
|---|
| 2914 | 3160 | * lpfc_issue_els_scr - Issue a scr to an node on a vport |
|---|
| 2915 | 3161 | * @vport: pointer to a host virtual N_Port data structure. |
|---|
| 2916 | | - * @nportid: N_Port identifier to the remote node. |
|---|
| 2917 | | - * @retry: number of retries to the command IOCB. |
|---|
| 3162 | + * @retry: retry counter for the command IOCB. |
|---|
| 2918 | 3163 | * |
|---|
| 2919 | 3164 | * This routine issues a State Change Request (SCR) to a fabric node |
|---|
| 2920 | | - * on a @vport. The remote node @nportid is passed into the function. It |
|---|
| 3165 | + * on a @vport. The remote node is Fabric Controller (0xfffffd). It |
|---|
| 2921 | 3166 | * first search the @vport node list to find the matching ndlp. If no such |
|---|
| 2922 | 3167 | * ndlp is found, a new ndlp shall be created for this (SCR) purpose. An |
|---|
| 2923 | 3168 | * IOCB is allocated, payload prepared, and the lpfc_sli_issue_iocb() |
|---|
| .. | .. |
|---|
| 2933 | 3178 | * 1 - Failed to issue scr command |
|---|
| 2934 | 3179 | **/ |
|---|
| 2935 | 3180 | int |
|---|
| 2936 | | -lpfc_issue_els_scr(struct lpfc_vport *vport, uint32_t nportid, uint8_t retry) |
|---|
| 3181 | +lpfc_issue_els_scr(struct lpfc_vport *vport, uint8_t retry) |
|---|
| 2937 | 3182 | { |
|---|
| 2938 | 3183 | struct lpfc_hba *phba = vport->phba; |
|---|
| 2939 | 3184 | struct lpfc_iocbq *elsiocb; |
|---|
| .. | .. |
|---|
| 2943 | 3188 | |
|---|
| 2944 | 3189 | cmdsize = (sizeof(uint32_t) + sizeof(SCR)); |
|---|
| 2945 | 3190 | |
|---|
| 2946 | | - ndlp = lpfc_findnode_did(vport, nportid); |
|---|
| 3191 | + ndlp = lpfc_findnode_did(vport, Fabric_Cntl_DID); |
|---|
| 2947 | 3192 | if (!ndlp) { |
|---|
| 2948 | | - ndlp = lpfc_nlp_init(vport, nportid); |
|---|
| 3193 | + ndlp = lpfc_nlp_init(vport, Fabric_Cntl_DID); |
|---|
| 2949 | 3194 | if (!ndlp) |
|---|
| 2950 | 3195 | return 1; |
|---|
| 2951 | 3196 | lpfc_enqueue_node(vport, ndlp); |
|---|
| .. | .. |
|---|
| 2980 | 3225 | ndlp->nlp_DID, 0, 0); |
|---|
| 2981 | 3226 | |
|---|
| 2982 | 3227 | phba->fc_stat.elsXmitSCR++; |
|---|
| 3228 | + elsiocb->iocb_cmpl = lpfc_cmpl_els_disc_cmd; |
|---|
| 3229 | + if (lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0) == |
|---|
| 3230 | + IOCB_ERROR) { |
|---|
| 3231 | + /* The additional lpfc_nlp_put will cause the following |
|---|
| 3232 | + * lpfc_els_free_iocb routine to trigger the rlease of |
|---|
| 3233 | + * the node. |
|---|
| 3234 | + */ |
|---|
| 3235 | + lpfc_nlp_put(ndlp); |
|---|
| 3236 | + lpfc_els_free_iocb(phba, elsiocb); |
|---|
| 3237 | + return 1; |
|---|
| 3238 | + } |
|---|
| 3239 | + /* This will cause the callback-function lpfc_cmpl_els_cmd to |
|---|
| 3240 | + * trigger the release of node. |
|---|
| 3241 | + */ |
|---|
| 3242 | + if (!(vport->fc_flag & FC_PT2PT)) |
|---|
| 3243 | + lpfc_nlp_put(ndlp); |
|---|
| 3244 | + return 0; |
|---|
| 3245 | +} |
|---|
| 3246 | + |
|---|
| 3247 | +/** |
|---|
| 3248 | + * lpfc_issue_els_rscn - Issue an RSCN to the Fabric Controller (Fabric) |
|---|
| 3249 | + * or the other nport (pt2pt). |
|---|
| 3250 | + * @vport: pointer to a host virtual N_Port data structure. |
|---|
| 3251 | + * @retry: number of retries to the command IOCB. |
|---|
| 3252 | + * |
|---|
| 3253 | + * This routine issues a RSCN to the Fabric Controller (DID 0xFFFFFD) |
|---|
| 3254 | + * when connected to a fabric, or to the remote port when connected |
|---|
| 3255 | + * in point-to-point mode. When sent to the Fabric Controller, it will |
|---|
| 3256 | + * replay the RSCN to registered recipients. |
|---|
| 3257 | + * |
|---|
| 3258 | + * Note that, in lpfc_prep_els_iocb() routine, the reference count of ndlp |
|---|
| 3259 | + * will be incremented by 1 for holding the ndlp and the reference to ndlp |
|---|
| 3260 | + * will be stored into the context1 field of the IOCB for the completion |
|---|
| 3261 | + * callback function to the RSCN ELS command. |
|---|
| 3262 | + * |
|---|
| 3263 | + * Return code |
|---|
| 3264 | + * 0 - Successfully issued RSCN command |
|---|
| 3265 | + * 1 - Failed to issue RSCN command |
|---|
| 3266 | + **/ |
|---|
| 3267 | +int |
|---|
| 3268 | +lpfc_issue_els_rscn(struct lpfc_vport *vport, uint8_t retry) |
|---|
| 3269 | +{ |
|---|
| 3270 | + struct lpfc_hba *phba = vport->phba; |
|---|
| 3271 | + struct lpfc_iocbq *elsiocb; |
|---|
| 3272 | + struct lpfc_nodelist *ndlp; |
|---|
| 3273 | + struct { |
|---|
| 3274 | + struct fc_els_rscn rscn; |
|---|
| 3275 | + struct fc_els_rscn_page portid; |
|---|
| 3276 | + } *event; |
|---|
| 3277 | + uint32_t nportid; |
|---|
| 3278 | + uint16_t cmdsize = sizeof(*event); |
|---|
| 3279 | + |
|---|
| 3280 | + /* Not supported for private loop */ |
|---|
| 3281 | + if (phba->fc_topology == LPFC_TOPOLOGY_LOOP && |
|---|
| 3282 | + !(vport->fc_flag & FC_PUBLIC_LOOP)) |
|---|
| 3283 | + return 1; |
|---|
| 3284 | + |
|---|
| 3285 | + if (vport->fc_flag & FC_PT2PT) { |
|---|
| 3286 | + /* find any mapped nport - that would be the other nport */ |
|---|
| 3287 | + ndlp = lpfc_findnode_mapped(vport); |
|---|
| 3288 | + if (!ndlp) |
|---|
| 3289 | + return 1; |
|---|
| 3290 | + } else { |
|---|
| 3291 | + nportid = FC_FID_FCTRL; |
|---|
| 3292 | + /* find the fabric controller node */ |
|---|
| 3293 | + ndlp = lpfc_findnode_did(vport, nportid); |
|---|
| 3294 | + if (!ndlp) { |
|---|
| 3295 | + /* if one didn't exist, make one */ |
|---|
| 3296 | + ndlp = lpfc_nlp_init(vport, nportid); |
|---|
| 3297 | + if (!ndlp) |
|---|
| 3298 | + return 1; |
|---|
| 3299 | + lpfc_enqueue_node(vport, ndlp); |
|---|
| 3300 | + } else if (!NLP_CHK_NODE_ACT(ndlp)) { |
|---|
| 3301 | + ndlp = lpfc_enable_node(vport, ndlp, |
|---|
| 3302 | + NLP_STE_UNUSED_NODE); |
|---|
| 3303 | + if (!ndlp) |
|---|
| 3304 | + return 1; |
|---|
| 3305 | + } |
|---|
| 3306 | + } |
|---|
| 3307 | + |
|---|
| 3308 | + elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp, |
|---|
| 3309 | + ndlp->nlp_DID, ELS_CMD_RSCN_XMT); |
|---|
| 3310 | + |
|---|
| 3311 | + if (!elsiocb) { |
|---|
| 3312 | + /* This will trigger the release of the node just |
|---|
| 3313 | + * allocated |
|---|
| 3314 | + */ |
|---|
| 3315 | + lpfc_nlp_put(ndlp); |
|---|
| 3316 | + return 1; |
|---|
| 3317 | + } |
|---|
| 3318 | + |
|---|
| 3319 | + event = ((struct lpfc_dmabuf *)elsiocb->context2)->virt; |
|---|
| 3320 | + |
|---|
| 3321 | + event->rscn.rscn_cmd = ELS_RSCN; |
|---|
| 3322 | + event->rscn.rscn_page_len = sizeof(struct fc_els_rscn_page); |
|---|
| 3323 | + event->rscn.rscn_plen = cpu_to_be16(cmdsize); |
|---|
| 3324 | + |
|---|
| 3325 | + nportid = vport->fc_myDID; |
|---|
| 3326 | + /* appears that page flags must be 0 for fabric to broadcast RSCN */ |
|---|
| 3327 | + event->portid.rscn_page_flags = 0; |
|---|
| 3328 | + event->portid.rscn_fid[0] = (nportid & 0x00FF0000) >> 16; |
|---|
| 3329 | + event->portid.rscn_fid[1] = (nportid & 0x0000FF00) >> 8; |
|---|
| 3330 | + event->portid.rscn_fid[2] = nportid & 0x000000FF; |
|---|
| 3331 | + |
|---|
| 3332 | + lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, |
|---|
| 3333 | + "Issue RSCN: did:x%x", |
|---|
| 3334 | + ndlp->nlp_DID, 0, 0); |
|---|
| 3335 | + |
|---|
| 3336 | + phba->fc_stat.elsXmitRSCN++; |
|---|
| 2983 | 3337 | elsiocb->iocb_cmpl = lpfc_cmpl_els_cmd; |
|---|
| 2984 | 3338 | if (lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0) == |
|---|
| 2985 | 3339 | IOCB_ERROR) { |
|---|
| .. | .. |
|---|
| 2996 | 3350 | */ |
|---|
| 2997 | 3351 | if (!(vport->fc_flag & FC_PT2PT)) |
|---|
| 2998 | 3352 | lpfc_nlp_put(ndlp); |
|---|
| 3353 | + |
|---|
| 2999 | 3354 | return 0; |
|---|
| 3000 | 3355 | } |
|---|
| 3001 | 3356 | |
|---|
| .. | .. |
|---|
| 3100 | 3455 | /* This will cause the callback-function lpfc_cmpl_els_cmd to |
|---|
| 3101 | 3456 | * trigger the release of the node. |
|---|
| 3102 | 3457 | */ |
|---|
| 3458 | + /* Don't release reference count as RDF is likely outstanding */ |
|---|
| 3459 | + return 0; |
|---|
| 3460 | +} |
|---|
| 3461 | + |
|---|
| 3462 | +/** |
|---|
| 3463 | + * lpfc_issue_els_rdf - Register for diagnostic functions from the fabric. |
|---|
| 3464 | + * @vport: pointer to a host virtual N_Port data structure. |
|---|
| 3465 | + * @retry: retry counter for the command IOCB. |
|---|
| 3466 | + * |
|---|
| 3467 | + * This routine issues an ELS RDF to the Fabric Controller to register |
|---|
| 3468 | + * for diagnostic functions. |
|---|
| 3469 | + * |
|---|
| 3470 | + * Note that, in lpfc_prep_els_iocb() routine, the reference count of ndlp |
|---|
| 3471 | + * will be incremented by 1 for holding the ndlp and the reference to ndlp |
|---|
| 3472 | + * will be stored into the context1 field of the IOCB for the completion |
|---|
| 3473 | + * callback function to the RDF ELS command. |
|---|
| 3474 | + * |
|---|
| 3475 | + * Return code |
|---|
| 3476 | + * 0 - Successfully issued rdf command |
|---|
| 3477 | + * 1 - Failed to issue rdf command |
|---|
| 3478 | + **/ |
|---|
| 3479 | +int |
|---|
| 3480 | +lpfc_issue_els_rdf(struct lpfc_vport *vport, uint8_t retry) |
|---|
| 3481 | +{ |
|---|
| 3482 | + struct lpfc_hba *phba = vport->phba; |
|---|
| 3483 | + struct lpfc_iocbq *elsiocb; |
|---|
| 3484 | + struct lpfc_els_rdf_req *prdf; |
|---|
| 3485 | + struct lpfc_nodelist *ndlp; |
|---|
| 3486 | + uint16_t cmdsize; |
|---|
| 3487 | + |
|---|
| 3488 | + cmdsize = sizeof(*prdf); |
|---|
| 3489 | + |
|---|
| 3490 | + ndlp = lpfc_findnode_did(vport, Fabric_Cntl_DID); |
|---|
| 3491 | + if (!ndlp) { |
|---|
| 3492 | + ndlp = lpfc_nlp_init(vport, Fabric_Cntl_DID); |
|---|
| 3493 | + if (!ndlp) |
|---|
| 3494 | + return -ENODEV; |
|---|
| 3495 | + lpfc_enqueue_node(vport, ndlp); |
|---|
| 3496 | + } else if (!NLP_CHK_NODE_ACT(ndlp)) { |
|---|
| 3497 | + ndlp = lpfc_enable_node(vport, ndlp, NLP_STE_UNUSED_NODE); |
|---|
| 3498 | + if (!ndlp) |
|---|
| 3499 | + return -ENODEV; |
|---|
| 3500 | + } |
|---|
| 3501 | + |
|---|
| 3502 | + /* RDF ELS is not required on an NPIV VN_Port. */ |
|---|
| 3503 | + if (vport->port_type == LPFC_NPIV_PORT) { |
|---|
| 3504 | + lpfc_nlp_put(ndlp); |
|---|
| 3505 | + return -EACCES; |
|---|
| 3506 | + } |
|---|
| 3507 | + |
|---|
| 3508 | + elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp, |
|---|
| 3509 | + ndlp->nlp_DID, ELS_CMD_RDF); |
|---|
| 3510 | + if (!elsiocb) { |
|---|
| 3511 | + /* This will trigger the release of the node just |
|---|
| 3512 | + * allocated |
|---|
| 3513 | + */ |
|---|
| 3514 | + lpfc_nlp_put(ndlp); |
|---|
| 3515 | + return -ENOMEM; |
|---|
| 3516 | + } |
|---|
| 3517 | + |
|---|
| 3518 | + /* Configure the payload for the supported FPIN events. */ |
|---|
| 3519 | + prdf = (struct lpfc_els_rdf_req *) |
|---|
| 3520 | + (((struct lpfc_dmabuf *)elsiocb->context2)->virt); |
|---|
| 3521 | + memset(prdf, 0, cmdsize); |
|---|
| 3522 | + prdf->rdf.fpin_cmd = ELS_RDF; |
|---|
| 3523 | + prdf->rdf.desc_len = cpu_to_be32(sizeof(struct lpfc_els_rdf_req) - |
|---|
| 3524 | + sizeof(struct fc_els_rdf)); |
|---|
| 3525 | + prdf->reg_d1.reg_desc.desc_tag = cpu_to_be32(ELS_DTAG_FPIN_REGISTER); |
|---|
| 3526 | + prdf->reg_d1.reg_desc.desc_len = cpu_to_be32( |
|---|
| 3527 | + FC_TLV_DESC_LENGTH_FROM_SZ(prdf->reg_d1)); |
|---|
| 3528 | + prdf->reg_d1.reg_desc.count = cpu_to_be32(ELS_RDF_REG_TAG_CNT); |
|---|
| 3529 | + prdf->reg_d1.desc_tags[0] = cpu_to_be32(ELS_DTAG_LNK_INTEGRITY); |
|---|
| 3530 | + prdf->reg_d1.desc_tags[1] = cpu_to_be32(ELS_DTAG_DELIVERY); |
|---|
| 3531 | + prdf->reg_d1.desc_tags[2] = cpu_to_be32(ELS_DTAG_PEER_CONGEST); |
|---|
| 3532 | + prdf->reg_d1.desc_tags[3] = cpu_to_be32(ELS_DTAG_CONGESTION); |
|---|
| 3533 | + |
|---|
| 3534 | + lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD, |
|---|
| 3535 | + "Issue RDF: did:x%x", |
|---|
| 3536 | + ndlp->nlp_DID, 0, 0); |
|---|
| 3537 | + |
|---|
| 3538 | + lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, |
|---|
| 3539 | + "6444 Xmit RDF to remote NPORT x%x\n", |
|---|
| 3540 | + ndlp->nlp_DID); |
|---|
| 3541 | + |
|---|
| 3542 | + elsiocb->iocb_cmpl = lpfc_cmpl_els_disc_cmd; |
|---|
| 3543 | + if (lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0) == |
|---|
| 3544 | + IOCB_ERROR) { |
|---|
| 3545 | + /* The additional lpfc_nlp_put will cause the following |
|---|
| 3546 | + * lpfc_els_free_iocb routine to trigger the rlease of |
|---|
| 3547 | + * the node. |
|---|
| 3548 | + */ |
|---|
| 3549 | + lpfc_nlp_put(ndlp); |
|---|
| 3550 | + lpfc_els_free_iocb(phba, elsiocb); |
|---|
| 3551 | + return -EIO; |
|---|
| 3552 | + } |
|---|
| 3553 | + |
|---|
| 3554 | + /* An RDF was issued - this put ensures the ndlp is cleaned up |
|---|
| 3555 | + * when the RDF completes. |
|---|
| 3556 | + */ |
|---|
| 3103 | 3557 | lpfc_nlp_put(ndlp); |
|---|
| 3104 | 3558 | return 0; |
|---|
| 3105 | 3559 | } |
|---|
| .. | .. |
|---|
| 3161 | 3615 | |
|---|
| 3162 | 3616 | /** |
|---|
| 3163 | 3617 | * lpfc_els_retry_delay - Timer function with a ndlp delayed function timer |
|---|
| 3164 | | - * @ptr: holder for the pointer to the timer function associated data (ndlp). |
|---|
| 3618 | + * @t: pointer to the timer function associated data (ndlp). |
|---|
| 3165 | 3619 | * |
|---|
| 3166 | 3620 | * This routine is invoked by the ndlp delayed-function timer to check |
|---|
| 3167 | 3621 | * whether there is any pending ELS retry event(s) with the node. If not, it |
|---|
| .. | .. |
|---|
| 3275 | 3729 | } |
|---|
| 3276 | 3730 | |
|---|
| 3277 | 3731 | /** |
|---|
| 3732 | + * lpfc_link_reset - Issue link reset |
|---|
| 3733 | + * @vport: pointer to a virtual N_Port data structure. |
|---|
| 3734 | + * |
|---|
| 3735 | + * This routine performs link reset by sending INIT_LINK mailbox command. |
|---|
| 3736 | + * For SLI-3 adapter, link attention interrupt is enabled before issuing |
|---|
| 3737 | + * INIT_LINK mailbox command. |
|---|
| 3738 | + * |
|---|
| 3739 | + * Return code |
|---|
| 3740 | + * 0 - Link reset initiated successfully |
|---|
| 3741 | + * 1 - Failed to initiate link reset |
|---|
| 3742 | + **/ |
|---|
| 3743 | +int |
|---|
| 3744 | +lpfc_link_reset(struct lpfc_vport *vport) |
|---|
| 3745 | +{ |
|---|
| 3746 | + struct lpfc_hba *phba = vport->phba; |
|---|
| 3747 | + LPFC_MBOXQ_t *mbox; |
|---|
| 3748 | + uint32_t control; |
|---|
| 3749 | + int rc; |
|---|
| 3750 | + |
|---|
| 3751 | + lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, |
|---|
| 3752 | + "2851 Attempt link reset\n"); |
|---|
| 3753 | + mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); |
|---|
| 3754 | + if (!mbox) { |
|---|
| 3755 | + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, |
|---|
| 3756 | + "2852 Failed to allocate mbox memory"); |
|---|
| 3757 | + return 1; |
|---|
| 3758 | + } |
|---|
| 3759 | + |
|---|
| 3760 | + /* Enable Link attention interrupts */ |
|---|
| 3761 | + if (phba->sli_rev <= LPFC_SLI_REV3) { |
|---|
| 3762 | + spin_lock_irq(&phba->hbalock); |
|---|
| 3763 | + phba->sli.sli_flag |= LPFC_PROCESS_LA; |
|---|
| 3764 | + control = readl(phba->HCregaddr); |
|---|
| 3765 | + control |= HC_LAINT_ENA; |
|---|
| 3766 | + writel(control, phba->HCregaddr); |
|---|
| 3767 | + readl(phba->HCregaddr); /* flush */ |
|---|
| 3768 | + spin_unlock_irq(&phba->hbalock); |
|---|
| 3769 | + } |
|---|
| 3770 | + |
|---|
| 3771 | + lpfc_init_link(phba, mbox, phba->cfg_topology, |
|---|
| 3772 | + phba->cfg_link_speed); |
|---|
| 3773 | + mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl; |
|---|
| 3774 | + mbox->vport = vport; |
|---|
| 3775 | + rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT); |
|---|
| 3776 | + if ((rc != MBX_BUSY) && (rc != MBX_SUCCESS)) { |
|---|
| 3777 | + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, |
|---|
| 3778 | + "2853 Failed to issue INIT_LINK " |
|---|
| 3779 | + "mbox command, rc:x%x\n", rc); |
|---|
| 3780 | + mempool_free(mbox, phba->mbox_mem_pool); |
|---|
| 3781 | + return 1; |
|---|
| 3782 | + } |
|---|
| 3783 | + |
|---|
| 3784 | + return 0; |
|---|
| 3785 | +} |
|---|
| 3786 | + |
|---|
| 3787 | +/** |
|---|
| 3278 | 3788 | * lpfc_els_retry - Make retry decision on an els command iocb |
|---|
| 3279 | 3789 | * @phba: pointer to lpfc hba data structure. |
|---|
| 3280 | 3790 | * @cmdiocb: pointer to lpfc command iocb data structure. |
|---|
| .. | .. |
|---|
| 3310 | 3820 | int logerr = 0; |
|---|
| 3311 | 3821 | uint32_t cmd = 0; |
|---|
| 3312 | 3822 | uint32_t did; |
|---|
| 3823 | + int link_reset = 0, rc; |
|---|
| 3313 | 3824 | |
|---|
| 3314 | 3825 | |
|---|
| 3315 | 3826 | /* Note: context2 may be 0 for internal driver abort |
|---|
| .. | .. |
|---|
| 3367 | 3878 | break; |
|---|
| 3368 | 3879 | |
|---|
| 3369 | 3880 | case IOERR_ILLEGAL_COMMAND: |
|---|
| 3370 | | - lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, |
|---|
| 3881 | + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, |
|---|
| 3371 | 3882 | "0124 Retry illegal cmd x%x " |
|---|
| 3372 | 3883 | "retry:x%x delay:x%x\n", |
|---|
| 3373 | 3884 | cmd, cmdiocb->retry, delay); |
|---|
| .. | .. |
|---|
| 3391 | 3902 | retry = 1; |
|---|
| 3392 | 3903 | break; |
|---|
| 3393 | 3904 | |
|---|
| 3394 | | - case IOERR_SEQUENCE_TIMEOUT: |
|---|
| 3395 | 3905 | case IOERR_INVALID_RPI: |
|---|
| 3396 | 3906 | if (cmd == ELS_CMD_PLOGI && |
|---|
| 3397 | 3907 | did == NameServer_DID) { |
|---|
| .. | .. |
|---|
| 3401 | 3911 | delay = 100; |
|---|
| 3402 | 3912 | } |
|---|
| 3403 | 3913 | retry = 1; |
|---|
| 3914 | + break; |
|---|
| 3915 | + |
|---|
| 3916 | + case IOERR_SEQUENCE_TIMEOUT: |
|---|
| 3917 | + if (cmd == ELS_CMD_PLOGI && |
|---|
| 3918 | + did == NameServer_DID && |
|---|
| 3919 | + (cmdiocb->retry + 1) == maxretry) { |
|---|
| 3920 | + /* Reset the Link */ |
|---|
| 3921 | + link_reset = 1; |
|---|
| 3922 | + break; |
|---|
| 3923 | + } |
|---|
| 3924 | + retry = 1; |
|---|
| 3925 | + delay = 100; |
|---|
| 3404 | 3926 | break; |
|---|
| 3405 | 3927 | } |
|---|
| 3406 | 3928 | break; |
|---|
| .. | .. |
|---|
| 3424 | 3946 | /* Added for Vendor specifc support |
|---|
| 3425 | 3947 | * Just keep retrying for these Rsn / Exp codes |
|---|
| 3426 | 3948 | */ |
|---|
| 3949 | + if ((vport->fc_flag & FC_PT2PT) && |
|---|
| 3950 | + cmd == ELS_CMD_NVMEPRLI) { |
|---|
| 3951 | + switch (stat.un.b.lsRjtRsnCode) { |
|---|
| 3952 | + case LSRJT_UNABLE_TPC: |
|---|
| 3953 | + case LSRJT_INVALID_CMD: |
|---|
| 3954 | + case LSRJT_LOGICAL_ERR: |
|---|
| 3955 | + case LSRJT_CMD_UNSUPPORTED: |
|---|
| 3956 | + lpfc_printf_vlog(vport, KERN_WARNING, LOG_ELS, |
|---|
| 3957 | + "0168 NVME PRLI LS_RJT " |
|---|
| 3958 | + "reason %x port doesn't " |
|---|
| 3959 | + "support NVME, disabling NVME\n", |
|---|
| 3960 | + stat.un.b.lsRjtRsnCode); |
|---|
| 3961 | + retry = 0; |
|---|
| 3962 | + vport->fc_flag |= FC_PT2PT_NO_NVME; |
|---|
| 3963 | + goto out_retry; |
|---|
| 3964 | + } |
|---|
| 3965 | + } |
|---|
| 3427 | 3966 | switch (stat.un.b.lsRjtRsnCode) { |
|---|
| 3428 | 3967 | case LSRJT_UNABLE_TPC: |
|---|
| 3429 | 3968 | /* The driver has a VALID PLOGI but the rport has |
|---|
| 3430 | 3969 | * rejected the PRLI - can't do it now. Delay |
|---|
| 3431 | | - * for 1 second and try again - don't care about |
|---|
| 3432 | | - * the explanation. |
|---|
| 3970 | + * for 1 second and try again. |
|---|
| 3971 | + * |
|---|
| 3972 | + * However, if explanation is REQ_UNSUPPORTED there's |
|---|
| 3973 | + * no point to retry PRLI. |
|---|
| 3433 | 3974 | */ |
|---|
| 3434 | | - if (cmd == ELS_CMD_PRLI || cmd == ELS_CMD_NVMEPRLI) { |
|---|
| 3975 | + if ((cmd == ELS_CMD_PRLI || cmd == ELS_CMD_NVMEPRLI) && |
|---|
| 3976 | + stat.un.b.lsRjtRsnCodeExp != |
|---|
| 3977 | + LSEXP_REQ_UNSUPPORTED) { |
|---|
| 3435 | 3978 | delay = 1000; |
|---|
| 3436 | 3979 | maxretry = lpfc_max_els_tries + 1; |
|---|
| 3437 | 3980 | retry = 1; |
|---|
| .. | .. |
|---|
| 3466 | 4009 | if ((phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) && |
|---|
| 3467 | 4010 | (cmd == ELS_CMD_FDISC) && |
|---|
| 3468 | 4011 | (stat.un.b.lsRjtRsnCodeExp == LSEXP_OUT_OF_RESOURCE)){ |
|---|
| 3469 | | - lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, |
|---|
| 4012 | + lpfc_printf_vlog(vport, KERN_ERR, |
|---|
| 4013 | + LOG_TRACE_EVENT, |
|---|
| 3470 | 4014 | "0125 FDISC Failed (x%x). " |
|---|
| 3471 | 4015 | "Fabric out of resources\n", |
|---|
| 3472 | 4016 | stat.un.lsRjtError); |
|---|
| .. | .. |
|---|
| 3505 | 4049 | LSEXP_NOTHING_MORE) { |
|---|
| 3506 | 4050 | vport->fc_sparam.cmn.bbRcvSizeMsb &= 0xf; |
|---|
| 3507 | 4051 | retry = 1; |
|---|
| 3508 | | - lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, |
|---|
| 4052 | + lpfc_printf_vlog(vport, KERN_ERR, |
|---|
| 4053 | + LOG_TRACE_EVENT, |
|---|
| 3509 | 4054 | "0820 FLOGI Failed (x%x). " |
|---|
| 3510 | 4055 | "BBCredit Not Supported\n", |
|---|
| 3511 | 4056 | stat.un.lsRjtError); |
|---|
| .. | .. |
|---|
| 3518 | 4063 | ((stat.un.b.lsRjtRsnCodeExp == LSEXP_INVALID_PNAME) || |
|---|
| 3519 | 4064 | (stat.un.b.lsRjtRsnCodeExp == LSEXP_INVALID_NPORT_ID)) |
|---|
| 3520 | 4065 | ) { |
|---|
| 3521 | | - lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, |
|---|
| 4066 | + lpfc_printf_vlog(vport, KERN_ERR, |
|---|
| 4067 | + LOG_TRACE_EVENT, |
|---|
| 3522 | 4068 | "0122 FDISC Failed (x%x). " |
|---|
| 3523 | 4069 | "Fabric Detected Bad WWN\n", |
|---|
| 3524 | 4070 | stat.un.lsRjtError); |
|---|
| .. | .. |
|---|
| 3556 | 4102 | |
|---|
| 3557 | 4103 | default: |
|---|
| 3558 | 4104 | break; |
|---|
| 4105 | + } |
|---|
| 4106 | + |
|---|
| 4107 | + if (link_reset) { |
|---|
| 4108 | + rc = lpfc_link_reset(vport); |
|---|
| 4109 | + if (rc) { |
|---|
| 4110 | + /* Do not give up. Retry PLOGI one more time and attempt |
|---|
| 4111 | + * link reset if PLOGI fails again. |
|---|
| 4112 | + */ |
|---|
| 4113 | + retry = 1; |
|---|
| 4114 | + delay = 100; |
|---|
| 4115 | + goto out_retry; |
|---|
| 4116 | + } |
|---|
| 4117 | + return 1; |
|---|
| 3559 | 4118 | } |
|---|
| 3560 | 4119 | |
|---|
| 3561 | 4120 | if (did == FDMI_DID) |
|---|
| .. | .. |
|---|
| 3683 | 4242 | } |
|---|
| 3684 | 4243 | /* No retry ELS command <elsCmd> to remote NPORT <did> */ |
|---|
| 3685 | 4244 | if (logerr) { |
|---|
| 3686 | | - lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, |
|---|
| 4245 | + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, |
|---|
| 3687 | 4246 | "0137 No retry ELS command x%x to remote " |
|---|
| 3688 | 4247 | "NPORT x%x: Out of Resources: Error:x%x/%x\n", |
|---|
| 3689 | 4248 | cmd, did, irsp->ulpStatus, |
|---|
| .. | .. |
|---|
| 3920 | 4479 | void |
|---|
| 3921 | 4480 | lpfc_mbx_cmpl_dflt_rpi(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) |
|---|
| 3922 | 4481 | { |
|---|
| 3923 | | - struct lpfc_dmabuf *mp = (struct lpfc_dmabuf *) (pmb->context1); |
|---|
| 3924 | | - struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) pmb->context2; |
|---|
| 4482 | + struct lpfc_dmabuf *mp = (struct lpfc_dmabuf *)(pmb->ctx_buf); |
|---|
| 4483 | + struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *)pmb->ctx_ndlp; |
|---|
| 3925 | 4484 | |
|---|
| 3926 | | - pmb->context1 = NULL; |
|---|
| 3927 | | - pmb->context2 = NULL; |
|---|
| 4485 | + pmb->ctx_buf = NULL; |
|---|
| 4486 | + pmb->ctx_ndlp = NULL; |
|---|
| 3928 | 4487 | |
|---|
| 3929 | 4488 | lpfc_mbuf_free(phba, mp->virt, mp->phys); |
|---|
| 3930 | 4489 | kfree(mp); |
|---|
| 3931 | 4490 | mempool_free(pmb, phba->mbox_mem_pool); |
|---|
| 3932 | 4491 | if (ndlp) { |
|---|
| 3933 | 4492 | lpfc_printf_vlog(ndlp->vport, KERN_INFO, LOG_NODE, |
|---|
| 3934 | | - "0006 rpi%x DID:%x flg:%x %d map:%x %p\n", |
|---|
| 4493 | + "0006 rpi%x DID:%x flg:%x %d map:%x x%px\n", |
|---|
| 3935 | 4494 | ndlp->nlp_rpi, ndlp->nlp_DID, ndlp->nlp_flag, |
|---|
| 3936 | 4495 | kref_read(&ndlp->kref), |
|---|
| 3937 | 4496 | ndlp->nlp_usg_map, ndlp); |
|---|
| .. | .. |
|---|
| 3981 | 4540 | |
|---|
| 3982 | 4541 | irsp = &rspiocb->iocb; |
|---|
| 3983 | 4542 | |
|---|
| 4543 | + if (!vport) { |
|---|
| 4544 | + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, |
|---|
| 4545 | + "3177 ELS response failed\n"); |
|---|
| 4546 | + goto out; |
|---|
| 4547 | + } |
|---|
| 3984 | 4548 | if (cmdiocb->context_un.mbox) |
|---|
| 3985 | 4549 | mbox = cmdiocb->context_un.mbox; |
|---|
| 3986 | 4550 | |
|---|
| .. | .. |
|---|
| 4000 | 4564 | /* Check to see if link went down during discovery */ |
|---|
| 4001 | 4565 | if (!ndlp || !NLP_CHK_NODE_ACT(ndlp) || lpfc_els_chk_latt(vport)) { |
|---|
| 4002 | 4566 | if (mbox) { |
|---|
| 4003 | | - mp = (struct lpfc_dmabuf *) mbox->context1; |
|---|
| 4567 | + mp = (struct lpfc_dmabuf *)mbox->ctx_buf; |
|---|
| 4004 | 4568 | if (mp) { |
|---|
| 4005 | 4569 | lpfc_mbuf_free(phba, mp->virt, mp->phys); |
|---|
| 4006 | 4570 | kfree(mp); |
|---|
| .. | .. |
|---|
| 4036 | 4600 | if ((rspiocb->iocb.ulpStatus == 0) |
|---|
| 4037 | 4601 | && (ndlp->nlp_flag & NLP_ACC_REGLOGIN)) { |
|---|
| 4038 | 4602 | if (!lpfc_unreg_rpi(vport, ndlp) && |
|---|
| 4603 | + (!(vport->fc_flag & FC_PT2PT)) && |
|---|
| 4039 | 4604 | (ndlp->nlp_state == NLP_STE_PLOGI_ISSUE || |
|---|
| 4040 | 4605 | ndlp->nlp_state == NLP_STE_REG_LOGIN_ISSUE)) { |
|---|
| 4041 | 4606 | lpfc_printf_vlog(vport, KERN_INFO, |
|---|
| .. | .. |
|---|
| 4044 | 4609 | "Data: x%x x%x x%x\n", |
|---|
| 4045 | 4610 | ndlp->nlp_DID, ndlp->nlp_state, |
|---|
| 4046 | 4611 | ndlp->nlp_rpi, ndlp->nlp_flag); |
|---|
| 4047 | | - mp = mbox->context1; |
|---|
| 4612 | + mp = mbox->ctx_buf; |
|---|
| 4048 | 4613 | if (mp) { |
|---|
| 4049 | 4614 | lpfc_mbuf_free(phba, mp->virt, |
|---|
| 4050 | 4615 | mp->phys); |
|---|
| .. | .. |
|---|
| 4057 | 4622 | /* Increment reference count to ndlp to hold the |
|---|
| 4058 | 4623 | * reference to ndlp for the callback function. |
|---|
| 4059 | 4624 | */ |
|---|
| 4060 | | - mbox->context2 = lpfc_nlp_get(ndlp); |
|---|
| 4625 | + mbox->ctx_ndlp = lpfc_nlp_get(ndlp); |
|---|
| 4061 | 4626 | mbox->vport = vport; |
|---|
| 4062 | 4627 | if (ndlp->nlp_flag & NLP_RM_DFLT_RPI) { |
|---|
| 4063 | 4628 | mbox->mbox_flag |= LPFC_MBX_IMED_UNREG; |
|---|
| .. | .. |
|---|
| 4082 | 4647 | ndlp->nlp_flag &= ~NLP_REG_LOGIN_SEND; |
|---|
| 4083 | 4648 | |
|---|
| 4084 | 4649 | /* ELS rsp: Cannot issue reg_login for <NPortid> */ |
|---|
| 4085 | | - lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, |
|---|
| 4650 | + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, |
|---|
| 4086 | 4651 | "0138 ELS rsp: Cannot issue reg_login for x%x " |
|---|
| 4087 | 4652 | "Data: x%x x%x x%x\n", |
|---|
| 4088 | 4653 | ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state, |
|---|
| .. | .. |
|---|
| 4111 | 4676 | } |
|---|
| 4112 | 4677 | } |
|---|
| 4113 | 4678 | } |
|---|
| 4114 | | - mp = (struct lpfc_dmabuf *) mbox->context1; |
|---|
| 4679 | + mp = (struct lpfc_dmabuf *)mbox->ctx_buf; |
|---|
| 4115 | 4680 | if (mp) { |
|---|
| 4116 | 4681 | lpfc_mbuf_free(phba, mp->virt, mp->phys); |
|---|
| 4117 | 4682 | kfree(mp); |
|---|
| .. | .. |
|---|
| 4322 | 4887 | /** |
|---|
| 4323 | 4888 | * lpfc_els_rsp_reject - Propare and issue a rjt response iocb command |
|---|
| 4324 | 4889 | * @vport: pointer to a virtual N_Port data structure. |
|---|
| 4325 | | - * @rejectError: |
|---|
| 4890 | + * @rejectError: reject response to issue |
|---|
| 4326 | 4891 | * @oldiocb: pointer to the original lpfc command iocb data structure. |
|---|
| 4327 | 4892 | * @ndlp: pointer to a node-list data structure. |
|---|
| 4328 | 4893 | * @mbox: pointer to the driver internal queue element for mailbox command. |
|---|
| .. | .. |
|---|
| 4951 | 5516 | } |
|---|
| 4952 | 5517 | } |
|---|
| 4953 | 5518 | } |
|---|
| 5519 | + |
|---|
| 5520 | + lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY, |
|---|
| 5521 | + "6452 Discover PLOGI %d flag x%x\n", |
|---|
| 5522 | + sentplogi, vport->fc_flag); |
|---|
| 5523 | + |
|---|
| 4954 | 5524 | if (sentplogi) { |
|---|
| 4955 | 5525 | lpfc_set_disctmo(vport); |
|---|
| 4956 | 5526 | } |
|---|
| .. | .. |
|---|
| 5309 | 5879 | |
|---|
| 5310 | 5880 | desc->info.port_speed.speed = cpu_to_be16(rdp_speed); |
|---|
| 5311 | 5881 | |
|---|
| 5882 | + if (phba->lmt & LMT_128Gb) |
|---|
| 5883 | + rdp_cap |= RDP_PS_128GB; |
|---|
| 5312 | 5884 | if (phba->lmt & LMT_64Gb) |
|---|
| 5313 | 5885 | rdp_cap |= RDP_PS_64GB; |
|---|
| 5314 | 5886 | if (phba->lmt & LMT_32Gb) |
|---|
| .. | .. |
|---|
| 5361 | 5933 | desc->tag = cpu_to_be32(RDP_PORT_NAMES_DESC_TAG); |
|---|
| 5362 | 5934 | if (vport->fc_flag & FC_FABRIC) { |
|---|
| 5363 | 5935 | memcpy(desc->port_names.wwnn, &vport->fabric_nodename, |
|---|
| 5364 | | - sizeof(desc->port_names.wwnn)); |
|---|
| 5936 | + sizeof(desc->port_names.wwnn)); |
|---|
| 5365 | 5937 | |
|---|
| 5366 | 5938 | memcpy(desc->port_names.wwpn, &vport->fabric_portname, |
|---|
| 5367 | | - sizeof(desc->port_names.wwpn)); |
|---|
| 5939 | + sizeof(desc->port_names.wwpn)); |
|---|
| 5368 | 5940 | } else { /* Point to Point */ |
|---|
| 5369 | 5941 | memcpy(desc->port_names.wwnn, &ndlp->nlp_nodename, |
|---|
| 5370 | | - sizeof(desc->port_names.wwnn)); |
|---|
| 5942 | + sizeof(desc->port_names.wwnn)); |
|---|
| 5371 | 5943 | |
|---|
| 5372 | | - memcpy(desc->port_names.wwnn, &ndlp->nlp_portname, |
|---|
| 5373 | | - sizeof(desc->port_names.wwpn)); |
|---|
| 5944 | + memcpy(desc->port_names.wwpn, &ndlp->nlp_portname, |
|---|
| 5945 | + sizeof(desc->port_names.wwpn)); |
|---|
| 5374 | 5946 | } |
|---|
| 5375 | 5947 | |
|---|
| 5376 | 5948 | desc->length = cpu_to_be32(sizeof(desc->port_names)); |
|---|
| .. | .. |
|---|
| 5527 | 6099 | goto prep_mbox_fail; |
|---|
| 5528 | 6100 | mbox->vport = rdp_context->ndlp->vport; |
|---|
| 5529 | 6101 | mbox->mbox_cmpl = lpfc_mbx_cmpl_rdp_page_a0; |
|---|
| 5530 | | - mbox->context2 = (struct lpfc_rdp_context *) rdp_context; |
|---|
| 6102 | + mbox->ctx_ndlp = (struct lpfc_rdp_context *)rdp_context; |
|---|
| 5531 | 6103 | rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT); |
|---|
| 5532 | 6104 | if (rc == MBX_NOT_FINISHED) |
|---|
| 5533 | 6105 | goto issue_mbox_fail; |
|---|
| .. | .. |
|---|
| 5652 | 6224 | int rc; |
|---|
| 5653 | 6225 | |
|---|
| 5654 | 6226 | mb = &pmb->u.mb; |
|---|
| 5655 | | - lcb_context = (struct lpfc_lcb_context *)pmb->context1; |
|---|
| 6227 | + lcb_context = (struct lpfc_lcb_context *)pmb->ctx_ndlp; |
|---|
| 5656 | 6228 | ndlp = lcb_context->ndlp; |
|---|
| 5657 | | - pmb->context1 = NULL; |
|---|
| 5658 | | - pmb->context2 = NULL; |
|---|
| 6229 | + pmb->ctx_ndlp = NULL; |
|---|
| 6230 | + pmb->ctx_buf = NULL; |
|---|
| 5659 | 6231 | |
|---|
| 5660 | 6232 | shdr = (union lpfc_sli4_cfg_shdr *) |
|---|
| 5661 | 6233 | &pmb->u.mqe.un.beacon_config.header.cfg_shdr; |
|---|
| .. | .. |
|---|
| 5762 | 6334 | lpfc_sli4_config(phba, mbox, LPFC_MBOX_SUBSYSTEM_COMMON, |
|---|
| 5763 | 6335 | LPFC_MBOX_OPCODE_SET_BEACON_CONFIG, len, |
|---|
| 5764 | 6336 | LPFC_SLI4_MBX_EMBED); |
|---|
| 5765 | | - mbox->context1 = (void *)lcb_context; |
|---|
| 6337 | + mbox->ctx_ndlp = (void *)lcb_context; |
|---|
| 5766 | 6338 | mbox->vport = phba->pport; |
|---|
| 5767 | 6339 | mbox->mbox_cmpl = lpfc_els_lcb_rsp; |
|---|
| 5768 | 6340 | bf_set(lpfc_mbx_set_beacon_port_num, &mbox->u.mqe.un.beacon_config, |
|---|
| .. | .. |
|---|
| 5883 | 6455 | lcb_context->rx_id = cmdiocb->iocb.ulpContext; |
|---|
| 5884 | 6456 | lcb_context->ndlp = lpfc_nlp_get(ndlp); |
|---|
| 5885 | 6457 | if (lpfc_sli4_set_beacon(vport, lcb_context, state)) { |
|---|
| 5886 | | - lpfc_printf_vlog(ndlp->vport, KERN_ERR, |
|---|
| 5887 | | - LOG_ELS, "0193 failed to send mail box"); |
|---|
| 6458 | + lpfc_printf_vlog(ndlp->vport, KERN_ERR, LOG_TRACE_EVENT, |
|---|
| 6459 | + "0193 failed to send mail box"); |
|---|
| 5888 | 6460 | kfree(lcb_context); |
|---|
| 5889 | 6461 | lpfc_nlp_put(ndlp); |
|---|
| 5890 | 6462 | rjt_err = LSRJT_UNABLE_TPC; |
|---|
| .. | .. |
|---|
| 6042 | 6614 | if (vport->phba->nvmet_support) |
|---|
| 6043 | 6615 | continue; |
|---|
| 6044 | 6616 | |
|---|
| 6617 | + /* If we are in the process of doing discovery on this |
|---|
| 6618 | + * NPort, let it continue on its own. |
|---|
| 6619 | + */ |
|---|
| 6620 | + switch (ndlp->nlp_state) { |
|---|
| 6621 | + case NLP_STE_PLOGI_ISSUE: |
|---|
| 6622 | + case NLP_STE_ADISC_ISSUE: |
|---|
| 6623 | + case NLP_STE_REG_LOGIN_ISSUE: |
|---|
| 6624 | + case NLP_STE_PRLI_ISSUE: |
|---|
| 6625 | + case NLP_STE_LOGO_ISSUE: |
|---|
| 6626 | + continue; |
|---|
| 6627 | + } |
|---|
| 6628 | + |
|---|
| 6629 | + /* Check to see if we need to NVME rescan this target |
|---|
| 6630 | + * remoteport. |
|---|
| 6631 | + */ |
|---|
| 6632 | + if (ndlp->nlp_fc4_type & NLP_FC4_NVME && |
|---|
| 6633 | + ndlp->nlp_type & (NLP_NVME_TARGET | NLP_NVME_DISCOVERY)) |
|---|
| 6634 | + lpfc_nvme_rescan_port(vport, ndlp); |
|---|
| 6635 | + |
|---|
| 6045 | 6636 | lpfc_disc_state_machine(vport, ndlp, NULL, |
|---|
| 6046 | 6637 | NLP_EVT_DEVICE_RECOVERY); |
|---|
| 6047 | 6638 | lpfc_cancel_retry_delay_tmo(vport, ndlp); |
|---|
| .. | .. |
|---|
| 6074 | 6665 | rscn_event_data = kmalloc(sizeof(struct lpfc_rscn_event_header) + |
|---|
| 6075 | 6666 | payload_len, GFP_KERNEL); |
|---|
| 6076 | 6667 | if (!rscn_event_data) { |
|---|
| 6077 | | - lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, |
|---|
| 6668 | + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, |
|---|
| 6078 | 6669 | "0147 Failed to allocate memory for RSCN event\n"); |
|---|
| 6079 | 6670 | return; |
|---|
| 6080 | 6671 | } |
|---|
| .. | .. |
|---|
| 6125 | 6716 | uint32_t payload_len, length, nportid, *cmd; |
|---|
| 6126 | 6717 | int rscn_cnt; |
|---|
| 6127 | 6718 | int rscn_id = 0, hba_id = 0; |
|---|
| 6128 | | - int i; |
|---|
| 6719 | + int i, tmo; |
|---|
| 6129 | 6720 | |
|---|
| 6130 | 6721 | pcmd = (struct lpfc_dmabuf *) cmdiocb->context2; |
|---|
| 6131 | 6722 | lp = (uint32_t *) pcmd->virt; |
|---|
| .. | .. |
|---|
| 6144 | 6735 | for (i = 0; i < payload_len/sizeof(uint32_t); i++) |
|---|
| 6145 | 6736 | fc_host_post_event(shost, fc_get_event_number(), |
|---|
| 6146 | 6737 | FCH_EVT_RSCN, lp[i]); |
|---|
| 6738 | + |
|---|
| 6739 | + /* Check if RSCN is coming from a direct-connected remote NPort */ |
|---|
| 6740 | + if (vport->fc_flag & FC_PT2PT) { |
|---|
| 6741 | + /* If so, just ACC it, no other action needed for now */ |
|---|
| 6742 | + lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, |
|---|
| 6743 | + "2024 pt2pt RSCN %08x Data: x%x x%x\n", |
|---|
| 6744 | + *lp, vport->fc_flag, payload_len); |
|---|
| 6745 | + lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL); |
|---|
| 6746 | + |
|---|
| 6747 | + /* Check to see if we need to NVME rescan this target |
|---|
| 6748 | + * remoteport. |
|---|
| 6749 | + */ |
|---|
| 6750 | + if (ndlp->nlp_fc4_type & NLP_FC4_NVME && |
|---|
| 6751 | + ndlp->nlp_type & (NLP_NVME_TARGET | NLP_NVME_DISCOVERY)) |
|---|
| 6752 | + lpfc_nvme_rescan_port(vport, ndlp); |
|---|
| 6753 | + return 0; |
|---|
| 6754 | + } |
|---|
| 6147 | 6755 | |
|---|
| 6148 | 6756 | /* If we are about to begin discovery, just ACC the RSCN. |
|---|
| 6149 | 6757 | * Discovery processing will satisfy it. |
|---|
| .. | .. |
|---|
| 6214 | 6822 | |
|---|
| 6215 | 6823 | spin_lock_irq(shost->host_lock); |
|---|
| 6216 | 6824 | vport->fc_flag |= FC_RSCN_DEFERRED; |
|---|
| 6825 | + |
|---|
| 6826 | + /* Restart disctmo if its already running */ |
|---|
| 6827 | + if (vport->fc_flag & FC_DISC_TMO) { |
|---|
| 6828 | + tmo = ((phba->fc_ratov * 3) + 3); |
|---|
| 6829 | + mod_timer(&vport->fc_disctmo, |
|---|
| 6830 | + jiffies + msecs_to_jiffies(1000 * tmo)); |
|---|
| 6831 | + } |
|---|
| 6217 | 6832 | if ((rscn_cnt < FC_MAX_HOLD_RSCN) && |
|---|
| 6218 | 6833 | !(vport->fc_flag & FC_RSCN_DISCOVERY)) { |
|---|
| 6219 | 6834 | vport->fc_flag |= FC_RSCN_MODE; |
|---|
| .. | .. |
|---|
| 6303 | 6918 | lpfc_els_handle_rscn(struct lpfc_vport *vport) |
|---|
| 6304 | 6919 | { |
|---|
| 6305 | 6920 | struct lpfc_nodelist *ndlp; |
|---|
| 6921 | + struct lpfc_hba *phba = vport->phba; |
|---|
| 6306 | 6922 | |
|---|
| 6307 | 6923 | /* Ignore RSCN if the port is being torn down. */ |
|---|
| 6308 | 6924 | if (vport->load_flag & FC_UNLOADING) { |
|---|
| .. | .. |
|---|
| 6315 | 6931 | |
|---|
| 6316 | 6932 | /* RSCN processed */ |
|---|
| 6317 | 6933 | lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY, |
|---|
| 6318 | | - "0215 RSCN processed Data: x%x x%x x%x x%x\n", |
|---|
| 6934 | + "0215 RSCN processed Data: x%x x%x x%x x%x x%x x%x\n", |
|---|
| 6319 | 6935 | vport->fc_flag, 0, vport->fc_rscn_id_cnt, |
|---|
| 6320 | | - vport->port_state); |
|---|
| 6936 | + vport->port_state, vport->num_disc_nodes, |
|---|
| 6937 | + vport->gidft_inp); |
|---|
| 6321 | 6938 | |
|---|
| 6322 | 6939 | /* To process RSCN, first compare RSCN data with NameServer */ |
|---|
| 6323 | 6940 | vport->fc_ns_retry = 0; |
|---|
| .. | .. |
|---|
| 6331 | 6948 | * flush the RSCN. Otherwise, the outstanding requests |
|---|
| 6332 | 6949 | * need to complete. |
|---|
| 6333 | 6950 | */ |
|---|
| 6334 | | - if (lpfc_issue_gidft(vport) > 0) |
|---|
| 6951 | + if (phba->cfg_ns_query == LPFC_NS_QUERY_GID_FT) { |
|---|
| 6952 | + if (lpfc_issue_gidft(vport) > 0) |
|---|
| 6953 | + return 1; |
|---|
| 6954 | + } else if (phba->cfg_ns_query == LPFC_NS_QUERY_GID_PT) { |
|---|
| 6955 | + if (lpfc_issue_gidpt(vport) > 0) |
|---|
| 6956 | + return 1; |
|---|
| 6957 | + } else { |
|---|
| 6335 | 6958 | return 1; |
|---|
| 6959 | + } |
|---|
| 6336 | 6960 | } else { |
|---|
| 6337 | 6961 | /* Nameserver login in question. Revalidate. */ |
|---|
| 6338 | 6962 | if (ndlp) { |
|---|
| .. | .. |
|---|
| 6418 | 7042 | |
|---|
| 6419 | 7043 | /* An FLOGI ELS command <elsCmd> was received from DID <did> in |
|---|
| 6420 | 7044 | Loop Mode */ |
|---|
| 6421 | | - lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, |
|---|
| 7045 | + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, |
|---|
| 6422 | 7046 | "0113 An FLOGI ELS command x%x was " |
|---|
| 6423 | 7047 | "received from DID x%x in Loop Mode\n", |
|---|
| 6424 | 7048 | cmd, did); |
|---|
| .. | .. |
|---|
| 6508 | 7132 | |
|---|
| 6509 | 7133 | memcpy(&phba->fc_fabparam, sp, sizeof(struct serv_parm)); |
|---|
| 6510 | 7134 | |
|---|
| 7135 | + /* Defer ACC response until AFTER we issue a FLOGI */ |
|---|
| 7136 | + if (!(phba->hba_flag & HBA_FLOGI_ISSUED)) { |
|---|
| 7137 | + phba->defer_flogi_acc_rx_id = cmdiocb->iocb.ulpContext; |
|---|
| 7138 | + phba->defer_flogi_acc_ox_id = |
|---|
| 7139 | + cmdiocb->iocb.unsli3.rcvsli3.ox_id; |
|---|
| 7140 | + |
|---|
| 7141 | + vport->fc_myDID = did; |
|---|
| 7142 | + |
|---|
| 7143 | + lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, |
|---|
| 7144 | + "3344 Deferring FLOGI ACC: rx_id: x%x," |
|---|
| 7145 | + " ox_id: x%x, hba_flag x%x\n", |
|---|
| 7146 | + phba->defer_flogi_acc_rx_id, |
|---|
| 7147 | + phba->defer_flogi_acc_ox_id, phba->hba_flag); |
|---|
| 7148 | + |
|---|
| 7149 | + phba->defer_flogi_acc_flag = true; |
|---|
| 7150 | + |
|---|
| 7151 | + return 0; |
|---|
| 7152 | + } |
|---|
| 7153 | + |
|---|
| 6511 | 7154 | /* Send back ACC */ |
|---|
| 6512 | 7155 | lpfc_els_rsp_acc(vport, ELS_CMD_FLOGI, cmdiocb, ndlp, NULL); |
|---|
| 6513 | 7156 | |
|---|
| .. | .. |
|---|
| 6541 | 7184 | uint32_t *lp; |
|---|
| 6542 | 7185 | RNID *rn; |
|---|
| 6543 | 7186 | struct ls_rjt stat; |
|---|
| 6544 | | - uint32_t cmd; |
|---|
| 6545 | 7187 | |
|---|
| 6546 | 7188 | pcmd = (struct lpfc_dmabuf *) cmdiocb->context2; |
|---|
| 6547 | 7189 | lp = (uint32_t *) pcmd->virt; |
|---|
| 6548 | 7190 | |
|---|
| 6549 | | - cmd = *lp++; |
|---|
| 7191 | + lp++; |
|---|
| 6550 | 7192 | rn = (RNID *) lp; |
|---|
| 6551 | 7193 | |
|---|
| 6552 | 7194 | /* RNID received */ |
|---|
| .. | .. |
|---|
| 6680 | 7322 | |
|---|
| 6681 | 7323 | mb = &pmb->u.mb; |
|---|
| 6682 | 7324 | |
|---|
| 6683 | | - ndlp = (struct lpfc_nodelist *) pmb->context2; |
|---|
| 6684 | | - rxid = (uint16_t) ((unsigned long)(pmb->context1) & 0xffff); |
|---|
| 6685 | | - oxid = (uint16_t) (((unsigned long)(pmb->context1) >> 16) & 0xffff); |
|---|
| 6686 | | - pmb->context1 = NULL; |
|---|
| 6687 | | - pmb->context2 = NULL; |
|---|
| 7325 | + ndlp = (struct lpfc_nodelist *)pmb->ctx_ndlp; |
|---|
| 7326 | + rxid = (uint16_t)((unsigned long)(pmb->ctx_buf) & 0xffff); |
|---|
| 7327 | + oxid = (uint16_t)(((unsigned long)(pmb->ctx_buf) >> 16) & 0xffff); |
|---|
| 7328 | + pmb->ctx_buf = NULL; |
|---|
| 7329 | + pmb->ctx_ndlp = NULL; |
|---|
| 6688 | 7330 | |
|---|
| 6689 | 7331 | if (mb->mbxStatus) { |
|---|
| 6690 | 7332 | mempool_free(pmb, phba->mbox_mem_pool); |
|---|
| .. | .. |
|---|
| 6734 | 7376 | } |
|---|
| 6735 | 7377 | |
|---|
| 6736 | 7378 | /** |
|---|
| 6737 | | - * lpfc_els_rsp_rps_acc - Completion callbk func for MBX_READ_LNK_STAT mbox cmd |
|---|
| 6738 | | - * @phba: pointer to lpfc hba data structure. |
|---|
| 6739 | | - * @pmb: pointer to the driver internal queue element for mailbox command. |
|---|
| 6740 | | - * |
|---|
| 6741 | | - * This routine is the completion callback function for the MBX_READ_LNK_STAT |
|---|
| 6742 | | - * mailbox command. This callback function is to actually send the Accept |
|---|
| 6743 | | - * (ACC) response to a Read Port Status (RPS) unsolicited IOCB event. It |
|---|
| 6744 | | - * collects the link statistics from the completion of the MBX_READ_LNK_STAT |
|---|
| 6745 | | - * mailbox command, constructs the RPS response with the link statistics |
|---|
| 6746 | | - * collected, and then invokes the lpfc_sli_issue_iocb() routine to send ACC |
|---|
| 6747 | | - * response to the RPS. |
|---|
| 6748 | | - * |
|---|
| 6749 | | - * Note that, in lpfc_prep_els_iocb() routine, the reference count of ndlp |
|---|
| 6750 | | - * will be incremented by 1 for holding the ndlp and the reference to ndlp |
|---|
| 6751 | | - * will be stored into the context1 field of the IOCB for the completion |
|---|
| 6752 | | - * callback function to the RPS Accept Response ELS IOCB command. |
|---|
| 6753 | | - * |
|---|
| 6754 | | - **/ |
|---|
| 6755 | | -static void |
|---|
| 6756 | | -lpfc_els_rsp_rps_acc(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) |
|---|
| 6757 | | -{ |
|---|
| 6758 | | - MAILBOX_t *mb; |
|---|
| 6759 | | - IOCB_t *icmd; |
|---|
| 6760 | | - RPS_RSP *rps_rsp; |
|---|
| 6761 | | - uint8_t *pcmd; |
|---|
| 6762 | | - struct lpfc_iocbq *elsiocb; |
|---|
| 6763 | | - struct lpfc_nodelist *ndlp; |
|---|
| 6764 | | - uint16_t status; |
|---|
| 6765 | | - uint16_t oxid; |
|---|
| 6766 | | - uint16_t rxid; |
|---|
| 6767 | | - uint32_t cmdsize; |
|---|
| 6768 | | - |
|---|
| 6769 | | - mb = &pmb->u.mb; |
|---|
| 6770 | | - |
|---|
| 6771 | | - ndlp = (struct lpfc_nodelist *) pmb->context2; |
|---|
| 6772 | | - rxid = (uint16_t) ((unsigned long)(pmb->context1) & 0xffff); |
|---|
| 6773 | | - oxid = (uint16_t) (((unsigned long)(pmb->context1) >> 16) & 0xffff); |
|---|
| 6774 | | - pmb->context1 = NULL; |
|---|
| 6775 | | - pmb->context2 = NULL; |
|---|
| 6776 | | - |
|---|
| 6777 | | - if (mb->mbxStatus) { |
|---|
| 6778 | | - mempool_free(pmb, phba->mbox_mem_pool); |
|---|
| 6779 | | - return; |
|---|
| 6780 | | - } |
|---|
| 6781 | | - |
|---|
| 6782 | | - cmdsize = sizeof(RPS_RSP) + sizeof(uint32_t); |
|---|
| 6783 | | - mempool_free(pmb, phba->mbox_mem_pool); |
|---|
| 6784 | | - elsiocb = lpfc_prep_els_iocb(phba->pport, 0, cmdsize, |
|---|
| 6785 | | - lpfc_max_els_tries, ndlp, |
|---|
| 6786 | | - ndlp->nlp_DID, ELS_CMD_ACC); |
|---|
| 6787 | | - |
|---|
| 6788 | | - /* Decrement the ndlp reference count from previous mbox command */ |
|---|
| 6789 | | - lpfc_nlp_put(ndlp); |
|---|
| 6790 | | - |
|---|
| 6791 | | - if (!elsiocb) |
|---|
| 6792 | | - return; |
|---|
| 6793 | | - |
|---|
| 6794 | | - icmd = &elsiocb->iocb; |
|---|
| 6795 | | - icmd->ulpContext = rxid; |
|---|
| 6796 | | - icmd->unsli3.rcvsli3.ox_id = oxid; |
|---|
| 6797 | | - |
|---|
| 6798 | | - pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt); |
|---|
| 6799 | | - *((uint32_t *) (pcmd)) = ELS_CMD_ACC; |
|---|
| 6800 | | - pcmd += sizeof(uint32_t); /* Skip past command */ |
|---|
| 6801 | | - rps_rsp = (RPS_RSP *)pcmd; |
|---|
| 6802 | | - |
|---|
| 6803 | | - if (phba->fc_topology != LPFC_TOPOLOGY_LOOP) |
|---|
| 6804 | | - status = 0x10; |
|---|
| 6805 | | - else |
|---|
| 6806 | | - status = 0x8; |
|---|
| 6807 | | - if (phba->pport->fc_flag & FC_FABRIC) |
|---|
| 6808 | | - status |= 0x4; |
|---|
| 6809 | | - |
|---|
| 6810 | | - rps_rsp->rsvd1 = 0; |
|---|
| 6811 | | - rps_rsp->portStatus = cpu_to_be16(status); |
|---|
| 6812 | | - rps_rsp->linkFailureCnt = cpu_to_be32(mb->un.varRdLnk.linkFailureCnt); |
|---|
| 6813 | | - rps_rsp->lossSyncCnt = cpu_to_be32(mb->un.varRdLnk.lossSyncCnt); |
|---|
| 6814 | | - rps_rsp->lossSignalCnt = cpu_to_be32(mb->un.varRdLnk.lossSignalCnt); |
|---|
| 6815 | | - rps_rsp->primSeqErrCnt = cpu_to_be32(mb->un.varRdLnk.primSeqErrCnt); |
|---|
| 6816 | | - rps_rsp->invalidXmitWord = cpu_to_be32(mb->un.varRdLnk.invalidXmitWord); |
|---|
| 6817 | | - rps_rsp->crcCnt = cpu_to_be32(mb->un.varRdLnk.crcCnt); |
|---|
| 6818 | | - /* Xmit ELS RPS ACC response tag <ulpIoTag> */ |
|---|
| 6819 | | - lpfc_printf_vlog(ndlp->vport, KERN_INFO, LOG_ELS, |
|---|
| 6820 | | - "0118 Xmit ELS RPS ACC response tag x%x xri x%x, " |
|---|
| 6821 | | - "did x%x, nlp_flag x%x, nlp_state x%x, rpi x%x\n", |
|---|
| 6822 | | - elsiocb->iotag, elsiocb->iocb.ulpContext, |
|---|
| 6823 | | - ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state, |
|---|
| 6824 | | - ndlp->nlp_rpi); |
|---|
| 6825 | | - elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp; |
|---|
| 6826 | | - phba->fc_stat.elsXmitACC++; |
|---|
| 6827 | | - if (lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0) == IOCB_ERROR) |
|---|
| 6828 | | - lpfc_els_free_iocb(phba, elsiocb); |
|---|
| 6829 | | - return; |
|---|
| 6830 | | -} |
|---|
| 6831 | | - |
|---|
| 6832 | | -/** |
|---|
| 6833 | 7379 | * lpfc_els_rcv_rls - Process an unsolicited rls iocb |
|---|
| 6834 | 7380 | * @vport: pointer to a host virtual N_Port data structure. |
|---|
| 6835 | 7381 | * @cmdiocb: pointer to lpfc command iocb data structure. |
|---|
| 6836 | 7382 | * @ndlp: pointer to a node-list data structure. |
|---|
| 6837 | 7383 | * |
|---|
| 6838 | | - * This routine processes Read Port Status (RPL) IOCB received as an |
|---|
| 7384 | + * This routine processes Read Link Status (RLS) IOCB received as an |
|---|
| 6839 | 7385 | * ELS unsolicited event. It first checks the remote port state. If the |
|---|
| 6840 | 7386 | * remote port is not in NLP_STE_UNMAPPED_NODE state or NLP_STE_MAPPED_NODE |
|---|
| 6841 | 7387 | * state, it invokes the lpfc_els_rsl_reject() routine to send the reject |
|---|
| .. | .. |
|---|
| 6857 | 7403 | |
|---|
| 6858 | 7404 | if ((ndlp->nlp_state != NLP_STE_UNMAPPED_NODE) && |
|---|
| 6859 | 7405 | (ndlp->nlp_state != NLP_STE_MAPPED_NODE)) |
|---|
| 6860 | | - /* reject the unsolicited RPS request and done with it */ |
|---|
| 7406 | + /* reject the unsolicited RLS request and done with it */ |
|---|
| 6861 | 7407 | goto reject_out; |
|---|
| 6862 | 7408 | |
|---|
| 6863 | 7409 | mbox = mempool_alloc(phba->mbox_mem_pool, GFP_ATOMIC); |
|---|
| 6864 | 7410 | if (mbox) { |
|---|
| 6865 | 7411 | lpfc_read_lnk_stat(phba, mbox); |
|---|
| 6866 | | - mbox->context1 = (void *)((unsigned long) |
|---|
| 7412 | + mbox->ctx_buf = (void *)((unsigned long) |
|---|
| 6867 | 7413 | ((cmdiocb->iocb.unsli3.rcvsli3.ox_id << 16) | |
|---|
| 6868 | 7414 | cmdiocb->iocb.ulpContext)); /* rx_id */ |
|---|
| 6869 | | - mbox->context2 = lpfc_nlp_get(ndlp); |
|---|
| 7415 | + mbox->ctx_ndlp = lpfc_nlp_get(ndlp); |
|---|
| 6870 | 7416 | mbox->vport = vport; |
|---|
| 6871 | 7417 | mbox->mbox_cmpl = lpfc_els_rsp_rls_acc; |
|---|
| 6872 | 7418 | if (lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT) |
|---|
| .. | .. |
|---|
| 6905 | 7451 | * Note that, in lpfc_prep_els_iocb() routine, the reference count of ndlp |
|---|
| 6906 | 7452 | * will be incremented by 1 for holding the ndlp and the reference to ndlp |
|---|
| 6907 | 7453 | * will be stored into the context1 field of the IOCB for the completion |
|---|
| 6908 | | - * callback function to the RPS Accept Response ELS IOCB command. |
|---|
| 7454 | + * callback function to the RTV Accept Response ELS IOCB command. |
|---|
| 6909 | 7455 | * |
|---|
| 6910 | 7456 | * Return codes |
|---|
| 6911 | 7457 | * 0 - Successfully processed rtv iocb (currently always return 0) |
|---|
| .. | .. |
|---|
| 6924 | 7470 | |
|---|
| 6925 | 7471 | if ((ndlp->nlp_state != NLP_STE_UNMAPPED_NODE) && |
|---|
| 6926 | 7472 | (ndlp->nlp_state != NLP_STE_MAPPED_NODE)) |
|---|
| 6927 | | - /* reject the unsolicited RPS request and done with it */ |
|---|
| 7473 | + /* reject the unsolicited RTV request and done with it */ |
|---|
| 6928 | 7474 | goto reject_out; |
|---|
| 6929 | 7475 | |
|---|
| 6930 | 7476 | cmdsize = sizeof(struct RTV_RSP) + sizeof(uint32_t); |
|---|
| .. | .. |
|---|
| 6977 | 7523 | return 0; |
|---|
| 6978 | 7524 | } |
|---|
| 6979 | 7525 | |
|---|
| 6980 | | -/* lpfc_els_rcv_rps - Process an unsolicited rps iocb |
|---|
| 6981 | | - * @vport: pointer to a host virtual N_Port data structure. |
|---|
| 6982 | | - * @cmdiocb: pointer to lpfc command iocb data structure. |
|---|
| 6983 | | - * @ndlp: pointer to a node-list data structure. |
|---|
| 6984 | | - * |
|---|
| 6985 | | - * This routine processes Read Port Status (RPS) IOCB received as an |
|---|
| 6986 | | - * ELS unsolicited event. It first checks the remote port state. If the |
|---|
| 6987 | | - * remote port is not in NLP_STE_UNMAPPED_NODE state or NLP_STE_MAPPED_NODE |
|---|
| 6988 | | - * state, it invokes the lpfc_els_rsp_reject() routine to send the reject |
|---|
| 6989 | | - * response. Otherwise, it issue the MBX_READ_LNK_STAT mailbox command |
|---|
| 6990 | | - * for reading the HBA link statistics. It is for the callback function, |
|---|
| 6991 | | - * lpfc_els_rsp_rps_acc(), set to the MBX_READ_LNK_STAT mailbox command |
|---|
| 6992 | | - * to actually sending out RPS Accept (ACC) response. |
|---|
| 6993 | | - * |
|---|
| 6994 | | - * Return codes |
|---|
| 6995 | | - * 0 - Successfully processed rps iocb (currently always return 0) |
|---|
| 6996 | | - **/ |
|---|
| 6997 | | -static int |
|---|
| 6998 | | -lpfc_els_rcv_rps(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, |
|---|
| 6999 | | - struct lpfc_nodelist *ndlp) |
|---|
| 7000 | | -{ |
|---|
| 7001 | | - struct lpfc_hba *phba = vport->phba; |
|---|
| 7002 | | - uint32_t *lp; |
|---|
| 7003 | | - uint8_t flag; |
|---|
| 7004 | | - LPFC_MBOXQ_t *mbox; |
|---|
| 7005 | | - struct lpfc_dmabuf *pcmd; |
|---|
| 7006 | | - RPS *rps; |
|---|
| 7007 | | - struct ls_rjt stat; |
|---|
| 7008 | | - |
|---|
| 7009 | | - if ((ndlp->nlp_state != NLP_STE_UNMAPPED_NODE) && |
|---|
| 7010 | | - (ndlp->nlp_state != NLP_STE_MAPPED_NODE)) |
|---|
| 7011 | | - /* reject the unsolicited RPS request and done with it */ |
|---|
| 7012 | | - goto reject_out; |
|---|
| 7013 | | - |
|---|
| 7014 | | - pcmd = (struct lpfc_dmabuf *) cmdiocb->context2; |
|---|
| 7015 | | - lp = (uint32_t *) pcmd->virt; |
|---|
| 7016 | | - flag = (be32_to_cpu(*lp++) & 0xf); |
|---|
| 7017 | | - rps = (RPS *) lp; |
|---|
| 7018 | | - |
|---|
| 7019 | | - if ((flag == 0) || |
|---|
| 7020 | | - ((flag == 1) && (be32_to_cpu(rps->un.portNum) == 0)) || |
|---|
| 7021 | | - ((flag == 2) && (memcmp(&rps->un.portName, &vport->fc_portname, |
|---|
| 7022 | | - sizeof(struct lpfc_name)) == 0))) { |
|---|
| 7023 | | - |
|---|
| 7024 | | - printk("Fix me....\n"); |
|---|
| 7025 | | - dump_stack(); |
|---|
| 7026 | | - mbox = mempool_alloc(phba->mbox_mem_pool, GFP_ATOMIC); |
|---|
| 7027 | | - if (mbox) { |
|---|
| 7028 | | - lpfc_read_lnk_stat(phba, mbox); |
|---|
| 7029 | | - mbox->context1 = (void *)((unsigned long) |
|---|
| 7030 | | - ((cmdiocb->iocb.unsli3.rcvsli3.ox_id << 16) | |
|---|
| 7031 | | - cmdiocb->iocb.ulpContext)); /* rx_id */ |
|---|
| 7032 | | - mbox->context2 = lpfc_nlp_get(ndlp); |
|---|
| 7033 | | - mbox->vport = vport; |
|---|
| 7034 | | - mbox->mbox_cmpl = lpfc_els_rsp_rps_acc; |
|---|
| 7035 | | - if (lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT) |
|---|
| 7036 | | - != MBX_NOT_FINISHED) |
|---|
| 7037 | | - /* Mbox completion will send ELS Response */ |
|---|
| 7038 | | - return 0; |
|---|
| 7039 | | - /* Decrement reference count used for the failed mbox |
|---|
| 7040 | | - * command. |
|---|
| 7041 | | - */ |
|---|
| 7042 | | - lpfc_nlp_put(ndlp); |
|---|
| 7043 | | - mempool_free(mbox, phba->mbox_mem_pool); |
|---|
| 7044 | | - } |
|---|
| 7045 | | - } |
|---|
| 7046 | | - |
|---|
| 7047 | | -reject_out: |
|---|
| 7048 | | - /* issue rejection response */ |
|---|
| 7049 | | - stat.un.b.lsRjtRsvd0 = 0; |
|---|
| 7050 | | - stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; |
|---|
| 7051 | | - stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA; |
|---|
| 7052 | | - stat.un.b.vendorUnique = 0; |
|---|
| 7053 | | - lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, NULL); |
|---|
| 7054 | | - return 0; |
|---|
| 7055 | | -} |
|---|
| 7056 | | - |
|---|
| 7057 | | -/* lpfc_issue_els_rrq - Process an unsolicited rps iocb |
|---|
| 7526 | +/* lpfc_issue_els_rrq - Process an unsolicited rrq iocb |
|---|
| 7058 | 7527 | * @vport: pointer to a host virtual N_Port data structure. |
|---|
| 7059 | 7528 | * @ndlp: pointer to a node-list data structure. |
|---|
| 7060 | 7529 | * @did: DID of the target. |
|---|
| .. | .. |
|---|
| 7308 | 7777 | uint32_t *lp; |
|---|
| 7309 | 7778 | IOCB_t *icmd; |
|---|
| 7310 | 7779 | FARP *fp; |
|---|
| 7311 | | - uint32_t cmd, cnt, did; |
|---|
| 7780 | + uint32_t cnt, did; |
|---|
| 7312 | 7781 | |
|---|
| 7313 | 7782 | icmd = &cmdiocb->iocb; |
|---|
| 7314 | 7783 | did = icmd->un.elsreq64.remoteID; |
|---|
| 7315 | 7784 | pcmd = (struct lpfc_dmabuf *) cmdiocb->context2; |
|---|
| 7316 | 7785 | lp = (uint32_t *) pcmd->virt; |
|---|
| 7317 | 7786 | |
|---|
| 7318 | | - cmd = *lp++; |
|---|
| 7787 | + lp++; |
|---|
| 7319 | 7788 | fp = (FARP *) lp; |
|---|
| 7320 | 7789 | /* FARP-REQ received from DID <did> */ |
|---|
| 7321 | 7790 | lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, |
|---|
| .. | .. |
|---|
| 7380 | 7849 | struct lpfc_dmabuf *pcmd; |
|---|
| 7381 | 7850 | uint32_t *lp; |
|---|
| 7382 | 7851 | IOCB_t *icmd; |
|---|
| 7383 | | - uint32_t cmd, did; |
|---|
| 7852 | + uint32_t did; |
|---|
| 7384 | 7853 | |
|---|
| 7385 | 7854 | icmd = &cmdiocb->iocb; |
|---|
| 7386 | 7855 | did = icmd->un.elsreq64.remoteID; |
|---|
| 7387 | 7856 | pcmd = (struct lpfc_dmabuf *) cmdiocb->context2; |
|---|
| 7388 | 7857 | lp = (uint32_t *) pcmd->virt; |
|---|
| 7389 | 7858 | |
|---|
| 7390 | | - cmd = *lp++; |
|---|
| 7859 | + lp++; |
|---|
| 7391 | 7860 | /* FARP-RSP received from DID <did> */ |
|---|
| 7392 | 7861 | lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, |
|---|
| 7393 | 7862 | "0600 FARP-RSP received from DID x%x\n", did); |
|---|
| .. | .. |
|---|
| 7454 | 7923 | |
|---|
| 7455 | 7924 | /** |
|---|
| 7456 | 7925 | * lpfc_els_timeout - Handler funciton to the els timer |
|---|
| 7457 | | - * @ptr: holder for the timer function associated data. |
|---|
| 7926 | + * @t: timer context used to obtain the vport. |
|---|
| 7458 | 7927 | * |
|---|
| 7459 | 7928 | * This routine is invoked by the ELS timer after timeout. It posts the ELS |
|---|
| 7460 | 7929 | * timer timeout event by setting the WORKER_ELS_TMO bit to the work port |
|---|
| .. | .. |
|---|
| 7511 | 7980 | if (unlikely(!pring)) |
|---|
| 7512 | 7981 | return; |
|---|
| 7513 | 7982 | |
|---|
| 7514 | | - if ((phba->pport->load_flag & FC_UNLOADING)) |
|---|
| 7983 | + if (phba->pport->load_flag & FC_UNLOADING) |
|---|
| 7515 | 7984 | return; |
|---|
| 7985 | + |
|---|
| 7516 | 7986 | spin_lock_irq(&phba->hbalock); |
|---|
| 7517 | 7987 | if (phba->sli_rev == LPFC_SLI_REV4) |
|---|
| 7518 | 7988 | spin_lock(&pring->ring_lock); |
|---|
| 7519 | | - |
|---|
| 7520 | | - if ((phba->pport->load_flag & FC_UNLOADING)) { |
|---|
| 7521 | | - if (phba->sli_rev == LPFC_SLI_REV4) |
|---|
| 7522 | | - spin_unlock(&pring->ring_lock); |
|---|
| 7523 | | - spin_unlock_irq(&phba->hbalock); |
|---|
| 7524 | | - return; |
|---|
| 7525 | | - } |
|---|
| 7526 | 7989 | |
|---|
| 7527 | 7990 | list_for_each_entry_safe(piocb, tmp_iocb, &pring->txcmplq, list) { |
|---|
| 7528 | 7991 | cmd = &piocb->iocb; |
|---|
| .. | .. |
|---|
| 7569 | 8032 | |
|---|
| 7570 | 8033 | list_for_each_entry_safe(piocb, tmp_iocb, &abort_list, dlist) { |
|---|
| 7571 | 8034 | cmd = &piocb->iocb; |
|---|
| 7572 | | - lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, |
|---|
| 8035 | + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, |
|---|
| 7573 | 8036 | "0127 ELS timeout Data: x%x x%x x%x " |
|---|
| 7574 | 8037 | "x%x\n", els_command, |
|---|
| 7575 | 8038 | remote_ID, cmd->ulpCommand, cmd->ulpIoTag); |
|---|
| .. | .. |
|---|
| 7613 | 8076 | struct lpfc_sli_ring *pring; |
|---|
| 7614 | 8077 | struct lpfc_iocbq *tmp_iocb, *piocb; |
|---|
| 7615 | 8078 | IOCB_t *cmd = NULL; |
|---|
| 8079 | + unsigned long iflags = 0; |
|---|
| 7616 | 8080 | |
|---|
| 7617 | 8081 | lpfc_fabric_abort_vport(vport); |
|---|
| 8082 | + |
|---|
| 7618 | 8083 | /* |
|---|
| 7619 | 8084 | * For SLI3, only the hbalock is required. But SLI4 needs to coordinate |
|---|
| 7620 | 8085 | * with the ring insert operation. Because lpfc_sli_issue_abort_iotag |
|---|
| 7621 | 8086 | * ultimately grabs the ring_lock, the driver must splice the list into |
|---|
| 7622 | 8087 | * a working list and release the locks before calling the abort. |
|---|
| 7623 | 8088 | */ |
|---|
| 7624 | | - spin_lock_irq(&phba->hbalock); |
|---|
| 8089 | + spin_lock_irqsave(&phba->hbalock, iflags); |
|---|
| 7625 | 8090 | pring = lpfc_phba_elsring(phba); |
|---|
| 7626 | 8091 | |
|---|
| 7627 | 8092 | /* Bail out if we've no ELS wq, like in PCI error recovery case. */ |
|---|
| 7628 | 8093 | if (unlikely(!pring)) { |
|---|
| 7629 | | - spin_unlock_irq(&phba->hbalock); |
|---|
| 8094 | + spin_unlock_irqrestore(&phba->hbalock, iflags); |
|---|
| 7630 | 8095 | return; |
|---|
| 7631 | 8096 | } |
|---|
| 7632 | 8097 | |
|---|
| 7633 | 8098 | if (phba->sli_rev == LPFC_SLI_REV4) |
|---|
| 7634 | 8099 | spin_lock(&pring->ring_lock); |
|---|
| 7635 | 8100 | |
|---|
| 8101 | + /* First we need to issue aborts to outstanding cmds on txcmpl */ |
|---|
| 7636 | 8102 | list_for_each_entry_safe(piocb, tmp_iocb, &pring->txcmplq, list) { |
|---|
| 7637 | 8103 | if (piocb->iocb_flag & LPFC_IO_LIBDFC) |
|---|
| 7638 | 8104 | continue; |
|---|
| 7639 | 8105 | |
|---|
| 7640 | 8106 | if (piocb->vport != vport) |
|---|
| 7641 | 8107 | continue; |
|---|
| 7642 | | - list_add_tail(&piocb->dlist, &abort_list); |
|---|
| 8108 | + |
|---|
| 8109 | + if (piocb->iocb_flag & LPFC_DRIVER_ABORTED) |
|---|
| 8110 | + continue; |
|---|
| 8111 | + |
|---|
| 8112 | + /* On the ELS ring we can have ELS_REQUESTs or |
|---|
| 8113 | + * GEN_REQUESTs waiting for a response. |
|---|
| 8114 | + */ |
|---|
| 8115 | + cmd = &piocb->iocb; |
|---|
| 8116 | + if (cmd->ulpCommand == CMD_ELS_REQUEST64_CR) { |
|---|
| 8117 | + list_add_tail(&piocb->dlist, &abort_list); |
|---|
| 8118 | + |
|---|
| 8119 | + /* If the link is down when flushing ELS commands |
|---|
| 8120 | + * the firmware will not complete them till after |
|---|
| 8121 | + * the link comes back up. This may confuse |
|---|
| 8122 | + * discovery for the new link up, so we need to |
|---|
| 8123 | + * change the compl routine to just clean up the iocb |
|---|
| 8124 | + * and avoid any retry logic. |
|---|
| 8125 | + */ |
|---|
| 8126 | + if (phba->link_state == LPFC_LINK_DOWN) |
|---|
| 8127 | + piocb->iocb_cmpl = lpfc_cmpl_els_link_down; |
|---|
| 8128 | + } |
|---|
| 8129 | + if (cmd->ulpCommand == CMD_GEN_REQUEST64_CR) |
|---|
| 8130 | + list_add_tail(&piocb->dlist, &abort_list); |
|---|
| 7643 | 8131 | } |
|---|
| 8132 | + |
|---|
| 7644 | 8133 | if (phba->sli_rev == LPFC_SLI_REV4) |
|---|
| 7645 | 8134 | spin_unlock(&pring->ring_lock); |
|---|
| 7646 | | - spin_unlock_irq(&phba->hbalock); |
|---|
| 7647 | | - /* Abort each iocb on the aborted list and remove the dlist links. */ |
|---|
| 8135 | + spin_unlock_irqrestore(&phba->hbalock, iflags); |
|---|
| 8136 | + |
|---|
| 8137 | + /* Abort each txcmpl iocb on aborted list and remove the dlist links. */ |
|---|
| 7648 | 8138 | list_for_each_entry_safe(piocb, tmp_iocb, &abort_list, dlist) { |
|---|
| 7649 | | - spin_lock_irq(&phba->hbalock); |
|---|
| 8139 | + spin_lock_irqsave(&phba->hbalock, iflags); |
|---|
| 7650 | 8140 | list_del_init(&piocb->dlist); |
|---|
| 7651 | 8141 | lpfc_sli_issue_abort_iotag(phba, pring, piocb); |
|---|
| 7652 | | - spin_unlock_irq(&phba->hbalock); |
|---|
| 8142 | + spin_unlock_irqrestore(&phba->hbalock, iflags); |
|---|
| 7653 | 8143 | } |
|---|
| 7654 | 8144 | if (!list_empty(&abort_list)) |
|---|
| 7655 | | - lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, |
|---|
| 8145 | + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, |
|---|
| 7656 | 8146 | "3387 abort list for txq not empty\n"); |
|---|
| 7657 | 8147 | INIT_LIST_HEAD(&abort_list); |
|---|
| 7658 | 8148 | |
|---|
| 7659 | | - spin_lock_irq(&phba->hbalock); |
|---|
| 8149 | + spin_lock_irqsave(&phba->hbalock, iflags); |
|---|
| 7660 | 8150 | if (phba->sli_rev == LPFC_SLI_REV4) |
|---|
| 7661 | 8151 | spin_lock(&pring->ring_lock); |
|---|
| 7662 | 8152 | |
|---|
| 8153 | + /* No need to abort the txq list, |
|---|
| 8154 | + * just queue them up for lpfc_sli_cancel_iocbs |
|---|
| 8155 | + */ |
|---|
| 7663 | 8156 | list_for_each_entry_safe(piocb, tmp_iocb, &pring->txq, list) { |
|---|
| 7664 | 8157 | cmd = &piocb->iocb; |
|---|
| 7665 | 8158 | |
|---|
| .. | .. |
|---|
| 7680 | 8173 | list_del_init(&piocb->list); |
|---|
| 7681 | 8174 | list_add_tail(&piocb->list, &abort_list); |
|---|
| 7682 | 8175 | } |
|---|
| 8176 | + |
|---|
| 8177 | + /* The same holds true for any FLOGI/FDISC on the fabric_iocb_list */ |
|---|
| 8178 | + if (vport == phba->pport) { |
|---|
| 8179 | + list_for_each_entry_safe(piocb, tmp_iocb, |
|---|
| 8180 | + &phba->fabric_iocb_list, list) { |
|---|
| 8181 | + cmd = &piocb->iocb; |
|---|
| 8182 | + list_del_init(&piocb->list); |
|---|
| 8183 | + list_add_tail(&piocb->list, &abort_list); |
|---|
| 8184 | + } |
|---|
| 8185 | + } |
|---|
| 8186 | + |
|---|
| 7683 | 8187 | if (phba->sli_rev == LPFC_SLI_REV4) |
|---|
| 7684 | 8188 | spin_unlock(&pring->ring_lock); |
|---|
| 7685 | | - spin_unlock_irq(&phba->hbalock); |
|---|
| 8189 | + spin_unlock_irqrestore(&phba->hbalock, iflags); |
|---|
| 7686 | 8190 | |
|---|
| 7687 | | - /* Cancell all the IOCBs from the completions list */ |
|---|
| 8191 | + /* Cancel all the IOCBs from the completions list */ |
|---|
| 7688 | 8192 | lpfc_sli_cancel_iocbs(phba, &abort_list, |
|---|
| 7689 | 8193 | IOSTAT_LOCAL_REJECT, IOERR_SLI_ABORTED); |
|---|
| 7690 | 8194 | |
|---|
| .. | .. |
|---|
| 7712 | 8216 | lpfc_els_flush_all_cmd(struct lpfc_hba *phba) |
|---|
| 7713 | 8217 | { |
|---|
| 7714 | 8218 | struct lpfc_vport *vport; |
|---|
| 8219 | + |
|---|
| 8220 | + spin_lock_irq(&phba->port_list_lock); |
|---|
| 7715 | 8221 | list_for_each_entry(vport, &phba->port_list, listentry) |
|---|
| 7716 | 8222 | lpfc_els_flush_cmd(vport); |
|---|
| 8223 | + spin_unlock_irq(&phba->port_list_lock); |
|---|
| 7717 | 8224 | |
|---|
| 7718 | 8225 | return; |
|---|
| 7719 | 8226 | } |
|---|
| .. | .. |
|---|
| 7789 | 8296 | * lpfc_send_els_event - Posts unsolicited els event |
|---|
| 7790 | 8297 | * @vport: Pointer to vport object. |
|---|
| 7791 | 8298 | * @ndlp: Pointer FC node object. |
|---|
| 7792 | | - * @cmd: ELS command code. |
|---|
| 8299 | + * @payload: ELS command code type. |
|---|
| 7793 | 8300 | * |
|---|
| 7794 | 8301 | * This function posts an event when there is an incoming |
|---|
| 7795 | 8302 | * unsolicited ELS command. |
|---|
| .. | .. |
|---|
| 7806 | 8313 | if (*payload == ELS_CMD_LOGO) { |
|---|
| 7807 | 8314 | logo_data = kmalloc(sizeof(struct lpfc_logo_event), GFP_KERNEL); |
|---|
| 7808 | 8315 | if (!logo_data) { |
|---|
| 7809 | | - lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, |
|---|
| 8316 | + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, |
|---|
| 7810 | 8317 | "0148 Failed to allocate memory " |
|---|
| 7811 | 8318 | "for LOGO event\n"); |
|---|
| 7812 | 8319 | return; |
|---|
| .. | .. |
|---|
| 7816 | 8323 | els_data = kmalloc(sizeof(struct lpfc_els_event_header), |
|---|
| 7817 | 8324 | GFP_KERNEL); |
|---|
| 7818 | 8325 | if (!els_data) { |
|---|
| 7819 | | - lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, |
|---|
| 8326 | + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, |
|---|
| 7820 | 8327 | "0149 Failed to allocate memory " |
|---|
| 7821 | 8328 | "for ELS event\n"); |
|---|
| 7822 | 8329 | return; |
|---|
| .. | .. |
|---|
| 7865 | 8372 | } |
|---|
| 7866 | 8373 | |
|---|
| 7867 | 8374 | |
|---|
| 8375 | +DECLARE_ENUM2STR_LOOKUP(lpfc_get_tlv_dtag_nm, fc_ls_tlv_dtag, |
|---|
| 8376 | + FC_LS_TLV_DTAG_INIT); |
|---|
| 8377 | + |
|---|
| 8378 | +DECLARE_ENUM2STR_LOOKUP(lpfc_get_fpin_li_event_nm, fc_fpin_li_event_types, |
|---|
| 8379 | + FC_FPIN_LI_EVT_TYPES_INIT); |
|---|
| 8380 | + |
|---|
| 8381 | +/** |
|---|
| 8382 | + * lpfc_els_rcv_fpin_li - Process an FPIN Link Integrity Event. |
|---|
| 8383 | + * @vport: Pointer to vport object. |
|---|
| 8384 | + * @tlv: Pointer to the Link Integrity Notification Descriptor. |
|---|
| 8385 | + * |
|---|
| 8386 | + * This function processes a link integrity FPIN event by |
|---|
| 8387 | + * logging a message |
|---|
| 8388 | + **/ |
|---|
| 8389 | +static void |
|---|
| 8390 | +lpfc_els_rcv_fpin_li(struct lpfc_vport *vport, struct fc_tlv_desc *tlv) |
|---|
| 8391 | +{ |
|---|
| 8392 | + struct fc_fn_li_desc *li = (struct fc_fn_li_desc *)tlv; |
|---|
| 8393 | + const char *li_evt_str; |
|---|
| 8394 | + u32 li_evt; |
|---|
| 8395 | + |
|---|
| 8396 | + li_evt = be16_to_cpu(li->event_type); |
|---|
| 8397 | + li_evt_str = lpfc_get_fpin_li_event_nm(li_evt); |
|---|
| 8398 | + |
|---|
| 8399 | + lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, |
|---|
| 8400 | + "4680 FPIN Link Integrity %s (x%x) " |
|---|
| 8401 | + "Detecting PN x%016llx Attached PN x%016llx " |
|---|
| 8402 | + "Duration %d mSecs Count %d Port Cnt %d\n", |
|---|
| 8403 | + li_evt_str, li_evt, |
|---|
| 8404 | + be64_to_cpu(li->detecting_wwpn), |
|---|
| 8405 | + be64_to_cpu(li->attached_wwpn), |
|---|
| 8406 | + be32_to_cpu(li->event_threshold), |
|---|
| 8407 | + be32_to_cpu(li->event_count), |
|---|
| 8408 | + be32_to_cpu(li->pname_count)); |
|---|
| 8409 | +} |
|---|
| 8410 | + |
|---|
| 8411 | +static void |
|---|
| 8412 | +lpfc_els_rcv_fpin(struct lpfc_vport *vport, struct fc_els_fpin *fpin, |
|---|
| 8413 | + u32 fpin_length) |
|---|
| 8414 | +{ |
|---|
| 8415 | + struct fc_tlv_desc *tlv; |
|---|
| 8416 | + const char *dtag_nm; |
|---|
| 8417 | + uint32_t desc_cnt = 0, bytes_remain; |
|---|
| 8418 | + u32 dtag; |
|---|
| 8419 | + |
|---|
| 8420 | + /* FPINs handled only if we are in the right discovery state */ |
|---|
| 8421 | + if (vport->port_state < LPFC_DISC_AUTH) |
|---|
| 8422 | + return; |
|---|
| 8423 | + |
|---|
| 8424 | + /* make sure there is the full fpin header */ |
|---|
| 8425 | + if (fpin_length < sizeof(struct fc_els_fpin)) |
|---|
| 8426 | + return; |
|---|
| 8427 | + |
|---|
| 8428 | + tlv = (struct fc_tlv_desc *)&fpin->fpin_desc[0]; |
|---|
| 8429 | + bytes_remain = fpin_length - offsetof(struct fc_els_fpin, fpin_desc); |
|---|
| 8430 | + bytes_remain = min_t(u32, bytes_remain, be32_to_cpu(fpin->desc_len)); |
|---|
| 8431 | + |
|---|
| 8432 | + /* process each descriptor */ |
|---|
| 8433 | + while (bytes_remain >= FC_TLV_DESC_HDR_SZ && |
|---|
| 8434 | + bytes_remain >= FC_TLV_DESC_SZ_FROM_LENGTH(tlv)) { |
|---|
| 8435 | + |
|---|
| 8436 | + dtag = be32_to_cpu(tlv->desc_tag); |
|---|
| 8437 | + switch (dtag) { |
|---|
| 8438 | + case ELS_DTAG_LNK_INTEGRITY: |
|---|
| 8439 | + lpfc_els_rcv_fpin_li(vport, tlv); |
|---|
| 8440 | + break; |
|---|
| 8441 | + default: |
|---|
| 8442 | + dtag_nm = lpfc_get_tlv_dtag_nm(dtag); |
|---|
| 8443 | + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, |
|---|
| 8444 | + "4678 skipped FPIN descriptor[%d]: " |
|---|
| 8445 | + "tag x%x (%s)\n", |
|---|
| 8446 | + desc_cnt, dtag, dtag_nm); |
|---|
| 8447 | + break; |
|---|
| 8448 | + } |
|---|
| 8449 | + |
|---|
| 8450 | + desc_cnt++; |
|---|
| 8451 | + bytes_remain -= FC_TLV_DESC_SZ_FROM_LENGTH(tlv); |
|---|
| 8452 | + tlv = fc_tlv_next_desc(tlv); |
|---|
| 8453 | + } |
|---|
| 8454 | + |
|---|
| 8455 | + fc_host_fpin_rcv(lpfc_shost_from_vport(vport), fpin_length, |
|---|
| 8456 | + (char *)fpin); |
|---|
| 8457 | +} |
|---|
| 8458 | + |
|---|
| 7868 | 8459 | /** |
|---|
| 7869 | 8460 | * lpfc_els_unsol_buffer - Process an unsolicited event data buffer |
|---|
| 7870 | 8461 | * @phba: pointer to lpfc hba data structure. |
|---|
| .. | .. |
|---|
| 7886 | 8477 | struct Scsi_Host *shost; |
|---|
| 7887 | 8478 | struct lpfc_nodelist *ndlp; |
|---|
| 7888 | 8479 | struct ls_rjt stat; |
|---|
| 7889 | | - uint32_t *payload; |
|---|
| 8480 | + uint32_t *payload, payload_len; |
|---|
| 7890 | 8481 | uint32_t cmd, did, newnode; |
|---|
| 7891 | 8482 | uint8_t rjt_exp, rjt_err = 0, init_link = 0; |
|---|
| 7892 | 8483 | IOCB_t *icmd = &elsiocb->iocb; |
|---|
| .. | .. |
|---|
| 7897 | 8488 | |
|---|
| 7898 | 8489 | newnode = 0; |
|---|
| 7899 | 8490 | payload = ((struct lpfc_dmabuf *)elsiocb->context2)->virt; |
|---|
| 8491 | + payload_len = elsiocb->iocb.unsli3.rcvsli3.acc_len; |
|---|
| 7900 | 8492 | cmd = *payload; |
|---|
| 7901 | 8493 | if ((phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) == 0) |
|---|
| 7902 | 8494 | lpfc_post_buffer(phba, pring, 1); |
|---|
| .. | .. |
|---|
| 7979 | 8571 | cmd, did, vport->port_state, vport->fc_flag, |
|---|
| 7980 | 8572 | vport->fc_myDID, vport->fc_prevDID); |
|---|
| 7981 | 8573 | |
|---|
| 7982 | | - /* reject till our FLOGI completes */ |
|---|
| 8574 | + /* reject till our FLOGI completes or PLOGI assigned DID via PT2PT */ |
|---|
| 7983 | 8575 | if ((vport->port_state < LPFC_FABRIC_CFG_LINK) && |
|---|
| 7984 | | - (cmd != ELS_CMD_FLOGI)) { |
|---|
| 8576 | + (cmd != ELS_CMD_FLOGI) && |
|---|
| 8577 | + !((cmd == ELS_CMD_PLOGI) && (vport->fc_flag & FC_PT2PT))) { |
|---|
| 7985 | 8578 | rjt_err = LSRJT_LOGICAL_BSY; |
|---|
| 7986 | 8579 | rjt_exp = LSEXP_NOTHING_MORE; |
|---|
| 7987 | 8580 | goto lsrjt; |
|---|
| .. | .. |
|---|
| 8188 | 8781 | if (newnode) |
|---|
| 8189 | 8782 | lpfc_nlp_put(ndlp); |
|---|
| 8190 | 8783 | break; |
|---|
| 8191 | | - case ELS_CMD_RPS: |
|---|
| 8192 | | - lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL, |
|---|
| 8193 | | - "RCV RPS: did:x%x/ste:x%x flg:x%x", |
|---|
| 8194 | | - did, vport->port_state, ndlp->nlp_flag); |
|---|
| 8195 | | - |
|---|
| 8196 | | - phba->fc_stat.elsRcvRPS++; |
|---|
| 8197 | | - lpfc_els_rcv_rps(vport, elsiocb, ndlp); |
|---|
| 8198 | | - if (newnode) |
|---|
| 8199 | | - lpfc_nlp_put(ndlp); |
|---|
| 8200 | | - break; |
|---|
| 8201 | 8784 | case ELS_CMD_RPL: |
|---|
| 8202 | 8785 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL, |
|---|
| 8203 | 8786 | "RCV RPL: did:x%x/ste:x%x flg:x%x", |
|---|
| .. | .. |
|---|
| 8252 | 8835 | rjt_err = LSRJT_UNABLE_TPC; |
|---|
| 8253 | 8836 | rjt_exp = LSEXP_INVALID_OX_RX; |
|---|
| 8254 | 8837 | break; |
|---|
| 8838 | + case ELS_CMD_FPIN: |
|---|
| 8839 | + lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL, |
|---|
| 8840 | + "RCV FPIN: did:x%x/ste:x%x flg:x%x", |
|---|
| 8841 | + did, vport->port_state, ndlp->nlp_flag); |
|---|
| 8842 | + |
|---|
| 8843 | + lpfc_els_rcv_fpin(vport, (struct fc_els_fpin *)payload, |
|---|
| 8844 | + payload_len); |
|---|
| 8845 | + |
|---|
| 8846 | + /* There are no replies, so no rjt codes */ |
|---|
| 8847 | + break; |
|---|
| 8255 | 8848 | default: |
|---|
| 8256 | 8849 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL, |
|---|
| 8257 | 8850 | "RCV ELS cmd: cmd:x%x did:x%x/ste:x%x", |
|---|
| .. | .. |
|---|
| 8262 | 8855 | rjt_exp = LSEXP_NOTHING_MORE; |
|---|
| 8263 | 8856 | |
|---|
| 8264 | 8857 | /* Unknown ELS command <elsCmd> received from NPORT <did> */ |
|---|
| 8265 | | - lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, |
|---|
| 8858 | + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, |
|---|
| 8266 | 8859 | "0115 Unknown ELS command x%x " |
|---|
| 8267 | 8860 | "received from NPORT x%x\n", cmd, did); |
|---|
| 8268 | 8861 | if (newnode) |
|---|
| .. | .. |
|---|
| 8307 | 8900 | |
|---|
| 8308 | 8901 | dropit: |
|---|
| 8309 | 8902 | if (vport && !(vport->load_flag & FC_UNLOADING)) |
|---|
| 8310 | | - lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, |
|---|
| 8903 | + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, |
|---|
| 8311 | 8904 | "0111 Dropping received ELS cmd " |
|---|
| 8312 | 8905 | "Data: x%x x%x x%x\n", |
|---|
| 8313 | 8906 | icmd->ulpStatus, icmd->un.ulpWord[4], icmd->ulpTimeout); |
|---|
| .. | .. |
|---|
| 8457 | 9050 | spin_lock_irq(shost->host_lock); |
|---|
| 8458 | 9051 | if (vport->fc_flag & FC_DISC_DELAYED) { |
|---|
| 8459 | 9052 | spin_unlock_irq(shost->host_lock); |
|---|
| 8460 | | - lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY, |
|---|
| 9053 | + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, |
|---|
| 8461 | 9054 | "3334 Delay fc port discovery for %d seconds\n", |
|---|
| 8462 | 9055 | phba->fc_ratov); |
|---|
| 8463 | 9056 | mod_timer(&vport->delayed_disc_tmo, |
|---|
| .. | .. |
|---|
| 8475 | 9068 | return; |
|---|
| 8476 | 9069 | } |
|---|
| 8477 | 9070 | lpfc_vport_set_state(vport, FC_VPORT_FAILED); |
|---|
| 8478 | | - lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, |
|---|
| 9071 | + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, |
|---|
| 8479 | 9072 | "0251 NameServer login: no memory\n"); |
|---|
| 8480 | 9073 | return; |
|---|
| 8481 | 9074 | } |
|---|
| .. | .. |
|---|
| 8487 | 9080 | return; |
|---|
| 8488 | 9081 | } |
|---|
| 8489 | 9082 | lpfc_vport_set_state(vport, FC_VPORT_FAILED); |
|---|
| 8490 | | - lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, |
|---|
| 9083 | + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, |
|---|
| 8491 | 9084 | "0348 NameServer login: node freed\n"); |
|---|
| 8492 | 9085 | return; |
|---|
| 8493 | 9086 | } |
|---|
| .. | .. |
|---|
| 8498 | 9091 | |
|---|
| 8499 | 9092 | if (lpfc_issue_els_plogi(vport, ndlp->nlp_DID, 0)) { |
|---|
| 8500 | 9093 | lpfc_vport_set_state(vport, FC_VPORT_FAILED); |
|---|
| 8501 | | - lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, |
|---|
| 9094 | + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, |
|---|
| 8502 | 9095 | "0252 Cannot issue NameServer login\n"); |
|---|
| 8503 | 9096 | return; |
|---|
| 8504 | 9097 | } |
|---|
| .. | .. |
|---|
| 8526 | 9119 | { |
|---|
| 8527 | 9120 | struct lpfc_vport *vport = pmb->vport; |
|---|
| 8528 | 9121 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); |
|---|
| 8529 | | - struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) pmb->context2; |
|---|
| 9122 | + struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *)pmb->ctx_ndlp; |
|---|
| 8530 | 9123 | MAILBOX_t *mb = &pmb->u.mb; |
|---|
| 8531 | 9124 | int rc; |
|---|
| 8532 | 9125 | |
|---|
| .. | .. |
|---|
| 8535 | 9128 | spin_unlock_irq(shost->host_lock); |
|---|
| 8536 | 9129 | |
|---|
| 8537 | 9130 | if (mb->mbxStatus) { |
|---|
| 8538 | | - lpfc_printf_vlog(vport, KERN_ERR, LOG_MBOX, |
|---|
| 9131 | + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, |
|---|
| 8539 | 9132 | "0915 Register VPI failed : Status: x%x" |
|---|
| 8540 | 9133 | " upd bit: x%x \n", mb->mbxStatus, |
|---|
| 8541 | 9134 | mb->un.varRegVpi.upd); |
|---|
| .. | .. |
|---|
| 8565 | 9158 | rc = lpfc_sli_issue_mbox(phba, pmb, |
|---|
| 8566 | 9159 | MBX_NOWAIT); |
|---|
| 8567 | 9160 | if (rc == MBX_NOT_FINISHED) { |
|---|
| 8568 | | - lpfc_printf_vlog(vport, |
|---|
| 8569 | | - KERN_ERR, LOG_MBOX, |
|---|
| 9161 | + lpfc_printf_vlog(vport, KERN_ERR, |
|---|
| 9162 | + LOG_TRACE_EVENT, |
|---|
| 8570 | 9163 | "2732 Failed to issue INIT_VPI" |
|---|
| 8571 | 9164 | " mailbox command\n"); |
|---|
| 8572 | 9165 | } else { |
|---|
| 8573 | 9166 | lpfc_nlp_put(ndlp); |
|---|
| 8574 | 9167 | return; |
|---|
| 8575 | 9168 | } |
|---|
| 8576 | | - |
|---|
| 9169 | + fallthrough; |
|---|
| 8577 | 9170 | default: |
|---|
| 8578 | 9171 | /* Try to recover from this error */ |
|---|
| 8579 | 9172 | if (phba->sli_rev == LPFC_SLI_REV4) |
|---|
| .. | .. |
|---|
| 8644 | 9237 | if (mbox) { |
|---|
| 8645 | 9238 | lpfc_reg_vpi(vport, mbox); |
|---|
| 8646 | 9239 | mbox->vport = vport; |
|---|
| 8647 | | - mbox->context2 = lpfc_nlp_get(ndlp); |
|---|
| 9240 | + mbox->ctx_ndlp = lpfc_nlp_get(ndlp); |
|---|
| 8648 | 9241 | mbox->mbox_cmpl = lpfc_cmpl_reg_new_vport; |
|---|
| 8649 | 9242 | if (lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT) |
|---|
| 8650 | 9243 | == MBX_NOT_FINISHED) { |
|---|
| .. | .. |
|---|
| 8654 | 9247 | lpfc_nlp_put(ndlp); |
|---|
| 8655 | 9248 | mempool_free(mbox, phba->mbox_mem_pool); |
|---|
| 8656 | 9249 | |
|---|
| 8657 | | - lpfc_printf_vlog(vport, KERN_ERR, LOG_MBOX, |
|---|
| 9250 | + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, |
|---|
| 8658 | 9251 | "0253 Register VPI: Can't send mbox\n"); |
|---|
| 8659 | 9252 | goto mbox_err_exit; |
|---|
| 8660 | 9253 | } |
|---|
| 8661 | 9254 | } else { |
|---|
| 8662 | | - lpfc_printf_vlog(vport, KERN_ERR, LOG_MBOX, |
|---|
| 9255 | + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, |
|---|
| 8663 | 9256 | "0254 Register VPI: no memory\n"); |
|---|
| 8664 | 9257 | goto mbox_err_exit; |
|---|
| 8665 | 9258 | } |
|---|
| .. | .. |
|---|
| 8821 | 9414 | if (lpfc_els_retry(phba, cmdiocb, rspiocb)) |
|---|
| 8822 | 9415 | goto out; |
|---|
| 8823 | 9416 | /* FDISC failed */ |
|---|
| 8824 | | - lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, |
|---|
| 9417 | + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, |
|---|
| 8825 | 9418 | "0126 FDISC failed. (x%x/x%x)\n", |
|---|
| 8826 | 9419 | irsp->ulpStatus, irsp->un.ulpWord[4]); |
|---|
| 8827 | 9420 | goto fdisc_failed; |
|---|
| .. | .. |
|---|
| 8943 | 9536 | ELS_CMD_FDISC); |
|---|
| 8944 | 9537 | if (!elsiocb) { |
|---|
| 8945 | 9538 | lpfc_vport_set_state(vport, FC_VPORT_FAILED); |
|---|
| 8946 | | - lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, |
|---|
| 9539 | + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, |
|---|
| 8947 | 9540 | "0255 Issue FDISC: no IOCB\n"); |
|---|
| 8948 | 9541 | return 1; |
|---|
| 8949 | 9542 | } |
|---|
| .. | .. |
|---|
| 8997 | 9590 | if (rc == IOCB_ERROR) { |
|---|
| 8998 | 9591 | lpfc_els_free_iocb(phba, elsiocb); |
|---|
| 8999 | 9592 | lpfc_vport_set_state(vport, FC_VPORT_FAILED); |
|---|
| 9000 | | - lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, |
|---|
| 9593 | + lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT, |
|---|
| 9001 | 9594 | "0256 Issue FDISC: Cannot send IOCB\n"); |
|---|
| 9002 | 9595 | return 1; |
|---|
| 9003 | 9596 | } |
|---|
| .. | .. |
|---|
| 9117 | 9710 | |
|---|
| 9118 | 9711 | /** |
|---|
| 9119 | 9712 | * lpfc_fabric_block_timeout - Handler function to the fabric block timer |
|---|
| 9120 | | - * @ptr: holder for the timer function associated data. |
|---|
| 9713 | + * @t: timer context used to obtain the lpfc hba. |
|---|
| 9121 | 9714 | * |
|---|
| 9122 | 9715 | * This routine is invoked by the fabric iocb block timer after |
|---|
| 9123 | 9716 | * timeout. It posts the fabric iocb block timeout event by setting the |
|---|
| .. | .. |
|---|
| 9578 | 10171 | "rport in state 0x%x\n", ndlp->nlp_state); |
|---|
| 9579 | 10172 | return; |
|---|
| 9580 | 10173 | } |
|---|
| 9581 | | - lpfc_printf_log(phba, KERN_ERR, |
|---|
| 9582 | | - LOG_ELS | LOG_FCP_ERROR | LOG_NVME_IOERR, |
|---|
| 10174 | + lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, |
|---|
| 9583 | 10175 | "3094 Start rport recovery on shost id 0x%x " |
|---|
| 9584 | 10176 | "fc_id 0x%06x vpi 0x%x rpi 0x%x state 0x%x " |
|---|
| 9585 | 10177 | "flags 0x%x\n", |
|---|