aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/lpfc/lpfc_els.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_els.c')
-rw-r--r--drivers/scsi/lpfc/lpfc_els.c273
1 files changed, 146 insertions, 127 deletions
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
index 0af33bead302..d48247b3b654 100644
--- a/drivers/scsi/lpfc/lpfc_els.c
+++ b/drivers/scsi/lpfc/lpfc_els.c
@@ -45,9 +45,7 @@ lpfc_els_chk_latt(struct lpfc_vport *vport)
45{ 45{
46 struct Scsi_Host *shost = lpfc_shost_from_vport(vport); 46 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
47 struct lpfc_hba *phba = vport->phba; 47 struct lpfc_hba *phba = vport->phba;
48 LPFC_MBOXQ_t *mbox;
49 uint32_t ha_copy; 48 uint32_t ha_copy;
50 int rc;
51 49
52 if (vport->port_state >= LPFC_VPORT_READY || 50 if (vport->port_state >= LPFC_VPORT_READY ||
53 phba->link_state == LPFC_LINK_DOWN) 51 phba->link_state == LPFC_LINK_DOWN)
@@ -76,20 +74,7 @@ lpfc_els_chk_latt(struct lpfc_vport *vport)
76 spin_unlock_irq(shost->host_lock); 74 spin_unlock_irq(shost->host_lock);
77 75
78 if (phba->link_state != LPFC_CLEAR_LA) { 76 if (phba->link_state != LPFC_CLEAR_LA) {
79 if ((mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL))) { 77 lpfc_issue_clear_la(phba, vport);
80 phba->link_state = LPFC_CLEAR_LA;
81 lpfc_clear_la(phba, mbox);
82 mbox->mbox_cmpl = lpfc_mbx_cmpl_clear_la;
83 mbox->vport = vport;
84 printk(KERN_ERR "%s (%d): do clear_la\n",
85 __FUNCTION__, __LINE__);
86 rc = lpfc_sli_issue_mbox(phba, mbox,
87 (MBX_NOWAIT | MBX_STOP_IOCB));
88 if (rc == MBX_NOT_FINISHED) {
89 mempool_free(mbox, phba->mbox_mem_pool);
90 phba->link_state = LPFC_HBA_ERROR;
91 }
92 }
93 } 78 }
94 79
95 return 1; 80 return 1;
@@ -153,8 +138,8 @@ lpfc_prep_els_iocb(struct lpfc_vport *vport, uint8_t expectRsp,
153 /* Allocate buffer for Buffer ptr list */ 138 /* Allocate buffer for Buffer ptr list */
154 pbuflist = kmalloc(sizeof (struct lpfc_dmabuf), GFP_KERNEL); 139 pbuflist = kmalloc(sizeof (struct lpfc_dmabuf), GFP_KERNEL);
155 if (pbuflist) 140 if (pbuflist)
156 pbuflist->virt = lpfc_mbuf_alloc(phba, MEM_PRI, 141 pbuflist->virt = lpfc_mbuf_alloc(phba, MEM_PRI,
157 &pbuflist->phys); 142 &pbuflist->phys);
158 if (pbuflist == 0 || pbuflist->virt == 0) { 143 if (pbuflist == 0 || pbuflist->virt == 0) {
159 lpfc_sli_release_iocbq(phba, elsiocb); 144 lpfc_sli_release_iocbq(phba, elsiocb);
160 lpfc_mbuf_free(phba, pcmd->virt, pcmd->phys); 145 lpfc_mbuf_free(phba, pcmd->virt, pcmd->phys);
@@ -289,6 +274,7 @@ lpfc_cmpl_els_flogi_fabric(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
289 vport->port_state = LPFC_FABRIC_CFG_LINK; 274 vport->port_state = LPFC_FABRIC_CFG_LINK;
290 lpfc_config_link(phba, mbox); 275 lpfc_config_link(phba, mbox);
291 mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl; 276 mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
277 mbox->vport = vport;
292 278
293 rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT | MBX_STOP_IOCB); 279 rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT | MBX_STOP_IOCB);
294 if (rc == MBX_NOT_FINISHED) 280 if (rc == MBX_NOT_FINISHED)
@@ -364,6 +350,7 @@ lpfc_cmpl_els_flogi_nport(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
364 lpfc_config_link(phba, mbox); 350 lpfc_config_link(phba, mbox);
365 351
366 mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl; 352 mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
353 mbox->vport = vport;
367 rc = lpfc_sli_issue_mbox(phba, mbox, 354 rc = lpfc_sli_issue_mbox(phba, mbox,
368 MBX_NOWAIT | MBX_STOP_IOCB); 355 MBX_NOWAIT | MBX_STOP_IOCB);
369 if (rc == MBX_NOT_FINISHED) { 356 if (rc == MBX_NOT_FINISHED) {
@@ -714,8 +701,10 @@ lpfc_cmpl_els_plogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
714 701
715 irsp = &rspiocb->iocb; 702 irsp = &rspiocb->iocb;
716 ndlp = lpfc_findnode_did(vport, irsp->un.elsreq64.remoteID); 703 ndlp = lpfc_findnode_did(vport, irsp->un.elsreq64.remoteID);
717 if (!ndlp) 704
705 if (!ndlp) {
718 goto out; 706 goto out;
707 }
719 708
720 /* Since ndlp can be freed in the disc state machine, note if this node 709 /* Since ndlp can be freed in the disc state machine, note if this node
721 * is being used during discovery. 710 * is being used during discovery.
@@ -1110,9 +1099,8 @@ lpfc_cmpl_els_adisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
1110 /* If we get here, there is nothing left to wait for */ 1099 /* If we get here, there is nothing left to wait for */
1111 if (vport->port_state < LPFC_VPORT_READY && 1100 if (vport->port_state < LPFC_VPORT_READY &&
1112 phba->link_state != LPFC_CLEAR_LA) { 1101 phba->link_state != LPFC_CLEAR_LA) {
1113 if (vport->port_type == LPFC_PHYSICAL_PORT) { 1102 if (vport->port_type == LPFC_PHYSICAL_PORT)
1114 lpfc_issue_clear_la(phba, vport); 1103 lpfc_issue_clear_la(phba, vport);
1115 }
1116 } else { 1104 } else {
1117 lpfc_rscn_disc(vport); 1105 lpfc_rscn_disc(vport);
1118 } 1106 }
@@ -1420,6 +1408,27 @@ lpfc_issue_els_farpr(struct lpfc_vport *vport, uint32_t nportid, uint8_t retry)
1420 return 0; 1408 return 0;
1421} 1409}
1422 1410
1411static void
1412lpfc_end_rscn(struct lpfc_vport *vport)
1413{
1414 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
1415
1416 if (vport->fc_flag & FC_RSCN_MODE) {
1417 /*
1418 * Check to see if more RSCNs came in while we were
1419 * processing this one.
1420 */
1421 if (vport->fc_rscn_id_cnt ||
1422 (vport->fc_flag & FC_RSCN_DISCOVERY) != 0)
1423 lpfc_els_handle_rscn(vport);
1424 else {
1425 spin_lock_irq(shost->host_lock);
1426 vport->fc_flag &= ~FC_RSCN_MODE;
1427 spin_unlock_irq(shost->host_lock);
1428 }
1429 }
1430}
1431
1423void 1432void
1424lpfc_cancel_retry_delay_tmo(struct lpfc_vport *vport, struct lpfc_nodelist *nlp) 1433lpfc_cancel_retry_delay_tmo(struct lpfc_vport *vport, struct lpfc_nodelist *nlp)
1425{ 1434{
@@ -1449,24 +1458,7 @@ lpfc_cancel_retry_delay_tmo(struct lpfc_vport *vport, struct lpfc_nodelist *nlp)
1449 vport->fc_flag &= ~FC_NDISC_ACTIVE; 1458 vport->fc_flag &= ~FC_NDISC_ACTIVE;
1450 spin_unlock_irq(shost->host_lock); 1459 spin_unlock_irq(shost->host_lock);
1451 lpfc_can_disctmo(vport); 1460 lpfc_can_disctmo(vport);
1452 if (vport->fc_flag & FC_RSCN_MODE) { 1461 lpfc_end_rscn(vport);
1453 /*
1454 * Check to see if more RSCNs
1455 * came in while we were
1456 * processing this one.
1457 */
1458 if (!vport->fc_rscn_id_cnt &&
1459 !(vport->fc_flag &
1460 FC_RSCN_DISCOVERY)) {
1461 spin_lock_irq(shost->host_lock);
1462 vport->fc_flag &= ~FC_RSCN_MODE;
1463 spin_unlock_irq(
1464 shost->host_lock);
1465 }
1466 else {
1467 lpfc_els_handle_rscn(vport);
1468 }
1469 }
1470 } 1462 }
1471 } 1463 }
1472 } 1464 }
@@ -1689,6 +1681,9 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
1689 retry = 0; 1681 retry = 0;
1690 } 1682 }
1691 1683
1684 if ((vport->load_flag & FC_UNLOADING) != 0)
1685 retry = 0;
1686
1692 if (retry) { 1687 if (retry) {
1693 1688
1694 /* Retry ELS command <elsCmd> to remote NPORT <did> */ 1689 /* Retry ELS command <elsCmd> to remote NPORT <did> */
@@ -2141,9 +2136,7 @@ lpfc_els_rsp_prli_acc(struct lpfc_vport *vport, struct lpfc_iocbq *oldiocb,
2141 2136
2142 cmdsize = sizeof (uint32_t) + sizeof (PRLI); 2137 cmdsize = sizeof (uint32_t) + sizeof (PRLI);
2143 elsiocb = lpfc_prep_els_iocb(vport, 0, cmdsize, oldiocb->retry, ndlp, 2138 elsiocb = lpfc_prep_els_iocb(vport, 0, cmdsize, oldiocb->retry, ndlp,
2144 ndlp->nlp_DID, 2139 ndlp->nlp_DID, (ELS_CMD_ACC | (ELS_CMD_PRLI & ~ELS_RSP_MASK)));
2145 (ELS_CMD_ACC |
2146 (ELS_CMD_PRLI & ~ELS_RSP_MASK)));
2147 if (!elsiocb) 2140 if (!elsiocb)
2148 return 1; 2141 return 1;
2149 2142
@@ -2361,8 +2354,12 @@ lpfc_els_flush_rscn(struct lpfc_vport *vport)
2361 2354
2362 for (i = 0; i < vport->fc_rscn_id_cnt; i++) { 2355 for (i = 0; i < vport->fc_rscn_id_cnt; i++) {
2363 mp = vport->fc_rscn_id_list[i]; 2356 mp = vport->fc_rscn_id_list[i];
2364 lpfc_mbuf_free(phba, mp->virt, mp->phys); 2357 if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED)
2365 kfree(mp); 2358 lpfc_sli_hbqbuf_free(phba, mp->virt, mp->phys);
2359 else {
2360 lpfc_mbuf_free(phba, mp->virt, mp->phys);
2361 kfree(mp);
2362 }
2366 vport->fc_rscn_id_list[i] = NULL; 2363 vport->fc_rscn_id_list[i] = NULL;
2367 } 2364 }
2368 spin_lock_irq(shost->host_lock); 2365 spin_lock_irq(shost->host_lock);
@@ -2486,9 +2483,7 @@ lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
2486 cmd &= ELS_CMD_MASK; 2483 cmd &= ELS_CMD_MASK;
2487 2484
2488 /* RSCN received */ 2485 /* RSCN received */
2489 lpfc_printf_log(phba, 2486 lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
2490 KERN_INFO,
2491 LOG_DISCOVERY,
2492 "%d:0214 RSCN received Data: x%x x%x x%x x%x\n", 2487 "%d:0214 RSCN received Data: x%x x%x x%x x%x\n",
2493 phba->brd_no, vport->fc_flag, payload_len, *lp, 2488 phba->brd_no, vport->fc_flag, payload_len, *lp,
2494 vport->fc_rscn_id_cnt); 2489 vport->fc_rscn_id_cnt);
@@ -2581,9 +2576,7 @@ lpfc_els_handle_rscn(struct lpfc_vport *vport)
2581 lpfc_set_disctmo(vport); 2576 lpfc_set_disctmo(vport);
2582 2577
2583 /* RSCN processed */ 2578 /* RSCN processed */
2584 lpfc_printf_log(phba, 2579 lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
2585 KERN_INFO,
2586 LOG_DISCOVERY,
2587 "%d:0215 RSCN processed Data: x%x x%x x%x x%x\n", 2580 "%d:0215 RSCN processed Data: x%x x%x x%x x%x\n",
2588 phba->brd_no, 2581 phba->brd_no,
2589 vport->fc_flag, 0, vport->fc_rscn_id_cnt, 2582 vport->fc_flag, 0, vport->fc_rscn_id_cnt,
@@ -2683,6 +2676,7 @@ lpfc_els_rcv_flogi(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
2683 phba->cfg_link_speed); 2676 phba->cfg_link_speed);
2684 mbox->mb.un.varInitLnk.lipsr_AL_PA = 0; 2677 mbox->mb.un.varInitLnk.lipsr_AL_PA = 0;
2685 mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl; 2678 mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
2679 mbox->vport = vport;
2686 rc = lpfc_sli_issue_mbox 2680 rc = lpfc_sli_issue_mbox
2687 (phba, mbox, (MBX_NOWAIT | MBX_STOP_IOCB)); 2681 (phba, mbox, (MBX_NOWAIT | MBX_STOP_IOCB));
2688 lpfc_set_loopback_flag(phba); 2682 lpfc_set_loopback_flag(phba);
@@ -2837,10 +2831,8 @@ lpfc_els_rsp_rps_acc(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
2837 2831
2838 elsiocb->iocb_cmpl = lpfc_cmpl_els_acc; 2832 elsiocb->iocb_cmpl = lpfc_cmpl_els_acc;
2839 phba->fc_stat.elsXmitACC++; 2833 phba->fc_stat.elsXmitACC++;
2840 2834 if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR)
2841 if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) {
2842 lpfc_els_free_iocb(phba, elsiocb); 2835 lpfc_els_free_iocb(phba, elsiocb);
2843 }
2844 return; 2836 return;
2845} 2837}
2846 2838
@@ -3015,9 +3007,7 @@ lpfc_els_rcv_farp(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
3015 fp = (FARP *) lp; 3007 fp = (FARP *) lp;
3016 3008
3017 /* FARP-REQ received from DID <did> */ 3009 /* FARP-REQ received from DID <did> */
3018 lpfc_printf_log(phba, 3010 lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
3019 KERN_INFO,
3020 LOG_ELS,
3021 "%d:0601 FARP-REQ received from DID x%x\n", 3011 "%d:0601 FARP-REQ received from DID x%x\n",
3022 phba->brd_no, did); 3012 phba->brd_no, did);
3023 3013
@@ -3077,12 +3067,9 @@ lpfc_els_rcv_farpr(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
3077 3067
3078 cmd = *lp++; 3068 cmd = *lp++;
3079 /* FARP-RSP received from DID <did> */ 3069 /* FARP-RSP received from DID <did> */
3080 lpfc_printf_log(phba, 3070 lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
3081 KERN_INFO,
3082 LOG_ELS,
3083 "%d:0600 FARP-RSP received from DID x%x\n", 3071 "%d:0600 FARP-RSP received from DID x%x\n",
3084 phba->brd_no, did); 3072 phba->brd_no, did);
3085
3086 /* ACCEPT the Farp resp request */ 3073 /* ACCEPT the Farp resp request */
3087 lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0); 3074 lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0);
3088 3075
@@ -3102,8 +3089,9 @@ lpfc_els_rcv_fan(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
3102 struct lpfc_hba *phba = vport->phba; 3089 struct lpfc_hba *phba = vport->phba;
3103 3090
3104 /* FAN received */ 3091 /* FAN received */
3105 lpfc_printf_log(phba, KERN_INFO, LOG_ELS, "%d:0265 FAN received\n", 3092 lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
3106 phba->brd_no); 3093 "%d:0265 FAN received\n",
3094 phba->brd_no);
3107 3095
3108 icmd = &cmdiocb->iocb; 3096 icmd = &cmdiocb->iocb;
3109 did = icmd->un.elsreq64.remoteID; 3097 did = icmd->un.elsreq64.remoteID;
@@ -3332,79 +3320,40 @@ lpfc_els_flush_cmd(struct lpfc_vport *vport)
3332 return; 3320 return;
3333} 3321}
3334 3322
3335void 3323static void
3336lpfc_els_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, 3324lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
3337 struct lpfc_iocbq *elsiocb) 3325 struct lpfc_vport *vport, struct lpfc_dmabuf *mp,
3326 struct lpfc_iocbq *elsiocb)
3338{ 3327{
3339 struct lpfc_sli *psli;
3340 struct lpfc_nodelist *ndlp; 3328 struct lpfc_nodelist *ndlp;
3341 struct lpfc_dmabuf *mp = NULL;
3342 uint32_t *lp;
3343 IOCB_t *icmd;
3344 struct ls_rjt stat; 3329 struct ls_rjt stat;
3330 uint32_t *lp;
3345 uint32_t cmd, did, newnode, rjt_err = 0; 3331 uint32_t cmd, did, newnode, rjt_err = 0;
3346 uint32_t drop_cmd = 0; /* by default do NOT drop received cmd */ 3332 IOCB_t *icmd = &elsiocb->iocb;
3347 struct lpfc_vport *vport = NULL;
3348
3349 psli = &phba->sli;
3350 icmd = &elsiocb->iocb;
3351 3333
3352 if ((icmd->ulpStatus == IOSTAT_LOCAL_REJECT) && 3334 if (!vport || !mp)
3353 ((icmd->un.ulpWord[4] & 0xff) == IOERR_RCV_BUFFER_WAITING)) {
3354 phba->fc_stat.NoRcvBuf++;
3355 /* Not enough posted buffers; Try posting more buffers */
3356 lpfc_post_buffer(phba, pring, 0, 1);
3357 return;
3358 }
3359
3360 /* If there are no BDEs associated with this IOCB,
3361 * there is nothing to do.
3362 */
3363 if (icmd->ulpBdeCount == 0)
3364 return;
3365
3366 /* type of ELS cmd is first 32bit word in packet */
3367 mp = lpfc_sli_ringpostbuf_get(phba, pring,
3368 getPaddr(icmd->un.cont64[0].addrHigh,
3369 icmd->un.cont64[0].addrLow));
3370 if (mp == 0) {
3371 drop_cmd = 1;
3372 goto dropit; 3335 goto dropit;
3373 }
3374
3375 vport = phba->pport;
3376 3336
3377 newnode = 0; 3337 newnode = 0;
3378 lp = (uint32_t *) mp->virt; 3338 lp = (uint32_t *) mp->virt;
3379 cmd = *lp++; 3339 cmd = *lp++;
3380 lpfc_post_buffer(phba, &psli->ring[LPFC_ELS_RING], 1, 1); 3340 if ((phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) == 0)
3341 lpfc_post_buffer(phba, pring, 1, 1);
3381 3342
3382 if (icmd->ulpStatus) { 3343 if (icmd->ulpStatus)
3383 lpfc_mbuf_free(phba, mp->virt, mp->phys);
3384 kfree(mp);
3385 drop_cmd = 1;
3386 goto dropit; 3344 goto dropit;
3387 }
3388 3345
3389 /* Check to see if link went down during discovery */ 3346 /* Check to see if link went down during discovery */
3390 if (lpfc_els_chk_latt(vport)) { 3347 if (lpfc_els_chk_latt(vport))
3391 lpfc_mbuf_free(phba, mp->virt, mp->phys);
3392 kfree(mp);
3393 drop_cmd = 1;
3394 goto dropit; 3348 goto dropit;
3395 }
3396 3349
3397 did = icmd->un.rcvels.remoteID; 3350 did = icmd->un.rcvels.remoteID;
3398 ndlp = lpfc_findnode_did(vport, did); 3351 ndlp = lpfc_findnode_did(vport, did);
3399 if (!ndlp) { 3352 if (!ndlp) {
3400 /* Cannot find existing Fabric ndlp, so allocate a new one */ 3353 /* Cannot find existing Fabric ndlp, so allocate a new one */
3401 ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL); 3354 ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL);
3402 if (!ndlp) { 3355 if (!ndlp)
3403 lpfc_mbuf_free(phba, mp->virt, mp->phys);
3404 kfree(mp);
3405 drop_cmd = 1;
3406 goto dropit; 3356 goto dropit;
3407 }
3408 3357
3409 lpfc_nlp_init(vport, ndlp, did); 3358 lpfc_nlp_init(vport, ndlp, did);
3410 newnode = 1; 3359 newnode = 1;
@@ -3428,7 +3377,7 @@ lpfc_els_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
3428 lpfc_printf_log(phba, KERN_INFO, LOG_ELS, 3377 lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
3429 "%d:0112 ELS command x%x received from NPORT x%x " 3378 "%d:0112 ELS command x%x received from NPORT x%x "
3430 "Data: x%x\n", phba->brd_no, cmd, did, 3379 "Data: x%x\n", phba->brd_no, cmd, did,
3431 vport->port_state); 3380 vport->port_state);
3432 3381
3433 switch (cmd) { 3382 switch (cmd) {
3434 case ELS_CMD_PLOGI: 3383 case ELS_CMD_PLOGI:
@@ -3537,8 +3486,9 @@ lpfc_els_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
3537 3486
3538 /* Unknown ELS command <elsCmd> received from NPORT <did> */ 3487 /* Unknown ELS command <elsCmd> received from NPORT <did> */
3539 lpfc_printf_log(phba, KERN_ERR, LOG_ELS, 3488 lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
3540 "%d:0115 Unknown ELS command x%x received from " 3489 "%d:0115 Unknown ELS command x%x "
3541 "NPORT x%x\n", phba->brd_no, cmd, did); 3490 "received from NPORT x%x\n",
3491 phba->brd_no, cmd, did);
3542 if (newnode) 3492 if (newnode)
3543 lpfc_drop_node(vport, ndlp); 3493 lpfc_drop_node(vport, ndlp);
3544 break; 3494 break;
@@ -3553,20 +3503,89 @@ lpfc_els_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
3553 lpfc_els_rsp_reject(vport, stat.un.lsRjtError, elsiocb, ndlp); 3503 lpfc_els_rsp_reject(vport, stat.un.lsRjtError, elsiocb, ndlp);
3554 } 3504 }
3555 3505
3506 return;
3507
3508dropit:
3509 lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
3510 "%d:0111 Dropping received ELS cmd "
3511 "Data: x%x x%x x%x\n",
3512 phba->brd_no,
3513 icmd->ulpStatus, icmd->un.ulpWord[4],
3514 icmd->ulpTimeout);
3515 phba->fc_stat.elsRcvDrop++;
3516}
3517
3518
3519void
3520lpfc_els_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
3521 struct lpfc_iocbq *elsiocb)
3522{
3523 struct lpfc_vport *vport = phba->pport;
3524 struct lpfc_dmabuf *mp = NULL;
3525 IOCB_t *icmd = &elsiocb->iocb;
3526 struct hbq_dmabuf *sp = NULL;
3527 dma_addr_t paddr;
3528
3529 if ((icmd->ulpStatus == IOSTAT_LOCAL_REJECT) &&
3530 ((icmd->un.ulpWord[4] & 0xff) == IOERR_RCV_BUFFER_WAITING)) {
3531 phba->fc_stat.NoRcvBuf++;
3532 /* Not enough posted buffers; Try posting more buffers */
3533 if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED)
3534 lpfc_sli_hbqbuf_fill_hbq(phba);
3535 else
3536 lpfc_post_buffer(phba, pring, 0, 1);
3537 return;
3538 }
3539
3540 /* If there are no BDEs associated with this IOCB,
3541 * there is nothing to do.
3542 */
3543 if (icmd->ulpBdeCount == 0)
3544 return;
3545
3546 /* type of ELS cmd is first 32bit word in packet */
3547 if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) {
3548 paddr = getPaddr(icmd->un.cont64[0].addrHigh,
3549 icmd->un.cont64[0].addrLow);
3550 sp = lpfc_sli_hbqbuf_find(phba, icmd->un.ulpWord[3]);
3551 if (sp)
3552 phba->hbq_buff_count--;
3553 mp = sp ? &sp->dbuf : NULL;
3554 } else {
3555 paddr = getPaddr(icmd->un.cont64[0].addrHigh,
3556 icmd->un.cont64[0].addrLow);
3557 mp = lpfc_sli_ringpostbuf_get(phba, pring, paddr);
3558 }
3559
3560 lpfc_els_unsol_buffer(phba, pring, vport, mp, elsiocb);
3561
3556 lpfc_nlp_put(elsiocb->context1); 3562 lpfc_nlp_put(elsiocb->context1);
3557 elsiocb->context1 = NULL; 3563 elsiocb->context1 = NULL;
3558 if (elsiocb->context2) { 3564 if (elsiocb->context2) {
3559 lpfc_mbuf_free(phba, mp->virt, mp->phys); 3565 if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED)
3560 kfree(mp); 3566 lpfc_sli_free_hbq(phba, sp);
3567 else {
3568 lpfc_mbuf_free(phba, mp->virt, mp->phys);
3569 kfree(mp);
3570 }
3561 } 3571 }
3562dropit: 3572
3563 /* check if need to drop received ELS cmd */ 3573 /* RCV_ELS64_CX provide for 2 BDEs - process 2nd if included */
3564 if (drop_cmd == 1) { 3574 if ((phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) != 0 &&
3565 lpfc_printf_log(phba, KERN_ERR, LOG_ELS, 3575 icmd->ulpBdeCount == 2) {
3566 "%d:0111 Dropping received ELS cmd " 3576 sp = lpfc_sli_hbqbuf_find(phba, icmd->un.ulpWord[15]);
3567 "Data: x%x x%x x%x\n", phba->brd_no, 3577 if (sp)
3568 icmd->ulpStatus, icmd->un.ulpWord[4], 3578 phba->hbq_buff_count--;
3569 icmd->ulpTimeout); 3579 mp = sp ? &sp->dbuf : NULL;
3570 phba->fc_stat.elsRcvDrop++; 3580 lpfc_els_unsol_buffer(phba, pring, vport, mp, elsiocb);
3581 /* free mp if we are done with it */
3582 if (elsiocb->context2) {
3583 if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED)
3584 lpfc_sli_free_hbq(phba, sp);
3585 else {
3586 lpfc_mbuf_free(phba, mp->virt, mp->phys);
3587 kfree(mp);
3588 }
3589 }
3571 } 3590 }
3572} 3591}