]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blame - drivers/scsi/lpfc/lpfc_nportdisc.c
[SCSI] lpfc 8.2.3 : FC Discovery Fixes
[mirror_ubuntu-bionic-kernel.git] / drivers / scsi / lpfc / lpfc_nportdisc.c
CommitLineData
92d7f7b0 1 /*******************************************************************
dea3101e 2 * This file is part of the Emulex Linux Device Driver for *
c44ce173 3 * Fibre Channel Host Bus Adapters. *
9413afff 4 * Copyright (C) 2004-2007 Emulex. All rights reserved. *
c44ce173 5 * EMULEX and SLI are trademarks of Emulex. *
dea3101e 6 * www.emulex.com *
c44ce173 7 * Portions Copyright (C) 2004-2005 Christoph Hellwig *
dea3101e
JB
8 * *
9 * This program is free software; you can redistribute it and/or *
c44ce173
JSEC
10 * modify it under the terms of version 2 of the GNU General *
11 * Public License as published by the Free Software Foundation. *
12 * This program is distributed in the hope that it will be useful. *
13 * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND *
14 * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, *
15 * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE *
16 * DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD *
17 * TO BE LEGALLY INVALID. See the GNU General Public License for *
18 * more details, a copy of which can be found in the file COPYING *
19 * included with this package. *
dea3101e
JB
20 *******************************************************************/
21
dea3101e
JB
22#include <linux/blkdev.h>
23#include <linux/pci.h>
24#include <linux/interrupt.h>
25
91886523 26#include <scsi/scsi.h>
dea3101e
JB
27#include <scsi/scsi_device.h>
28#include <scsi/scsi_host.h>
29#include <scsi/scsi_transport_fc.h>
30
31#include "lpfc_hw.h"
32#include "lpfc_sli.h"
33#include "lpfc_disc.h"
34#include "lpfc_scsi.h"
35#include "lpfc.h"
36#include "lpfc_logmsg.h"
37#include "lpfc_crtn.h"
92d7f7b0 38#include "lpfc_vport.h"
858c9f6c 39#include "lpfc_debugfs.h"
dea3101e
JB
40
41
42/* Called to verify a rcv'ed ADISC was intended for us. */
43static int
2e0fef85
JS
44lpfc_check_adisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
45 struct lpfc_name *nn, struct lpfc_name *pn)
dea3101e
JB
46{
47 /* Compare the ADISC rsp WWNN / WWPN matches our internal node
48 * table entry for that node.
49 */
2e0fef85 50 if (memcmp(nn, &ndlp->nlp_nodename, sizeof (struct lpfc_name)))
c9f8735b 51 return 0;
dea3101e 52
2e0fef85 53 if (memcmp(pn, &ndlp->nlp_portname, sizeof (struct lpfc_name)))
c9f8735b 54 return 0;
dea3101e
JB
55
56 /* we match, return success */
c9f8735b 57 return 1;
dea3101e
JB
58}
59
dea3101e 60int
2e0fef85
JS
61lpfc_check_sparm(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
62 struct serv_parm * sp, uint32_t class)
dea3101e 63{
2e0fef85 64 volatile struct serv_parm *hsp = &vport->fc_sparam;
2fb70f79
JSEC
65 uint16_t hsp_value, ssp_value = 0;
66
67 /*
68 * The receive data field size and buffer-to-buffer receive data field
69 * size entries are 16 bits but are represented as two 8-bit fields in
70 * the driver data structure to account for rsvd bits and other control
71 * bits. Reconstruct and compare the fields as a 16-bit values before
72 * correcting the byte values.
73 */
dea3101e 74 if (sp->cls1.classValid) {
2fb70f79
JSEC
75 hsp_value = (hsp->cls1.rcvDataSizeMsb << 8) |
76 hsp->cls1.rcvDataSizeLsb;
77 ssp_value = (sp->cls1.rcvDataSizeMsb << 8) |
78 sp->cls1.rcvDataSizeLsb;
92d7f7b0
JS
79 if (!ssp_value)
80 goto bad_service_param;
2fb70f79 81 if (ssp_value > hsp_value) {
dea3101e 82 sp->cls1.rcvDataSizeLsb = hsp->cls1.rcvDataSizeLsb;
2fb70f79
JSEC
83 sp->cls1.rcvDataSizeMsb = hsp->cls1.rcvDataSizeMsb;
84 }
dea3101e 85 } else if (class == CLASS1) {
92d7f7b0 86 goto bad_service_param;
dea3101e
JB
87 }
88
89 if (sp->cls2.classValid) {
2fb70f79
JSEC
90 hsp_value = (hsp->cls2.rcvDataSizeMsb << 8) |
91 hsp->cls2.rcvDataSizeLsb;
92 ssp_value = (sp->cls2.rcvDataSizeMsb << 8) |
93 sp->cls2.rcvDataSizeLsb;
92d7f7b0
JS
94 if (!ssp_value)
95 goto bad_service_param;
2fb70f79 96 if (ssp_value > hsp_value) {
dea3101e 97 sp->cls2.rcvDataSizeLsb = hsp->cls2.rcvDataSizeLsb;
2fb70f79
JSEC
98 sp->cls2.rcvDataSizeMsb = hsp->cls2.rcvDataSizeMsb;
99 }
dea3101e 100 } else if (class == CLASS2) {
92d7f7b0 101 goto bad_service_param;
dea3101e
JB
102 }
103
104 if (sp->cls3.classValid) {
2fb70f79
JSEC
105 hsp_value = (hsp->cls3.rcvDataSizeMsb << 8) |
106 hsp->cls3.rcvDataSizeLsb;
107 ssp_value = (sp->cls3.rcvDataSizeMsb << 8) |
108 sp->cls3.rcvDataSizeLsb;
92d7f7b0
JS
109 if (!ssp_value)
110 goto bad_service_param;
2fb70f79 111 if (ssp_value > hsp_value) {
dea3101e 112 sp->cls3.rcvDataSizeLsb = hsp->cls3.rcvDataSizeLsb;
2fb70f79
JSEC
113 sp->cls3.rcvDataSizeMsb = hsp->cls3.rcvDataSizeMsb;
114 }
dea3101e 115 } else if (class == CLASS3) {
92d7f7b0 116 goto bad_service_param;
dea3101e
JB
117 }
118
2fb70f79
JSEC
119 /*
120 * Preserve the upper four bits of the MSB from the PLOGI response.
121 * These bits contain the Buffer-to-Buffer State Change Number
122 * from the target and need to be passed to the FW.
123 */
124 hsp_value = (hsp->cmn.bbRcvSizeMsb << 8) | hsp->cmn.bbRcvSizeLsb;
125 ssp_value = (sp->cmn.bbRcvSizeMsb << 8) | sp->cmn.bbRcvSizeLsb;
126 if (ssp_value > hsp_value) {
dea3101e 127 sp->cmn.bbRcvSizeLsb = hsp->cmn.bbRcvSizeLsb;
2fb70f79
JSEC
128 sp->cmn.bbRcvSizeMsb = (sp->cmn.bbRcvSizeMsb & 0xF0) |
129 (hsp->cmn.bbRcvSizeMsb & 0x0F);
130 }
dea3101e 131
dea3101e
JB
132 memcpy(&ndlp->nlp_nodename, &sp->nodeName, sizeof (struct lpfc_name));
133 memcpy(&ndlp->nlp_portname, &sp->portName, sizeof (struct lpfc_name));
2fb70f79 134 return 1;
92d7f7b0 135bad_service_param:
e8b62011
JS
136 lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY,
137 "0207 Device %x "
138 "(%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x) sent "
139 "invalid service parameters. Ignoring device.\n",
140 ndlp->nlp_DID,
141 sp->nodeName.u.wwn[0], sp->nodeName.u.wwn[1],
142 sp->nodeName.u.wwn[2], sp->nodeName.u.wwn[3],
143 sp->nodeName.u.wwn[4], sp->nodeName.u.wwn[5],
144 sp->nodeName.u.wwn[6], sp->nodeName.u.wwn[7]);
92d7f7b0 145 return 0;
dea3101e
JB
146}
147
148static void *
2e0fef85 149lpfc_check_elscmpl_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
92d7f7b0 150 struct lpfc_iocbq *rspiocb)
dea3101e
JB
151{
152 struct lpfc_dmabuf *pcmd, *prsp;
153 uint32_t *lp;
154 void *ptr = NULL;
155 IOCB_t *irsp;
156
157 irsp = &rspiocb->iocb;
158 pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
159
160 /* For lpfc_els_abort, context2 could be zero'ed to delay
161 * freeing associated memory till after ABTS completes.
162 */
163 if (pcmd) {
164 prsp = list_get_first(&pcmd->list, struct lpfc_dmabuf,
165 list);
166 if (prsp) {
167 lp = (uint32_t *) prsp->virt;
168 ptr = (void *)((uint8_t *)lp + sizeof(uint32_t));
169 }
2fe165b6 170 } else {
dea3101e
JB
171 /* Force ulpStatus error since we are returning NULL ptr */
172 if (!(irsp->ulpStatus)) {
173 irsp->ulpStatus = IOSTAT_LOCAL_REJECT;
174 irsp->un.ulpWord[4] = IOERR_SLI_ABORTED;
175 }
176 ptr = NULL;
177 }
c9f8735b 178 return ptr;
dea3101e
JB
179}
180
181
182/*
183 * Free resources / clean up outstanding I/Os
184 * associated with a LPFC_NODELIST entry. This
185 * routine effectively results in a "software abort".
186 */
187int
2e0fef85 188lpfc_els_abort(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
dea3101e 189{
2534ba75 190 LIST_HEAD(completions);
2e0fef85
JS
191 struct lpfc_sli *psli = &phba->sli;
192 struct lpfc_sli_ring *pring = &psli->ring[LPFC_ELS_RING];
dea3101e 193 struct lpfc_iocbq *iocb, *next_iocb;
2534ba75 194 IOCB_t *cmd;
dea3101e
JB
195
196 /* Abort outstanding I/O on NPort <nlp_DID> */
e8b62011
JS
197 lpfc_printf_vlog(ndlp->vport, KERN_INFO, LOG_DISCOVERY,
198 "0205 Abort outstanding I/O on NPort x%x "
199 "Data: x%x x%x x%x\n",
200 ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state,
201 ndlp->nlp_rpi);
92d7f7b0
JS
202
203 lpfc_fabric_abort_nport(ndlp);
dea3101e 204
dea3101e 205 /* First check the txq */
2e0fef85 206 spin_lock_irq(&phba->hbalock);
2534ba75 207 list_for_each_entry_safe(iocb, next_iocb, &pring->txq, list) {
858c9f6c 208 /* Check to see if iocb matches the nport we are looking for */
2534ba75 209 if (lpfc_check_sli_ndlp(phba, pring, iocb, ndlp)) {
858c9f6c 210 /* It matches, so deque and call compl with anp error */
2534ba75
JS
211 list_move_tail(&iocb->list, &completions);
212 pring->txq_cnt--;
dea3101e 213 }
2534ba75 214 }
dea3101e 215
dea3101e 216 /* Next check the txcmplq */
07951076 217 list_for_each_entry_safe(iocb, next_iocb, &pring->txcmplq, list) {
858c9f6c 218 /* Check to see if iocb matches the nport we are looking for */
92d7f7b0 219 if (lpfc_check_sli_ndlp(phba, pring, iocb, ndlp)) {
07951076 220 lpfc_sli_issue_abort_iotag(phba, pring, iocb);
92d7f7b0 221 }
07951076 222 }
2e0fef85 223 spin_unlock_irq(&phba->hbalock);
dea3101e 224
2534ba75
JS
225 while (!list_empty(&completions)) {
226 iocb = list_get_first(&completions, struct lpfc_iocbq, list);
227 cmd = &iocb->iocb;
92d7f7b0 228 list_del_init(&iocb->list);
2534ba75 229
2e0fef85
JS
230 if (!iocb->iocb_cmpl)
231 lpfc_sli_release_iocbq(phba, iocb);
232 else {
2534ba75
JS
233 cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
234 cmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
235 (iocb->iocb_cmpl) (phba, iocb, iocb);
2e0fef85 236 }
2534ba75
JS
237 }
238
dea3101e 239 /* If we are delaying issuing an ELS command, cancel it */
fdcebe28 240 if (ndlp->nlp_flag & NLP_DELAY_TMO)
2e0fef85 241 lpfc_cancel_retry_delay_tmo(phba->pport, ndlp);
c9f8735b 242 return 0;
dea3101e
JB
243}
244
245static int
2e0fef85 246lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
92d7f7b0 247 struct lpfc_iocbq *cmdiocb)
dea3101e 248{
2e0fef85
JS
249 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
250 struct lpfc_hba *phba = vport->phba;
dea3101e
JB
251 struct lpfc_dmabuf *pcmd;
252 uint32_t *lp;
253 IOCB_t *icmd;
254 struct serv_parm *sp;
255 LPFC_MBOXQ_t *mbox;
256 struct ls_rjt stat;
257 int rc;
258
259 memset(&stat, 0, sizeof (struct ls_rjt));
2e0fef85 260 if (vport->port_state <= LPFC_FLOGI) {
dea3101e
JB
261 /* Before responding to PLOGI, check for pt2pt mode.
262 * If we are pt2pt, with an outstanding FLOGI, abort
263 * the FLOGI and resend it first.
264 */
2e0fef85 265 if (vport->fc_flag & FC_PT2PT) {
92d7f7b0 266 lpfc_els_abort_flogi(phba);
2e0fef85 267 if (!(vport->fc_flag & FC_PT2PT_PLOGI)) {
dea3101e
JB
268 /* If the other side is supposed to initiate
269 * the PLOGI anyway, just ACC it now and
270 * move on with discovery.
271 */
272 phba->fc_edtov = FF_DEF_EDTOV;
273 phba->fc_ratov = FF_DEF_RATOV;
274 /* Start discovery - this should just do
275 CLEAR_LA */
2e0fef85 276 lpfc_disc_start(vport);
ed957684 277 } else
2e0fef85 278 lpfc_initial_flogi(vport);
2fe165b6 279 } else {
dea3101e
JB
280 stat.un.b.lsRjtRsnCode = LSRJT_LOGICAL_BSY;
281 stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE;
2e0fef85 282 lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb,
858c9f6c 283 ndlp, NULL);
dea3101e
JB
284 return 0;
285 }
286 }
287 pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
288 lp = (uint32_t *) pcmd->virt;
289 sp = (struct serv_parm *) ((uint8_t *) lp + sizeof (uint32_t));
2e0fef85 290 if ((lpfc_check_sparm(vport, ndlp, sp, CLASS3) == 0)) {
dea3101e
JB
291 /* Reject this request because invalid parameters */
292 stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
293 stat.un.b.lsRjtRsnCodeExp = LSEXP_SPARM_OPTIONS;
858c9f6c
JS
294 lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp,
295 NULL);
c9f8735b 296 return 0;
dea3101e
JB
297 }
298 icmd = &cmdiocb->iocb;
299
300 /* PLOGI chkparm OK */
e8b62011
JS
301 lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
302 "0114 PLOGI chkparm OK Data: x%x x%x x%x x%x\n",
303 ndlp->nlp_DID, ndlp->nlp_state, ndlp->nlp_flag,
304 ndlp->nlp_rpi);
dea3101e 305
3de2a653 306 if (vport->cfg_fcp_class == 2 && sp->cls2.classValid)
dea3101e 307 ndlp->nlp_fcp_info |= CLASS2;
ed957684 308 else
dea3101e 309 ndlp->nlp_fcp_info |= CLASS3;
2e0fef85 310
dea3101e
JB
311 ndlp->nlp_class_sup = 0;
312 if (sp->cls1.classValid)
313 ndlp->nlp_class_sup |= FC_COS_CLASS1;
314 if (sp->cls2.classValid)
315 ndlp->nlp_class_sup |= FC_COS_CLASS2;
316 if (sp->cls3.classValid)
317 ndlp->nlp_class_sup |= FC_COS_CLASS3;
318 if (sp->cls4.classValid)
319 ndlp->nlp_class_sup |= FC_COS_CLASS4;
320 ndlp->nlp_maxframe =
321 ((sp->cmn.bbRcvSizeMsb & 0x0F) << 8) | sp->cmn.bbRcvSizeLsb;
322
323 /* no need to reg_login if we are already in one of these states */
2fe165b6 324 switch (ndlp->nlp_state) {
dea3101e
JB
325 case NLP_STE_NPR_NODE:
326 if (!(ndlp->nlp_flag & NLP_NPR_ADISC))
327 break;
328 case NLP_STE_REG_LOGIN_ISSUE:
329 case NLP_STE_PRLI_ISSUE:
330 case NLP_STE_UNMAPPED_NODE:
331 case NLP_STE_MAPPED_NODE:
51ef4c26 332 lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb, ndlp, NULL);
c9f8735b 333 return 1;
dea3101e
JB
334 }
335
92d7f7b0
JS
336 if ((vport->fc_flag & FC_PT2PT) &&
337 !(vport->fc_flag & FC_PT2PT_PLOGI)) {
dea3101e 338 /* rcv'ed PLOGI decides what our NPortId will be */
2e0fef85 339 vport->fc_myDID = icmd->un.rcvels.parmRo;
dea3101e
JB
340 mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
341 if (mbox == NULL)
342 goto out;
343 lpfc_config_link(phba, mbox);
344 mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
ed957684 345 mbox->vport = vport;
0b727fea 346 rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT);
dea3101e 347 if (rc == MBX_NOT_FINISHED) {
92d7f7b0 348 mempool_free(mbox, phba->mbox_mem_pool);
dea3101e
JB
349 goto out;
350 }
351
2e0fef85 352 lpfc_can_disctmo(vport);
dea3101e
JB
353 }
354 mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
2e0fef85 355 if (!mbox)
dea3101e
JB
356 goto out;
357
92d7f7b0
JS
358 rc = lpfc_reg_login(phba, vport->vpi, icmd->un.rcvels.remoteID,
359 (uint8_t *) sp, mbox, 0);
2e0fef85
JS
360 if (rc) {
361 mempool_free(mbox, phba->mbox_mem_pool);
dea3101e
JB
362 goto out;
363 }
364
365 /* ACC PLOGI rsp command needs to execute first,
366 * queue this mbox command to be processed later.
367 */
368 mbox->mbox_cmpl = lpfc_mbx_cmpl_reg_login;
329f9bc7
JS
369 /*
370 * mbox->context2 = lpfc_nlp_get(ndlp) deferred until mailbox
371 * command issued in lpfc_cmpl_els_acc().
372 */
2e0fef85
JS
373 mbox->vport = vport;
374 spin_lock_irq(shost->host_lock);
5024ab17 375 ndlp->nlp_flag |= (NLP_ACC_REGLOGIN | NLP_RCV_PLOGI);
2e0fef85 376 spin_unlock_irq(shost->host_lock);
dea3101e 377
33ccf8d1
JS
378 /*
379 * If there is an outstanding PLOGI issued, abort it before
380 * sending ACC rsp for received PLOGI. If pending plogi
381 * is not canceled here, the plogi will be rejected by
382 * remote port and will be retried. On a configuration with
383 * single discovery thread, this will cause a huge delay in
384 * discovery. Also this will cause multiple state machines
385 * running in parallel for this node.
386 */
387 if (ndlp->nlp_state == NLP_STE_PLOGI_ISSUE) {
388 /* software abort outstanding PLOGI */
07951076 389 lpfc_els_abort(phba, ndlp);
33ccf8d1
JS
390 }
391
858c9f6c 392 if ((vport->port_type == LPFC_NPIV_PORT &&
3de2a653 393 vport->cfg_restrict_login)) {
858c9f6c
JS
394
395 /* In order to preserve RPIs, we want to cleanup
396 * the default RPI the firmware created to rcv
397 * this ELS request. The only way to do this is
398 * to register, then unregister the RPI.
399 */
400 spin_lock_irq(shost->host_lock);
401 ndlp->nlp_flag |= NLP_RM_DFLT_RPI;
402 spin_unlock_irq(shost->host_lock);
403 stat.un.b.lsRjtRsnCode = LSRJT_INVALID_CMD;
404 stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE;
405 lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb,
406 ndlp, mbox);
407 return 1;
408 }
87af33fe
JS
409
410 /* If the remote NPort logs into us, before we can initiate
411 * discovery to them, cleanup the NPort from discovery accordingly.
412 */
413 if (ndlp->nlp_state == NLP_STE_NPR_NODE) {
414 spin_lock_irq(shost->host_lock);
415 ndlp->nlp_flag &= ~NLP_DELAY_TMO;
416 spin_unlock_irq(shost->host_lock);
417 del_timer_sync(&ndlp->nlp_delayfunc);
418 ndlp->nlp_last_elscmd = 0;
419
420 if (!list_empty(&ndlp->els_retry_evt.evt_listp))
421 list_del_init(&ndlp->els_retry_evt.evt_listp);
422
423 if (ndlp->nlp_flag & NLP_NPR_2B_DISC) {
424 spin_lock_irq(shost->host_lock);
425 ndlp->nlp_flag &= ~NLP_NPR_2B_DISC;
426 spin_unlock_irq(shost->host_lock);
427 if (vport->num_disc_nodes) {
428 /* Check to see if there are more
429 * PLOGIs to be sent
430 */
431 lpfc_more_plogi(vport);
432
433 if (vport->num_disc_nodes == 0) {
434 spin_lock_irq(shost->host_lock);
435 vport->fc_flag &= ~FC_NDISC_ACTIVE;
436 spin_unlock_irq(shost->host_lock);
437 lpfc_can_disctmo(vport);
438 lpfc_end_rscn(vport);
439 }
440 }
441 }
442 }
443
51ef4c26 444 lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb, ndlp, mbox);
c9f8735b 445 return 1;
dea3101e
JB
446
447out:
448 stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
449 stat.un.b.lsRjtRsnCodeExp = LSEXP_OUT_OF_RESOURCE;
858c9f6c 450 lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, NULL);
c9f8735b 451 return 0;
dea3101e
JB
452}
453
454static int
2e0fef85 455lpfc_rcv_padisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
dea3101e
JB
456 struct lpfc_iocbq *cmdiocb)
457{
2e0fef85 458 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
dea3101e 459 struct lpfc_dmabuf *pcmd;
2e0fef85
JS
460 struct serv_parm *sp;
461 struct lpfc_name *pnn, *ppn;
dea3101e
JB
462 struct ls_rjt stat;
463 ADISC *ap;
464 IOCB_t *icmd;
465 uint32_t *lp;
466 uint32_t cmd;
467
468 pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
469 lp = (uint32_t *) pcmd->virt;
470
471 cmd = *lp++;
472 if (cmd == ELS_CMD_ADISC) {
473 ap = (ADISC *) lp;
474 pnn = (struct lpfc_name *) & ap->nodeName;
475 ppn = (struct lpfc_name *) & ap->portName;
476 } else {
477 sp = (struct serv_parm *) lp;
478 pnn = (struct lpfc_name *) & sp->nodeName;
479 ppn = (struct lpfc_name *) & sp->portName;
480 }
481
482 icmd = &cmdiocb->iocb;
2e0fef85 483 if (icmd->ulpStatus == 0 && lpfc_check_adisc(vport, ndlp, pnn, ppn)) {
dea3101e 484 if (cmd == ELS_CMD_ADISC) {
2e0fef85 485 lpfc_els_rsp_adisc_acc(vport, cmdiocb, ndlp);
2fe165b6 486 } else {
2e0fef85 487 lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb, ndlp,
51ef4c26 488 NULL);
dea3101e 489 }
c9f8735b 490 return 1;
dea3101e
JB
491 }
492 /* Reject this request because invalid parameters */
493 stat.un.b.lsRjtRsvd0 = 0;
494 stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
495 stat.un.b.lsRjtRsnCodeExp = LSEXP_SPARM_OPTIONS;
496 stat.un.b.vendorUnique = 0;
858c9f6c 497 lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, NULL);
dea3101e 498
dea3101e
JB
499 /* 1 sec timeout */
500 mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ);
501
2e0fef85 502 spin_lock_irq(shost->host_lock);
dea3101e 503 ndlp->nlp_flag |= NLP_DELAY_TMO;
2e0fef85 504 spin_unlock_irq(shost->host_lock);
5024ab17
JW
505 ndlp->nlp_last_elscmd = ELS_CMD_PLOGI;
506 ndlp->nlp_prev_state = ndlp->nlp_state;
2e0fef85 507 lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
c9f8735b 508 return 0;
dea3101e
JB
509}
510
511static int
2e0fef85
JS
512lpfc_rcv_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
513 struct lpfc_iocbq *cmdiocb, uint32_t els_cmd)
dea3101e 514{
2e0fef85
JS
515 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
516
517 /* Put ndlp in NPR state with 1 sec timeout for plogi, ACC logo */
dea3101e
JB
518 /* Only call LOGO ACC for first LOGO, this avoids sending unnecessary
519 * PLOGIs during LOGO storms from a device.
520 */
2e0fef85 521 spin_lock_irq(shost->host_lock);
dea3101e 522 ndlp->nlp_flag |= NLP_LOGO_ACC;
2e0fef85 523 spin_unlock_irq(shost->host_lock);
82d9a2a2 524 if (els_cmd == ELS_CMD_PRLO)
51ef4c26 525 lpfc_els_rsp_acc(vport, ELS_CMD_PRLO, cmdiocb, ndlp, NULL);
82d9a2a2 526 else
51ef4c26 527 lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL);
dea3101e 528
c9f8735b 529 if (!(ndlp->nlp_type & NLP_FABRIC) ||
92d7f7b0 530 (ndlp->nlp_state == NLP_STE_ADISC_ISSUE)) {
dea3101e 531 /* Only try to re-login if this is NOT a Fabric Node */
dea3101e 532 mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ * 1);
2e0fef85 533 spin_lock_irq(shost->host_lock);
dea3101e 534 ndlp->nlp_flag |= NLP_DELAY_TMO;
2e0fef85 535 spin_unlock_irq(shost->host_lock);
dea3101e 536
5024ab17 537 ndlp->nlp_last_elscmd = ELS_CMD_PLOGI;
c9f8735b 538 }
87af33fe
JS
539 ndlp->nlp_prev_state = ndlp->nlp_state;
540 lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
dea3101e 541
2e0fef85 542 spin_lock_irq(shost->host_lock);
dea3101e 543 ndlp->nlp_flag &= ~NLP_NPR_ADISC;
2e0fef85 544 spin_unlock_irq(shost->host_lock);
dea3101e
JB
545 /* The driver has to wait until the ACC completes before it continues
546 * processing the LOGO. The action will resume in
547 * lpfc_cmpl_els_logo_acc routine. Since part of processing includes an
548 * unreg_login, the driver waits so the ACC does not get aborted.
549 */
c9f8735b 550 return 0;
dea3101e
JB
551}
552
553static void
2e0fef85
JS
554lpfc_rcv_prli(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
555 struct lpfc_iocbq *cmdiocb)
dea3101e
JB
556{
557 struct lpfc_dmabuf *pcmd;
558 uint32_t *lp;
559 PRLI *npr;
560 struct fc_rport *rport = ndlp->rport;
561 u32 roles;
562
563 pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
564 lp = (uint32_t *) pcmd->virt;
565 npr = (PRLI *) ((uint8_t *) lp + sizeof (uint32_t));
566
567 ndlp->nlp_type &= ~(NLP_FCP_TARGET | NLP_FCP_INITIATOR);
568 ndlp->nlp_fcp_info &= ~NLP_FCP_2_DEVICE;
92d7f7b0 569 if (npr->prliType == PRLI_FCP_TYPE) {
dea3101e
JB
570 if (npr->initiatorFunc)
571 ndlp->nlp_type |= NLP_FCP_INITIATOR;
572 if (npr->targetFunc)
573 ndlp->nlp_type |= NLP_FCP_TARGET;
574 if (npr->Retry)
575 ndlp->nlp_fcp_info |= NLP_FCP_2_DEVICE;
576 }
577 if (rport) {
578 /* We need to update the rport role values */
579 roles = FC_RPORT_ROLE_UNKNOWN;
580 if (ndlp->nlp_type & NLP_FCP_INITIATOR)
581 roles |= FC_RPORT_ROLE_FCP_INITIATOR;
582 if (ndlp->nlp_type & NLP_FCP_TARGET)
583 roles |= FC_RPORT_ROLE_FCP_TARGET;
858c9f6c
JS
584
585 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_RPORT,
586 "rport rolechg: role:x%x did:x%x flg:x%x",
587 roles, ndlp->nlp_DID, ndlp->nlp_flag);
588
dea3101e
JB
589 fc_remote_port_rolechg(rport, roles);
590 }
591}
592
593static uint32_t
2e0fef85 594lpfc_disc_set_adisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
dea3101e 595{
2e0fef85 596 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
2e0fef85 597
51ef4c26
JS
598 if (!ndlp->nlp_rpi) {
599 ndlp->nlp_flag &= ~NLP_NPR_ADISC;
600 return 0;
601 }
602
dea3101e 603 /* Check config parameter use-adisc or FCP-2 */
3de2a653 604 if ((vport->cfg_use_adisc && (vport->fc_flag & FC_RSCN_MODE)) ||
92d7f7b0
JS
605 ndlp->nlp_fcp_info & NLP_FCP_2_DEVICE) {
606 spin_lock_irq(shost->host_lock);
607 ndlp->nlp_flag |= NLP_NPR_ADISC;
608 spin_unlock_irq(shost->host_lock);
609 return 1;
610 }
611 ndlp->nlp_flag &= ~NLP_NPR_ADISC;
612 lpfc_unreg_rpi(vport, ndlp);
613 return 0;
dea3101e
JB
614}
615
616static uint32_t
2e0fef85
JS
617lpfc_disc_illegal(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
618 void *arg, uint32_t evt)
dea3101e 619{
e8b62011
JS
620 lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY,
621 "0253 Illegal State Transition: node x%x "
622 "event x%x, state x%x Data: x%x x%x\n",
623 ndlp->nlp_DID, evt, ndlp->nlp_state, ndlp->nlp_rpi,
624 ndlp->nlp_flag);
c9f8735b 625 return ndlp->nlp_state;
dea3101e
JB
626}
627
87af33fe
JS
628static uint32_t
629lpfc_cmpl_plogi_illegal(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
630 void *arg, uint32_t evt)
631{
632 /* This transition is only legal if we previously
633 * rcv'ed a PLOGI. Since we don't want 2 discovery threads
634 * working on the same NPortID, do nothing for this thread
635 * to stop it.
636 */
637 if (!(ndlp->nlp_flag & NLP_RCV_PLOGI)) {
638 lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY,
639 "0253 Illegal State Transition: node x%x "
640 "event x%x, state x%x Data: x%x x%x\n",
641 ndlp->nlp_DID, evt, ndlp->nlp_state, ndlp->nlp_rpi,
642 ndlp->nlp_flag);
643 }
644 return ndlp->nlp_state;
645}
646
dea3101e
JB
647/* Start of Discovery State Machine routines */
648
649static uint32_t
2e0fef85
JS
650lpfc_rcv_plogi_unused_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
651 void *arg, uint32_t evt)
dea3101e
JB
652{
653 struct lpfc_iocbq *cmdiocb;
654
655 cmdiocb = (struct lpfc_iocbq *) arg;
656
2e0fef85 657 if (lpfc_rcv_plogi(vport, ndlp, cmdiocb)) {
c9f8735b 658 return ndlp->nlp_state;
dea3101e 659 }
c9f8735b 660 return NLP_STE_FREED_NODE;
dea3101e
JB
661}
662
663static uint32_t
2e0fef85
JS
664lpfc_rcv_els_unused_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
665 void *arg, uint32_t evt)
dea3101e 666{
2e0fef85 667 lpfc_issue_els_logo(vport, ndlp, 0);
c9f8735b 668 return ndlp->nlp_state;
dea3101e
JB
669}
670
671static uint32_t
2e0fef85
JS
672lpfc_rcv_logo_unused_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
673 void *arg, uint32_t evt)
dea3101e 674{
2e0fef85
JS
675 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
676 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
dea3101e 677
2e0fef85 678 spin_lock_irq(shost->host_lock);
dea3101e 679 ndlp->nlp_flag |= NLP_LOGO_ACC;
2e0fef85 680 spin_unlock_irq(shost->host_lock);
51ef4c26 681 lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL);
dea3101e 682
c9f8735b 683 return ndlp->nlp_state;
dea3101e
JB
684}
685
686static uint32_t
2e0fef85
JS
687lpfc_cmpl_logo_unused_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
688 void *arg, uint32_t evt)
dea3101e 689{
c9f8735b 690 return NLP_STE_FREED_NODE;
dea3101e
JB
691}
692
693static uint32_t
2e0fef85
JS
694lpfc_device_rm_unused_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
695 void *arg, uint32_t evt)
dea3101e 696{
c9f8735b 697 return NLP_STE_FREED_NODE;
dea3101e
JB
698}
699
700static uint32_t
2e0fef85 701lpfc_rcv_plogi_plogi_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
dea3101e
JB
702 void *arg, uint32_t evt)
703{
2e0fef85 704 struct lpfc_hba *phba = vport->phba;
dea3101e 705 struct lpfc_iocbq *cmdiocb = arg;
2e0fef85
JS
706 struct lpfc_dmabuf *pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
707 uint32_t *lp = (uint32_t *) pcmd->virt;
708 struct serv_parm *sp = (struct serv_parm *) (lp + 1);
dea3101e
JB
709 struct ls_rjt stat;
710 int port_cmp;
711
dea3101e
JB
712 memset(&stat, 0, sizeof (struct ls_rjt));
713
714 /* For a PLOGI, we only accept if our portname is less
715 * than the remote portname.
716 */
717 phba->fc_stat.elsLogiCol++;
2e0fef85 718 port_cmp = memcmp(&vport->fc_portname, &sp->portName,
92d7f7b0 719 sizeof(struct lpfc_name));
dea3101e
JB
720
721 if (port_cmp >= 0) {
722 /* Reject this request because the remote node will accept
723 ours */
724 stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
725 stat.un.b.lsRjtRsnCodeExp = LSEXP_CMD_IN_PROGRESS;
858c9f6c
JS
726 lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp,
727 NULL);
2fe165b6 728 } else {
2e0fef85
JS
729 lpfc_rcv_plogi(vport, ndlp, cmdiocb);
730 } /* If our portname was less */
dea3101e 731
c9f8735b
JW
732 return ndlp->nlp_state;
733}
734
92d7f7b0
JS
735static uint32_t
736lpfc_rcv_prli_plogi_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
737 void *arg, uint32_t evt)
738{
739 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
740 struct ls_rjt stat;
741
742 memset(&stat, 0, sizeof (struct ls_rjt));
743 stat.un.b.lsRjtRsnCode = LSRJT_LOGICAL_BSY;
744 stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE;
858c9f6c 745 lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, NULL);
92d7f7b0
JS
746 return ndlp->nlp_state;
747}
748
c9f8735b 749static uint32_t
2e0fef85
JS
750lpfc_rcv_logo_plogi_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
751 void *arg, uint32_t evt)
c9f8735b 752{
2e0fef85 753 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
c9f8735b 754
92d7f7b0 755 /* software abort outstanding PLOGI */
2e0fef85 756 lpfc_els_abort(vport->phba, ndlp);
c9f8735b 757
2e0fef85 758 lpfc_rcv_logo(vport, ndlp, cmdiocb, ELS_CMD_LOGO);
c9f8735b 759 return ndlp->nlp_state;
dea3101e
JB
760}
761
762static uint32_t
2e0fef85
JS
763lpfc_rcv_els_plogi_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
764 void *arg, uint32_t evt)
dea3101e 765{
2e0fef85
JS
766 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
767 struct lpfc_hba *phba = vport->phba;
768 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
dea3101e
JB
769
770 /* software abort outstanding PLOGI */
07951076 771 lpfc_els_abort(phba, ndlp);
dea3101e
JB
772
773 if (evt == NLP_EVT_RCV_LOGO) {
51ef4c26 774 lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL);
2fe165b6 775 } else {
2e0fef85 776 lpfc_issue_els_logo(vport, ndlp, 0);
dea3101e
JB
777 }
778
2e0fef85 779 /* Put ndlp in npr state set plogi timer for 1 sec */
5024ab17 780 mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ * 1);
2e0fef85 781 spin_lock_irq(shost->host_lock);
5024ab17 782 ndlp->nlp_flag |= NLP_DELAY_TMO;
2e0fef85 783 spin_unlock_irq(shost->host_lock);
5024ab17
JW
784 ndlp->nlp_last_elscmd = ELS_CMD_PLOGI;
785 ndlp->nlp_prev_state = NLP_STE_PLOGI_ISSUE;
2e0fef85 786 lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
dea3101e 787
c9f8735b 788 return ndlp->nlp_state;
dea3101e
JB
789}
790
791static uint32_t
2e0fef85
JS
792lpfc_cmpl_plogi_plogi_issue(struct lpfc_vport *vport,
793 struct lpfc_nodelist *ndlp,
794 void *arg,
dea3101e
JB
795 uint32_t evt)
796{
2e0fef85
JS
797 struct lpfc_hba *phba = vport->phba;
798 struct lpfc_iocbq *cmdiocb, *rspiocb;
14691150 799 struct lpfc_dmabuf *pcmd, *prsp, *mp;
dea3101e
JB
800 uint32_t *lp;
801 IOCB_t *irsp;
802 struct serv_parm *sp;
803 LPFC_MBOXQ_t *mbox;
804
805 cmdiocb = (struct lpfc_iocbq *) arg;
806 rspiocb = cmdiocb->context_un.rsp_iocb;
807
808 if (ndlp->nlp_flag & NLP_ACC_REGLOGIN) {
5024ab17 809 /* Recovery from PLOGI collision logic */
c9f8735b 810 return ndlp->nlp_state;
dea3101e
JB
811 }
812
813 irsp = &rspiocb->iocb;
814
815 if (irsp->ulpStatus)
816 goto out;
817
818 pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
819
2e0fef85 820 prsp = list_get_first(&pcmd->list, struct lpfc_dmabuf, list);
dea3101e 821
2e0fef85 822 lp = (uint32_t *) prsp->virt;
dea3101e 823 sp = (struct serv_parm *) ((uint8_t *) lp + sizeof (uint32_t));
2e0fef85 824 if (!lpfc_check_sparm(vport, ndlp, sp, CLASS3))
dea3101e 825 goto out;
dea3101e 826 /* PLOGI chkparm OK */
e8b62011
JS
827 lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
828 "0121 PLOGI chkparm OK Data: x%x x%x x%x x%x\n",
829 ndlp->nlp_DID, ndlp->nlp_state,
830 ndlp->nlp_flag, ndlp->nlp_rpi);
3de2a653 831 if (vport->cfg_fcp_class == 2 && (sp->cls2.classValid))
dea3101e 832 ndlp->nlp_fcp_info |= CLASS2;
2e0fef85 833 else
dea3101e 834 ndlp->nlp_fcp_info |= CLASS3;
2e0fef85 835
dea3101e
JB
836 ndlp->nlp_class_sup = 0;
837 if (sp->cls1.classValid)
838 ndlp->nlp_class_sup |= FC_COS_CLASS1;
839 if (sp->cls2.classValid)
840 ndlp->nlp_class_sup |= FC_COS_CLASS2;
841 if (sp->cls3.classValid)
842 ndlp->nlp_class_sup |= FC_COS_CLASS3;
843 if (sp->cls4.classValid)
844 ndlp->nlp_class_sup |= FC_COS_CLASS4;
845 ndlp->nlp_maxframe =
2e0fef85 846 ((sp->cmn.bbRcvSizeMsb & 0x0F) << 8) | sp->cmn.bbRcvSizeLsb;
dea3101e 847
2e0fef85 848 mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
92d7f7b0 849 if (!mbox) {
e8b62011
JS
850 lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
851 "0133 PLOGI: no memory for reg_login "
92d7f7b0 852 "Data: x%x x%x x%x x%x\n",
92d7f7b0
JS
853 ndlp->nlp_DID, ndlp->nlp_state,
854 ndlp->nlp_flag, ndlp->nlp_rpi);
dea3101e 855 goto out;
92d7f7b0 856 }
dea3101e 857
2e0fef85
JS
858 lpfc_unreg_rpi(vport, ndlp);
859
92d7f7b0
JS
860 if (lpfc_reg_login(phba, vport->vpi, irsp->un.elsreq64.remoteID,
861 (uint8_t *) sp, mbox, 0) == 0) {
2fe165b6 862 switch (ndlp->nlp_DID) {
dea3101e 863 case NameServer_DID:
de0c5b32 864 mbox->mbox_cmpl = lpfc_mbx_cmpl_ns_reg_login;
dea3101e
JB
865 break;
866 case FDMI_DID:
de0c5b32 867 mbox->mbox_cmpl = lpfc_mbx_cmpl_fdmi_reg_login;
dea3101e
JB
868 break;
869 default:
de0c5b32 870 mbox->mbox_cmpl = lpfc_mbx_cmpl_reg_login;
dea3101e 871 }
329f9bc7 872 mbox->context2 = lpfc_nlp_get(ndlp);
2e0fef85 873 mbox->vport = vport;
0b727fea 874 if (lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT)
dea3101e 875 != MBX_NOT_FINISHED) {
2e0fef85
JS
876 lpfc_nlp_set_state(vport, ndlp,
877 NLP_STE_REG_LOGIN_ISSUE);
c9f8735b 878 return ndlp->nlp_state;
dea3101e 879 }
329f9bc7 880 lpfc_nlp_put(ndlp);
92d7f7b0 881 mp = (struct lpfc_dmabuf *) mbox->context1;
14691150
JS
882 lpfc_mbuf_free(phba, mp->virt, mp->phys);
883 kfree(mp);
dea3101e 884 mempool_free(mbox, phba->mbox_mem_pool);
92d7f7b0 885
e8b62011
JS
886 lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
887 "0134 PLOGI: cannot issue reg_login "
888 "Data: x%x x%x x%x x%x\n",
889 ndlp->nlp_DID, ndlp->nlp_state,
890 ndlp->nlp_flag, ndlp->nlp_rpi);
dea3101e
JB
891 } else {
892 mempool_free(mbox, phba->mbox_mem_pool);
92d7f7b0 893
e8b62011
JS
894 lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
895 "0135 PLOGI: cannot format reg_login "
896 "Data: x%x x%x x%x x%x\n",
897 ndlp->nlp_DID, ndlp->nlp_state,
898 ndlp->nlp_flag, ndlp->nlp_rpi);
dea3101e
JB
899 }
900
901
92d7f7b0
JS
902out:
903 if (ndlp->nlp_DID == NameServer_DID) {
904 lpfc_vport_set_state(vport, FC_VPORT_FAILED);
e8b62011
JS
905 lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
906 "0261 Cannot Register NameServer login\n");
92d7f7b0
JS
907 }
908
dea3101e
JB
909 /* Free this node since the driver cannot login or has the wrong
910 sparm */
87af33fe 911 lpfc_nlp_not_used(ndlp);
c9f8735b 912 return NLP_STE_FREED_NODE;
dea3101e
JB
913}
914
915static uint32_t
2e0fef85
JS
916lpfc_device_rm_plogi_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
917 void *arg, uint32_t evt)
dea3101e 918{
2e0fef85
JS
919 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
920
921 if (ndlp->nlp_flag & NLP_NPR_2B_DISC) {
922 spin_lock_irq(shost->host_lock);
a0f9b48d 923 ndlp->nlp_flag |= NLP_NODEV_REMOVE;
2e0fef85 924 spin_unlock_irq(shost->host_lock);
a0f9b48d 925 return ndlp->nlp_state;
2e0fef85 926 } else {
a0f9b48d 927 /* software abort outstanding PLOGI */
2e0fef85 928 lpfc_els_abort(vport->phba, ndlp);
dea3101e 929
2e0fef85 930 lpfc_drop_node(vport, ndlp);
a0f9b48d
JS
931 return NLP_STE_FREED_NODE;
932 }
dea3101e
JB
933}
934
935static uint32_t
2e0fef85
JS
936lpfc_device_recov_plogi_issue(struct lpfc_vport *vport,
937 struct lpfc_nodelist *ndlp,
938 void *arg,
939 uint32_t evt)
dea3101e 940{
2e0fef85
JS
941 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
942 struct lpfc_hba *phba = vport->phba;
943
92d7f7b0
JS
944 /* Don't do anything that will mess up processing of the
945 * previous RSCN.
946 */
947 if (vport->fc_flag & FC_RSCN_DEFERRED)
948 return ndlp->nlp_state;
949
dea3101e 950 /* software abort outstanding PLOGI */
07951076 951 lpfc_els_abort(phba, ndlp);
dea3101e 952
5024ab17 953 ndlp->nlp_prev_state = NLP_STE_PLOGI_ISSUE;
2e0fef85 954 lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
92d7f7b0 955 spin_lock_irq(shost->host_lock);
a0f9b48d 956 ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC);
2e0fef85 957 spin_unlock_irq(shost->host_lock);
dea3101e 958
c9f8735b 959 return ndlp->nlp_state;
dea3101e
JB
960}
961
962static uint32_t
2e0fef85
JS
963lpfc_rcv_plogi_adisc_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
964 void *arg, uint32_t evt)
dea3101e 965{
2e0fef85 966 struct lpfc_hba *phba = vport->phba;
dea3101e
JB
967 struct lpfc_iocbq *cmdiocb;
968
969 /* software abort outstanding ADISC */
07951076 970 lpfc_els_abort(phba, ndlp);
dea3101e
JB
971
972 cmdiocb = (struct lpfc_iocbq *) arg;
973
2e0fef85 974 if (lpfc_rcv_plogi(vport, ndlp, cmdiocb))
c9f8735b 975 return ndlp->nlp_state;
2e0fef85 976
5024ab17 977 ndlp->nlp_prev_state = NLP_STE_ADISC_ISSUE;
2e0fef85
JS
978 lpfc_issue_els_plogi(vport, ndlp->nlp_DID, 0);
979 lpfc_nlp_set_state(vport, ndlp, NLP_STE_PLOGI_ISSUE);
dea3101e 980
c9f8735b 981 return ndlp->nlp_state;
dea3101e
JB
982}
983
984static uint32_t
2e0fef85
JS
985lpfc_rcv_prli_adisc_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
986 void *arg, uint32_t evt)
dea3101e 987{
2e0fef85 988 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
dea3101e 989
2e0fef85 990 lpfc_els_rsp_prli_acc(vport, cmdiocb, ndlp);
c9f8735b 991 return ndlp->nlp_state;
dea3101e
JB
992}
993
994static uint32_t
2e0fef85
JS
995lpfc_rcv_logo_adisc_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
996 void *arg, uint32_t evt)
dea3101e 997{
2e0fef85 998 struct lpfc_hba *phba = vport->phba;
dea3101e
JB
999 struct lpfc_iocbq *cmdiocb;
1000
1001 cmdiocb = (struct lpfc_iocbq *) arg;
1002
1003 /* software abort outstanding ADISC */
07951076 1004 lpfc_els_abort(phba, ndlp);
dea3101e 1005
2e0fef85 1006 lpfc_rcv_logo(vport, ndlp, cmdiocb, ELS_CMD_LOGO);
c9f8735b 1007 return ndlp->nlp_state;
dea3101e
JB
1008}
1009
1010static uint32_t
2e0fef85
JS
1011lpfc_rcv_padisc_adisc_issue(struct lpfc_vport *vport,
1012 struct lpfc_nodelist *ndlp,
1013 void *arg, uint32_t evt)
dea3101e
JB
1014{
1015 struct lpfc_iocbq *cmdiocb;
1016
1017 cmdiocb = (struct lpfc_iocbq *) arg;
1018
2e0fef85 1019 lpfc_rcv_padisc(vport, ndlp, cmdiocb);
c9f8735b 1020 return ndlp->nlp_state;
dea3101e
JB
1021}
1022
1023static uint32_t
2e0fef85
JS
1024lpfc_rcv_prlo_adisc_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
1025 void *arg, uint32_t evt)
dea3101e
JB
1026{
1027 struct lpfc_iocbq *cmdiocb;
1028
1029 cmdiocb = (struct lpfc_iocbq *) arg;
1030
1031 /* Treat like rcv logo */
2e0fef85 1032 lpfc_rcv_logo(vport, ndlp, cmdiocb, ELS_CMD_PRLO);
c9f8735b 1033 return ndlp->nlp_state;
dea3101e
JB
1034}
1035
1036static uint32_t
2e0fef85
JS
1037lpfc_cmpl_adisc_adisc_issue(struct lpfc_vport *vport,
1038 struct lpfc_nodelist *ndlp,
1039 void *arg, uint32_t evt)
dea3101e 1040{
2e0fef85
JS
1041 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
1042 struct lpfc_hba *phba = vport->phba;
dea3101e
JB
1043 struct lpfc_iocbq *cmdiocb, *rspiocb;
1044 IOCB_t *irsp;
1045 ADISC *ap;
1046
1047 cmdiocb = (struct lpfc_iocbq *) arg;
1048 rspiocb = cmdiocb->context_un.rsp_iocb;
1049
1050 ap = (ADISC *)lpfc_check_elscmpl_iocb(phba, cmdiocb, rspiocb);
1051 irsp = &rspiocb->iocb;
1052
1053 if ((irsp->ulpStatus) ||
92d7f7b0 1054 (!lpfc_check_adisc(vport, ndlp, &ap->nodeName, &ap->portName))) {
dea3101e
JB
1055 /* 1 sec timeout */
1056 mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ);
2e0fef85 1057 spin_lock_irq(shost->host_lock);
dea3101e 1058 ndlp->nlp_flag |= NLP_DELAY_TMO;
2e0fef85 1059 spin_unlock_irq(shost->host_lock);
5024ab17 1060 ndlp->nlp_last_elscmd = ELS_CMD_PLOGI;
dea3101e 1061
2e0fef85
JS
1062 memset(&ndlp->nlp_nodename, 0, sizeof(struct lpfc_name));
1063 memset(&ndlp->nlp_portname, 0, sizeof(struct lpfc_name));
dea3101e 1064
5024ab17 1065 ndlp->nlp_prev_state = NLP_STE_ADISC_ISSUE;
2e0fef85
JS
1066 lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
1067 lpfc_unreg_rpi(vport, ndlp);
c9f8735b 1068 return ndlp->nlp_state;
dea3101e 1069 }
5024ab17 1070
2501322e 1071 if (ndlp->nlp_type & NLP_FCP_TARGET) {
5024ab17 1072 ndlp->nlp_prev_state = NLP_STE_ADISC_ISSUE;
2e0fef85 1073 lpfc_nlp_set_state(vport, ndlp, NLP_STE_MAPPED_NODE);
2501322e 1074 } else {
5024ab17 1075 ndlp->nlp_prev_state = NLP_STE_ADISC_ISSUE;
2e0fef85 1076 lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE);
2501322e 1077 }
c9f8735b 1078 return ndlp->nlp_state;
dea3101e
JB
1079}
1080
1081static uint32_t
2e0fef85
JS
1082lpfc_device_rm_adisc_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
1083 void *arg, uint32_t evt)
dea3101e 1084{
2e0fef85
JS
1085 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
1086
1087 if (ndlp->nlp_flag & NLP_NPR_2B_DISC) {
1088 spin_lock_irq(shost->host_lock);
a0f9b48d 1089 ndlp->nlp_flag |= NLP_NODEV_REMOVE;
2e0fef85 1090 spin_unlock_irq(shost->host_lock);
a0f9b48d 1091 return ndlp->nlp_state;
2e0fef85 1092 } else {
a0f9b48d 1093 /* software abort outstanding ADISC */
2e0fef85 1094 lpfc_els_abort(vport->phba, ndlp);
dea3101e 1095
2e0fef85 1096 lpfc_drop_node(vport, ndlp);
a0f9b48d
JS
1097 return NLP_STE_FREED_NODE;
1098 }
dea3101e
JB
1099}
1100
1101static uint32_t
2e0fef85
JS
1102lpfc_device_recov_adisc_issue(struct lpfc_vport *vport,
1103 struct lpfc_nodelist *ndlp,
1104 void *arg,
1105 uint32_t evt)
dea3101e 1106{
2e0fef85
JS
1107 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
1108 struct lpfc_hba *phba = vport->phba;
1109
92d7f7b0
JS
1110 /* Don't do anything that will mess up processing of the
1111 * previous RSCN.
1112 */
1113 if (vport->fc_flag & FC_RSCN_DEFERRED)
1114 return ndlp->nlp_state;
1115
dea3101e 1116 /* software abort outstanding ADISC */
07951076 1117 lpfc_els_abort(phba, ndlp);
dea3101e 1118
5024ab17 1119 ndlp->nlp_prev_state = NLP_STE_ADISC_ISSUE;
2e0fef85
JS
1120 lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
1121 spin_lock_irq(shost->host_lock);
a0f9b48d 1122 ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC);
2e0fef85 1123 spin_unlock_irq(shost->host_lock);
92d7f7b0 1124 lpfc_disc_set_adisc(vport, ndlp);
c9f8735b 1125 return ndlp->nlp_state;
dea3101e
JB
1126}
1127
1128static uint32_t
2e0fef85
JS
1129lpfc_rcv_plogi_reglogin_issue(struct lpfc_vport *vport,
1130 struct lpfc_nodelist *ndlp,
1131 void *arg,
dea3101e
JB
1132 uint32_t evt)
1133{
2e0fef85 1134 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
dea3101e 1135
2e0fef85 1136 lpfc_rcv_plogi(vport, ndlp, cmdiocb);
c9f8735b 1137 return ndlp->nlp_state;
dea3101e
JB
1138}
1139
1140static uint32_t
2e0fef85
JS
1141lpfc_rcv_prli_reglogin_issue(struct lpfc_vport *vport,
1142 struct lpfc_nodelist *ndlp,
1143 void *arg,
dea3101e
JB
1144 uint32_t evt)
1145{
2e0fef85 1146 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
dea3101e 1147
2e0fef85 1148 lpfc_els_rsp_prli_acc(vport, cmdiocb, ndlp);
c9f8735b 1149 return ndlp->nlp_state;
dea3101e
JB
1150}
1151
1152static uint32_t
2e0fef85
JS
1153lpfc_rcv_logo_reglogin_issue(struct lpfc_vport *vport,
1154 struct lpfc_nodelist *ndlp,
1155 void *arg,
dea3101e
JB
1156 uint32_t evt)
1157{
2e0fef85
JS
1158 struct lpfc_hba *phba = vport->phba;
1159 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
7054a606
JS
1160 LPFC_MBOXQ_t *mb;
1161 LPFC_MBOXQ_t *nextmb;
1162 struct lpfc_dmabuf *mp;
dea3101e
JB
1163
1164 cmdiocb = (struct lpfc_iocbq *) arg;
1165
7054a606
JS
1166 /* cleanup any ndlp on mbox q waiting for reglogin cmpl */
1167 if ((mb = phba->sli.mbox_active)) {
1168 if ((mb->mb.mbxCommand == MBX_REG_LOGIN64) &&
1169 (ndlp == (struct lpfc_nodelist *) mb->context2)) {
92d7f7b0 1170 lpfc_nlp_put(ndlp);
7054a606
JS
1171 mb->context2 = NULL;
1172 mb->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
1173 }
1174 }
1175
2e0fef85 1176 spin_lock_irq(&phba->hbalock);
7054a606
JS
1177 list_for_each_entry_safe(mb, nextmb, &phba->sli.mboxq, list) {
1178 if ((mb->mb.mbxCommand == MBX_REG_LOGIN64) &&
1179 (ndlp == (struct lpfc_nodelist *) mb->context2)) {
1180 mp = (struct lpfc_dmabuf *) (mb->context1);
1181 if (mp) {
98c9ea5c 1182 __lpfc_mbuf_free(phba, mp->virt, mp->phys);
7054a606
JS
1183 kfree(mp);
1184 }
92d7f7b0 1185 lpfc_nlp_put(ndlp);
7054a606
JS
1186 list_del(&mb->list);
1187 mempool_free(mb, phba->mbox_mem_pool);
1188 }
1189 }
2e0fef85 1190 spin_unlock_irq(&phba->hbalock);
7054a606 1191
2e0fef85 1192 lpfc_rcv_logo(vport, ndlp, cmdiocb, ELS_CMD_LOGO);
c9f8735b 1193 return ndlp->nlp_state;
dea3101e
JB
1194}
1195
1196static uint32_t
2e0fef85
JS
1197lpfc_rcv_padisc_reglogin_issue(struct lpfc_vport *vport,
1198 struct lpfc_nodelist *ndlp,
1199 void *arg,
dea3101e
JB
1200 uint32_t evt)
1201{
2e0fef85 1202 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
dea3101e 1203
2e0fef85 1204 lpfc_rcv_padisc(vport, ndlp, cmdiocb);
c9f8735b 1205 return ndlp->nlp_state;
dea3101e
JB
1206}
1207
1208static uint32_t
2e0fef85
JS
1209lpfc_rcv_prlo_reglogin_issue(struct lpfc_vport *vport,
1210 struct lpfc_nodelist *ndlp,
1211 void *arg,
dea3101e
JB
1212 uint32_t evt)
1213{
1214 struct lpfc_iocbq *cmdiocb;
1215
1216 cmdiocb = (struct lpfc_iocbq *) arg;
51ef4c26 1217 lpfc_els_rsp_acc(vport, ELS_CMD_PRLO, cmdiocb, ndlp, NULL);
c9f8735b 1218 return ndlp->nlp_state;
dea3101e
JB
1219}
1220
1221static uint32_t
2e0fef85
JS
1222lpfc_cmpl_reglogin_reglogin_issue(struct lpfc_vport *vport,
1223 struct lpfc_nodelist *ndlp,
1224 void *arg,
1225 uint32_t evt)
dea3101e 1226{
2e0fef85 1227 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
2e0fef85
JS
1228 LPFC_MBOXQ_t *pmb = (LPFC_MBOXQ_t *) arg;
1229 MAILBOX_t *mb = &pmb->mb;
1230 uint32_t did = mb->un.varWords[1];
dea3101e 1231
dea3101e
JB
1232 if (mb->mbxStatus) {
1233 /* RegLogin failed */
e8b62011
JS
1234 lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY,
1235 "0246 RegLogin failed Data: x%x x%x x%x\n",
2e0fef85 1236 did, mb->mbxStatus, vport->port_state);
d0e56dad
JS
1237 /*
1238 * If RegLogin failed due to lack of HBA resources do not
1239 * retry discovery.
1240 */
1241 if (mb->mbxStatus == MBXERR_RPI_FULL) {
87af33fe
JS
1242 ndlp->nlp_prev_state = NLP_STE_REG_LOGIN_ISSUE;
1243 lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
d0e56dad
JS
1244 return ndlp->nlp_state;
1245 }
1246
2e0fef85 1247 /* Put ndlp in npr state set plogi timer for 1 sec */
dea3101e 1248 mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ * 1);
2e0fef85 1249 spin_lock_irq(shost->host_lock);
dea3101e 1250 ndlp->nlp_flag |= NLP_DELAY_TMO;
2e0fef85 1251 spin_unlock_irq(shost->host_lock);
5024ab17 1252 ndlp->nlp_last_elscmd = ELS_CMD_PLOGI;
dea3101e 1253
2e0fef85 1254 lpfc_issue_els_logo(vport, ndlp, 0);
5024ab17 1255 ndlp->nlp_prev_state = NLP_STE_REG_LOGIN_ISSUE;
2e0fef85 1256 lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
c9f8735b 1257 return ndlp->nlp_state;
dea3101e
JB
1258 }
1259
dea3101e 1260 ndlp->nlp_rpi = mb->un.varWords[0];
dea3101e
JB
1261
1262 /* Only if we are not a fabric nport do we issue PRLI */
1263 if (!(ndlp->nlp_type & NLP_FABRIC)) {
5024ab17 1264 ndlp->nlp_prev_state = NLP_STE_REG_LOGIN_ISSUE;
2e0fef85
JS
1265 lpfc_nlp_set_state(vport, ndlp, NLP_STE_PRLI_ISSUE);
1266 lpfc_issue_els_prli(vport, ndlp, 0);
dea3101e 1267 } else {
5024ab17 1268 ndlp->nlp_prev_state = NLP_STE_REG_LOGIN_ISSUE;
2e0fef85 1269 lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE);
dea3101e 1270 }
c9f8735b 1271 return ndlp->nlp_state;
dea3101e
JB
1272}
1273
1274static uint32_t
2e0fef85
JS
1275lpfc_device_rm_reglogin_issue(struct lpfc_vport *vport,
1276 struct lpfc_nodelist *ndlp,
1277 void *arg,
dea3101e
JB
1278 uint32_t evt)
1279{
2e0fef85
JS
1280 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
1281
1282 if (ndlp->nlp_flag & NLP_NPR_2B_DISC) {
1283 spin_lock_irq(shost->host_lock);
a0f9b48d 1284 ndlp->nlp_flag |= NLP_NODEV_REMOVE;
2e0fef85 1285 spin_unlock_irq(shost->host_lock);
a0f9b48d 1286 return ndlp->nlp_state;
2e0fef85
JS
1287 } else {
1288 lpfc_drop_node(vport, ndlp);
a0f9b48d
JS
1289 return NLP_STE_FREED_NODE;
1290 }
dea3101e
JB
1291}
1292
1293static uint32_t
2e0fef85
JS
1294lpfc_device_recov_reglogin_issue(struct lpfc_vport *vport,
1295 struct lpfc_nodelist *ndlp,
1296 void *arg,
1297 uint32_t evt)
dea3101e 1298{
2e0fef85
JS
1299 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
1300
92d7f7b0
JS
1301 /* Don't do anything that will mess up processing of the
1302 * previous RSCN.
1303 */
1304 if (vport->fc_flag & FC_RSCN_DEFERRED)
1305 return ndlp->nlp_state;
1306
5024ab17 1307 ndlp->nlp_prev_state = NLP_STE_REG_LOGIN_ISSUE;
2e0fef85
JS
1308 lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
1309 spin_lock_irq(shost->host_lock);
a0f9b48d 1310 ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC);
2e0fef85 1311 spin_unlock_irq(shost->host_lock);
92d7f7b0 1312 lpfc_disc_set_adisc(vport, ndlp);
c9f8735b 1313 return ndlp->nlp_state;
dea3101e
JB
1314}
1315
1316static uint32_t
2e0fef85
JS
1317lpfc_rcv_plogi_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
1318 void *arg, uint32_t evt)
dea3101e
JB
1319{
1320 struct lpfc_iocbq *cmdiocb;
1321
1322 cmdiocb = (struct lpfc_iocbq *) arg;
1323
2e0fef85 1324 lpfc_rcv_plogi(vport, ndlp, cmdiocb);
c9f8735b 1325 return ndlp->nlp_state;
dea3101e
JB
1326}
1327
1328static uint32_t
2e0fef85
JS
1329lpfc_rcv_prli_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
1330 void *arg, uint32_t evt)
dea3101e 1331{
2e0fef85 1332 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
dea3101e 1333
2e0fef85 1334 lpfc_els_rsp_prli_acc(vport, cmdiocb, ndlp);
c9f8735b 1335 return ndlp->nlp_state;
dea3101e
JB
1336}
1337
1338static uint32_t
2e0fef85
JS
1339lpfc_rcv_logo_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
1340 void *arg, uint32_t evt)
dea3101e 1341{
2e0fef85 1342 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
dea3101e
JB
1343
1344 /* Software abort outstanding PRLI before sending acc */
2e0fef85 1345 lpfc_els_abort(vport->phba, ndlp);
dea3101e 1346
2e0fef85 1347 lpfc_rcv_logo(vport, ndlp, cmdiocb, ELS_CMD_LOGO);
c9f8735b 1348 return ndlp->nlp_state;
dea3101e
JB
1349}
1350
1351static uint32_t
2e0fef85
JS
1352lpfc_rcv_padisc_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
1353 void *arg, uint32_t evt)
dea3101e 1354{
2e0fef85 1355 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
dea3101e 1356
2e0fef85 1357 lpfc_rcv_padisc(vport, ndlp, cmdiocb);
c9f8735b 1358 return ndlp->nlp_state;
dea3101e
JB
1359}
1360
1361/* This routine is envoked when we rcv a PRLO request from a nport
1362 * we are logged into. We should send back a PRLO rsp setting the
1363 * appropriate bits.
1364 * NEXT STATE = PRLI_ISSUE
1365 */
1366static uint32_t
2e0fef85
JS
1367lpfc_rcv_prlo_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
1368 void *arg, uint32_t evt)
dea3101e 1369{
2e0fef85 1370 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
dea3101e 1371
51ef4c26 1372 lpfc_els_rsp_acc(vport, ELS_CMD_PRLO, cmdiocb, ndlp, NULL);
c9f8735b 1373 return ndlp->nlp_state;
dea3101e
JB
1374}
1375
1376static uint32_t
2e0fef85
JS
1377lpfc_cmpl_prli_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
1378 void *arg, uint32_t evt)
dea3101e 1379{
92d7f7b0 1380 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
dea3101e 1381 struct lpfc_iocbq *cmdiocb, *rspiocb;
2e0fef85 1382 struct lpfc_hba *phba = vport->phba;
dea3101e
JB
1383 IOCB_t *irsp;
1384 PRLI *npr;
1385
1386 cmdiocb = (struct lpfc_iocbq *) arg;
1387 rspiocb = cmdiocb->context_un.rsp_iocb;
1388 npr = (PRLI *)lpfc_check_elscmpl_iocb(phba, cmdiocb, rspiocb);
1389
1390 irsp = &rspiocb->iocb;
1391 if (irsp->ulpStatus) {
858c9f6c 1392 if ((vport->port_type == LPFC_NPIV_PORT) &&
3de2a653 1393 vport->cfg_restrict_login) {
858c9f6c
JS
1394 goto out;
1395 }
5024ab17 1396 ndlp->nlp_prev_state = NLP_STE_PRLI_ISSUE;
2e0fef85 1397 lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE);
c9f8735b 1398 return ndlp->nlp_state;
dea3101e
JB
1399 }
1400
1401 /* Check out PRLI rsp */
1402 ndlp->nlp_type &= ~(NLP_FCP_TARGET | NLP_FCP_INITIATOR);
1403 ndlp->nlp_fcp_info &= ~NLP_FCP_2_DEVICE;
1404 if ((npr->acceptRspCode == PRLI_REQ_EXECUTED) &&
1405 (npr->prliType == PRLI_FCP_TYPE)) {
1406 if (npr->initiatorFunc)
1407 ndlp->nlp_type |= NLP_FCP_INITIATOR;
1408 if (npr->targetFunc)
1409 ndlp->nlp_type |= NLP_FCP_TARGET;
1410 if (npr->Retry)
1411 ndlp->nlp_fcp_info |= NLP_FCP_2_DEVICE;
1412 }
92d7f7b0
JS
1413 if (!(ndlp->nlp_type & NLP_FCP_TARGET) &&
1414 (vport->port_type == LPFC_NPIV_PORT) &&
3de2a653 1415 vport->cfg_restrict_login) {
858c9f6c 1416out:
92d7f7b0
JS
1417 spin_lock_irq(shost->host_lock);
1418 ndlp->nlp_flag |= NLP_TARGET_REMOVE;
1419 spin_unlock_irq(shost->host_lock);
1420 lpfc_issue_els_logo(vport, ndlp, 0);
1421
1422 ndlp->nlp_prev_state = NLP_STE_PRLI_ISSUE;
87af33fe 1423 lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
92d7f7b0
JS
1424 return ndlp->nlp_state;
1425 }
dea3101e 1426
5024ab17 1427 ndlp->nlp_prev_state = NLP_STE_PRLI_ISSUE;
92d7f7b0
JS
1428 if (ndlp->nlp_type & NLP_FCP_TARGET)
1429 lpfc_nlp_set_state(vport, ndlp, NLP_STE_MAPPED_NODE);
1430 else
1431 lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE);
c9f8735b 1432 return ndlp->nlp_state;
dea3101e
JB
1433}
1434
1435/*! lpfc_device_rm_prli_issue
92d7f7b0
JS
1436 *
1437 * \pre
1438 * \post
1439 * \param phba
1440 * \param ndlp
1441 * \param arg
1442 * \param evt
1443 * \return uint32_t
1444 *
1445 * \b Description:
1446 * This routine is envoked when we a request to remove a nport we are in the
1447 * process of PRLIing. We should software abort outstanding prli, unreg
1448 * login, send a logout. We will change node state to UNUSED_NODE, put it
1449 * on plogi list so it can be freed when LOGO completes.
1450 *
1451 */
1452
dea3101e 1453static uint32_t
2e0fef85
JS
1454lpfc_device_rm_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
1455 void *arg, uint32_t evt)
dea3101e 1456{
2e0fef85
JS
1457 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
1458
1459 if (ndlp->nlp_flag & NLP_NPR_2B_DISC) {
1460 spin_lock_irq(shost->host_lock);
a0f9b48d 1461 ndlp->nlp_flag |= NLP_NODEV_REMOVE;
2e0fef85 1462 spin_unlock_irq(shost->host_lock);
a0f9b48d 1463 return ndlp->nlp_state;
2e0fef85 1464 } else {
a0f9b48d 1465 /* software abort outstanding PLOGI */
2e0fef85 1466 lpfc_els_abort(vport->phba, ndlp);
dea3101e 1467
2e0fef85 1468 lpfc_drop_node(vport, ndlp);
a0f9b48d
JS
1469 return NLP_STE_FREED_NODE;
1470 }
dea3101e
JB
1471}
1472
1473
1474/*! lpfc_device_recov_prli_issue
92d7f7b0
JS
1475 *
1476 * \pre
1477 * \post
1478 * \param phba
1479 * \param ndlp
1480 * \param arg
1481 * \param evt
1482 * \return uint32_t
1483 *
1484 * \b Description:
1485 * The routine is envoked when the state of a device is unknown, like
1486 * during a link down. We should remove the nodelist entry from the
1487 * unmapped list, issue a UNREG_LOGIN, do a software abort of the
1488 * outstanding PRLI command, then free the node entry.
1489 */
dea3101e 1490static uint32_t
2e0fef85
JS
1491lpfc_device_recov_prli_issue(struct lpfc_vport *vport,
1492 struct lpfc_nodelist *ndlp,
1493 void *arg,
1494 uint32_t evt)
dea3101e 1495{
2e0fef85
JS
1496 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
1497 struct lpfc_hba *phba = vport->phba;
1498
92d7f7b0
JS
1499 /* Don't do anything that will mess up processing of the
1500 * previous RSCN.
1501 */
1502 if (vport->fc_flag & FC_RSCN_DEFERRED)
1503 return ndlp->nlp_state;
1504
dea3101e 1505 /* software abort outstanding PRLI */
07951076 1506 lpfc_els_abort(phba, ndlp);
dea3101e 1507
5024ab17 1508 ndlp->nlp_prev_state = NLP_STE_PRLI_ISSUE;
2e0fef85
JS
1509 lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
1510 spin_lock_irq(shost->host_lock);
a0f9b48d 1511 ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC);
2e0fef85 1512 spin_unlock_irq(shost->host_lock);
92d7f7b0 1513 lpfc_disc_set_adisc(vport, ndlp);
c9f8735b 1514 return ndlp->nlp_state;
dea3101e
JB
1515}
1516
1517static uint32_t
2e0fef85
JS
1518lpfc_rcv_plogi_unmap_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
1519 void *arg, uint32_t evt)
dea3101e 1520{
2e0fef85 1521 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
dea3101e 1522
2e0fef85 1523 lpfc_rcv_plogi(vport, ndlp, cmdiocb);
c9f8735b 1524 return ndlp->nlp_state;
dea3101e
JB
1525}
1526
1527static uint32_t
2e0fef85
JS
1528lpfc_rcv_prli_unmap_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
1529 void *arg, uint32_t evt)
dea3101e 1530{
2e0fef85 1531 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
dea3101e 1532
2e0fef85
JS
1533 lpfc_rcv_prli(vport, ndlp, cmdiocb);
1534 lpfc_els_rsp_prli_acc(vport, cmdiocb, ndlp);
c9f8735b 1535 return ndlp->nlp_state;
dea3101e
JB
1536}
1537
1538static uint32_t
2e0fef85
JS
1539lpfc_rcv_logo_unmap_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
1540 void *arg, uint32_t evt)
dea3101e 1541{
2e0fef85 1542 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
dea3101e 1543
2e0fef85 1544 lpfc_rcv_logo(vport, ndlp, cmdiocb, ELS_CMD_LOGO);
c9f8735b 1545 return ndlp->nlp_state;
dea3101e
JB
1546}
1547
1548static uint32_t
2e0fef85
JS
1549lpfc_rcv_padisc_unmap_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
1550 void *arg, uint32_t evt)
dea3101e 1551{
2e0fef85 1552 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
dea3101e 1553
2e0fef85 1554 lpfc_rcv_padisc(vport, ndlp, cmdiocb);
c9f8735b 1555 return ndlp->nlp_state;
dea3101e
JB
1556}
1557
1558static uint32_t
2e0fef85
JS
1559lpfc_rcv_prlo_unmap_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
1560 void *arg, uint32_t evt)
dea3101e 1561{
2e0fef85 1562 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
dea3101e 1563
51ef4c26 1564 lpfc_els_rsp_acc(vport, ELS_CMD_PRLO, cmdiocb, ndlp, NULL);
c9f8735b 1565 return ndlp->nlp_state;
dea3101e
JB
1566}
1567
1568static uint32_t
2e0fef85
JS
1569lpfc_device_recov_unmap_node(struct lpfc_vport *vport,
1570 struct lpfc_nodelist *ndlp,
1571 void *arg,
1572 uint32_t evt)
dea3101e 1573{
2e0fef85
JS
1574 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
1575
5024ab17 1576 ndlp->nlp_prev_state = NLP_STE_UNMAPPED_NODE;
2e0fef85
JS
1577 lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
1578 spin_lock_irq(shost->host_lock);
a0f9b48d 1579 ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC);
2e0fef85
JS
1580 spin_unlock_irq(shost->host_lock);
1581 lpfc_disc_set_adisc(vport, ndlp);
dea3101e 1582
c9f8735b 1583 return ndlp->nlp_state;
dea3101e
JB
1584}
1585
1586static uint32_t
2e0fef85
JS
1587lpfc_rcv_plogi_mapped_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
1588 void *arg, uint32_t evt)
dea3101e 1589{
2e0fef85 1590 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
dea3101e 1591
2e0fef85 1592 lpfc_rcv_plogi(vport, ndlp, cmdiocb);
c9f8735b 1593 return ndlp->nlp_state;
dea3101e
JB
1594}
1595
1596static uint32_t
2e0fef85
JS
1597lpfc_rcv_prli_mapped_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
1598 void *arg, uint32_t evt)
dea3101e 1599{
2e0fef85 1600 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
dea3101e 1601
2e0fef85 1602 lpfc_els_rsp_prli_acc(vport, cmdiocb, ndlp);
c9f8735b 1603 return ndlp->nlp_state;
dea3101e
JB
1604}
1605
1606static uint32_t
2e0fef85
JS
1607lpfc_rcv_logo_mapped_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
1608 void *arg, uint32_t evt)
dea3101e 1609{
2e0fef85 1610 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
dea3101e 1611
2e0fef85 1612 lpfc_rcv_logo(vport, ndlp, cmdiocb, ELS_CMD_LOGO);
c9f8735b 1613 return ndlp->nlp_state;
dea3101e
JB
1614}
1615
1616static uint32_t
2e0fef85
JS
1617lpfc_rcv_padisc_mapped_node(struct lpfc_vport *vport,
1618 struct lpfc_nodelist *ndlp,
1619 void *arg, uint32_t evt)
dea3101e 1620{
2e0fef85 1621 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
dea3101e 1622
2e0fef85 1623 lpfc_rcv_padisc(vport, ndlp, cmdiocb);
c9f8735b 1624 return ndlp->nlp_state;
dea3101e
JB
1625}
1626
1627static uint32_t
2e0fef85
JS
1628lpfc_rcv_prlo_mapped_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
1629 void *arg, uint32_t evt)
dea3101e 1630{
2e0fef85
JS
1631 struct lpfc_hba *phba = vport->phba;
1632 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
dea3101e
JB
1633
1634 /* flush the target */
51ef4c26
JS
1635 lpfc_sli_abort_iocb(vport, &phba->sli.ring[phba->sli.fcp_ring],
1636 ndlp->nlp_sid, 0, LPFC_CTX_TGT);
dea3101e
JB
1637
1638 /* Treat like rcv logo */
2e0fef85 1639 lpfc_rcv_logo(vport, ndlp, cmdiocb, ELS_CMD_PRLO);
c9f8735b 1640 return ndlp->nlp_state;
dea3101e
JB
1641}
1642
1643static uint32_t
2e0fef85
JS
1644lpfc_device_recov_mapped_node(struct lpfc_vport *vport,
1645 struct lpfc_nodelist *ndlp,
1646 void *arg,
1647 uint32_t evt)
dea3101e 1648{
2e0fef85
JS
1649 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
1650
5024ab17 1651 ndlp->nlp_prev_state = NLP_STE_MAPPED_NODE;
2e0fef85
JS
1652 lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
1653 spin_lock_irq(shost->host_lock);
a0f9b48d 1654 ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC);
2e0fef85
JS
1655 spin_unlock_irq(shost->host_lock);
1656 lpfc_disc_set_adisc(vport, ndlp);
c9f8735b 1657 return ndlp->nlp_state;
dea3101e
JB
1658}
1659
1660static uint32_t
2e0fef85
JS
1661lpfc_rcv_plogi_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
1662 void *arg, uint32_t evt)
dea3101e 1663{
2e0fef85
JS
1664 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
1665 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
dea3101e
JB
1666
1667 /* Ignore PLOGI if we have an outstanding LOGO */
858c9f6c 1668 if (ndlp->nlp_flag & (NLP_LOGO_SND | NLP_LOGO_ACC)) {
c9f8735b 1669 return ndlp->nlp_state;
dea3101e
JB
1670 }
1671
2e0fef85
JS
1672 if (lpfc_rcv_plogi(vport, ndlp, cmdiocb)) {
1673 spin_lock_irq(shost->host_lock);
fdcebe28 1674 ndlp->nlp_flag &= ~NLP_NPR_ADISC;
2e0fef85 1675 spin_unlock_irq(shost->host_lock);
c9f8735b 1676 return ndlp->nlp_state;
dea3101e
JB
1677 }
1678
1679 /* send PLOGI immediately, move to PLOGI issue state */
1680 if (!(ndlp->nlp_flag & NLP_DELAY_TMO)) {
488d1469 1681 ndlp->nlp_prev_state = NLP_STE_NPR_NODE;
2e0fef85
JS
1682 lpfc_nlp_set_state(vport, ndlp, NLP_STE_PLOGI_ISSUE);
1683 lpfc_issue_els_plogi(vport, ndlp->nlp_DID, 0);
dea3101e 1684 }
488d1469 1685
c9f8735b 1686 return ndlp->nlp_state;
dea3101e
JB
1687}
1688
1689static uint32_t
2e0fef85
JS
1690lpfc_rcv_prli_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
1691 void *arg, uint32_t evt)
dea3101e 1692{
2e0fef85
JS
1693 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
1694 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
1695 struct ls_rjt stat;
dea3101e
JB
1696
1697 memset(&stat, 0, sizeof (struct ls_rjt));
1698 stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
1699 stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE;
858c9f6c 1700 lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, NULL);
dea3101e
JB
1701
1702 if (!(ndlp->nlp_flag & NLP_DELAY_TMO)) {
1703 if (ndlp->nlp_flag & NLP_NPR_ADISC) {
2e0fef85 1704 spin_lock_irq(shost->host_lock);
c9f8735b 1705 ndlp->nlp_flag &= ~NLP_NPR_ADISC;
5024ab17 1706 ndlp->nlp_prev_state = NLP_STE_NPR_NODE;
2e0fef85
JS
1707 spin_unlock_irq(shost->host_lock);
1708 lpfc_nlp_set_state(vport, ndlp, NLP_STE_ADISC_ISSUE);
1709 lpfc_issue_els_adisc(vport, ndlp, 0);
dea3101e 1710 } else {
5024ab17 1711 ndlp->nlp_prev_state = NLP_STE_NPR_NODE;
2e0fef85
JS
1712 lpfc_nlp_set_state(vport, ndlp, NLP_STE_PLOGI_ISSUE);
1713 lpfc_issue_els_plogi(vport, ndlp->nlp_DID, 0);
dea3101e
JB
1714 }
1715 }
c9f8735b 1716 return ndlp->nlp_state;
dea3101e
JB
1717}
1718
1719static uint32_t
2e0fef85
JS
1720lpfc_rcv_logo_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
1721 void *arg, uint32_t evt)
dea3101e 1722{
2e0fef85 1723 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
dea3101e 1724
2e0fef85 1725 lpfc_rcv_logo(vport, ndlp, cmdiocb, ELS_CMD_LOGO);
c9f8735b 1726 return ndlp->nlp_state;
dea3101e
JB
1727}
1728
1729static uint32_t
2e0fef85
JS
1730lpfc_rcv_padisc_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
1731 void *arg, uint32_t evt)
dea3101e 1732{
2e0fef85 1733 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
dea3101e 1734
2e0fef85 1735 lpfc_rcv_padisc(vport, ndlp, cmdiocb);
dea3101e 1736
33ccf8d1
JS
1737 /*
1738 * Do not start discovery if discovery is about to start
1739 * or discovery in progress for this node. Starting discovery
1740 * here will affect the counting of discovery threads.
1741 */
2fb9bd8b 1742 if (!(ndlp->nlp_flag & NLP_DELAY_TMO) &&
92d7f7b0 1743 !(ndlp->nlp_flag & NLP_NPR_2B_DISC)) {
dea3101e 1744 if (ndlp->nlp_flag & NLP_NPR_ADISC) {
92d7f7b0 1745 ndlp->nlp_flag &= ~NLP_NPR_ADISC;
5024ab17 1746 ndlp->nlp_prev_state = NLP_STE_NPR_NODE;
2e0fef85
JS
1747 lpfc_nlp_set_state(vport, ndlp, NLP_STE_ADISC_ISSUE);
1748 lpfc_issue_els_adisc(vport, ndlp, 0);
dea3101e 1749 } else {
5024ab17 1750 ndlp->nlp_prev_state = NLP_STE_NPR_NODE;
2e0fef85
JS
1751 lpfc_nlp_set_state(vport, ndlp, NLP_STE_PLOGI_ISSUE);
1752 lpfc_issue_els_plogi(vport, ndlp->nlp_DID, 0);
dea3101e
JB
1753 }
1754 }
c9f8735b 1755 return ndlp->nlp_state;
dea3101e
JB
1756}
1757
1758static uint32_t
2e0fef85
JS
1759lpfc_rcv_prlo_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
1760 void *arg, uint32_t evt)
dea3101e 1761{
2e0fef85
JS
1762 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
1763 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
dea3101e 1764
2e0fef85 1765 spin_lock_irq(shost->host_lock);
c9f8735b 1766 ndlp->nlp_flag |= NLP_LOGO_ACC;
2e0fef85 1767 spin_unlock_irq(shost->host_lock);
c9f8735b 1768
51ef4c26 1769 lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL);
dea3101e 1770
2e0fef85 1771 if ((ndlp->nlp_flag & NLP_DELAY_TMO) == 0) {
c9f8735b 1772 mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ * 1);
2e0fef85 1773 spin_lock_irq(shost->host_lock);
c9f8735b
JW
1774 ndlp->nlp_flag |= NLP_DELAY_TMO;
1775 ndlp->nlp_flag &= ~NLP_NPR_ADISC;
2e0fef85 1776 spin_unlock_irq(shost->host_lock);
5024ab17 1777 ndlp->nlp_last_elscmd = ELS_CMD_PLOGI;
c9f8735b 1778 } else {
2e0fef85 1779 spin_lock_irq(shost->host_lock);
c9f8735b 1780 ndlp->nlp_flag &= ~NLP_NPR_ADISC;
2e0fef85 1781 spin_unlock_irq(shost->host_lock);
dea3101e 1782 }
c9f8735b
JW
1783 return ndlp->nlp_state;
1784}
dea3101e 1785
c9f8735b 1786static uint32_t
2e0fef85
JS
1787lpfc_cmpl_plogi_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
1788 void *arg, uint32_t evt)
c9f8735b
JW
1789{
1790 struct lpfc_iocbq *cmdiocb, *rspiocb;
a0f9b48d 1791 IOCB_t *irsp;
c9f8735b
JW
1792
1793 cmdiocb = (struct lpfc_iocbq *) arg;
1794 rspiocb = cmdiocb->context_un.rsp_iocb;
a0f9b48d
JS
1795
1796 irsp = &rspiocb->iocb;
1797 if (irsp->ulpStatus) {
87af33fe 1798 lpfc_nlp_not_used(ndlp);
a0f9b48d
JS
1799 return NLP_STE_FREED_NODE;
1800 }
c9f8735b
JW
1801 return ndlp->nlp_state;
1802}
1803
1804static uint32_t
2e0fef85
JS
1805lpfc_cmpl_prli_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
1806 void *arg, uint32_t evt)
c9f8735b
JW
1807{
1808 struct lpfc_iocbq *cmdiocb, *rspiocb;
a0f9b48d 1809 IOCB_t *irsp;
c9f8735b
JW
1810
1811 cmdiocb = (struct lpfc_iocbq *) arg;
1812 rspiocb = cmdiocb->context_un.rsp_iocb;
a0f9b48d
JS
1813
1814 irsp = &rspiocb->iocb;
1815 if (irsp->ulpStatus && (ndlp->nlp_flag & NLP_NODEV_REMOVE)) {
2e0fef85 1816 lpfc_drop_node(vport, ndlp);
a0f9b48d
JS
1817 return NLP_STE_FREED_NODE;
1818 }
c9f8735b 1819 return ndlp->nlp_state;
dea3101e
JB
1820}
1821
1822static uint32_t
2e0fef85
JS
1823lpfc_cmpl_logo_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
1824 void *arg, uint32_t evt)
dea3101e 1825{
2e0fef85 1826 lpfc_unreg_rpi(vport, ndlp);
dea3101e 1827 /* This routine does nothing, just return the current state */
c9f8735b
JW
1828 return ndlp->nlp_state;
1829}
1830
1831static uint32_t
2e0fef85
JS
1832lpfc_cmpl_adisc_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
1833 void *arg, uint32_t evt)
c9f8735b
JW
1834{
1835 struct lpfc_iocbq *cmdiocb, *rspiocb;
a0f9b48d 1836 IOCB_t *irsp;
c9f8735b
JW
1837
1838 cmdiocb = (struct lpfc_iocbq *) arg;
1839 rspiocb = cmdiocb->context_un.rsp_iocb;
a0f9b48d
JS
1840
1841 irsp = &rspiocb->iocb;
1842 if (irsp->ulpStatus && (ndlp->nlp_flag & NLP_NODEV_REMOVE)) {
2e0fef85 1843 lpfc_drop_node(vport, ndlp);
a0f9b48d
JS
1844 return NLP_STE_FREED_NODE;
1845 }
c9f8735b 1846 return ndlp->nlp_state;
dea3101e
JB
1847}
1848
1849static uint32_t
2e0fef85
JS
1850lpfc_cmpl_reglogin_npr_node(struct lpfc_vport *vport,
1851 struct lpfc_nodelist *ndlp,
1852 void *arg, uint32_t evt)
dea3101e 1853{
2e0fef85
JS
1854 LPFC_MBOXQ_t *pmb = (LPFC_MBOXQ_t *) arg;
1855 MAILBOX_t *mb = &pmb->mb;
dea3101e 1856
c9f8735b
JW
1857 if (!mb->mbxStatus)
1858 ndlp->nlp_rpi = mb->un.varWords[0];
a0f9b48d
JS
1859 else {
1860 if (ndlp->nlp_flag & NLP_NODEV_REMOVE) {
2e0fef85 1861 lpfc_drop_node(vport, ndlp);
a0f9b48d
JS
1862 return NLP_STE_FREED_NODE;
1863 }
1864 }
c9f8735b 1865 return ndlp->nlp_state;
dea3101e
JB
1866}
1867
1868static uint32_t
2e0fef85
JS
1869lpfc_device_rm_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
1870 void *arg, uint32_t evt)
dea3101e 1871{
2e0fef85
JS
1872 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
1873
a0f9b48d 1874 if (ndlp->nlp_flag & NLP_NPR_2B_DISC) {
2e0fef85 1875 spin_lock_irq(shost->host_lock);
a0f9b48d 1876 ndlp->nlp_flag |= NLP_NODEV_REMOVE;
2e0fef85 1877 spin_unlock_irq(shost->host_lock);
a0f9b48d
JS
1878 return ndlp->nlp_state;
1879 }
2e0fef85 1880 lpfc_drop_node(vport, ndlp);
c9f8735b 1881 return NLP_STE_FREED_NODE;
dea3101e
JB
1882}
1883
1884static uint32_t
2e0fef85
JS
1885lpfc_device_recov_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
1886 void *arg, uint32_t evt)
dea3101e 1887{
2e0fef85
JS
1888 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
1889
92d7f7b0
JS
1890 /* Don't do anything that will mess up processing of the
1891 * previous RSCN.
1892 */
1893 if (vport->fc_flag & FC_RSCN_DEFERRED)
1894 return ndlp->nlp_state;
1895
2e0fef85 1896 spin_lock_irq(shost->host_lock);
a0f9b48d 1897 ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC);
2e0fef85 1898 spin_unlock_irq(shost->host_lock);
6ad42535 1899 if (ndlp->nlp_flag & NLP_DELAY_TMO) {
2e0fef85 1900 lpfc_cancel_retry_delay_tmo(vport, ndlp);
6ad42535 1901 }
c9f8735b 1902 return ndlp->nlp_state;
dea3101e
JB
1903}
1904
1905
1906/* This next section defines the NPort Discovery State Machine */
1907
1908/* There are 4 different double linked lists nodelist entries can reside on.
1909 * The plogi list and adisc list are used when Link Up discovery or RSCN
1910 * processing is needed. Each list holds the nodes that we will send PLOGI
1911 * or ADISC on. These lists will keep track of what nodes will be effected
1912 * by an RSCN, or a Link Up (Typically, all nodes are effected on Link Up).
1913 * The unmapped_list will contain all nodes that we have successfully logged
1914 * into at the Fibre Channel level. The mapped_list will contain all nodes
1915 * that are mapped FCP targets.
1916 */
1917/*
1918 * The bind list is a list of undiscovered (potentially non-existent) nodes
1919 * that we have saved binding information on. This information is used when
1920 * nodes transition from the unmapped to the mapped list.
1921 */
1922/* For UNUSED_NODE state, the node has just been allocated .
1923 * For PLOGI_ISSUE and REG_LOGIN_ISSUE, the node is on
1924 * the PLOGI list. For REG_LOGIN_COMPL, the node is taken off the PLOGI list
1925 * and put on the unmapped list. For ADISC processing, the node is taken off
1926 * the ADISC list and placed on either the mapped or unmapped list (depending
1927 * on its previous state). Once on the unmapped list, a PRLI is issued and the
1928 * state changed to PRLI_ISSUE. When the PRLI completion occurs, the state is
1929 * changed to UNMAPPED_NODE. If the completion indicates a mapped
1930 * node, the node is taken off the unmapped list. The binding list is checked
1931 * for a valid binding, or a binding is automatically assigned. If binding
1932 * assignment is unsuccessful, the node is left on the unmapped list. If
1933 * binding assignment is successful, the associated binding list entry (if
1934 * any) is removed, and the node is placed on the mapped list.
1935 */
1936/*
1937 * For a Link Down, all nodes on the ADISC, PLOGI, unmapped or mapped
c01f3208 1938 * lists will receive a DEVICE_RECOVERY event. If the linkdown or devloss timers
dea3101e
JB
1939 * expire, all effected nodes will receive a DEVICE_RM event.
1940 */
1941/*
1942 * For a Link Up or RSCN, all nodes will move from the mapped / unmapped lists
1943 * to either the ADISC or PLOGI list. After a Nameserver query or ALPA loopmap
1944 * check, additional nodes may be added or removed (via DEVICE_RM) to / from
1945 * the PLOGI or ADISC lists. Once the PLOGI and ADISC lists are populated,
1946 * we will first process the ADISC list. 32 entries are processed initially and
1947 * ADISC is initited for each one. Completions / Events for each node are
1948 * funnelled thru the state machine. As each node finishes ADISC processing, it
1949 * starts ADISC for any nodes waiting for ADISC processing. If no nodes are
1950 * waiting, and the ADISC list count is identically 0, then we are done. For
1951 * Link Up discovery, since all nodes on the PLOGI list are UNREG_LOGIN'ed, we
1952 * can issue a CLEAR_LA and reenable Link Events. Next we will process the PLOGI
1953 * list. 32 entries are processed initially and PLOGI is initited for each one.
1954 * Completions / Events for each node are funnelled thru the state machine. As
1955 * each node finishes PLOGI processing, it starts PLOGI for any nodes waiting
1956 * for PLOGI processing. If no nodes are waiting, and the PLOGI list count is
1957 * indentically 0, then we are done. We have now completed discovery / RSCN
1958 * handling. Upon completion, ALL nodes should be on either the mapped or
1959 * unmapped lists.
1960 */
1961
1962static uint32_t (*lpfc_disc_action[NLP_STE_MAX_STATE * NLP_EVT_MAX_EVENT])
2e0fef85 1963 (struct lpfc_vport *, struct lpfc_nodelist *, void *, uint32_t) = {
dea3101e
JB
1964 /* Action routine Event Current State */
1965 lpfc_rcv_plogi_unused_node, /* RCV_PLOGI UNUSED_NODE */
1966 lpfc_rcv_els_unused_node, /* RCV_PRLI */
1967 lpfc_rcv_logo_unused_node, /* RCV_LOGO */
1968 lpfc_rcv_els_unused_node, /* RCV_ADISC */
1969 lpfc_rcv_els_unused_node, /* RCV_PDISC */
1970 lpfc_rcv_els_unused_node, /* RCV_PRLO */
1971 lpfc_disc_illegal, /* CMPL_PLOGI */
1972 lpfc_disc_illegal, /* CMPL_PRLI */
1973 lpfc_cmpl_logo_unused_node, /* CMPL_LOGO */
1974 lpfc_disc_illegal, /* CMPL_ADISC */
1975 lpfc_disc_illegal, /* CMPL_REG_LOGIN */
1976 lpfc_device_rm_unused_node, /* DEVICE_RM */
1977 lpfc_disc_illegal, /* DEVICE_RECOVERY */
1978
1979 lpfc_rcv_plogi_plogi_issue, /* RCV_PLOGI PLOGI_ISSUE */
92d7f7b0 1980 lpfc_rcv_prli_plogi_issue, /* RCV_PRLI */
c9f8735b 1981 lpfc_rcv_logo_plogi_issue, /* RCV_LOGO */
dea3101e
JB
1982 lpfc_rcv_els_plogi_issue, /* RCV_ADISC */
1983 lpfc_rcv_els_plogi_issue, /* RCV_PDISC */
1984 lpfc_rcv_els_plogi_issue, /* RCV_PRLO */
1985 lpfc_cmpl_plogi_plogi_issue, /* CMPL_PLOGI */
1986 lpfc_disc_illegal, /* CMPL_PRLI */
1987 lpfc_disc_illegal, /* CMPL_LOGO */
1988 lpfc_disc_illegal, /* CMPL_ADISC */
1989 lpfc_disc_illegal, /* CMPL_REG_LOGIN */
1990 lpfc_device_rm_plogi_issue, /* DEVICE_RM */
1991 lpfc_device_recov_plogi_issue, /* DEVICE_RECOVERY */
1992
1993 lpfc_rcv_plogi_adisc_issue, /* RCV_PLOGI ADISC_ISSUE */
1994 lpfc_rcv_prli_adisc_issue, /* RCV_PRLI */
1995 lpfc_rcv_logo_adisc_issue, /* RCV_LOGO */
1996 lpfc_rcv_padisc_adisc_issue, /* RCV_ADISC */
1997 lpfc_rcv_padisc_adisc_issue, /* RCV_PDISC */
1998 lpfc_rcv_prlo_adisc_issue, /* RCV_PRLO */
1999 lpfc_disc_illegal, /* CMPL_PLOGI */
2000 lpfc_disc_illegal, /* CMPL_PRLI */
2001 lpfc_disc_illegal, /* CMPL_LOGO */
2002 lpfc_cmpl_adisc_adisc_issue, /* CMPL_ADISC */
2003 lpfc_disc_illegal, /* CMPL_REG_LOGIN */
2004 lpfc_device_rm_adisc_issue, /* DEVICE_RM */
2005 lpfc_device_recov_adisc_issue, /* DEVICE_RECOVERY */
2006
2007 lpfc_rcv_plogi_reglogin_issue, /* RCV_PLOGI REG_LOGIN_ISSUE */
2008 lpfc_rcv_prli_reglogin_issue, /* RCV_PLOGI */
2009 lpfc_rcv_logo_reglogin_issue, /* RCV_LOGO */
2010 lpfc_rcv_padisc_reglogin_issue, /* RCV_ADISC */
2011 lpfc_rcv_padisc_reglogin_issue, /* RCV_PDISC */
2012 lpfc_rcv_prlo_reglogin_issue, /* RCV_PRLO */
87af33fe 2013 lpfc_cmpl_plogi_illegal, /* CMPL_PLOGI */
dea3101e
JB
2014 lpfc_disc_illegal, /* CMPL_PRLI */
2015 lpfc_disc_illegal, /* CMPL_LOGO */
2016 lpfc_disc_illegal, /* CMPL_ADISC */
2017 lpfc_cmpl_reglogin_reglogin_issue,/* CMPL_REG_LOGIN */
2018 lpfc_device_rm_reglogin_issue, /* DEVICE_RM */
2019 lpfc_device_recov_reglogin_issue,/* DEVICE_RECOVERY */
2020
2021 lpfc_rcv_plogi_prli_issue, /* RCV_PLOGI PRLI_ISSUE */
2022 lpfc_rcv_prli_prli_issue, /* RCV_PRLI */
2023 lpfc_rcv_logo_prli_issue, /* RCV_LOGO */
2024 lpfc_rcv_padisc_prli_issue, /* RCV_ADISC */
2025 lpfc_rcv_padisc_prli_issue, /* RCV_PDISC */
2026 lpfc_rcv_prlo_prli_issue, /* RCV_PRLO */
87af33fe 2027 lpfc_cmpl_plogi_illegal, /* CMPL_PLOGI */
dea3101e
JB
2028 lpfc_cmpl_prli_prli_issue, /* CMPL_PRLI */
2029 lpfc_disc_illegal, /* CMPL_LOGO */
2030 lpfc_disc_illegal, /* CMPL_ADISC */
2031 lpfc_disc_illegal, /* CMPL_REG_LOGIN */
2032 lpfc_device_rm_prli_issue, /* DEVICE_RM */
2033 lpfc_device_recov_prli_issue, /* DEVICE_RECOVERY */
2034
2035 lpfc_rcv_plogi_unmap_node, /* RCV_PLOGI UNMAPPED_NODE */
2036 lpfc_rcv_prli_unmap_node, /* RCV_PRLI */
2037 lpfc_rcv_logo_unmap_node, /* RCV_LOGO */
2038 lpfc_rcv_padisc_unmap_node, /* RCV_ADISC */
2039 lpfc_rcv_padisc_unmap_node, /* RCV_PDISC */
2040 lpfc_rcv_prlo_unmap_node, /* RCV_PRLO */
2041 lpfc_disc_illegal, /* CMPL_PLOGI */
2042 lpfc_disc_illegal, /* CMPL_PRLI */
2043 lpfc_disc_illegal, /* CMPL_LOGO */
2044 lpfc_disc_illegal, /* CMPL_ADISC */
2045 lpfc_disc_illegal, /* CMPL_REG_LOGIN */
2046 lpfc_disc_illegal, /* DEVICE_RM */
2047 lpfc_device_recov_unmap_node, /* DEVICE_RECOVERY */
2048
2049 lpfc_rcv_plogi_mapped_node, /* RCV_PLOGI MAPPED_NODE */
2050 lpfc_rcv_prli_mapped_node, /* RCV_PRLI */
2051 lpfc_rcv_logo_mapped_node, /* RCV_LOGO */
2052 lpfc_rcv_padisc_mapped_node, /* RCV_ADISC */
2053 lpfc_rcv_padisc_mapped_node, /* RCV_PDISC */
2054 lpfc_rcv_prlo_mapped_node, /* RCV_PRLO */
2055 lpfc_disc_illegal, /* CMPL_PLOGI */
2056 lpfc_disc_illegal, /* CMPL_PRLI */
2057 lpfc_disc_illegal, /* CMPL_LOGO */
2058 lpfc_disc_illegal, /* CMPL_ADISC */
2059 lpfc_disc_illegal, /* CMPL_REG_LOGIN */
2060 lpfc_disc_illegal, /* DEVICE_RM */
2061 lpfc_device_recov_mapped_node, /* DEVICE_RECOVERY */
2062
2063 lpfc_rcv_plogi_npr_node, /* RCV_PLOGI NPR_NODE */
2064 lpfc_rcv_prli_npr_node, /* RCV_PRLI */
2065 lpfc_rcv_logo_npr_node, /* RCV_LOGO */
2066 lpfc_rcv_padisc_npr_node, /* RCV_ADISC */
2067 lpfc_rcv_padisc_npr_node, /* RCV_PDISC */
2068 lpfc_rcv_prlo_npr_node, /* RCV_PRLO */
c9f8735b
JW
2069 lpfc_cmpl_plogi_npr_node, /* CMPL_PLOGI */
2070 lpfc_cmpl_prli_npr_node, /* CMPL_PRLI */
dea3101e 2071 lpfc_cmpl_logo_npr_node, /* CMPL_LOGO */
c9f8735b 2072 lpfc_cmpl_adisc_npr_node, /* CMPL_ADISC */
dea3101e
JB
2073 lpfc_cmpl_reglogin_npr_node, /* CMPL_REG_LOGIN */
2074 lpfc_device_rm_npr_node, /* DEVICE_RM */
2075 lpfc_device_recov_npr_node, /* DEVICE_RECOVERY */
2076};
2077
2078int
2e0fef85
JS
2079lpfc_disc_state_machine(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
2080 void *arg, uint32_t evt)
dea3101e
JB
2081{
2082 uint32_t cur_state, rc;
2e0fef85 2083 uint32_t(*func) (struct lpfc_vport *, struct lpfc_nodelist *, void *,
dea3101e
JB
2084 uint32_t);
2085
329f9bc7 2086 lpfc_nlp_get(ndlp);
dea3101e
JB
2087 cur_state = ndlp->nlp_state;
2088
2089 /* DSM in event <evt> on NPort <nlp_DID> in state <cur_state> */
e8b62011
JS
2090 lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
2091 "0211 DSM in event x%x on NPort x%x in "
2092 "state %d Data: x%x\n",
2093 evt, ndlp->nlp_DID, cur_state, ndlp->nlp_flag);
dea3101e 2094
858c9f6c
JS
2095 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_DSM,
2096 "DSM in: evt:%d ste:%d did:x%x",
2097 evt, cur_state, ndlp->nlp_DID);
2098
dea3101e 2099 func = lpfc_disc_action[(cur_state * NLP_EVT_MAX_EVENT) + evt];
2e0fef85 2100 rc = (func) (vport, ndlp, arg, evt);
dea3101e
JB
2101
2102 /* DSM out state <rc> on NPort <nlp_DID> */
e8b62011
JS
2103 lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
2104 "0212 DSM out state %d on NPort x%x Data: x%x\n",
2105 rc, ndlp->nlp_DID, ndlp->nlp_flag);
dea3101e 2106
858c9f6c
JS
2107 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_DSM,
2108 "DSM out: ste:%d did:x%x flg:x%x",
2109 rc, ndlp->nlp_DID, ndlp->nlp_flag);
2110
329f9bc7 2111 lpfc_nlp_put(ndlp);
dea3101e 2112
c9f8735b 2113 return rc;
dea3101e 2114}