blob: abc361259d6de12bb57c6a9d0f206dbc48b0f6f9 [file] [log] [blame]
James Smart92d7f7b2007-06-17 19:56:38 -05001 /*******************************************************************
dea31012005-04-17 16:05:31 -05002 * This file is part of the Emulex Linux Device Driver for *
James.Smart@Emulex.Comc44ce172005-06-25 10:34:39 -04003 * Fibre Channel Host Bus Adapters. *
James Smart92c13f22013-05-31 17:05:45 -04004 * Copyright (C) 2004-2013 Emulex. All rights reserved. *
James.Smart@Emulex.Comc44ce172005-06-25 10:34:39 -04005 * EMULEX and SLI are trademarks of Emulex. *
dea31012005-04-17 16:05:31 -05006 * www.emulex.com *
James.Smart@Emulex.Comc44ce172005-06-25 10:34:39 -04007 * Portions Copyright (C) 2004-2005 Christoph Hellwig *
dea31012005-04-17 16:05:31 -05008 * *
9 * This program is free software; you can redistribute it and/or *
James.Smart@Emulex.Comc44ce172005-06-25 10:34:39 -040010 * 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. *
dea31012005-04-17 16:05:31 -050020 *******************************************************************/
21
dea31012005-04-17 16:05:31 -050022#include <linux/blkdev.h>
23#include <linux/pci.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090024#include <linux/slab.h>
dea31012005-04-17 16:05:31 -050025#include <linux/interrupt.h>
26
James.Smart@Emulex.Com91886522005-08-10 15:03:09 -040027#include <scsi/scsi.h>
dea31012005-04-17 16:05:31 -050028#include <scsi/scsi_device.h>
29#include <scsi/scsi_host.h>
30#include <scsi/scsi_transport_fc.h>
31
James Smartda0436e2009-05-22 14:51:39 -040032#include "lpfc_hw4.h"
dea31012005-04-17 16:05:31 -050033#include "lpfc_hw.h"
34#include "lpfc_sli.h"
James Smartda0436e2009-05-22 14:51:39 -040035#include "lpfc_sli4.h"
James Smartea2151b2008-09-07 11:52:10 -040036#include "lpfc_nl.h"
dea31012005-04-17 16:05:31 -050037#include "lpfc_disc.h"
38#include "lpfc_scsi.h"
39#include "lpfc.h"
40#include "lpfc_logmsg.h"
41#include "lpfc_crtn.h"
James Smart92d7f7b2007-06-17 19:56:38 -050042#include "lpfc_vport.h"
James Smart858c9f62007-06-17 19:56:39 -050043#include "lpfc_debugfs.h"
dea31012005-04-17 16:05:31 -050044
45
46/* Called to verify a rcv'ed ADISC was intended for us. */
47static int
James Smart2e0fef82007-06-17 19:56:36 -050048lpfc_check_adisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
49 struct lpfc_name *nn, struct lpfc_name *pn)
dea31012005-04-17 16:05:31 -050050{
James Smart6b5151f2012-01-18 16:24:06 -050051 /* First, we MUST have a RPI registered */
52 if (!(ndlp->nlp_flag & NLP_RPI_REGISTERED))
53 return 0;
54
dea31012005-04-17 16:05:31 -050055 /* Compare the ADISC rsp WWNN / WWPN matches our internal node
56 * table entry for that node.
57 */
James Smart2e0fef82007-06-17 19:56:36 -050058 if (memcmp(nn, &ndlp->nlp_nodename, sizeof (struct lpfc_name)))
Jamie Wellnitzc9f87352006-02-28 19:25:23 -050059 return 0;
dea31012005-04-17 16:05:31 -050060
James Smart2e0fef82007-06-17 19:56:36 -050061 if (memcmp(pn, &ndlp->nlp_portname, sizeof (struct lpfc_name)))
Jamie Wellnitzc9f87352006-02-28 19:25:23 -050062 return 0;
dea31012005-04-17 16:05:31 -050063
64 /* we match, return success */
Jamie Wellnitzc9f87352006-02-28 19:25:23 -050065 return 1;
dea31012005-04-17 16:05:31 -050066}
67
dea31012005-04-17 16:05:31 -050068int
James Smart2e0fef82007-06-17 19:56:36 -050069lpfc_check_sparm(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
James Smart341af102010-01-26 23:07:37 -050070 struct serv_parm *sp, uint32_t class, int flogi)
dea31012005-04-17 16:05:31 -050071{
James Smart2e0fef82007-06-17 19:56:36 -050072 volatile struct serv_parm *hsp = &vport->fc_sparam;
James.Smart@Emulex.Com2fb70f72005-11-28 11:41:24 -050073 uint16_t hsp_value, ssp_value = 0;
dea31012005-04-17 16:05:31 -050074
James.Smart@Emulex.Com2fb70f72005-11-28 11:41:24 -050075 /*
76 * The receive data field size and buffer-to-buffer receive data field
77 * size entries are 16 bits but are represented as two 8-bit fields in
78 * the driver data structure to account for rsvd bits and other control
79 * bits. Reconstruct and compare the fields as a 16-bit values before
80 * correcting the byte values.
81 */
dea31012005-04-17 16:05:31 -050082 if (sp->cls1.classValid) {
James Smart341af102010-01-26 23:07:37 -050083 if (!flogi) {
84 hsp_value = ((hsp->cls1.rcvDataSizeMsb << 8) |
85 hsp->cls1.rcvDataSizeLsb);
86 ssp_value = ((sp->cls1.rcvDataSizeMsb << 8) |
87 sp->cls1.rcvDataSizeLsb);
88 if (!ssp_value)
89 goto bad_service_param;
90 if (ssp_value > hsp_value) {
91 sp->cls1.rcvDataSizeLsb =
92 hsp->cls1.rcvDataSizeLsb;
93 sp->cls1.rcvDataSizeMsb =
94 hsp->cls1.rcvDataSizeMsb;
95 }
James.Smart@Emulex.Com2fb70f72005-11-28 11:41:24 -050096 }
James Smart341af102010-01-26 23:07:37 -050097 } else if (class == CLASS1)
James Smart92d7f7b2007-06-17 19:56:38 -050098 goto bad_service_param;
dea31012005-04-17 16:05:31 -050099 if (sp->cls2.classValid) {
James Smart341af102010-01-26 23:07:37 -0500100 if (!flogi) {
101 hsp_value = ((hsp->cls2.rcvDataSizeMsb << 8) |
102 hsp->cls2.rcvDataSizeLsb);
103 ssp_value = ((sp->cls2.rcvDataSizeMsb << 8) |
104 sp->cls2.rcvDataSizeLsb);
105 if (!ssp_value)
106 goto bad_service_param;
107 if (ssp_value > hsp_value) {
108 sp->cls2.rcvDataSizeLsb =
109 hsp->cls2.rcvDataSizeLsb;
110 sp->cls2.rcvDataSizeMsb =
111 hsp->cls2.rcvDataSizeMsb;
112 }
James.Smart@Emulex.Com2fb70f72005-11-28 11:41:24 -0500113 }
James Smart341af102010-01-26 23:07:37 -0500114 } else if (class == CLASS2)
James Smart92d7f7b2007-06-17 19:56:38 -0500115 goto bad_service_param;
dea31012005-04-17 16:05:31 -0500116 if (sp->cls3.classValid) {
James Smart341af102010-01-26 23:07:37 -0500117 if (!flogi) {
118 hsp_value = ((hsp->cls3.rcvDataSizeMsb << 8) |
119 hsp->cls3.rcvDataSizeLsb);
120 ssp_value = ((sp->cls3.rcvDataSizeMsb << 8) |
121 sp->cls3.rcvDataSizeLsb);
122 if (!ssp_value)
123 goto bad_service_param;
124 if (ssp_value > hsp_value) {
125 sp->cls3.rcvDataSizeLsb =
126 hsp->cls3.rcvDataSizeLsb;
127 sp->cls3.rcvDataSizeMsb =
128 hsp->cls3.rcvDataSizeMsb;
129 }
James.Smart@Emulex.Com2fb70f72005-11-28 11:41:24 -0500130 }
James Smart341af102010-01-26 23:07:37 -0500131 } else if (class == CLASS3)
James Smart92d7f7b2007-06-17 19:56:38 -0500132 goto bad_service_param;
dea31012005-04-17 16:05:31 -0500133
James.Smart@Emulex.Com2fb70f72005-11-28 11:41:24 -0500134 /*
135 * Preserve the upper four bits of the MSB from the PLOGI response.
136 * These bits contain the Buffer-to-Buffer State Change Number
137 * from the target and need to be passed to the FW.
138 */
139 hsp_value = (hsp->cmn.bbRcvSizeMsb << 8) | hsp->cmn.bbRcvSizeLsb;
140 ssp_value = (sp->cmn.bbRcvSizeMsb << 8) | sp->cmn.bbRcvSizeLsb;
141 if (ssp_value > hsp_value) {
dea31012005-04-17 16:05:31 -0500142 sp->cmn.bbRcvSizeLsb = hsp->cmn.bbRcvSizeLsb;
James.Smart@Emulex.Com2fb70f72005-11-28 11:41:24 -0500143 sp->cmn.bbRcvSizeMsb = (sp->cmn.bbRcvSizeMsb & 0xF0) |
144 (hsp->cmn.bbRcvSizeMsb & 0x0F);
145 }
dea31012005-04-17 16:05:31 -0500146
dea31012005-04-17 16:05:31 -0500147 memcpy(&ndlp->nlp_nodename, &sp->nodeName, sizeof (struct lpfc_name));
148 memcpy(&ndlp->nlp_portname, &sp->portName, sizeof (struct lpfc_name));
James.Smart@Emulex.Com2fb70f72005-11-28 11:41:24 -0500149 return 1;
James Smart92d7f7b2007-06-17 19:56:38 -0500150bad_service_param:
James Smarte8b62012007-08-02 11:10:09 -0400151 lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY,
152 "0207 Device %x "
153 "(%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x) sent "
154 "invalid service parameters. Ignoring device.\n",
155 ndlp->nlp_DID,
156 sp->nodeName.u.wwn[0], sp->nodeName.u.wwn[1],
157 sp->nodeName.u.wwn[2], sp->nodeName.u.wwn[3],
158 sp->nodeName.u.wwn[4], sp->nodeName.u.wwn[5],
159 sp->nodeName.u.wwn[6], sp->nodeName.u.wwn[7]);
James Smart92d7f7b2007-06-17 19:56:38 -0500160 return 0;
dea31012005-04-17 16:05:31 -0500161}
162
163static void *
James Smart2e0fef82007-06-17 19:56:36 -0500164lpfc_check_elscmpl_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
James Smart92d7f7b2007-06-17 19:56:38 -0500165 struct lpfc_iocbq *rspiocb)
dea31012005-04-17 16:05:31 -0500166{
167 struct lpfc_dmabuf *pcmd, *prsp;
168 uint32_t *lp;
169 void *ptr = NULL;
170 IOCB_t *irsp;
171
172 irsp = &rspiocb->iocb;
173 pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
174
175 /* For lpfc_els_abort, context2 could be zero'ed to delay
176 * freeing associated memory till after ABTS completes.
177 */
178 if (pcmd) {
179 prsp = list_get_first(&pcmd->list, struct lpfc_dmabuf,
180 list);
181 if (prsp) {
182 lp = (uint32_t *) prsp->virt;
183 ptr = (void *)((uint8_t *)lp + sizeof(uint32_t));
184 }
Jamie Wellnitz2fe165b2006-02-28 19:25:31 -0500185 } else {
dea31012005-04-17 16:05:31 -0500186 /* Force ulpStatus error since we are returning NULL ptr */
187 if (!(irsp->ulpStatus)) {
188 irsp->ulpStatus = IOSTAT_LOCAL_REJECT;
189 irsp->un.ulpWord[4] = IOERR_SLI_ABORTED;
190 }
191 ptr = NULL;
192 }
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500193 return ptr;
dea31012005-04-17 16:05:31 -0500194}
195
196
James Smart2a9bf3d2010-06-07 15:24:45 -0400197
dea31012005-04-17 16:05:31 -0500198/*
199 * Free resources / clean up outstanding I/Os
200 * associated with a LPFC_NODELIST entry. This
201 * routine effectively results in a "software abort".
202 */
203int
James Smart2e0fef82007-06-17 19:56:36 -0500204lpfc_els_abort(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
dea31012005-04-17 16:05:31 -0500205{
James Smart2534ba72007-04-25 09:52:20 -0400206 LIST_HEAD(completions);
James Smart2a9bf3d2010-06-07 15:24:45 -0400207 LIST_HEAD(txcmplq_completions);
208 LIST_HEAD(abort_list);
James Smart2e0fef82007-06-17 19:56:36 -0500209 struct lpfc_sli *psli = &phba->sli;
210 struct lpfc_sli_ring *pring = &psli->ring[LPFC_ELS_RING];
dea31012005-04-17 16:05:31 -0500211 struct lpfc_iocbq *iocb, *next_iocb;
dea31012005-04-17 16:05:31 -0500212
213 /* Abort outstanding I/O on NPort <nlp_DID> */
James Smarte8b62012007-08-02 11:10:09 -0400214 lpfc_printf_vlog(ndlp->vport, KERN_INFO, LOG_DISCOVERY,
James Smart2a9bf3d2010-06-07 15:24:45 -0400215 "2819 Abort outstanding I/O on NPort x%x "
James Smarte8b62012007-08-02 11:10:09 -0400216 "Data: x%x x%x x%x\n",
217 ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state,
218 ndlp->nlp_rpi);
James Smart92d7f7b2007-06-17 19:56:38 -0500219
220 lpfc_fabric_abort_nport(ndlp);
dea31012005-04-17 16:05:31 -0500221
dea31012005-04-17 16:05:31 -0500222 /* First check the txq */
James Smart2e0fef82007-06-17 19:56:36 -0500223 spin_lock_irq(&phba->hbalock);
James Smart2534ba72007-04-25 09:52:20 -0400224 list_for_each_entry_safe(iocb, next_iocb, &pring->txq, list) {
James Smart858c9f62007-06-17 19:56:39 -0500225 /* Check to see if iocb matches the nport we are looking for */
James Smart2534ba72007-04-25 09:52:20 -0400226 if (lpfc_check_sli_ndlp(phba, pring, iocb, ndlp)) {
James Smart858c9f62007-06-17 19:56:39 -0500227 /* It matches, so deque and call compl with anp error */
James Smart2534ba72007-04-25 09:52:20 -0400228 list_move_tail(&iocb->list, &completions);
dea31012005-04-17 16:05:31 -0500229 }
James Smart2534ba72007-04-25 09:52:20 -0400230 }
dea31012005-04-17 16:05:31 -0500231
dea31012005-04-17 16:05:31 -0500232 /* Next check the txcmplq */
James Smart2a9bf3d2010-06-07 15:24:45 -0400233 list_splice_init(&pring->txcmplq, &txcmplq_completions);
James Smart2e0fef82007-06-17 19:56:36 -0500234 spin_unlock_irq(&phba->hbalock);
dea31012005-04-17 16:05:31 -0500235
James Smart2a9bf3d2010-06-07 15:24:45 -0400236 list_for_each_entry_safe(iocb, next_iocb, &txcmplq_completions, list) {
237 /* Check to see if iocb matches the nport we are looking for */
238 if (lpfc_check_sli_ndlp(phba, pring, iocb, ndlp))
239 list_add_tail(&iocb->dlist, &abort_list);
240 }
241 spin_lock_irq(&phba->hbalock);
242 list_splice(&txcmplq_completions, &pring->txcmplq);
243 spin_unlock_irq(&phba->hbalock);
244
245 list_for_each_entry_safe(iocb, next_iocb, &abort_list, dlist) {
246 spin_lock_irq(&phba->hbalock);
247 list_del_init(&iocb->dlist);
248 lpfc_sli_issue_abort_iotag(phba, pring, iocb);
249 spin_unlock_irq(&phba->hbalock);
250 }
251
James Smarta257bf92009-04-06 18:48:10 -0400252 /* Cancel all the IOCBs from the completions list */
253 lpfc_sli_cancel_iocbs(phba, &completions, IOSTAT_LOCAL_REJECT,
254 IOERR_SLI_ABORTED);
James Smart2534ba72007-04-25 09:52:20 -0400255
James Smart0d2b6b82008-06-14 22:52:47 -0400256 lpfc_cancel_retry_delay_tmo(phba->pport, ndlp);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500257 return 0;
dea31012005-04-17 16:05:31 -0500258}
259
260static int
James Smart2e0fef82007-06-17 19:56:36 -0500261lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
James Smart92d7f7b2007-06-17 19:56:38 -0500262 struct lpfc_iocbq *cmdiocb)
dea31012005-04-17 16:05:31 -0500263{
James Smart2e0fef82007-06-17 19:56:36 -0500264 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
265 struct lpfc_hba *phba = vport->phba;
dea31012005-04-17 16:05:31 -0500266 struct lpfc_dmabuf *pcmd;
267 uint32_t *lp;
268 IOCB_t *icmd;
269 struct serv_parm *sp;
270 LPFC_MBOXQ_t *mbox;
271 struct ls_rjt stat;
272 int rc;
273
274 memset(&stat, 0, sizeof (struct ls_rjt));
James Smart695a8142010-01-26 23:08:03 -0500275 if (vport->port_state <= LPFC_FDISC) {
dea31012005-04-17 16:05:31 -0500276 /* Before responding to PLOGI, check for pt2pt mode.
277 * If we are pt2pt, with an outstanding FLOGI, abort
278 * the FLOGI and resend it first.
279 */
James Smart2e0fef82007-06-17 19:56:36 -0500280 if (vport->fc_flag & FC_PT2PT) {
James Smart92d7f7b2007-06-17 19:56:38 -0500281 lpfc_els_abort_flogi(phba);
James Smart2e0fef82007-06-17 19:56:36 -0500282 if (!(vport->fc_flag & FC_PT2PT_PLOGI)) {
dea31012005-04-17 16:05:31 -0500283 /* If the other side is supposed to initiate
284 * the PLOGI anyway, just ACC it now and
285 * move on with discovery.
286 */
287 phba->fc_edtov = FF_DEF_EDTOV;
288 phba->fc_ratov = FF_DEF_RATOV;
289 /* Start discovery - this should just do
290 CLEAR_LA */
James Smart2e0fef82007-06-17 19:56:36 -0500291 lpfc_disc_start(vport);
James Smarted957682007-06-17 19:56:37 -0500292 } else
James Smart2e0fef82007-06-17 19:56:36 -0500293 lpfc_initial_flogi(vport);
Jamie Wellnitz2fe165b2006-02-28 19:25:31 -0500294 } else {
dea31012005-04-17 16:05:31 -0500295 stat.un.b.lsRjtRsnCode = LSRJT_LOGICAL_BSY;
296 stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE;
James Smart2e0fef82007-06-17 19:56:36 -0500297 lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb,
James Smart858c9f62007-06-17 19:56:39 -0500298 ndlp, NULL);
dea31012005-04-17 16:05:31 -0500299 return 0;
300 }
301 }
302 pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
303 lp = (uint32_t *) pcmd->virt;
304 sp = (struct serv_parm *) ((uint8_t *) lp + sizeof (uint32_t));
James Smarta8adb832007-10-27 13:37:53 -0400305 if (wwn_to_u64(sp->portName.u.wwn) == 0) {
306 lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
307 "0140 PLOGI Reject: invalid nname\n");
308 stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
309 stat.un.b.lsRjtRsnCodeExp = LSEXP_INVALID_PNAME;
310 lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp,
311 NULL);
312 return 0;
313 }
314 if (wwn_to_u64(sp->nodeName.u.wwn) == 0) {
315 lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
316 "0141 PLOGI Reject: invalid pname\n");
317 stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
318 stat.un.b.lsRjtRsnCodeExp = LSEXP_INVALID_NNAME;
319 lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp,
320 NULL);
321 return 0;
322 }
James Smart341af102010-01-26 23:07:37 -0500323 if ((lpfc_check_sparm(vport, ndlp, sp, CLASS3, 0) == 0)) {
dea31012005-04-17 16:05:31 -0500324 /* Reject this request because invalid parameters */
325 stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
326 stat.un.b.lsRjtRsnCodeExp = LSEXP_SPARM_OPTIONS;
James Smart858c9f62007-06-17 19:56:39 -0500327 lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp,
328 NULL);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500329 return 0;
dea31012005-04-17 16:05:31 -0500330 }
331 icmd = &cmdiocb->iocb;
332
333 /* PLOGI chkparm OK */
James Smarte8b62012007-08-02 11:10:09 -0400334 lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
James Smarte74c03c2013-04-17 20:15:19 -0400335 "0114 PLOGI chkparm OK Data: x%x x%x x%x "
336 "x%x x%x x%x\n",
James Smarte8b62012007-08-02 11:10:09 -0400337 ndlp->nlp_DID, ndlp->nlp_state, ndlp->nlp_flag,
James Smarte74c03c2013-04-17 20:15:19 -0400338 ndlp->nlp_rpi, vport->port_state,
339 vport->fc_flag);
dea31012005-04-17 16:05:31 -0500340
James Smart3de2a652007-08-02 11:09:59 -0400341 if (vport->cfg_fcp_class == 2 && sp->cls2.classValid)
dea31012005-04-17 16:05:31 -0500342 ndlp->nlp_fcp_info |= CLASS2;
James Smarted957682007-06-17 19:56:37 -0500343 else
dea31012005-04-17 16:05:31 -0500344 ndlp->nlp_fcp_info |= CLASS3;
James Smart2e0fef82007-06-17 19:56:36 -0500345
dea31012005-04-17 16:05:31 -0500346 ndlp->nlp_class_sup = 0;
347 if (sp->cls1.classValid)
348 ndlp->nlp_class_sup |= FC_COS_CLASS1;
349 if (sp->cls2.classValid)
350 ndlp->nlp_class_sup |= FC_COS_CLASS2;
351 if (sp->cls3.classValid)
352 ndlp->nlp_class_sup |= FC_COS_CLASS3;
353 if (sp->cls4.classValid)
354 ndlp->nlp_class_sup |= FC_COS_CLASS4;
355 ndlp->nlp_maxframe =
356 ((sp->cmn.bbRcvSizeMsb & 0x0F) << 8) | sp->cmn.bbRcvSizeLsb;
357
James Smart05580562011-05-24 11:40:48 -0400358 /* no need to reg_login if we are already in one of these states */
Jamie Wellnitz2fe165b2006-02-28 19:25:31 -0500359 switch (ndlp->nlp_state) {
dea31012005-04-17 16:05:31 -0500360 case NLP_STE_NPR_NODE:
361 if (!(ndlp->nlp_flag & NLP_NPR_ADISC))
362 break;
363 case NLP_STE_REG_LOGIN_ISSUE:
364 case NLP_STE_PRLI_ISSUE:
365 case NLP_STE_UNMAPPED_NODE:
366 case NLP_STE_MAPPED_NODE:
James Smart05580562011-05-24 11:40:48 -0400367 lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb, ndlp, NULL);
368 return 1;
dea31012005-04-17 16:05:31 -0500369 }
370
James Smart939723a2012-05-09 21:19:03 -0400371 /* Check for Nport to NPort pt2pt protocol */
James Smart92d7f7b2007-06-17 19:56:38 -0500372 if ((vport->fc_flag & FC_PT2PT) &&
373 !(vport->fc_flag & FC_PT2PT_PLOGI)) {
James Smart939723a2012-05-09 21:19:03 -0400374
dea31012005-04-17 16:05:31 -0500375 /* rcv'ed PLOGI decides what our NPortId will be */
James Smart2e0fef82007-06-17 19:56:36 -0500376 vport->fc_myDID = icmd->un.rcvels.parmRo;
dea31012005-04-17 16:05:31 -0500377 mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
378 if (mbox == NULL)
379 goto out;
380 lpfc_config_link(phba, mbox);
381 mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
James Smarted957682007-06-17 19:56:37 -0500382 mbox->vport = vport;
James Smart0b727fe2007-10-27 13:37:25 -0400383 rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT);
dea31012005-04-17 16:05:31 -0500384 if (rc == MBX_NOT_FINISHED) {
James Smart92d7f7b2007-06-17 19:56:38 -0500385 mempool_free(mbox, phba->mbox_mem_pool);
dea31012005-04-17 16:05:31 -0500386 goto out;
387 }
James Smart939723a2012-05-09 21:19:03 -0400388 /*
389 * For SLI4, the VFI/VPI are registered AFTER the
390 * Nport with the higher WWPN sends us a PLOGI with
391 * our assigned NPortId.
392 */
393 if (phba->sli_rev == LPFC_SLI_REV4)
394 lpfc_issue_reg_vfi(vport);
dea31012005-04-17 16:05:31 -0500395
James Smart2e0fef82007-06-17 19:56:36 -0500396 lpfc_can_disctmo(vport);
dea31012005-04-17 16:05:31 -0500397 }
398 mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
James Smart2e0fef82007-06-17 19:56:36 -0500399 if (!mbox)
dea31012005-04-17 16:05:31 -0500400 goto out;
401
James Smart6b5151f2012-01-18 16:24:06 -0500402 /* Registering an existing RPI behaves differently for SLI3 vs SLI4 */
403 if (phba->sli_rev == LPFC_SLI_REV4)
404 lpfc_unreg_rpi(vport, ndlp);
405
James Smart6fb120a2009-05-22 14:52:59 -0400406 rc = lpfc_reg_rpi(phba, vport->vpi, icmd->un.rcvels.remoteID,
James Smart40426292010-12-15 17:58:10 -0500407 (uint8_t *) sp, mbox, ndlp->nlp_rpi);
James Smart2e0fef82007-06-17 19:56:36 -0500408 if (rc) {
409 mempool_free(mbox, phba->mbox_mem_pool);
dea31012005-04-17 16:05:31 -0500410 goto out;
411 }
412
413 /* ACC PLOGI rsp command needs to execute first,
414 * queue this mbox command to be processed later.
415 */
416 mbox->mbox_cmpl = lpfc_mbx_cmpl_reg_login;
James Smart329f9bc2007-04-25 09:53:01 -0400417 /*
418 * mbox->context2 = lpfc_nlp_get(ndlp) deferred until mailbox
419 * command issued in lpfc_cmpl_els_acc().
420 */
James Smart2e0fef82007-06-17 19:56:36 -0500421 mbox->vport = vport;
422 spin_lock_irq(shost->host_lock);
Jamie Wellnitz5024ab12006-02-28 19:25:28 -0500423 ndlp->nlp_flag |= (NLP_ACC_REGLOGIN | NLP_RCV_PLOGI);
James Smart2e0fef82007-06-17 19:56:36 -0500424 spin_unlock_irq(shost->host_lock);
dea31012005-04-17 16:05:31 -0500425
James Smart33ccf8d2006-08-17 11:57:58 -0400426 /*
427 * If there is an outstanding PLOGI issued, abort it before
428 * sending ACC rsp for received PLOGI. If pending plogi
429 * is not canceled here, the plogi will be rejected by
430 * remote port and will be retried. On a configuration with
431 * single discovery thread, this will cause a huge delay in
432 * discovery. Also this will cause multiple state machines
433 * running in parallel for this node.
434 */
435 if (ndlp->nlp_state == NLP_STE_PLOGI_ISSUE) {
436 /* software abort outstanding PLOGI */
James Smart07951072007-04-25 09:51:38 -0400437 lpfc_els_abort(phba, ndlp);
James Smart33ccf8d2006-08-17 11:57:58 -0400438 }
439
James Smart858c9f62007-06-17 19:56:39 -0500440 if ((vport->port_type == LPFC_NPIV_PORT &&
James Smart3de2a652007-08-02 11:09:59 -0400441 vport->cfg_restrict_login)) {
James Smart858c9f62007-06-17 19:56:39 -0500442
443 /* In order to preserve RPIs, we want to cleanup
444 * the default RPI the firmware created to rcv
445 * this ELS request. The only way to do this is
446 * to register, then unregister the RPI.
447 */
448 spin_lock_irq(shost->host_lock);
449 ndlp->nlp_flag |= NLP_RM_DFLT_RPI;
450 spin_unlock_irq(shost->host_lock);
451 stat.un.b.lsRjtRsnCode = LSRJT_INVALID_CMD;
452 stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE;
James Smart0a8a86f2012-03-01 22:36:15 -0500453 rc = lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb,
James Smart858c9f62007-06-17 19:56:39 -0500454 ndlp, mbox);
James Smart0a8a86f2012-03-01 22:36:15 -0500455 if (rc)
456 mempool_free(mbox, phba->mbox_mem_pool);
James Smart858c9f62007-06-17 19:56:39 -0500457 return 1;
458 }
James Smart0a8a86f2012-03-01 22:36:15 -0500459 rc = lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb, ndlp, mbox);
460 if (rc)
461 mempool_free(mbox, phba->mbox_mem_pool);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500462 return 1;
dea31012005-04-17 16:05:31 -0500463out:
464 stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
465 stat.un.b.lsRjtRsnCodeExp = LSEXP_OUT_OF_RESOURCE;
James Smart858c9f62007-06-17 19:56:39 -0500466 lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, NULL);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500467 return 0;
dea31012005-04-17 16:05:31 -0500468}
469
James Smart6b5151f2012-01-18 16:24:06 -0500470/**
471 * lpfc_mbx_cmpl_resume_rpi - Resume RPI completion routine
472 * @phba: pointer to lpfc hba data structure.
473 * @mboxq: pointer to mailbox object
474 *
475 * This routine is invoked to issue a completion to a rcv'ed
476 * ADISC or PDISC after the paused RPI has been resumed.
477 **/
478static void
479lpfc_mbx_cmpl_resume_rpi(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
480{
481 struct lpfc_vport *vport;
482 struct lpfc_iocbq *elsiocb;
483 struct lpfc_nodelist *ndlp;
484 uint32_t cmd;
485
486 elsiocb = (struct lpfc_iocbq *)mboxq->context1;
487 ndlp = (struct lpfc_nodelist *) mboxq->context2;
488 vport = mboxq->vport;
489 cmd = elsiocb->drvrTimeout;
490
491 if (cmd == ELS_CMD_ADISC) {
492 lpfc_els_rsp_adisc_acc(vport, elsiocb, ndlp);
493 } else {
494 lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, elsiocb,
495 ndlp, NULL);
496 }
497 kfree(elsiocb);
James Smart72859902012-01-18 16:25:38 -0500498 mempool_free(mboxq, phba->mbox_mem_pool);
James Smart6b5151f2012-01-18 16:24:06 -0500499}
500
dea31012005-04-17 16:05:31 -0500501static int
James Smart2e0fef82007-06-17 19:56:36 -0500502lpfc_rcv_padisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
dea31012005-04-17 16:05:31 -0500503 struct lpfc_iocbq *cmdiocb)
504{
James Smart2e0fef82007-06-17 19:56:36 -0500505 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
James Smart6b5151f2012-01-18 16:24:06 -0500506 struct lpfc_iocbq *elsiocb;
dea31012005-04-17 16:05:31 -0500507 struct lpfc_dmabuf *pcmd;
James Smart2e0fef82007-06-17 19:56:36 -0500508 struct serv_parm *sp;
509 struct lpfc_name *pnn, *ppn;
dea31012005-04-17 16:05:31 -0500510 struct ls_rjt stat;
511 ADISC *ap;
512 IOCB_t *icmd;
513 uint32_t *lp;
514 uint32_t cmd;
515
516 pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
517 lp = (uint32_t *) pcmd->virt;
518
519 cmd = *lp++;
520 if (cmd == ELS_CMD_ADISC) {
521 ap = (ADISC *) lp;
522 pnn = (struct lpfc_name *) & ap->nodeName;
523 ppn = (struct lpfc_name *) & ap->portName;
524 } else {
525 sp = (struct serv_parm *) lp;
526 pnn = (struct lpfc_name *) & sp->nodeName;
527 ppn = (struct lpfc_name *) & sp->portName;
528 }
529
530 icmd = &cmdiocb->iocb;
James Smart2e0fef82007-06-17 19:56:36 -0500531 if (icmd->ulpStatus == 0 && lpfc_check_adisc(vport, ndlp, pnn, ppn)) {
James Smart6b5151f2012-01-18 16:24:06 -0500532
533 /*
534 * As soon as we send ACC, the remote NPort can
535 * start sending us data. Thus, for SLI4 we must
536 * resume the RPI before the ACC goes out.
537 */
538 if (vport->phba->sli_rev == LPFC_SLI_REV4) {
539 elsiocb = kmalloc(sizeof(struct lpfc_iocbq),
540 GFP_KERNEL);
541 if (elsiocb) {
542
543 /* Save info from cmd IOCB used in rsp */
544 memcpy((uint8_t *)elsiocb, (uint8_t *)cmdiocb,
545 sizeof(struct lpfc_iocbq));
546
547 /* Save the ELS cmd */
548 elsiocb->drvrTimeout = cmd;
549
550 lpfc_sli4_resume_rpi(ndlp,
551 lpfc_mbx_cmpl_resume_rpi, elsiocb);
552 goto out;
553 }
554 }
555
dea31012005-04-17 16:05:31 -0500556 if (cmd == ELS_CMD_ADISC) {
James Smart2e0fef82007-06-17 19:56:36 -0500557 lpfc_els_rsp_adisc_acc(vport, cmdiocb, ndlp);
Jamie Wellnitz2fe165b2006-02-28 19:25:31 -0500558 } else {
James Smart6b5151f2012-01-18 16:24:06 -0500559 lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb,
560 ndlp, NULL);
dea31012005-04-17 16:05:31 -0500561 }
James Smart6b5151f2012-01-18 16:24:06 -0500562out:
563 /* If we are authenticated, move to the proper state */
564 if (ndlp->nlp_type & NLP_FCP_TARGET)
565 lpfc_nlp_set_state(vport, ndlp, NLP_STE_MAPPED_NODE);
566 else
567 lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE);
568
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500569 return 1;
dea31012005-04-17 16:05:31 -0500570 }
571 /* Reject this request because invalid parameters */
572 stat.un.b.lsRjtRsvd0 = 0;
573 stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
574 stat.un.b.lsRjtRsnCodeExp = LSEXP_SPARM_OPTIONS;
575 stat.un.b.vendorUnique = 0;
James Smart858c9f62007-06-17 19:56:39 -0500576 lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, NULL);
dea31012005-04-17 16:05:31 -0500577
dea31012005-04-17 16:05:31 -0500578 /* 1 sec timeout */
James Smart256ec0d2013-04-17 20:14:58 -0400579 mod_timer(&ndlp->nlp_delayfunc, jiffies + msecs_to_jiffies(1000));
dea31012005-04-17 16:05:31 -0500580
James Smart2e0fef82007-06-17 19:56:36 -0500581 spin_lock_irq(shost->host_lock);
dea31012005-04-17 16:05:31 -0500582 ndlp->nlp_flag |= NLP_DELAY_TMO;
James Smart2e0fef82007-06-17 19:56:36 -0500583 spin_unlock_irq(shost->host_lock);
Jamie Wellnitz5024ab12006-02-28 19:25:28 -0500584 ndlp->nlp_last_elscmd = ELS_CMD_PLOGI;
585 ndlp->nlp_prev_state = ndlp->nlp_state;
James Smart2e0fef82007-06-17 19:56:36 -0500586 lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500587 return 0;
dea31012005-04-17 16:05:31 -0500588}
589
590static int
James Smart2e0fef82007-06-17 19:56:36 -0500591lpfc_rcv_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
592 struct lpfc_iocbq *cmdiocb, uint32_t els_cmd)
dea31012005-04-17 16:05:31 -0500593{
James Smart2e0fef82007-06-17 19:56:36 -0500594 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
James Smart4b40c592010-03-15 11:25:44 -0400595 struct lpfc_hba *phba = vport->phba;
596 struct lpfc_vport **vports;
597 int i, active_vlink_present = 0 ;
James Smart2e0fef82007-06-17 19:56:36 -0500598
599 /* Put ndlp in NPR state with 1 sec timeout for plogi, ACC logo */
dea31012005-04-17 16:05:31 -0500600 /* Only call LOGO ACC for first LOGO, this avoids sending unnecessary
601 * PLOGIs during LOGO storms from a device.
602 */
James Smart2e0fef82007-06-17 19:56:36 -0500603 spin_lock_irq(shost->host_lock);
dea31012005-04-17 16:05:31 -0500604 ndlp->nlp_flag |= NLP_LOGO_ACC;
James Smart2e0fef82007-06-17 19:56:36 -0500605 spin_unlock_irq(shost->host_lock);
James Smart82d9a2a2006-04-15 11:53:05 -0400606 if (els_cmd == ELS_CMD_PRLO)
James Smart51ef4c22007-08-02 11:10:31 -0400607 lpfc_els_rsp_acc(vport, ELS_CMD_PRLO, cmdiocb, ndlp, NULL);
James Smart82d9a2a2006-04-15 11:53:05 -0400608 else
James Smart51ef4c22007-08-02 11:10:31 -0400609 lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL);
James Smart4b40c592010-03-15 11:25:44 -0400610 if (ndlp->nlp_DID == Fabric_DID) {
611 if (vport->port_state <= LPFC_FDISC)
612 goto out;
James Smart6fb120a2009-05-22 14:52:59 -0400613 lpfc_linkdown_port(vport);
James Smart6fb120a2009-05-22 14:52:59 -0400614 spin_lock_irq(shost->host_lock);
James Smart4b40c592010-03-15 11:25:44 -0400615 vport->fc_flag |= FC_VPORT_LOGO_RCVD;
James Smart6fb120a2009-05-22 14:52:59 -0400616 spin_unlock_irq(shost->host_lock);
James Smart4b40c592010-03-15 11:25:44 -0400617 vports = lpfc_create_vport_work_array(phba);
618 if (vports) {
619 for (i = 0; i <= phba->max_vports && vports[i] != NULL;
620 i++) {
621 if ((!(vports[i]->fc_flag &
622 FC_VPORT_LOGO_RCVD)) &&
623 (vports[i]->port_state > LPFC_FDISC)) {
624 active_vlink_present = 1;
625 break;
626 }
627 }
628 lpfc_destroy_vport_work_array(phba, vports);
629 }
dea31012005-04-17 16:05:31 -0500630
James Smart4b40c592010-03-15 11:25:44 -0400631 if (active_vlink_present) {
632 /*
633 * If there are other active VLinks present,
634 * re-instantiate the Vlink using FDISC.
635 */
James Smart256ec0d2013-04-17 20:14:58 -0400636 mod_timer(&ndlp->nlp_delayfunc,
637 jiffies + msecs_to_jiffies(1000));
James Smart4b40c592010-03-15 11:25:44 -0400638 spin_lock_irq(shost->host_lock);
639 ndlp->nlp_flag |= NLP_DELAY_TMO;
640 spin_unlock_irq(shost->host_lock);
641 ndlp->nlp_last_elscmd = ELS_CMD_FDISC;
642 vport->port_state = LPFC_FDISC;
643 } else {
644 spin_lock_irq(shost->host_lock);
645 phba->pport->fc_flag &= ~FC_LOGO_RCVD_DID_CHNG;
646 spin_unlock_irq(shost->host_lock);
647 lpfc_retry_pport_discovery(phba);
648 }
James Smart6fb120a2009-05-22 14:52:59 -0400649 } else if ((!(ndlp->nlp_type & NLP_FABRIC) &&
650 ((ndlp->nlp_type & NLP_FCP_TARGET) ||
651 !(ndlp->nlp_type & NLP_FCP_INITIATOR))) ||
652 (ndlp->nlp_state == NLP_STE_ADISC_ISSUE)) {
dea31012005-04-17 16:05:31 -0500653 /* Only try to re-login if this is NOT a Fabric Node */
James Smart256ec0d2013-04-17 20:14:58 -0400654 mod_timer(&ndlp->nlp_delayfunc,
655 jiffies + msecs_to_jiffies(1000 * 1));
James Smart2e0fef82007-06-17 19:56:36 -0500656 spin_lock_irq(shost->host_lock);
dea31012005-04-17 16:05:31 -0500657 ndlp->nlp_flag |= NLP_DELAY_TMO;
James Smart2e0fef82007-06-17 19:56:36 -0500658 spin_unlock_irq(shost->host_lock);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500659
Jamie Wellnitz5024ab12006-02-28 19:25:28 -0500660 ndlp->nlp_last_elscmd = ELS_CMD_PLOGI;
dea31012005-04-17 16:05:31 -0500661 }
James Smart4b40c592010-03-15 11:25:44 -0400662out:
James Smart87af33f2007-10-27 13:37:43 -0400663 ndlp->nlp_prev_state = ndlp->nlp_state;
664 lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
dea31012005-04-17 16:05:31 -0500665
James Smart2e0fef82007-06-17 19:56:36 -0500666 spin_lock_irq(shost->host_lock);
dea31012005-04-17 16:05:31 -0500667 ndlp->nlp_flag &= ~NLP_NPR_ADISC;
James Smart2e0fef82007-06-17 19:56:36 -0500668 spin_unlock_irq(shost->host_lock);
dea31012005-04-17 16:05:31 -0500669 /* The driver has to wait until the ACC completes before it continues
670 * processing the LOGO. The action will resume in
671 * lpfc_cmpl_els_logo_acc routine. Since part of processing includes an
672 * unreg_login, the driver waits so the ACC does not get aborted.
673 */
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500674 return 0;
dea31012005-04-17 16:05:31 -0500675}
676
677static void
James Smart2e0fef82007-06-17 19:56:36 -0500678lpfc_rcv_prli(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
679 struct lpfc_iocbq *cmdiocb)
dea31012005-04-17 16:05:31 -0500680{
681 struct lpfc_dmabuf *pcmd;
682 uint32_t *lp;
683 PRLI *npr;
684 struct fc_rport *rport = ndlp->rport;
685 u32 roles;
686
687 pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
688 lp = (uint32_t *) pcmd->virt;
689 npr = (PRLI *) ((uint8_t *) lp + sizeof (uint32_t));
690
691 ndlp->nlp_type &= ~(NLP_FCP_TARGET | NLP_FCP_INITIATOR);
692 ndlp->nlp_fcp_info &= ~NLP_FCP_2_DEVICE;
James Smart3cb01c52013-07-15 18:35:04 -0400693 ndlp->nlp_flag &= ~NLP_FIRSTBURST;
James Smart92d7f7b2007-06-17 19:56:38 -0500694 if (npr->prliType == PRLI_FCP_TYPE) {
dea31012005-04-17 16:05:31 -0500695 if (npr->initiatorFunc)
696 ndlp->nlp_type |= NLP_FCP_INITIATOR;
James Smart3cb01c52013-07-15 18:35:04 -0400697 if (npr->targetFunc) {
dea31012005-04-17 16:05:31 -0500698 ndlp->nlp_type |= NLP_FCP_TARGET;
James Smart3cb01c52013-07-15 18:35:04 -0400699 if (npr->writeXferRdyDis)
700 ndlp->nlp_flag |= NLP_FIRSTBURST;
701 }
dea31012005-04-17 16:05:31 -0500702 if (npr->Retry)
703 ndlp->nlp_fcp_info |= NLP_FCP_2_DEVICE;
704 }
705 if (rport) {
706 /* We need to update the rport role values */
707 roles = FC_RPORT_ROLE_UNKNOWN;
708 if (ndlp->nlp_type & NLP_FCP_INITIATOR)
709 roles |= FC_RPORT_ROLE_FCP_INITIATOR;
710 if (ndlp->nlp_type & NLP_FCP_TARGET)
711 roles |= FC_RPORT_ROLE_FCP_TARGET;
James Smart858c9f62007-06-17 19:56:39 -0500712
713 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_RPORT,
714 "rport rolechg: role:x%x did:x%x flg:x%x",
715 roles, ndlp->nlp_DID, ndlp->nlp_flag);
716
dea31012005-04-17 16:05:31 -0500717 fc_remote_port_rolechg(rport, roles);
718 }
719}
720
721static uint32_t
James Smart2e0fef82007-06-17 19:56:36 -0500722lpfc_disc_set_adisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
dea31012005-04-17 16:05:31 -0500723{
James Smart2e0fef82007-06-17 19:56:36 -0500724 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
James Smart2e0fef82007-06-17 19:56:36 -0500725
James Smart40426292010-12-15 17:58:10 -0500726 if (!(ndlp->nlp_flag & NLP_RPI_REGISTERED)) {
James Smart51ef4c22007-08-02 11:10:31 -0400727 ndlp->nlp_flag &= ~NLP_NPR_ADISC;
728 return 0;
729 }
730
James Smart1b32f6a2008-02-08 18:49:39 -0500731 if (!(vport->fc_flag & FC_PT2PT)) {
732 /* Check config parameter use-adisc or FCP-2 */
733 if ((vport->cfg_use_adisc && (vport->fc_flag & FC_RSCN_MODE)) ||
James Smartffc95492010-06-07 15:23:17 -0400734 ((ndlp->nlp_fcp_info & NLP_FCP_2_DEVICE) &&
735 (ndlp->nlp_type & NLP_FCP_TARGET))) {
James Smart1b32f6a2008-02-08 18:49:39 -0500736 spin_lock_irq(shost->host_lock);
737 ndlp->nlp_flag |= NLP_NPR_ADISC;
738 spin_unlock_irq(shost->host_lock);
739 return 1;
740 }
James Smart92d7f7b2007-06-17 19:56:38 -0500741 }
742 ndlp->nlp_flag &= ~NLP_NPR_ADISC;
743 lpfc_unreg_rpi(vport, ndlp);
744 return 0;
dea31012005-04-17 16:05:31 -0500745}
James Smart6d368e52011-05-24 11:44:12 -0400746
James Smart78730cf2010-04-06 15:06:30 -0400747/**
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300748 * lpfc_release_rpi - Release a RPI by issuing unreg_login mailbox cmd.
James Smart78730cf2010-04-06 15:06:30 -0400749 * @phba : Pointer to lpfc_hba structure.
750 * @vport: Pointer to lpfc_vport structure.
751 * @rpi : rpi to be release.
752 *
753 * This function will send a unreg_login mailbox command to the firmware
754 * to release a rpi.
755 **/
756void
757lpfc_release_rpi(struct lpfc_hba *phba,
758 struct lpfc_vport *vport,
759 uint16_t rpi)
760{
761 LPFC_MBOXQ_t *pmb;
762 int rc;
763
764 pmb = (LPFC_MBOXQ_t *) mempool_alloc(phba->mbox_mem_pool,
765 GFP_KERNEL);
766 if (!pmb)
767 lpfc_printf_vlog(vport, KERN_ERR, LOG_MBOX,
768 "2796 mailbox memory allocation failed \n");
769 else {
770 lpfc_unreg_login(phba, vport->vpi, rpi, pmb);
771 pmb->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
772 rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT);
773 if (rc == MBX_NOT_FINISHED)
774 mempool_free(pmb, phba->mbox_mem_pool);
775 }
776}
dea31012005-04-17 16:05:31 -0500777
778static uint32_t
James Smart2e0fef82007-06-17 19:56:36 -0500779lpfc_disc_illegal(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
780 void *arg, uint32_t evt)
dea31012005-04-17 16:05:31 -0500781{
James Smart78730cf2010-04-06 15:06:30 -0400782 struct lpfc_hba *phba;
783 LPFC_MBOXQ_t *pmb = (LPFC_MBOXQ_t *) arg;
784 MAILBOX_t *mb;
785 uint16_t rpi;
786
787 phba = vport->phba;
788 /* Release the RPI if reglogin completing */
789 if (!(phba->pport->load_flag & FC_UNLOADING) &&
790 (evt == NLP_EVT_CMPL_REG_LOGIN) &&
791 (!pmb->u.mb.mbxStatus)) {
792 mb = &pmb->u.mb;
793 rpi = pmb->u.mb.un.varWords[0];
794 lpfc_release_rpi(phba, vport, rpi);
795 }
James Smarte8b62012007-08-02 11:10:09 -0400796 lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY,
James Smarte47c9092008-02-08 18:49:26 -0500797 "0271 Illegal State Transition: node x%x "
James Smarte8b62012007-08-02 11:10:09 -0400798 "event x%x, state x%x Data: x%x x%x\n",
799 ndlp->nlp_DID, evt, ndlp->nlp_state, ndlp->nlp_rpi,
800 ndlp->nlp_flag);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500801 return ndlp->nlp_state;
dea31012005-04-17 16:05:31 -0500802}
803
James Smart87af33f2007-10-27 13:37:43 -0400804static uint32_t
805lpfc_cmpl_plogi_illegal(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
806 void *arg, uint32_t evt)
807{
808 /* This transition is only legal if we previously
809 * rcv'ed a PLOGI. Since we don't want 2 discovery threads
810 * working on the same NPortID, do nothing for this thread
811 * to stop it.
812 */
813 if (!(ndlp->nlp_flag & NLP_RCV_PLOGI)) {
814 lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY,
James Smarte47c9092008-02-08 18:49:26 -0500815 "0272 Illegal State Transition: node x%x "
James Smart87af33f2007-10-27 13:37:43 -0400816 "event x%x, state x%x Data: x%x x%x\n",
817 ndlp->nlp_DID, evt, ndlp->nlp_state, ndlp->nlp_rpi,
818 ndlp->nlp_flag);
819 }
820 return ndlp->nlp_state;
821}
822
dea31012005-04-17 16:05:31 -0500823/* Start of Discovery State Machine routines */
824
825static uint32_t
James Smart2e0fef82007-06-17 19:56:36 -0500826lpfc_rcv_plogi_unused_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
827 void *arg, uint32_t evt)
dea31012005-04-17 16:05:31 -0500828{
829 struct lpfc_iocbq *cmdiocb;
830
831 cmdiocb = (struct lpfc_iocbq *) arg;
832
James Smart2e0fef82007-06-17 19:56:36 -0500833 if (lpfc_rcv_plogi(vport, ndlp, cmdiocb)) {
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500834 return ndlp->nlp_state;
dea31012005-04-17 16:05:31 -0500835 }
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500836 return NLP_STE_FREED_NODE;
dea31012005-04-17 16:05:31 -0500837}
838
839static uint32_t
James Smart2e0fef82007-06-17 19:56:36 -0500840lpfc_rcv_els_unused_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
841 void *arg, uint32_t evt)
dea31012005-04-17 16:05:31 -0500842{
James Smart2e0fef82007-06-17 19:56:36 -0500843 lpfc_issue_els_logo(vport, ndlp, 0);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500844 return ndlp->nlp_state;
dea31012005-04-17 16:05:31 -0500845}
846
847static uint32_t
James Smart2e0fef82007-06-17 19:56:36 -0500848lpfc_rcv_logo_unused_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
849 void *arg, uint32_t evt)
dea31012005-04-17 16:05:31 -0500850{
James Smart2e0fef82007-06-17 19:56:36 -0500851 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
852 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
dea31012005-04-17 16:05:31 -0500853
James Smart2e0fef82007-06-17 19:56:36 -0500854 spin_lock_irq(shost->host_lock);
dea31012005-04-17 16:05:31 -0500855 ndlp->nlp_flag |= NLP_LOGO_ACC;
James Smart2e0fef82007-06-17 19:56:36 -0500856 spin_unlock_irq(shost->host_lock);
James Smart51ef4c22007-08-02 11:10:31 -0400857 lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL);
dea31012005-04-17 16:05:31 -0500858
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500859 return ndlp->nlp_state;
dea31012005-04-17 16:05:31 -0500860}
861
862static uint32_t
James Smart2e0fef82007-06-17 19:56:36 -0500863lpfc_cmpl_logo_unused_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
dea31012005-04-17 16:05:31 -0500864 void *arg, uint32_t evt)
865{
James Smart2e0fef82007-06-17 19:56:36 -0500866 return NLP_STE_FREED_NODE;
867}
868
869static uint32_t
870lpfc_device_rm_unused_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
871 void *arg, uint32_t evt)
872{
James Smart2e0fef82007-06-17 19:56:36 -0500873 return NLP_STE_FREED_NODE;
874}
875
876static uint32_t
James Smartdf9e1b52011-12-13 13:22:17 -0500877lpfc_device_recov_unused_node(struct lpfc_vport *vport,
878 struct lpfc_nodelist *ndlp,
879 void *arg, uint32_t evt)
880{
881 return ndlp->nlp_state;
882}
883
884static uint32_t
James Smart2e0fef82007-06-17 19:56:36 -0500885lpfc_rcv_plogi_plogi_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
886 void *arg, uint32_t evt)
887{
James Smart0d2b6b82008-06-14 22:52:47 -0400888 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
James Smart2e0fef82007-06-17 19:56:36 -0500889 struct lpfc_hba *phba = vport->phba;
dea31012005-04-17 16:05:31 -0500890 struct lpfc_iocbq *cmdiocb = arg;
James Smart2e0fef82007-06-17 19:56:36 -0500891 struct lpfc_dmabuf *pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
892 uint32_t *lp = (uint32_t *) pcmd->virt;
893 struct serv_parm *sp = (struct serv_parm *) (lp + 1);
dea31012005-04-17 16:05:31 -0500894 struct ls_rjt stat;
895 int port_cmp;
896
dea31012005-04-17 16:05:31 -0500897 memset(&stat, 0, sizeof (struct ls_rjt));
898
899 /* For a PLOGI, we only accept if our portname is less
900 * than the remote portname.
901 */
902 phba->fc_stat.elsLogiCol++;
James Smart2e0fef82007-06-17 19:56:36 -0500903 port_cmp = memcmp(&vport->fc_portname, &sp->portName,
James Smart92d7f7b2007-06-17 19:56:38 -0500904 sizeof(struct lpfc_name));
dea31012005-04-17 16:05:31 -0500905
906 if (port_cmp >= 0) {
907 /* Reject this request because the remote node will accept
908 ours */
909 stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
910 stat.un.b.lsRjtRsnCodeExp = LSEXP_CMD_IN_PROGRESS;
James Smart858c9f62007-06-17 19:56:39 -0500911 lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp,
912 NULL);
Jamie Wellnitz2fe165b2006-02-28 19:25:31 -0500913 } else {
James Smart0d2b6b82008-06-14 22:52:47 -0400914 if (lpfc_rcv_plogi(vport, ndlp, cmdiocb) &&
915 (ndlp->nlp_flag & NLP_NPR_2B_DISC) &&
916 (vport->num_disc_nodes)) {
917 spin_lock_irq(shost->host_lock);
918 ndlp->nlp_flag &= ~NLP_NPR_2B_DISC;
919 spin_unlock_irq(shost->host_lock);
920 /* Check if there are more PLOGIs to be sent */
921 lpfc_more_plogi(vport);
922 if (vport->num_disc_nodes == 0) {
923 spin_lock_irq(shost->host_lock);
924 vport->fc_flag &= ~FC_NDISC_ACTIVE;
925 spin_unlock_irq(shost->host_lock);
926 lpfc_can_disctmo(vport);
927 lpfc_end_rscn(vport);
928 }
929 }
James Smart2e0fef82007-06-17 19:56:36 -0500930 } /* If our portname was less */
dea31012005-04-17 16:05:31 -0500931
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500932 return ndlp->nlp_state;
933}
934
935static uint32_t
James Smart92d7f7b2007-06-17 19:56:38 -0500936lpfc_rcv_prli_plogi_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
937 void *arg, uint32_t evt)
938{
939 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
940 struct ls_rjt stat;
941
942 memset(&stat, 0, sizeof (struct ls_rjt));
943 stat.un.b.lsRjtRsnCode = LSRJT_LOGICAL_BSY;
944 stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE;
James Smart858c9f62007-06-17 19:56:39 -0500945 lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, NULL);
James Smart92d7f7b2007-06-17 19:56:38 -0500946 return ndlp->nlp_state;
947}
948
949static uint32_t
James Smart2e0fef82007-06-17 19:56:36 -0500950lpfc_rcv_logo_plogi_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
951 void *arg, uint32_t evt)
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500952{
James Smart2e0fef82007-06-17 19:56:36 -0500953 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500954
James Smart92d7f7b2007-06-17 19:56:38 -0500955 /* software abort outstanding PLOGI */
James Smart2e0fef82007-06-17 19:56:36 -0500956 lpfc_els_abort(vport->phba, ndlp);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500957
James Smart2e0fef82007-06-17 19:56:36 -0500958 lpfc_rcv_logo(vport, ndlp, cmdiocb, ELS_CMD_LOGO);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500959 return ndlp->nlp_state;
dea31012005-04-17 16:05:31 -0500960}
961
962static uint32_t
James Smart2e0fef82007-06-17 19:56:36 -0500963lpfc_rcv_els_plogi_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
964 void *arg, uint32_t evt)
dea31012005-04-17 16:05:31 -0500965{
James Smart2e0fef82007-06-17 19:56:36 -0500966 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
967 struct lpfc_hba *phba = vport->phba;
968 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
dea31012005-04-17 16:05:31 -0500969
970 /* software abort outstanding PLOGI */
James Smart07951072007-04-25 09:51:38 -0400971 lpfc_els_abort(phba, ndlp);
dea31012005-04-17 16:05:31 -0500972
973 if (evt == NLP_EVT_RCV_LOGO) {
James Smart51ef4c22007-08-02 11:10:31 -0400974 lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL);
Jamie Wellnitz2fe165b2006-02-28 19:25:31 -0500975 } else {
James Smart2e0fef82007-06-17 19:56:36 -0500976 lpfc_issue_els_logo(vport, ndlp, 0);
dea31012005-04-17 16:05:31 -0500977 }
978
James Smart2e0fef82007-06-17 19:56:36 -0500979 /* Put ndlp in npr state set plogi timer for 1 sec */
James Smart256ec0d2013-04-17 20:14:58 -0400980 mod_timer(&ndlp->nlp_delayfunc, jiffies + msecs_to_jiffies(1000 * 1));
James Smart2e0fef82007-06-17 19:56:36 -0500981 spin_lock_irq(shost->host_lock);
Jamie Wellnitz5024ab12006-02-28 19:25:28 -0500982 ndlp->nlp_flag |= NLP_DELAY_TMO;
James Smart2e0fef82007-06-17 19:56:36 -0500983 spin_unlock_irq(shost->host_lock);
Jamie Wellnitz5024ab12006-02-28 19:25:28 -0500984 ndlp->nlp_last_elscmd = ELS_CMD_PLOGI;
985 ndlp->nlp_prev_state = NLP_STE_PLOGI_ISSUE;
James Smart2e0fef82007-06-17 19:56:36 -0500986 lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
dea31012005-04-17 16:05:31 -0500987
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500988 return ndlp->nlp_state;
dea31012005-04-17 16:05:31 -0500989}
990
991static uint32_t
James Smart2e0fef82007-06-17 19:56:36 -0500992lpfc_cmpl_plogi_plogi_issue(struct lpfc_vport *vport,
993 struct lpfc_nodelist *ndlp,
994 void *arg,
dea31012005-04-17 16:05:31 -0500995 uint32_t evt)
996{
James Smart2e0fef82007-06-17 19:56:36 -0500997 struct lpfc_hba *phba = vport->phba;
James Smart0ff10d42008-01-11 01:52:36 -0500998 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
James Smart2e0fef82007-06-17 19:56:36 -0500999 struct lpfc_iocbq *cmdiocb, *rspiocb;
James Smart14691152006-12-02 13:34:28 -05001000 struct lpfc_dmabuf *pcmd, *prsp, *mp;
dea31012005-04-17 16:05:31 -05001001 uint32_t *lp;
1002 IOCB_t *irsp;
1003 struct serv_parm *sp;
1004 LPFC_MBOXQ_t *mbox;
1005
1006 cmdiocb = (struct lpfc_iocbq *) arg;
1007 rspiocb = cmdiocb->context_un.rsp_iocb;
1008
1009 if (ndlp->nlp_flag & NLP_ACC_REGLOGIN) {
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05001010 /* Recovery from PLOGI collision logic */
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001011 return ndlp->nlp_state;
dea31012005-04-17 16:05:31 -05001012 }
1013
1014 irsp = &rspiocb->iocb;
1015
1016 if (irsp->ulpStatus)
1017 goto out;
1018
1019 pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
1020
James Smart2e0fef82007-06-17 19:56:36 -05001021 prsp = list_get_first(&pcmd->list, struct lpfc_dmabuf, list);
dea31012005-04-17 16:05:31 -05001022
James Smart2e0fef82007-06-17 19:56:36 -05001023 lp = (uint32_t *) prsp->virt;
dea31012005-04-17 16:05:31 -05001024 sp = (struct serv_parm *) ((uint8_t *) lp + sizeof (uint32_t));
James Smart58da1ff2008-04-07 10:15:56 -04001025
1026 /* Some switches have FDMI servers returning 0 for WWN */
1027 if ((ndlp->nlp_DID != FDMI_DID) &&
1028 (wwn_to_u64(sp->portName.u.wwn) == 0 ||
1029 wwn_to_u64(sp->nodeName.u.wwn) == 0)) {
James Smarta8adb832007-10-27 13:37:53 -04001030 lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
1031 "0142 PLOGI RSP: Invalid WWN.\n");
1032 goto out;
1033 }
James Smart341af102010-01-26 23:07:37 -05001034 if (!lpfc_check_sparm(vport, ndlp, sp, CLASS3, 0))
dea31012005-04-17 16:05:31 -05001035 goto out;
dea31012005-04-17 16:05:31 -05001036 /* PLOGI chkparm OK */
James Smarte8b62012007-08-02 11:10:09 -04001037 lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
1038 "0121 PLOGI chkparm OK Data: x%x x%x x%x x%x\n",
1039 ndlp->nlp_DID, ndlp->nlp_state,
1040 ndlp->nlp_flag, ndlp->nlp_rpi);
James Smart3de2a652007-08-02 11:09:59 -04001041 if (vport->cfg_fcp_class == 2 && (sp->cls2.classValid))
dea31012005-04-17 16:05:31 -05001042 ndlp->nlp_fcp_info |= CLASS2;
James Smart2e0fef82007-06-17 19:56:36 -05001043 else
dea31012005-04-17 16:05:31 -05001044 ndlp->nlp_fcp_info |= CLASS3;
James Smart2e0fef82007-06-17 19:56:36 -05001045
dea31012005-04-17 16:05:31 -05001046 ndlp->nlp_class_sup = 0;
1047 if (sp->cls1.classValid)
1048 ndlp->nlp_class_sup |= FC_COS_CLASS1;
1049 if (sp->cls2.classValid)
1050 ndlp->nlp_class_sup |= FC_COS_CLASS2;
1051 if (sp->cls3.classValid)
1052 ndlp->nlp_class_sup |= FC_COS_CLASS3;
1053 if (sp->cls4.classValid)
1054 ndlp->nlp_class_sup |= FC_COS_CLASS4;
1055 ndlp->nlp_maxframe =
James Smart2e0fef82007-06-17 19:56:36 -05001056 ((sp->cmn.bbRcvSizeMsb & 0x0F) << 8) | sp->cmn.bbRcvSizeLsb;
dea31012005-04-17 16:05:31 -05001057
James Smart2e0fef82007-06-17 19:56:36 -05001058 mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
James Smart92d7f7b2007-06-17 19:56:38 -05001059 if (!mbox) {
James Smarte8b62012007-08-02 11:10:09 -04001060 lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
1061 "0133 PLOGI: no memory for reg_login "
James Smart92d7f7b2007-06-17 19:56:38 -05001062 "Data: x%x x%x x%x x%x\n",
James Smart92d7f7b2007-06-17 19:56:38 -05001063 ndlp->nlp_DID, ndlp->nlp_state,
1064 ndlp->nlp_flag, ndlp->nlp_rpi);
dea31012005-04-17 16:05:31 -05001065 goto out;
James Smart92d7f7b2007-06-17 19:56:38 -05001066 }
dea31012005-04-17 16:05:31 -05001067
James Smart2e0fef82007-06-17 19:56:36 -05001068 lpfc_unreg_rpi(vport, ndlp);
1069
James Smart6fb120a2009-05-22 14:52:59 -04001070 if (lpfc_reg_rpi(phba, vport->vpi, irsp->un.elsreq64.remoteID,
James Smart40426292010-12-15 17:58:10 -05001071 (uint8_t *) sp, mbox, ndlp->nlp_rpi) == 0) {
Jamie Wellnitz2fe165b2006-02-28 19:25:31 -05001072 switch (ndlp->nlp_DID) {
dea31012005-04-17 16:05:31 -05001073 case NameServer_DID:
James Smartde0c5b32007-04-25 09:52:27 -04001074 mbox->mbox_cmpl = lpfc_mbx_cmpl_ns_reg_login;
dea31012005-04-17 16:05:31 -05001075 break;
1076 case FDMI_DID:
James Smartde0c5b32007-04-25 09:52:27 -04001077 mbox->mbox_cmpl = lpfc_mbx_cmpl_fdmi_reg_login;
dea31012005-04-17 16:05:31 -05001078 break;
1079 default:
James Smartffc95492010-06-07 15:23:17 -04001080 ndlp->nlp_flag |= NLP_REG_LOGIN_SEND;
James Smartde0c5b32007-04-25 09:52:27 -04001081 mbox->mbox_cmpl = lpfc_mbx_cmpl_reg_login;
dea31012005-04-17 16:05:31 -05001082 }
James Smart329f9bc2007-04-25 09:53:01 -04001083 mbox->context2 = lpfc_nlp_get(ndlp);
James Smart2e0fef82007-06-17 19:56:36 -05001084 mbox->vport = vport;
James Smart0b727fe2007-10-27 13:37:25 -04001085 if (lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT)
dea31012005-04-17 16:05:31 -05001086 != MBX_NOT_FINISHED) {
James Smart2e0fef82007-06-17 19:56:36 -05001087 lpfc_nlp_set_state(vport, ndlp,
1088 NLP_STE_REG_LOGIN_ISSUE);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001089 return ndlp->nlp_state;
dea31012005-04-17 16:05:31 -05001090 }
James Smartffc95492010-06-07 15:23:17 -04001091 if (ndlp->nlp_flag & NLP_REG_LOGIN_SEND)
1092 ndlp->nlp_flag &= ~NLP_REG_LOGIN_SEND;
James Smartfa4066b2008-01-11 01:53:27 -05001093 /* decrement node reference count to the failed mbox
1094 * command
1095 */
James Smart329f9bc2007-04-25 09:53:01 -04001096 lpfc_nlp_put(ndlp);
James Smart92d7f7b2007-06-17 19:56:38 -05001097 mp = (struct lpfc_dmabuf *) mbox->context1;
James Smart14691152006-12-02 13:34:28 -05001098 lpfc_mbuf_free(phba, mp->virt, mp->phys);
1099 kfree(mp);
dea31012005-04-17 16:05:31 -05001100 mempool_free(mbox, phba->mbox_mem_pool);
James Smart92d7f7b2007-06-17 19:56:38 -05001101
James Smarte8b62012007-08-02 11:10:09 -04001102 lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
1103 "0134 PLOGI: cannot issue reg_login "
1104 "Data: x%x x%x x%x x%x\n",
1105 ndlp->nlp_DID, ndlp->nlp_state,
1106 ndlp->nlp_flag, ndlp->nlp_rpi);
dea31012005-04-17 16:05:31 -05001107 } else {
1108 mempool_free(mbox, phba->mbox_mem_pool);
James Smart92d7f7b2007-06-17 19:56:38 -05001109
James Smarte8b62012007-08-02 11:10:09 -04001110 lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
1111 "0135 PLOGI: cannot format reg_login "
1112 "Data: x%x x%x x%x x%x\n",
1113 ndlp->nlp_DID, ndlp->nlp_state,
1114 ndlp->nlp_flag, ndlp->nlp_rpi);
dea31012005-04-17 16:05:31 -05001115 }
1116
1117
James Smart92d7f7b2007-06-17 19:56:38 -05001118out:
1119 if (ndlp->nlp_DID == NameServer_DID) {
1120 lpfc_vport_set_state(vport, FC_VPORT_FAILED);
James Smarte8b62012007-08-02 11:10:09 -04001121 lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
1122 "0261 Cannot Register NameServer login\n");
James Smart92d7f7b2007-06-17 19:56:38 -05001123 }
1124
James Smart8b455cf2013-01-03 15:43:53 -05001125 /*
1126 ** In case the node reference counter does not go to zero, ensure that
1127 ** the stale state for the node is not processed.
1128 */
1129
1130 ndlp->nlp_prev_state = ndlp->nlp_state;
1131 lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
James Smart0ff10d42008-01-11 01:52:36 -05001132 spin_lock_irq(shost->host_lock);
James Smarta8adb832007-10-27 13:37:53 -04001133 ndlp->nlp_flag |= NLP_DEFER_RM;
James Smart0ff10d42008-01-11 01:52:36 -05001134 spin_unlock_irq(shost->host_lock);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001135 return NLP_STE_FREED_NODE;
dea31012005-04-17 16:05:31 -05001136}
1137
1138static uint32_t
James Smart0ff10d42008-01-11 01:52:36 -05001139lpfc_cmpl_logo_plogi_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
1140 void *arg, uint32_t evt)
1141{
1142 return ndlp->nlp_state;
1143}
1144
1145static uint32_t
1146lpfc_cmpl_reglogin_plogi_issue(struct lpfc_vport *vport,
1147 struct lpfc_nodelist *ndlp, void *arg, uint32_t evt)
1148{
James Smart78730cf2010-04-06 15:06:30 -04001149 struct lpfc_hba *phba;
1150 LPFC_MBOXQ_t *pmb = (LPFC_MBOXQ_t *) arg;
1151 MAILBOX_t *mb = &pmb->u.mb;
1152 uint16_t rpi;
1153
1154 phba = vport->phba;
1155 /* Release the RPI */
1156 if (!(phba->pport->load_flag & FC_UNLOADING) &&
1157 !mb->mbxStatus) {
1158 rpi = pmb->u.mb.un.varWords[0];
1159 lpfc_release_rpi(phba, vport, rpi);
1160 }
James Smart0ff10d42008-01-11 01:52:36 -05001161 return ndlp->nlp_state;
1162}
1163
1164static uint32_t
James Smart2e0fef82007-06-17 19:56:36 -05001165lpfc_device_rm_plogi_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
1166 void *arg, uint32_t evt)
dea31012005-04-17 16:05:31 -05001167{
James Smart2e0fef82007-06-17 19:56:36 -05001168 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
dea31012005-04-17 16:05:31 -05001169
James Smart2e0fef82007-06-17 19:56:36 -05001170 if (ndlp->nlp_flag & NLP_NPR_2B_DISC) {
1171 spin_lock_irq(shost->host_lock);
1172 ndlp->nlp_flag |= NLP_NODEV_REMOVE;
1173 spin_unlock_irq(shost->host_lock);
1174 return ndlp->nlp_state;
1175 } else {
1176 /* software abort outstanding PLOGI */
1177 lpfc_els_abort(vport->phba, ndlp);
1178
1179 lpfc_drop_node(vport, ndlp);
James Smarta0f9b482006-04-15 11:52:56 -04001180 return NLP_STE_FREED_NODE;
1181 }
dea31012005-04-17 16:05:31 -05001182}
1183
1184static uint32_t
James Smart2e0fef82007-06-17 19:56:36 -05001185lpfc_device_recov_plogi_issue(struct lpfc_vport *vport,
1186 struct lpfc_nodelist *ndlp,
1187 void *arg,
1188 uint32_t evt)
dea31012005-04-17 16:05:31 -05001189{
James Smart2e0fef82007-06-17 19:56:36 -05001190 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
1191 struct lpfc_hba *phba = vport->phba;
1192
James Smart92d7f7b2007-06-17 19:56:38 -05001193 /* Don't do anything that will mess up processing of the
1194 * previous RSCN.
1195 */
1196 if (vport->fc_flag & FC_RSCN_DEFERRED)
1197 return ndlp->nlp_state;
1198
dea31012005-04-17 16:05:31 -05001199 /* software abort outstanding PLOGI */
James Smart07951072007-04-25 09:51:38 -04001200 lpfc_els_abort(phba, ndlp);
dea31012005-04-17 16:05:31 -05001201
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05001202 ndlp->nlp_prev_state = NLP_STE_PLOGI_ISSUE;
James Smart2e0fef82007-06-17 19:56:36 -05001203 lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
James Smart92d7f7b2007-06-17 19:56:38 -05001204 spin_lock_irq(shost->host_lock);
James Smarta0f9b482006-04-15 11:52:56 -04001205 ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC);
James Smart2e0fef82007-06-17 19:56:36 -05001206 spin_unlock_irq(shost->host_lock);
dea31012005-04-17 16:05:31 -05001207
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001208 return ndlp->nlp_state;
dea31012005-04-17 16:05:31 -05001209}
1210
1211static uint32_t
James Smart2e0fef82007-06-17 19:56:36 -05001212lpfc_rcv_plogi_adisc_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
1213 void *arg, uint32_t evt)
dea31012005-04-17 16:05:31 -05001214{
James Smart0d2b6b82008-06-14 22:52:47 -04001215 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
James Smart2e0fef82007-06-17 19:56:36 -05001216 struct lpfc_hba *phba = vport->phba;
dea31012005-04-17 16:05:31 -05001217 struct lpfc_iocbq *cmdiocb;
1218
1219 /* software abort outstanding ADISC */
James Smart07951072007-04-25 09:51:38 -04001220 lpfc_els_abort(phba, ndlp);
dea31012005-04-17 16:05:31 -05001221
1222 cmdiocb = (struct lpfc_iocbq *) arg;
1223
James Smart0d2b6b82008-06-14 22:52:47 -04001224 if (lpfc_rcv_plogi(vport, ndlp, cmdiocb)) {
1225 if (ndlp->nlp_flag & NLP_NPR_2B_DISC) {
1226 spin_lock_irq(shost->host_lock);
1227 ndlp->nlp_flag &= ~NLP_NPR_2B_DISC;
1228 spin_unlock_irq(shost->host_lock);
James Smart90160e02008-08-24 21:49:45 -04001229 if (vport->num_disc_nodes)
James Smart0d2b6b82008-06-14 22:52:47 -04001230 lpfc_more_adisc(vport);
James Smart0d2b6b82008-06-14 22:52:47 -04001231 }
1232 return ndlp->nlp_state;
1233 }
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05001234 ndlp->nlp_prev_state = NLP_STE_ADISC_ISSUE;
James Smart2e0fef82007-06-17 19:56:36 -05001235 lpfc_issue_els_plogi(vport, ndlp->nlp_DID, 0);
1236 lpfc_nlp_set_state(vport, ndlp, NLP_STE_PLOGI_ISSUE);
dea31012005-04-17 16:05:31 -05001237
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001238 return ndlp->nlp_state;
dea31012005-04-17 16:05:31 -05001239}
1240
1241static uint32_t
James Smart2e0fef82007-06-17 19:56:36 -05001242lpfc_rcv_prli_adisc_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
1243 void *arg, uint32_t evt)
dea31012005-04-17 16:05:31 -05001244{
James Smart2e0fef82007-06-17 19:56:36 -05001245 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
dea31012005-04-17 16:05:31 -05001246
James Smart2e0fef82007-06-17 19:56:36 -05001247 lpfc_els_rsp_prli_acc(vport, cmdiocb, ndlp);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001248 return ndlp->nlp_state;
dea31012005-04-17 16:05:31 -05001249}
1250
1251static uint32_t
James Smart2e0fef82007-06-17 19:56:36 -05001252lpfc_rcv_logo_adisc_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
1253 void *arg, uint32_t evt)
dea31012005-04-17 16:05:31 -05001254{
James Smart2e0fef82007-06-17 19:56:36 -05001255 struct lpfc_hba *phba = vport->phba;
dea31012005-04-17 16:05:31 -05001256 struct lpfc_iocbq *cmdiocb;
1257
1258 cmdiocb = (struct lpfc_iocbq *) arg;
1259
1260 /* software abort outstanding ADISC */
James Smart07951072007-04-25 09:51:38 -04001261 lpfc_els_abort(phba, ndlp);
dea31012005-04-17 16:05:31 -05001262
James Smart2e0fef82007-06-17 19:56:36 -05001263 lpfc_rcv_logo(vport, ndlp, cmdiocb, ELS_CMD_LOGO);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001264 return ndlp->nlp_state;
dea31012005-04-17 16:05:31 -05001265}
1266
1267static uint32_t
James Smart2e0fef82007-06-17 19:56:36 -05001268lpfc_rcv_padisc_adisc_issue(struct lpfc_vport *vport,
1269 struct lpfc_nodelist *ndlp,
1270 void *arg, uint32_t evt)
dea31012005-04-17 16:05:31 -05001271{
1272 struct lpfc_iocbq *cmdiocb;
1273
1274 cmdiocb = (struct lpfc_iocbq *) arg;
1275
James Smart2e0fef82007-06-17 19:56:36 -05001276 lpfc_rcv_padisc(vport, ndlp, cmdiocb);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001277 return ndlp->nlp_state;
dea31012005-04-17 16:05:31 -05001278}
1279
1280static uint32_t
James Smart2e0fef82007-06-17 19:56:36 -05001281lpfc_rcv_prlo_adisc_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
1282 void *arg, uint32_t evt)
dea31012005-04-17 16:05:31 -05001283{
1284 struct lpfc_iocbq *cmdiocb;
1285
1286 cmdiocb = (struct lpfc_iocbq *) arg;
1287
1288 /* Treat like rcv logo */
James Smart2e0fef82007-06-17 19:56:36 -05001289 lpfc_rcv_logo(vport, ndlp, cmdiocb, ELS_CMD_PRLO);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001290 return ndlp->nlp_state;
dea31012005-04-17 16:05:31 -05001291}
1292
1293static uint32_t
James Smart2e0fef82007-06-17 19:56:36 -05001294lpfc_cmpl_adisc_adisc_issue(struct lpfc_vport *vport,
1295 struct lpfc_nodelist *ndlp,
1296 void *arg, uint32_t evt)
dea31012005-04-17 16:05:31 -05001297{
James Smart2e0fef82007-06-17 19:56:36 -05001298 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
1299 struct lpfc_hba *phba = vport->phba;
dea31012005-04-17 16:05:31 -05001300 struct lpfc_iocbq *cmdiocb, *rspiocb;
1301 IOCB_t *irsp;
1302 ADISC *ap;
James Smart6fb120a2009-05-22 14:52:59 -04001303 int rc;
dea31012005-04-17 16:05:31 -05001304
1305 cmdiocb = (struct lpfc_iocbq *) arg;
1306 rspiocb = cmdiocb->context_un.rsp_iocb;
1307
1308 ap = (ADISC *)lpfc_check_elscmpl_iocb(phba, cmdiocb, rspiocb);
1309 irsp = &rspiocb->iocb;
1310
1311 if ((irsp->ulpStatus) ||
James Smart92d7f7b2007-06-17 19:56:38 -05001312 (!lpfc_check_adisc(vport, ndlp, &ap->nodeName, &ap->portName))) {
dea31012005-04-17 16:05:31 -05001313 /* 1 sec timeout */
James Smart256ec0d2013-04-17 20:14:58 -04001314 mod_timer(&ndlp->nlp_delayfunc,
1315 jiffies + msecs_to_jiffies(1000));
James Smart2e0fef82007-06-17 19:56:36 -05001316 spin_lock_irq(shost->host_lock);
dea31012005-04-17 16:05:31 -05001317 ndlp->nlp_flag |= NLP_DELAY_TMO;
James Smart2e0fef82007-06-17 19:56:36 -05001318 spin_unlock_irq(shost->host_lock);
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05001319 ndlp->nlp_last_elscmd = ELS_CMD_PLOGI;
dea31012005-04-17 16:05:31 -05001320
James Smart2e0fef82007-06-17 19:56:36 -05001321 memset(&ndlp->nlp_nodename, 0, sizeof(struct lpfc_name));
1322 memset(&ndlp->nlp_portname, 0, sizeof(struct lpfc_name));
dea31012005-04-17 16:05:31 -05001323
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05001324 ndlp->nlp_prev_state = NLP_STE_ADISC_ISSUE;
James Smart2e0fef82007-06-17 19:56:36 -05001325 lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
1326 lpfc_unreg_rpi(vport, ndlp);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001327 return ndlp->nlp_state;
dea31012005-04-17 16:05:31 -05001328 }
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05001329
James Smart6fb120a2009-05-22 14:52:59 -04001330 if (phba->sli_rev == LPFC_SLI_REV4) {
James Smart6b5151f2012-01-18 16:24:06 -05001331 rc = lpfc_sli4_resume_rpi(ndlp, NULL, NULL);
James Smart6fb120a2009-05-22 14:52:59 -04001332 if (rc) {
1333 /* Stay in state and retry. */
1334 ndlp->nlp_prev_state = NLP_STE_ADISC_ISSUE;
1335 return ndlp->nlp_state;
1336 }
1337 }
1338
James.Smart@Emulex.Com25013222005-06-25 10:34:33 -04001339 if (ndlp->nlp_type & NLP_FCP_TARGET) {
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05001340 ndlp->nlp_prev_state = NLP_STE_ADISC_ISSUE;
James Smart2e0fef82007-06-17 19:56:36 -05001341 lpfc_nlp_set_state(vport, ndlp, NLP_STE_MAPPED_NODE);
James.Smart@Emulex.Com25013222005-06-25 10:34:33 -04001342 } else {
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05001343 ndlp->nlp_prev_state = NLP_STE_ADISC_ISSUE;
James Smart2e0fef82007-06-17 19:56:36 -05001344 lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE);
James.Smart@Emulex.Com25013222005-06-25 10:34:33 -04001345 }
James Smart6fb120a2009-05-22 14:52:59 -04001346
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001347 return ndlp->nlp_state;
dea31012005-04-17 16:05:31 -05001348}
1349
1350static uint32_t
James Smart2e0fef82007-06-17 19:56:36 -05001351lpfc_device_rm_adisc_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
1352 void *arg, uint32_t evt)
dea31012005-04-17 16:05:31 -05001353{
James Smart2e0fef82007-06-17 19:56:36 -05001354 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
dea31012005-04-17 16:05:31 -05001355
James Smart2e0fef82007-06-17 19:56:36 -05001356 if (ndlp->nlp_flag & NLP_NPR_2B_DISC) {
1357 spin_lock_irq(shost->host_lock);
1358 ndlp->nlp_flag |= NLP_NODEV_REMOVE;
1359 spin_unlock_irq(shost->host_lock);
1360 return ndlp->nlp_state;
1361 } else {
1362 /* software abort outstanding ADISC */
1363 lpfc_els_abort(vport->phba, ndlp);
1364
1365 lpfc_drop_node(vport, ndlp);
James Smarta0f9b482006-04-15 11:52:56 -04001366 return NLP_STE_FREED_NODE;
1367 }
dea31012005-04-17 16:05:31 -05001368}
1369
1370static uint32_t
James Smart2e0fef82007-06-17 19:56:36 -05001371lpfc_device_recov_adisc_issue(struct lpfc_vport *vport,
1372 struct lpfc_nodelist *ndlp,
1373 void *arg,
1374 uint32_t evt)
dea31012005-04-17 16:05:31 -05001375{
James Smart2e0fef82007-06-17 19:56:36 -05001376 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
1377 struct lpfc_hba *phba = vport->phba;
1378
James Smart92d7f7b2007-06-17 19:56:38 -05001379 /* Don't do anything that will mess up processing of the
1380 * previous RSCN.
1381 */
1382 if (vport->fc_flag & FC_RSCN_DEFERRED)
1383 return ndlp->nlp_state;
1384
dea31012005-04-17 16:05:31 -05001385 /* software abort outstanding ADISC */
James Smart07951072007-04-25 09:51:38 -04001386 lpfc_els_abort(phba, ndlp);
dea31012005-04-17 16:05:31 -05001387
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05001388 ndlp->nlp_prev_state = NLP_STE_ADISC_ISSUE;
James Smart2e0fef82007-06-17 19:56:36 -05001389 lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
1390 spin_lock_irq(shost->host_lock);
James Smarta0f9b482006-04-15 11:52:56 -04001391 ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC);
James Smart2e0fef82007-06-17 19:56:36 -05001392 spin_unlock_irq(shost->host_lock);
James Smart92d7f7b2007-06-17 19:56:38 -05001393 lpfc_disc_set_adisc(vport, ndlp);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001394 return ndlp->nlp_state;
dea31012005-04-17 16:05:31 -05001395}
1396
1397static uint32_t
James Smart2e0fef82007-06-17 19:56:36 -05001398lpfc_rcv_plogi_reglogin_issue(struct lpfc_vport *vport,
1399 struct lpfc_nodelist *ndlp,
1400 void *arg,
dea31012005-04-17 16:05:31 -05001401 uint32_t evt)
1402{
James Smart2e0fef82007-06-17 19:56:36 -05001403 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
dea31012005-04-17 16:05:31 -05001404
James Smart2e0fef82007-06-17 19:56:36 -05001405 lpfc_rcv_plogi(vport, ndlp, cmdiocb);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001406 return ndlp->nlp_state;
dea31012005-04-17 16:05:31 -05001407}
1408
1409static uint32_t
James Smart2e0fef82007-06-17 19:56:36 -05001410lpfc_rcv_prli_reglogin_issue(struct lpfc_vport *vport,
1411 struct lpfc_nodelist *ndlp,
1412 void *arg,
dea31012005-04-17 16:05:31 -05001413 uint32_t evt)
1414{
James Smart2e0fef82007-06-17 19:56:36 -05001415 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
dea31012005-04-17 16:05:31 -05001416
James Smart2e0fef82007-06-17 19:56:36 -05001417 lpfc_els_rsp_prli_acc(vport, cmdiocb, ndlp);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001418 return ndlp->nlp_state;
dea31012005-04-17 16:05:31 -05001419}
1420
1421static uint32_t
James Smart2e0fef82007-06-17 19:56:36 -05001422lpfc_rcv_logo_reglogin_issue(struct lpfc_vport *vport,
1423 struct lpfc_nodelist *ndlp,
1424 void *arg,
dea31012005-04-17 16:05:31 -05001425 uint32_t evt)
1426{
James Smart2e0fef82007-06-17 19:56:36 -05001427 struct lpfc_hba *phba = vport->phba;
1428 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
James Smart7054a602007-04-25 09:52:34 -04001429 LPFC_MBOXQ_t *mb;
1430 LPFC_MBOXQ_t *nextmb;
1431 struct lpfc_dmabuf *mp;
dea31012005-04-17 16:05:31 -05001432
1433 cmdiocb = (struct lpfc_iocbq *) arg;
1434
James Smart7054a602007-04-25 09:52:34 -04001435 /* cleanup any ndlp on mbox q waiting for reglogin cmpl */
1436 if ((mb = phba->sli.mbox_active)) {
James Smart04c68492009-05-22 14:52:52 -04001437 if ((mb->u.mb.mbxCommand == MBX_REG_LOGIN64) &&
James Smart7054a602007-04-25 09:52:34 -04001438 (ndlp == (struct lpfc_nodelist *) mb->context2)) {
James Smart92d7f7b2007-06-17 19:56:38 -05001439 lpfc_nlp_put(ndlp);
James Smart7054a602007-04-25 09:52:34 -04001440 mb->context2 = NULL;
1441 mb->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
1442 }
1443 }
1444
James Smart2e0fef82007-06-17 19:56:36 -05001445 spin_lock_irq(&phba->hbalock);
James Smart7054a602007-04-25 09:52:34 -04001446 list_for_each_entry_safe(mb, nextmb, &phba->sli.mboxq, list) {
James Smart04c68492009-05-22 14:52:52 -04001447 if ((mb->u.mb.mbxCommand == MBX_REG_LOGIN64) &&
James Smart7054a602007-04-25 09:52:34 -04001448 (ndlp == (struct lpfc_nodelist *) mb->context2)) {
1449 mp = (struct lpfc_dmabuf *) (mb->context1);
1450 if (mp) {
James Smart98c9ea52007-10-27 13:37:33 -04001451 __lpfc_mbuf_free(phba, mp->virt, mp->phys);
James Smart7054a602007-04-25 09:52:34 -04001452 kfree(mp);
1453 }
James Smart92d7f7b2007-06-17 19:56:38 -05001454 lpfc_nlp_put(ndlp);
James Smart7054a602007-04-25 09:52:34 -04001455 list_del(&mb->list);
James Smart5ffc2662009-11-18 15:39:44 -05001456 phba->sli.mboxq_cnt--;
James Smart7054a602007-04-25 09:52:34 -04001457 mempool_free(mb, phba->mbox_mem_pool);
1458 }
1459 }
James Smart2e0fef82007-06-17 19:56:36 -05001460 spin_unlock_irq(&phba->hbalock);
James Smart7054a602007-04-25 09:52:34 -04001461
James Smart2e0fef82007-06-17 19:56:36 -05001462 lpfc_rcv_logo(vport, ndlp, cmdiocb, ELS_CMD_LOGO);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001463 return ndlp->nlp_state;
dea31012005-04-17 16:05:31 -05001464}
1465
1466static uint32_t
James Smart2e0fef82007-06-17 19:56:36 -05001467lpfc_rcv_padisc_reglogin_issue(struct lpfc_vport *vport,
1468 struct lpfc_nodelist *ndlp,
1469 void *arg,
dea31012005-04-17 16:05:31 -05001470 uint32_t evt)
1471{
James Smart2e0fef82007-06-17 19:56:36 -05001472 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
dea31012005-04-17 16:05:31 -05001473
James Smart2e0fef82007-06-17 19:56:36 -05001474 lpfc_rcv_padisc(vport, ndlp, cmdiocb);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001475 return ndlp->nlp_state;
dea31012005-04-17 16:05:31 -05001476}
1477
1478static uint32_t
James Smart2e0fef82007-06-17 19:56:36 -05001479lpfc_rcv_prlo_reglogin_issue(struct lpfc_vport *vport,
1480 struct lpfc_nodelist *ndlp,
1481 void *arg,
dea31012005-04-17 16:05:31 -05001482 uint32_t evt)
1483{
1484 struct lpfc_iocbq *cmdiocb;
1485
1486 cmdiocb = (struct lpfc_iocbq *) arg;
James Smart51ef4c22007-08-02 11:10:31 -04001487 lpfc_els_rsp_acc(vport, ELS_CMD_PRLO, cmdiocb, ndlp, NULL);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001488 return ndlp->nlp_state;
dea31012005-04-17 16:05:31 -05001489}
1490
1491static uint32_t
James Smart2e0fef82007-06-17 19:56:36 -05001492lpfc_cmpl_reglogin_reglogin_issue(struct lpfc_vport *vport,
1493 struct lpfc_nodelist *ndlp,
1494 void *arg,
1495 uint32_t evt)
dea31012005-04-17 16:05:31 -05001496{
James Smart2e0fef82007-06-17 19:56:36 -05001497 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
James Smart2e0fef82007-06-17 19:56:36 -05001498 LPFC_MBOXQ_t *pmb = (LPFC_MBOXQ_t *) arg;
James Smart04c68492009-05-22 14:52:52 -04001499 MAILBOX_t *mb = &pmb->u.mb;
James Smart2e0fef82007-06-17 19:56:36 -05001500 uint32_t did = mb->un.varWords[1];
dea31012005-04-17 16:05:31 -05001501
dea31012005-04-17 16:05:31 -05001502 if (mb->mbxStatus) {
1503 /* RegLogin failed */
James Smarte8b62012007-08-02 11:10:09 -04001504 lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY,
James Smart6d368e52011-05-24 11:44:12 -04001505 "0246 RegLogin failed Data: x%x x%x x%x x%x "
1506 "x%x\n",
1507 did, mb->mbxStatus, vport->port_state,
1508 mb->un.varRegLogin.vpi,
1509 mb->un.varRegLogin.rpi);
James Smartd0e56da2006-07-06 15:49:42 -04001510 /*
1511 * If RegLogin failed due to lack of HBA resources do not
1512 * retry discovery.
1513 */
1514 if (mb->mbxStatus == MBXERR_RPI_FULL) {
James Smart87af33f2007-10-27 13:37:43 -04001515 ndlp->nlp_prev_state = NLP_STE_REG_LOGIN_ISSUE;
1516 lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
James Smartd0e56da2006-07-06 15:49:42 -04001517 return ndlp->nlp_state;
1518 }
1519
James Smart2e0fef82007-06-17 19:56:36 -05001520 /* Put ndlp in npr state set plogi timer for 1 sec */
James Smart256ec0d2013-04-17 20:14:58 -04001521 mod_timer(&ndlp->nlp_delayfunc,
1522 jiffies + msecs_to_jiffies(1000 * 1));
James Smart2e0fef82007-06-17 19:56:36 -05001523 spin_lock_irq(shost->host_lock);
dea31012005-04-17 16:05:31 -05001524 ndlp->nlp_flag |= NLP_DELAY_TMO;
James Smart2e0fef82007-06-17 19:56:36 -05001525 spin_unlock_irq(shost->host_lock);
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05001526 ndlp->nlp_last_elscmd = ELS_CMD_PLOGI;
dea31012005-04-17 16:05:31 -05001527
James Smart2e0fef82007-06-17 19:56:36 -05001528 lpfc_issue_els_logo(vport, ndlp, 0);
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05001529 ndlp->nlp_prev_state = NLP_STE_REG_LOGIN_ISSUE;
James Smart2e0fef82007-06-17 19:56:36 -05001530 lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001531 return ndlp->nlp_state;
dea31012005-04-17 16:05:31 -05001532 }
1533
James Smart6d368e52011-05-24 11:44:12 -04001534 /* SLI4 ports have preallocated logical rpis. */
1535 if (vport->phba->sli_rev < LPFC_SLI_REV4)
1536 ndlp->nlp_rpi = mb->un.varWords[0];
1537
James Smart40426292010-12-15 17:58:10 -05001538 ndlp->nlp_flag |= NLP_RPI_REGISTERED;
dea31012005-04-17 16:05:31 -05001539
1540 /* Only if we are not a fabric nport do we issue PRLI */
1541 if (!(ndlp->nlp_type & NLP_FABRIC)) {
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05001542 ndlp->nlp_prev_state = NLP_STE_REG_LOGIN_ISSUE;
James Smart2e0fef82007-06-17 19:56:36 -05001543 lpfc_nlp_set_state(vport, ndlp, NLP_STE_PRLI_ISSUE);
1544 lpfc_issue_els_prli(vport, ndlp, 0);
dea31012005-04-17 16:05:31 -05001545 } else {
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05001546 ndlp->nlp_prev_state = NLP_STE_REG_LOGIN_ISSUE;
James Smart2e0fef82007-06-17 19:56:36 -05001547 lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE);
dea31012005-04-17 16:05:31 -05001548 }
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001549 return ndlp->nlp_state;
dea31012005-04-17 16:05:31 -05001550}
1551
1552static uint32_t
James Smart2e0fef82007-06-17 19:56:36 -05001553lpfc_device_rm_reglogin_issue(struct lpfc_vport *vport,
1554 struct lpfc_nodelist *ndlp,
1555 void *arg,
dea31012005-04-17 16:05:31 -05001556 uint32_t evt)
1557{
James Smart2e0fef82007-06-17 19:56:36 -05001558 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
1559
1560 if (ndlp->nlp_flag & NLP_NPR_2B_DISC) {
1561 spin_lock_irq(shost->host_lock);
James Smarta0f9b482006-04-15 11:52:56 -04001562 ndlp->nlp_flag |= NLP_NODEV_REMOVE;
James Smart2e0fef82007-06-17 19:56:36 -05001563 spin_unlock_irq(shost->host_lock);
James Smarta0f9b482006-04-15 11:52:56 -04001564 return ndlp->nlp_state;
James Smart2e0fef82007-06-17 19:56:36 -05001565 } else {
1566 lpfc_drop_node(vport, ndlp);
James Smarta0f9b482006-04-15 11:52:56 -04001567 return NLP_STE_FREED_NODE;
1568 }
dea31012005-04-17 16:05:31 -05001569}
1570
1571static uint32_t
James Smart2e0fef82007-06-17 19:56:36 -05001572lpfc_device_recov_reglogin_issue(struct lpfc_vport *vport,
1573 struct lpfc_nodelist *ndlp,
1574 void *arg,
1575 uint32_t evt)
dea31012005-04-17 16:05:31 -05001576{
James Smart2e0fef82007-06-17 19:56:36 -05001577 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
1578
James Smart92d7f7b2007-06-17 19:56:38 -05001579 /* Don't do anything that will mess up processing of the
1580 * previous RSCN.
1581 */
1582 if (vport->fc_flag & FC_RSCN_DEFERRED)
1583 return ndlp->nlp_state;
1584
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05001585 ndlp->nlp_prev_state = NLP_STE_REG_LOGIN_ISSUE;
James Smart2e0fef82007-06-17 19:56:36 -05001586 lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
1587 spin_lock_irq(shost->host_lock);
James Smartffc95492010-06-07 15:23:17 -04001588 ndlp->nlp_flag |= NLP_IGNR_REG_CMPL;
James Smarta0f9b482006-04-15 11:52:56 -04001589 ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC);
James Smart2e0fef82007-06-17 19:56:36 -05001590 spin_unlock_irq(shost->host_lock);
James Smart92d7f7b2007-06-17 19:56:38 -05001591 lpfc_disc_set_adisc(vport, ndlp);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001592 return ndlp->nlp_state;
dea31012005-04-17 16:05:31 -05001593}
1594
1595static uint32_t
James Smart2e0fef82007-06-17 19:56:36 -05001596lpfc_rcv_plogi_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
1597 void *arg, uint32_t evt)
dea31012005-04-17 16:05:31 -05001598{
1599 struct lpfc_iocbq *cmdiocb;
1600
1601 cmdiocb = (struct lpfc_iocbq *) arg;
1602
James Smart2e0fef82007-06-17 19:56:36 -05001603 lpfc_rcv_plogi(vport, ndlp, cmdiocb);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001604 return ndlp->nlp_state;
dea31012005-04-17 16:05:31 -05001605}
1606
1607static uint32_t
James Smart2e0fef82007-06-17 19:56:36 -05001608lpfc_rcv_prli_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
1609 void *arg, uint32_t evt)
dea31012005-04-17 16:05:31 -05001610{
James Smart2e0fef82007-06-17 19:56:36 -05001611 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
dea31012005-04-17 16:05:31 -05001612
James Smart2e0fef82007-06-17 19:56:36 -05001613 lpfc_els_rsp_prli_acc(vport, cmdiocb, ndlp);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001614 return ndlp->nlp_state;
dea31012005-04-17 16:05:31 -05001615}
1616
1617static uint32_t
James Smart2e0fef82007-06-17 19:56:36 -05001618lpfc_rcv_logo_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
1619 void *arg, uint32_t evt)
dea31012005-04-17 16:05:31 -05001620{
James Smart2e0fef82007-06-17 19:56:36 -05001621 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
dea31012005-04-17 16:05:31 -05001622
1623 /* Software abort outstanding PRLI before sending acc */
James Smart2e0fef82007-06-17 19:56:36 -05001624 lpfc_els_abort(vport->phba, ndlp);
dea31012005-04-17 16:05:31 -05001625
James Smart2e0fef82007-06-17 19:56:36 -05001626 lpfc_rcv_logo(vport, ndlp, cmdiocb, ELS_CMD_LOGO);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001627 return ndlp->nlp_state;
dea31012005-04-17 16:05:31 -05001628}
1629
1630static uint32_t
James Smart2e0fef82007-06-17 19:56:36 -05001631lpfc_rcv_padisc_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
1632 void *arg, uint32_t evt)
dea31012005-04-17 16:05:31 -05001633{
James Smart2e0fef82007-06-17 19:56:36 -05001634 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
dea31012005-04-17 16:05:31 -05001635
James Smart2e0fef82007-06-17 19:56:36 -05001636 lpfc_rcv_padisc(vport, ndlp, cmdiocb);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001637 return ndlp->nlp_state;
dea31012005-04-17 16:05:31 -05001638}
1639
1640/* This routine is envoked when we rcv a PRLO request from a nport
1641 * we are logged into. We should send back a PRLO rsp setting the
1642 * appropriate bits.
1643 * NEXT STATE = PRLI_ISSUE
1644 */
1645static uint32_t
James Smart2e0fef82007-06-17 19:56:36 -05001646lpfc_rcv_prlo_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
1647 void *arg, uint32_t evt)
dea31012005-04-17 16:05:31 -05001648{
James Smart2e0fef82007-06-17 19:56:36 -05001649 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
dea31012005-04-17 16:05:31 -05001650
James Smart51ef4c22007-08-02 11:10:31 -04001651 lpfc_els_rsp_acc(vport, ELS_CMD_PRLO, cmdiocb, ndlp, NULL);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001652 return ndlp->nlp_state;
dea31012005-04-17 16:05:31 -05001653}
1654
1655static uint32_t
James Smart2e0fef82007-06-17 19:56:36 -05001656lpfc_cmpl_prli_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
1657 void *arg, uint32_t evt)
dea31012005-04-17 16:05:31 -05001658{
James Smart92d7f7b2007-06-17 19:56:38 -05001659 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
dea31012005-04-17 16:05:31 -05001660 struct lpfc_iocbq *cmdiocb, *rspiocb;
James Smart2e0fef82007-06-17 19:56:36 -05001661 struct lpfc_hba *phba = vport->phba;
dea31012005-04-17 16:05:31 -05001662 IOCB_t *irsp;
1663 PRLI *npr;
1664
1665 cmdiocb = (struct lpfc_iocbq *) arg;
1666 rspiocb = cmdiocb->context_un.rsp_iocb;
1667 npr = (PRLI *)lpfc_check_elscmpl_iocb(phba, cmdiocb, rspiocb);
1668
1669 irsp = &rspiocb->iocb;
1670 if (irsp->ulpStatus) {
James Smart858c9f62007-06-17 19:56:39 -05001671 if ((vport->port_type == LPFC_NPIV_PORT) &&
James Smart3de2a652007-08-02 11:09:59 -04001672 vport->cfg_restrict_login) {
James Smart858c9f62007-06-17 19:56:39 -05001673 goto out;
1674 }
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05001675 ndlp->nlp_prev_state = NLP_STE_PRLI_ISSUE;
James Smart2e0fef82007-06-17 19:56:36 -05001676 lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001677 return ndlp->nlp_state;
dea31012005-04-17 16:05:31 -05001678 }
1679
1680 /* Check out PRLI rsp */
1681 ndlp->nlp_type &= ~(NLP_FCP_TARGET | NLP_FCP_INITIATOR);
1682 ndlp->nlp_fcp_info &= ~NLP_FCP_2_DEVICE;
James Smart3cb01c52013-07-15 18:35:04 -04001683 ndlp->nlp_flag &= ~NLP_FIRSTBURST;
dea31012005-04-17 16:05:31 -05001684 if ((npr->acceptRspCode == PRLI_REQ_EXECUTED) &&
1685 (npr->prliType == PRLI_FCP_TYPE)) {
1686 if (npr->initiatorFunc)
1687 ndlp->nlp_type |= NLP_FCP_INITIATOR;
James Smart3cb01c52013-07-15 18:35:04 -04001688 if (npr->targetFunc) {
dea31012005-04-17 16:05:31 -05001689 ndlp->nlp_type |= NLP_FCP_TARGET;
James Smart3cb01c52013-07-15 18:35:04 -04001690 if (npr->writeXferRdyDis)
1691 ndlp->nlp_flag |= NLP_FIRSTBURST;
1692 }
dea31012005-04-17 16:05:31 -05001693 if (npr->Retry)
1694 ndlp->nlp_fcp_info |= NLP_FCP_2_DEVICE;
1695 }
James Smart92d7f7b2007-06-17 19:56:38 -05001696 if (!(ndlp->nlp_type & NLP_FCP_TARGET) &&
1697 (vport->port_type == LPFC_NPIV_PORT) &&
James Smart3de2a652007-08-02 11:09:59 -04001698 vport->cfg_restrict_login) {
James Smart858c9f62007-06-17 19:56:39 -05001699out:
James Smart92d7f7b2007-06-17 19:56:38 -05001700 spin_lock_irq(shost->host_lock);
1701 ndlp->nlp_flag |= NLP_TARGET_REMOVE;
1702 spin_unlock_irq(shost->host_lock);
1703 lpfc_issue_els_logo(vport, ndlp, 0);
1704
1705 ndlp->nlp_prev_state = NLP_STE_PRLI_ISSUE;
James Smart87af33f2007-10-27 13:37:43 -04001706 lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
James Smart92d7f7b2007-06-17 19:56:38 -05001707 return ndlp->nlp_state;
1708 }
dea31012005-04-17 16:05:31 -05001709
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05001710 ndlp->nlp_prev_state = NLP_STE_PRLI_ISSUE;
James Smart92d7f7b2007-06-17 19:56:38 -05001711 if (ndlp->nlp_type & NLP_FCP_TARGET)
1712 lpfc_nlp_set_state(vport, ndlp, NLP_STE_MAPPED_NODE);
1713 else
1714 lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001715 return ndlp->nlp_state;
dea31012005-04-17 16:05:31 -05001716}
1717
1718/*! lpfc_device_rm_prli_issue
James Smart92d7f7b2007-06-17 19:56:38 -05001719 *
1720 * \pre
1721 * \post
1722 * \param phba
1723 * \param ndlp
1724 * \param arg
1725 * \param evt
1726 * \return uint32_t
1727 *
1728 * \b Description:
1729 * This routine is envoked when we a request to remove a nport we are in the
1730 * process of PRLIing. We should software abort outstanding prli, unreg
1731 * login, send a logout. We will change node state to UNUSED_NODE, put it
1732 * on plogi list so it can be freed when LOGO completes.
1733 *
1734 */
1735
dea31012005-04-17 16:05:31 -05001736static uint32_t
James Smart2e0fef82007-06-17 19:56:36 -05001737lpfc_device_rm_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
1738 void *arg, uint32_t evt)
dea31012005-04-17 16:05:31 -05001739{
James Smart2e0fef82007-06-17 19:56:36 -05001740 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
dea31012005-04-17 16:05:31 -05001741
James Smart2e0fef82007-06-17 19:56:36 -05001742 if (ndlp->nlp_flag & NLP_NPR_2B_DISC) {
1743 spin_lock_irq(shost->host_lock);
1744 ndlp->nlp_flag |= NLP_NODEV_REMOVE;
1745 spin_unlock_irq(shost->host_lock);
1746 return ndlp->nlp_state;
1747 } else {
1748 /* software abort outstanding PLOGI */
1749 lpfc_els_abort(vport->phba, ndlp);
1750
1751 lpfc_drop_node(vport, ndlp);
James Smarta0f9b482006-04-15 11:52:56 -04001752 return NLP_STE_FREED_NODE;
1753 }
dea31012005-04-17 16:05:31 -05001754}
1755
1756
1757/*! lpfc_device_recov_prli_issue
James Smart92d7f7b2007-06-17 19:56:38 -05001758 *
1759 * \pre
1760 * \post
1761 * \param phba
1762 * \param ndlp
1763 * \param arg
1764 * \param evt
1765 * \return uint32_t
1766 *
1767 * \b Description:
1768 * The routine is envoked when the state of a device is unknown, like
1769 * during a link down. We should remove the nodelist entry from the
1770 * unmapped list, issue a UNREG_LOGIN, do a software abort of the
1771 * outstanding PRLI command, then free the node entry.
1772 */
dea31012005-04-17 16:05:31 -05001773static uint32_t
James Smart2e0fef82007-06-17 19:56:36 -05001774lpfc_device_recov_prli_issue(struct lpfc_vport *vport,
1775 struct lpfc_nodelist *ndlp,
1776 void *arg,
1777 uint32_t evt)
dea31012005-04-17 16:05:31 -05001778{
James Smart2e0fef82007-06-17 19:56:36 -05001779 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
1780 struct lpfc_hba *phba = vport->phba;
1781
James Smart92d7f7b2007-06-17 19:56:38 -05001782 /* Don't do anything that will mess up processing of the
1783 * previous RSCN.
1784 */
1785 if (vport->fc_flag & FC_RSCN_DEFERRED)
1786 return ndlp->nlp_state;
1787
dea31012005-04-17 16:05:31 -05001788 /* software abort outstanding PRLI */
James Smart07951072007-04-25 09:51:38 -04001789 lpfc_els_abort(phba, ndlp);
dea31012005-04-17 16:05:31 -05001790
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05001791 ndlp->nlp_prev_state = NLP_STE_PRLI_ISSUE;
James Smart2e0fef82007-06-17 19:56:36 -05001792 lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
1793 spin_lock_irq(shost->host_lock);
James Smarta0f9b482006-04-15 11:52:56 -04001794 ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC);
James Smart2e0fef82007-06-17 19:56:36 -05001795 spin_unlock_irq(shost->host_lock);
James Smart92d7f7b2007-06-17 19:56:38 -05001796 lpfc_disc_set_adisc(vport, ndlp);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001797 return ndlp->nlp_state;
dea31012005-04-17 16:05:31 -05001798}
1799
1800static uint32_t
James Smart086a3452012-08-14 14:25:21 -04001801lpfc_rcv_plogi_logo_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
1802 void *arg, uint32_t evt)
1803{
1804 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *)arg;
1805 struct ls_rjt stat;
1806
1807 memset(&stat, 0, sizeof(struct ls_rjt));
1808 stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
1809 stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE;
1810 lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, NULL);
1811 return ndlp->nlp_state;
1812}
1813
1814static uint32_t
1815lpfc_rcv_prli_logo_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
1816 void *arg, uint32_t evt)
1817{
1818 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *)arg;
1819 struct ls_rjt stat;
1820
1821 memset(&stat, 0, sizeof(struct ls_rjt));
1822 stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
1823 stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE;
1824 lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, NULL);
1825 return ndlp->nlp_state;
1826}
1827
1828static uint32_t
1829lpfc_rcv_logo_logo_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
1830 void *arg, uint32_t evt)
1831{
1832 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
1833 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *)arg;
1834
1835 spin_lock_irq(shost->host_lock);
1836 ndlp->nlp_flag &= NLP_LOGO_ACC;
1837 spin_unlock_irq(shost->host_lock);
1838 lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL);
1839 return ndlp->nlp_state;
1840}
1841
1842static uint32_t
1843lpfc_rcv_padisc_logo_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
1844 void *arg, uint32_t evt)
1845{
1846 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *)arg;
1847 struct ls_rjt stat;
1848
1849 memset(&stat, 0, sizeof(struct ls_rjt));
1850 stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
1851 stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE;
1852 lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, NULL);
1853 return ndlp->nlp_state;
1854}
1855
1856static uint32_t
1857lpfc_rcv_prlo_logo_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
1858 void *arg, uint32_t evt)
1859{
1860 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *)arg;
1861 struct ls_rjt stat;
1862
1863 memset(&stat, 0, sizeof(struct ls_rjt));
1864 stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
1865 stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE;
1866 lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, NULL);
1867 return ndlp->nlp_state;
1868}
1869
1870static uint32_t
1871lpfc_cmpl_logo_logo_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
1872 void *arg, uint32_t evt)
1873{
1874 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
1875
1876 ndlp->nlp_prev_state = NLP_STE_LOGO_ISSUE;
1877 lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
1878 spin_lock_irq(shost->host_lock);
1879 ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC);
1880 spin_unlock_irq(shost->host_lock);
1881 lpfc_disc_set_adisc(vport, ndlp);
1882 return ndlp->nlp_state;
1883}
1884
1885static uint32_t
1886lpfc_device_rm_logo_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
1887 void *arg, uint32_t evt)
1888{
1889 /*
1890 * Take no action. If a LOGO is outstanding, then possibly DevLoss has
1891 * timed out and is calling for Device Remove. In this case, the LOGO
1892 * must be allowed to complete in state LOGO_ISSUE so that the rpi
1893 * and other NLP flags are correctly cleaned up.
1894 */
1895 return ndlp->nlp_state;
1896}
1897
1898static uint32_t
1899lpfc_device_recov_logo_issue(struct lpfc_vport *vport,
1900 struct lpfc_nodelist *ndlp,
1901 void *arg, uint32_t evt)
1902{
1903 /*
1904 * Device Recovery events have no meaning for a node with a LOGO
1905 * outstanding. The LOGO has to complete first and handle the
1906 * node from that point.
1907 */
1908 return ndlp->nlp_state;
1909}
1910
1911static uint32_t
James Smart2e0fef82007-06-17 19:56:36 -05001912lpfc_rcv_plogi_unmap_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
1913 void *arg, uint32_t evt)
dea31012005-04-17 16:05:31 -05001914{
James Smart2e0fef82007-06-17 19:56:36 -05001915 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
dea31012005-04-17 16:05:31 -05001916
James Smart2e0fef82007-06-17 19:56:36 -05001917 lpfc_rcv_plogi(vport, ndlp, cmdiocb);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001918 return ndlp->nlp_state;
dea31012005-04-17 16:05:31 -05001919}
1920
1921static uint32_t
James Smart2e0fef82007-06-17 19:56:36 -05001922lpfc_rcv_prli_unmap_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
1923 void *arg, uint32_t evt)
dea31012005-04-17 16:05:31 -05001924{
James Smart2e0fef82007-06-17 19:56:36 -05001925 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
dea31012005-04-17 16:05:31 -05001926
James Smart2e0fef82007-06-17 19:56:36 -05001927 lpfc_rcv_prli(vport, ndlp, cmdiocb);
1928 lpfc_els_rsp_prli_acc(vport, cmdiocb, ndlp);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001929 return ndlp->nlp_state;
dea31012005-04-17 16:05:31 -05001930}
1931
1932static uint32_t
James Smart2e0fef82007-06-17 19:56:36 -05001933lpfc_rcv_logo_unmap_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
1934 void *arg, uint32_t evt)
dea31012005-04-17 16:05:31 -05001935{
James Smart2e0fef82007-06-17 19:56:36 -05001936 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
dea31012005-04-17 16:05:31 -05001937
James Smart2e0fef82007-06-17 19:56:36 -05001938 lpfc_rcv_logo(vport, ndlp, cmdiocb, ELS_CMD_LOGO);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001939 return ndlp->nlp_state;
dea31012005-04-17 16:05:31 -05001940}
1941
1942static uint32_t
James Smart2e0fef82007-06-17 19:56:36 -05001943lpfc_rcv_padisc_unmap_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
1944 void *arg, uint32_t evt)
dea31012005-04-17 16:05:31 -05001945{
James Smart2e0fef82007-06-17 19:56:36 -05001946 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
dea31012005-04-17 16:05:31 -05001947
James Smart2e0fef82007-06-17 19:56:36 -05001948 lpfc_rcv_padisc(vport, ndlp, cmdiocb);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001949 return ndlp->nlp_state;
dea31012005-04-17 16:05:31 -05001950}
1951
1952static uint32_t
James Smart2e0fef82007-06-17 19:56:36 -05001953lpfc_rcv_prlo_unmap_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
1954 void *arg, uint32_t evt)
dea31012005-04-17 16:05:31 -05001955{
James Smart2e0fef82007-06-17 19:56:36 -05001956 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
dea31012005-04-17 16:05:31 -05001957
James Smart51ef4c22007-08-02 11:10:31 -04001958 lpfc_els_rsp_acc(vport, ELS_CMD_PRLO, cmdiocb, ndlp, NULL);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001959 return ndlp->nlp_state;
dea31012005-04-17 16:05:31 -05001960}
1961
1962static uint32_t
James Smart2e0fef82007-06-17 19:56:36 -05001963lpfc_device_recov_unmap_node(struct lpfc_vport *vport,
1964 struct lpfc_nodelist *ndlp,
1965 void *arg,
1966 uint32_t evt)
dea31012005-04-17 16:05:31 -05001967{
James Smart2e0fef82007-06-17 19:56:36 -05001968 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
1969
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05001970 ndlp->nlp_prev_state = NLP_STE_UNMAPPED_NODE;
James Smart2e0fef82007-06-17 19:56:36 -05001971 lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
1972 spin_lock_irq(shost->host_lock);
James Smarta0f9b482006-04-15 11:52:56 -04001973 ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC);
James Smart2e0fef82007-06-17 19:56:36 -05001974 spin_unlock_irq(shost->host_lock);
1975 lpfc_disc_set_adisc(vport, ndlp);
dea31012005-04-17 16:05:31 -05001976
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001977 return ndlp->nlp_state;
dea31012005-04-17 16:05:31 -05001978}
1979
1980static uint32_t
James Smart2e0fef82007-06-17 19:56:36 -05001981lpfc_rcv_plogi_mapped_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
1982 void *arg, uint32_t evt)
dea31012005-04-17 16:05:31 -05001983{
James Smart2e0fef82007-06-17 19:56:36 -05001984 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
dea31012005-04-17 16:05:31 -05001985
James Smart2e0fef82007-06-17 19:56:36 -05001986 lpfc_rcv_plogi(vport, ndlp, cmdiocb);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001987 return ndlp->nlp_state;
dea31012005-04-17 16:05:31 -05001988}
1989
1990static uint32_t
James Smart2e0fef82007-06-17 19:56:36 -05001991lpfc_rcv_prli_mapped_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
1992 void *arg, uint32_t evt)
dea31012005-04-17 16:05:31 -05001993{
James Smart2e0fef82007-06-17 19:56:36 -05001994 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
dea31012005-04-17 16:05:31 -05001995
James Smart2e0fef82007-06-17 19:56:36 -05001996 lpfc_els_rsp_prli_acc(vport, cmdiocb, ndlp);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001997 return ndlp->nlp_state;
dea31012005-04-17 16:05:31 -05001998}
1999
2000static uint32_t
James Smart2e0fef82007-06-17 19:56:36 -05002001lpfc_rcv_logo_mapped_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
2002 void *arg, uint32_t evt)
dea31012005-04-17 16:05:31 -05002003{
James Smart2e0fef82007-06-17 19:56:36 -05002004 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
dea31012005-04-17 16:05:31 -05002005
James Smart2e0fef82007-06-17 19:56:36 -05002006 lpfc_rcv_logo(vport, ndlp, cmdiocb, ELS_CMD_LOGO);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002007 return ndlp->nlp_state;
dea31012005-04-17 16:05:31 -05002008}
2009
2010static uint32_t
James Smart2e0fef82007-06-17 19:56:36 -05002011lpfc_rcv_padisc_mapped_node(struct lpfc_vport *vport,
2012 struct lpfc_nodelist *ndlp,
2013 void *arg, uint32_t evt)
dea31012005-04-17 16:05:31 -05002014{
James Smart2e0fef82007-06-17 19:56:36 -05002015 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
dea31012005-04-17 16:05:31 -05002016
James Smart2e0fef82007-06-17 19:56:36 -05002017 lpfc_rcv_padisc(vport, ndlp, cmdiocb);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002018 return ndlp->nlp_state;
dea31012005-04-17 16:05:31 -05002019}
2020
2021static uint32_t
James Smart2e0fef82007-06-17 19:56:36 -05002022lpfc_rcv_prlo_mapped_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
2023 void *arg, uint32_t evt)
dea31012005-04-17 16:05:31 -05002024{
James Smart2e0fef82007-06-17 19:56:36 -05002025 struct lpfc_hba *phba = vport->phba;
2026 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
dea31012005-04-17 16:05:31 -05002027
2028 /* flush the target */
James Smart51ef4c22007-08-02 11:10:31 -04002029 lpfc_sli_abort_iocb(vport, &phba->sli.ring[phba->sli.fcp_ring],
2030 ndlp->nlp_sid, 0, LPFC_CTX_TGT);
dea31012005-04-17 16:05:31 -05002031
2032 /* Treat like rcv logo */
James Smart2e0fef82007-06-17 19:56:36 -05002033 lpfc_rcv_logo(vport, ndlp, cmdiocb, ELS_CMD_PRLO);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002034 return ndlp->nlp_state;
dea31012005-04-17 16:05:31 -05002035}
2036
2037static uint32_t
James Smart2e0fef82007-06-17 19:56:36 -05002038lpfc_device_recov_mapped_node(struct lpfc_vport *vport,
2039 struct lpfc_nodelist *ndlp,
2040 void *arg,
2041 uint32_t evt)
dea31012005-04-17 16:05:31 -05002042{
James Smart2e0fef82007-06-17 19:56:36 -05002043 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
2044
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05002045 ndlp->nlp_prev_state = NLP_STE_MAPPED_NODE;
James Smart2e0fef82007-06-17 19:56:36 -05002046 lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
2047 spin_lock_irq(shost->host_lock);
James Smarta0f9b482006-04-15 11:52:56 -04002048 ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC);
James Smart2e0fef82007-06-17 19:56:36 -05002049 spin_unlock_irq(shost->host_lock);
2050 lpfc_disc_set_adisc(vport, ndlp);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002051 return ndlp->nlp_state;
dea31012005-04-17 16:05:31 -05002052}
2053
2054static uint32_t
James Smart2e0fef82007-06-17 19:56:36 -05002055lpfc_rcv_plogi_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
2056 void *arg, uint32_t evt)
dea31012005-04-17 16:05:31 -05002057{
James Smart2e0fef82007-06-17 19:56:36 -05002058 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
2059 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
dea31012005-04-17 16:05:31 -05002060
2061 /* Ignore PLOGI if we have an outstanding LOGO */
James Smart0d2b6b82008-06-14 22:52:47 -04002062 if (ndlp->nlp_flag & (NLP_LOGO_SND | NLP_LOGO_ACC))
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002063 return ndlp->nlp_state;
James Smart2e0fef82007-06-17 19:56:36 -05002064 if (lpfc_rcv_plogi(vport, ndlp, cmdiocb)) {
James Smart0d2b6b82008-06-14 22:52:47 -04002065 lpfc_cancel_retry_delay_tmo(vport, ndlp);
James Smart2e0fef82007-06-17 19:56:36 -05002066 spin_lock_irq(shost->host_lock);
James Smart0d2b6b82008-06-14 22:52:47 -04002067 ndlp->nlp_flag &= ~(NLP_NPR_ADISC | NLP_NPR_2B_DISC);
James Smart2e0fef82007-06-17 19:56:36 -05002068 spin_unlock_irq(shost->host_lock);
James Smart0d2b6b82008-06-14 22:52:47 -04002069 } else if (!(ndlp->nlp_flag & NLP_NPR_2B_DISC)) {
2070 /* send PLOGI immediately, move to PLOGI issue state */
2071 if (!(ndlp->nlp_flag & NLP_DELAY_TMO)) {
2072 ndlp->nlp_prev_state = NLP_STE_NPR_NODE;
2073 lpfc_nlp_set_state(vport, ndlp, NLP_STE_PLOGI_ISSUE);
2074 lpfc_issue_els_plogi(vport, ndlp->nlp_DID, 0);
2075 }
dea31012005-04-17 16:05:31 -05002076 }
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002077 return ndlp->nlp_state;
dea31012005-04-17 16:05:31 -05002078}
2079
2080static uint32_t
James Smart2e0fef82007-06-17 19:56:36 -05002081lpfc_rcv_prli_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
2082 void *arg, uint32_t evt)
dea31012005-04-17 16:05:31 -05002083{
James Smart2e0fef82007-06-17 19:56:36 -05002084 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
2085 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
2086 struct ls_rjt stat;
dea31012005-04-17 16:05:31 -05002087
2088 memset(&stat, 0, sizeof (struct ls_rjt));
2089 stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
2090 stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE;
James Smart858c9f62007-06-17 19:56:39 -05002091 lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, NULL);
dea31012005-04-17 16:05:31 -05002092
2093 if (!(ndlp->nlp_flag & NLP_DELAY_TMO)) {
2094 if (ndlp->nlp_flag & NLP_NPR_ADISC) {
James Smart2e0fef82007-06-17 19:56:36 -05002095 spin_lock_irq(shost->host_lock);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002096 ndlp->nlp_flag &= ~NLP_NPR_ADISC;
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05002097 ndlp->nlp_prev_state = NLP_STE_NPR_NODE;
James Smart2e0fef82007-06-17 19:56:36 -05002098 spin_unlock_irq(shost->host_lock);
2099 lpfc_nlp_set_state(vport, ndlp, NLP_STE_ADISC_ISSUE);
2100 lpfc_issue_els_adisc(vport, ndlp, 0);
dea31012005-04-17 16:05:31 -05002101 } else {
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05002102 ndlp->nlp_prev_state = NLP_STE_NPR_NODE;
James Smart2e0fef82007-06-17 19:56:36 -05002103 lpfc_nlp_set_state(vport, ndlp, NLP_STE_PLOGI_ISSUE);
2104 lpfc_issue_els_plogi(vport, ndlp->nlp_DID, 0);
dea31012005-04-17 16:05:31 -05002105 }
2106 }
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002107 return ndlp->nlp_state;
dea31012005-04-17 16:05:31 -05002108}
2109
2110static uint32_t
James Smart2e0fef82007-06-17 19:56:36 -05002111lpfc_rcv_logo_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
2112 void *arg, uint32_t evt)
dea31012005-04-17 16:05:31 -05002113{
James Smart2e0fef82007-06-17 19:56:36 -05002114 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
dea31012005-04-17 16:05:31 -05002115
James Smart2e0fef82007-06-17 19:56:36 -05002116 lpfc_rcv_logo(vport, ndlp, cmdiocb, ELS_CMD_LOGO);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002117 return ndlp->nlp_state;
dea31012005-04-17 16:05:31 -05002118}
2119
2120static uint32_t
James Smart2e0fef82007-06-17 19:56:36 -05002121lpfc_rcv_padisc_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
2122 void *arg, uint32_t evt)
dea31012005-04-17 16:05:31 -05002123{
James Smart2e0fef82007-06-17 19:56:36 -05002124 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
dea31012005-04-17 16:05:31 -05002125
James Smart2e0fef82007-06-17 19:56:36 -05002126 lpfc_rcv_padisc(vport, ndlp, cmdiocb);
James Smart33ccf8d2006-08-17 11:57:58 -04002127 /*
2128 * Do not start discovery if discovery is about to start
2129 * or discovery in progress for this node. Starting discovery
2130 * here will affect the counting of discovery threads.
2131 */
James Smart2fb9bd82006-12-02 13:33:57 -05002132 if (!(ndlp->nlp_flag & NLP_DELAY_TMO) &&
James Smart92d7f7b2007-06-17 19:56:38 -05002133 !(ndlp->nlp_flag & NLP_NPR_2B_DISC)) {
dea31012005-04-17 16:05:31 -05002134 if (ndlp->nlp_flag & NLP_NPR_ADISC) {
James Smart92d7f7b2007-06-17 19:56:38 -05002135 ndlp->nlp_flag &= ~NLP_NPR_ADISC;
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05002136 ndlp->nlp_prev_state = NLP_STE_NPR_NODE;
James Smart2e0fef82007-06-17 19:56:36 -05002137 lpfc_nlp_set_state(vport, ndlp, NLP_STE_ADISC_ISSUE);
2138 lpfc_issue_els_adisc(vport, ndlp, 0);
dea31012005-04-17 16:05:31 -05002139 } else {
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05002140 ndlp->nlp_prev_state = NLP_STE_NPR_NODE;
James Smart2e0fef82007-06-17 19:56:36 -05002141 lpfc_nlp_set_state(vport, ndlp, NLP_STE_PLOGI_ISSUE);
2142 lpfc_issue_els_plogi(vport, ndlp->nlp_DID, 0);
dea31012005-04-17 16:05:31 -05002143 }
2144 }
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002145 return ndlp->nlp_state;
dea31012005-04-17 16:05:31 -05002146}
2147
2148static uint32_t
James Smart2e0fef82007-06-17 19:56:36 -05002149lpfc_rcv_prlo_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
2150 void *arg, uint32_t evt)
dea31012005-04-17 16:05:31 -05002151{
James Smart2e0fef82007-06-17 19:56:36 -05002152 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
2153 struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
dea31012005-04-17 16:05:31 -05002154
James Smart2e0fef82007-06-17 19:56:36 -05002155 spin_lock_irq(shost->host_lock);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002156 ndlp->nlp_flag |= NLP_LOGO_ACC;
James Smart2e0fef82007-06-17 19:56:36 -05002157 spin_unlock_irq(shost->host_lock);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002158
James Smart51ef4c22007-08-02 11:10:31 -04002159 lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL);
dea31012005-04-17 16:05:31 -05002160
James Smart2e0fef82007-06-17 19:56:36 -05002161 if ((ndlp->nlp_flag & NLP_DELAY_TMO) == 0) {
James Smart256ec0d2013-04-17 20:14:58 -04002162 mod_timer(&ndlp->nlp_delayfunc,
2163 jiffies + msecs_to_jiffies(1000 * 1));
James Smart2e0fef82007-06-17 19:56:36 -05002164 spin_lock_irq(shost->host_lock);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002165 ndlp->nlp_flag |= NLP_DELAY_TMO;
2166 ndlp->nlp_flag &= ~NLP_NPR_ADISC;
James Smart2e0fef82007-06-17 19:56:36 -05002167 spin_unlock_irq(shost->host_lock);
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05002168 ndlp->nlp_last_elscmd = ELS_CMD_PLOGI;
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002169 } else {
James Smart2e0fef82007-06-17 19:56:36 -05002170 spin_lock_irq(shost->host_lock);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002171 ndlp->nlp_flag &= ~NLP_NPR_ADISC;
James Smart2e0fef82007-06-17 19:56:36 -05002172 spin_unlock_irq(shost->host_lock);
dea31012005-04-17 16:05:31 -05002173 }
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002174 return ndlp->nlp_state;
2175}
dea31012005-04-17 16:05:31 -05002176
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002177static uint32_t
James Smart2e0fef82007-06-17 19:56:36 -05002178lpfc_cmpl_plogi_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
2179 void *arg, uint32_t evt)
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002180{
2181 struct lpfc_iocbq *cmdiocb, *rspiocb;
James Smarta0f9b482006-04-15 11:52:56 -04002182 IOCB_t *irsp;
James Smart8b455cf2013-01-03 15:43:53 -05002183 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002184
2185 cmdiocb = (struct lpfc_iocbq *) arg;
2186 rspiocb = cmdiocb->context_un.rsp_iocb;
James Smarta0f9b482006-04-15 11:52:56 -04002187
2188 irsp = &rspiocb->iocb;
2189 if (irsp->ulpStatus) {
James Smart8b455cf2013-01-03 15:43:53 -05002190 spin_lock_irq(shost->host_lock);
James Smarta8adb832007-10-27 13:37:53 -04002191 ndlp->nlp_flag |= NLP_DEFER_RM;
James Smart8b455cf2013-01-03 15:43:53 -05002192 spin_unlock_irq(shost->host_lock);
James Smarta0f9b482006-04-15 11:52:56 -04002193 return NLP_STE_FREED_NODE;
2194 }
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002195 return ndlp->nlp_state;
2196}
2197
2198static uint32_t
James Smart2e0fef82007-06-17 19:56:36 -05002199lpfc_cmpl_prli_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
2200 void *arg, uint32_t evt)
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002201{
2202 struct lpfc_iocbq *cmdiocb, *rspiocb;
James Smarta0f9b482006-04-15 11:52:56 -04002203 IOCB_t *irsp;
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002204
2205 cmdiocb = (struct lpfc_iocbq *) arg;
2206 rspiocb = cmdiocb->context_un.rsp_iocb;
James Smarta0f9b482006-04-15 11:52:56 -04002207
2208 irsp = &rspiocb->iocb;
2209 if (irsp->ulpStatus && (ndlp->nlp_flag & NLP_NODEV_REMOVE)) {
James Smart2e0fef82007-06-17 19:56:36 -05002210 lpfc_drop_node(vport, ndlp);
James Smarta0f9b482006-04-15 11:52:56 -04002211 return NLP_STE_FREED_NODE;
2212 }
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002213 return ndlp->nlp_state;
dea31012005-04-17 16:05:31 -05002214}
2215
2216static uint32_t
James Smart2e0fef82007-06-17 19:56:36 -05002217lpfc_cmpl_logo_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
2218 void *arg, uint32_t evt)
dea31012005-04-17 16:05:31 -05002219{
James Smartd7c255b2008-08-24 21:50:00 -04002220 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
James Smart086a3452012-08-14 14:25:21 -04002221
2222 /* For the fabric port just clear the fc flags. */
James Smartd7c255b2008-08-24 21:50:00 -04002223 if (ndlp->nlp_DID == Fabric_DID) {
2224 spin_lock_irq(shost->host_lock);
2225 vport->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP);
2226 spin_unlock_irq(shost->host_lock);
2227 }
James Smart2e0fef82007-06-17 19:56:36 -05002228 lpfc_unreg_rpi(vport, ndlp);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002229 return ndlp->nlp_state;
2230}
2231
2232static uint32_t
James Smart2e0fef82007-06-17 19:56:36 -05002233lpfc_cmpl_adisc_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
2234 void *arg, uint32_t evt)
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002235{
2236 struct lpfc_iocbq *cmdiocb, *rspiocb;
James Smarta0f9b482006-04-15 11:52:56 -04002237 IOCB_t *irsp;
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002238
2239 cmdiocb = (struct lpfc_iocbq *) arg;
2240 rspiocb = cmdiocb->context_un.rsp_iocb;
James Smarta0f9b482006-04-15 11:52:56 -04002241
2242 irsp = &rspiocb->iocb;
2243 if (irsp->ulpStatus && (ndlp->nlp_flag & NLP_NODEV_REMOVE)) {
James Smart2e0fef82007-06-17 19:56:36 -05002244 lpfc_drop_node(vport, ndlp);
James Smarta0f9b482006-04-15 11:52:56 -04002245 return NLP_STE_FREED_NODE;
2246 }
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002247 return ndlp->nlp_state;
dea31012005-04-17 16:05:31 -05002248}
2249
2250static uint32_t
James Smart2e0fef82007-06-17 19:56:36 -05002251lpfc_cmpl_reglogin_npr_node(struct lpfc_vport *vport,
2252 struct lpfc_nodelist *ndlp,
2253 void *arg, uint32_t evt)
dea31012005-04-17 16:05:31 -05002254{
James Smart2e0fef82007-06-17 19:56:36 -05002255 LPFC_MBOXQ_t *pmb = (LPFC_MBOXQ_t *) arg;
James Smart04c68492009-05-22 14:52:52 -04002256 MAILBOX_t *mb = &pmb->u.mb;
dea31012005-04-17 16:05:31 -05002257
James Smart04c68492009-05-22 14:52:52 -04002258 if (!mb->mbxStatus) {
James Smart6d368e52011-05-24 11:44:12 -04002259 /* SLI4 ports have preallocated logical rpis. */
2260 if (vport->phba->sli_rev < LPFC_SLI_REV4)
2261 ndlp->nlp_rpi = mb->un.varWords[0];
James Smart40426292010-12-15 17:58:10 -05002262 ndlp->nlp_flag |= NLP_RPI_REGISTERED;
James Smart04c68492009-05-22 14:52:52 -04002263 } else {
James Smarta0f9b482006-04-15 11:52:56 -04002264 if (ndlp->nlp_flag & NLP_NODEV_REMOVE) {
James Smart2e0fef82007-06-17 19:56:36 -05002265 lpfc_drop_node(vport, ndlp);
James Smarta0f9b482006-04-15 11:52:56 -04002266 return NLP_STE_FREED_NODE;
2267 }
2268 }
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002269 return ndlp->nlp_state;
dea31012005-04-17 16:05:31 -05002270}
2271
2272static uint32_t
James Smart2e0fef82007-06-17 19:56:36 -05002273lpfc_device_rm_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
2274 void *arg, uint32_t evt)
dea31012005-04-17 16:05:31 -05002275{
James Smart2e0fef82007-06-17 19:56:36 -05002276 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
2277
James Smarta0f9b482006-04-15 11:52:56 -04002278 if (ndlp->nlp_flag & NLP_NPR_2B_DISC) {
James Smart2e0fef82007-06-17 19:56:36 -05002279 spin_lock_irq(shost->host_lock);
James Smarta0f9b482006-04-15 11:52:56 -04002280 ndlp->nlp_flag |= NLP_NODEV_REMOVE;
James Smart2e0fef82007-06-17 19:56:36 -05002281 spin_unlock_irq(shost->host_lock);
James Smarta0f9b482006-04-15 11:52:56 -04002282 return ndlp->nlp_state;
2283 }
James Smart2e0fef82007-06-17 19:56:36 -05002284 lpfc_drop_node(vport, ndlp);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002285 return NLP_STE_FREED_NODE;
dea31012005-04-17 16:05:31 -05002286}
2287
2288static uint32_t
James Smart2e0fef82007-06-17 19:56:36 -05002289lpfc_device_recov_npr_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
2290 void *arg, uint32_t evt)
dea31012005-04-17 16:05:31 -05002291{
James Smart2e0fef82007-06-17 19:56:36 -05002292 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
2293
James Smart92d7f7b2007-06-17 19:56:38 -05002294 /* Don't do anything that will mess up processing of the
2295 * previous RSCN.
2296 */
2297 if (vport->fc_flag & FC_RSCN_DEFERRED)
2298 return ndlp->nlp_state;
2299
James Smarteaf15d52008-12-04 22:39:29 -05002300 lpfc_cancel_retry_delay_tmo(vport, ndlp);
James Smart2e0fef82007-06-17 19:56:36 -05002301 spin_lock_irq(shost->host_lock);
James Smarta0f9b482006-04-15 11:52:56 -04002302 ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC);
James Smart2e0fef82007-06-17 19:56:36 -05002303 spin_unlock_irq(shost->host_lock);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002304 return ndlp->nlp_state;
dea31012005-04-17 16:05:31 -05002305}
2306
2307
2308/* This next section defines the NPort Discovery State Machine */
2309
2310/* There are 4 different double linked lists nodelist entries can reside on.
2311 * The plogi list and adisc list are used when Link Up discovery or RSCN
2312 * processing is needed. Each list holds the nodes that we will send PLOGI
2313 * or ADISC on. These lists will keep track of what nodes will be effected
2314 * by an RSCN, or a Link Up (Typically, all nodes are effected on Link Up).
2315 * The unmapped_list will contain all nodes that we have successfully logged
2316 * into at the Fibre Channel level. The mapped_list will contain all nodes
2317 * that are mapped FCP targets.
2318 */
2319/*
2320 * The bind list is a list of undiscovered (potentially non-existent) nodes
2321 * that we have saved binding information on. This information is used when
2322 * nodes transition from the unmapped to the mapped list.
2323 */
2324/* For UNUSED_NODE state, the node has just been allocated .
2325 * For PLOGI_ISSUE and REG_LOGIN_ISSUE, the node is on
2326 * the PLOGI list. For REG_LOGIN_COMPL, the node is taken off the PLOGI list
2327 * and put on the unmapped list. For ADISC processing, the node is taken off
2328 * the ADISC list and placed on either the mapped or unmapped list (depending
2329 * on its previous state). Once on the unmapped list, a PRLI is issued and the
2330 * state changed to PRLI_ISSUE. When the PRLI completion occurs, the state is
2331 * changed to UNMAPPED_NODE. If the completion indicates a mapped
2332 * node, the node is taken off the unmapped list. The binding list is checked
2333 * for a valid binding, or a binding is automatically assigned. If binding
2334 * assignment is unsuccessful, the node is left on the unmapped list. If
2335 * binding assignment is successful, the associated binding list entry (if
2336 * any) is removed, and the node is placed on the mapped list.
2337 */
2338/*
2339 * For a Link Down, all nodes on the ADISC, PLOGI, unmapped or mapped
James Smartc01f3202006-08-18 17:47:08 -04002340 * lists will receive a DEVICE_RECOVERY event. If the linkdown or devloss timers
dea31012005-04-17 16:05:31 -05002341 * expire, all effected nodes will receive a DEVICE_RM event.
2342 */
2343/*
2344 * For a Link Up or RSCN, all nodes will move from the mapped / unmapped lists
2345 * to either the ADISC or PLOGI list. After a Nameserver query or ALPA loopmap
2346 * check, additional nodes may be added or removed (via DEVICE_RM) to / from
2347 * the PLOGI or ADISC lists. Once the PLOGI and ADISC lists are populated,
2348 * we will first process the ADISC list. 32 entries are processed initially and
2349 * ADISC is initited for each one. Completions / Events for each node are
2350 * funnelled thru the state machine. As each node finishes ADISC processing, it
2351 * starts ADISC for any nodes waiting for ADISC processing. If no nodes are
2352 * waiting, and the ADISC list count is identically 0, then we are done. For
2353 * Link Up discovery, since all nodes on the PLOGI list are UNREG_LOGIN'ed, we
2354 * can issue a CLEAR_LA and reenable Link Events. Next we will process the PLOGI
2355 * list. 32 entries are processed initially and PLOGI is initited for each one.
2356 * Completions / Events for each node are funnelled thru the state machine. As
2357 * each node finishes PLOGI processing, it starts PLOGI for any nodes waiting
2358 * for PLOGI processing. If no nodes are waiting, and the PLOGI list count is
2359 * indentically 0, then we are done. We have now completed discovery / RSCN
2360 * handling. Upon completion, ALL nodes should be on either the mapped or
2361 * unmapped lists.
2362 */
2363
2364static uint32_t (*lpfc_disc_action[NLP_STE_MAX_STATE * NLP_EVT_MAX_EVENT])
James Smart2e0fef82007-06-17 19:56:36 -05002365 (struct lpfc_vport *, struct lpfc_nodelist *, void *, uint32_t) = {
dea31012005-04-17 16:05:31 -05002366 /* Action routine Event Current State */
2367 lpfc_rcv_plogi_unused_node, /* RCV_PLOGI UNUSED_NODE */
2368 lpfc_rcv_els_unused_node, /* RCV_PRLI */
2369 lpfc_rcv_logo_unused_node, /* RCV_LOGO */
2370 lpfc_rcv_els_unused_node, /* RCV_ADISC */
2371 lpfc_rcv_els_unused_node, /* RCV_PDISC */
2372 lpfc_rcv_els_unused_node, /* RCV_PRLO */
2373 lpfc_disc_illegal, /* CMPL_PLOGI */
2374 lpfc_disc_illegal, /* CMPL_PRLI */
2375 lpfc_cmpl_logo_unused_node, /* CMPL_LOGO */
2376 lpfc_disc_illegal, /* CMPL_ADISC */
2377 lpfc_disc_illegal, /* CMPL_REG_LOGIN */
2378 lpfc_device_rm_unused_node, /* DEVICE_RM */
James Smartdf9e1b52011-12-13 13:22:17 -05002379 lpfc_device_recov_unused_node, /* DEVICE_RECOVERY */
dea31012005-04-17 16:05:31 -05002380
2381 lpfc_rcv_plogi_plogi_issue, /* RCV_PLOGI PLOGI_ISSUE */
James Smart92d7f7b2007-06-17 19:56:38 -05002382 lpfc_rcv_prli_plogi_issue, /* RCV_PRLI */
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002383 lpfc_rcv_logo_plogi_issue, /* RCV_LOGO */
dea31012005-04-17 16:05:31 -05002384 lpfc_rcv_els_plogi_issue, /* RCV_ADISC */
2385 lpfc_rcv_els_plogi_issue, /* RCV_PDISC */
2386 lpfc_rcv_els_plogi_issue, /* RCV_PRLO */
2387 lpfc_cmpl_plogi_plogi_issue, /* CMPL_PLOGI */
2388 lpfc_disc_illegal, /* CMPL_PRLI */
James Smart0ff10d42008-01-11 01:52:36 -05002389 lpfc_cmpl_logo_plogi_issue, /* CMPL_LOGO */
dea31012005-04-17 16:05:31 -05002390 lpfc_disc_illegal, /* CMPL_ADISC */
James Smart0ff10d42008-01-11 01:52:36 -05002391 lpfc_cmpl_reglogin_plogi_issue,/* CMPL_REG_LOGIN */
dea31012005-04-17 16:05:31 -05002392 lpfc_device_rm_plogi_issue, /* DEVICE_RM */
2393 lpfc_device_recov_plogi_issue, /* DEVICE_RECOVERY */
2394
2395 lpfc_rcv_plogi_adisc_issue, /* RCV_PLOGI ADISC_ISSUE */
2396 lpfc_rcv_prli_adisc_issue, /* RCV_PRLI */
2397 lpfc_rcv_logo_adisc_issue, /* RCV_LOGO */
2398 lpfc_rcv_padisc_adisc_issue, /* RCV_ADISC */
2399 lpfc_rcv_padisc_adisc_issue, /* RCV_PDISC */
2400 lpfc_rcv_prlo_adisc_issue, /* RCV_PRLO */
2401 lpfc_disc_illegal, /* CMPL_PLOGI */
2402 lpfc_disc_illegal, /* CMPL_PRLI */
2403 lpfc_disc_illegal, /* CMPL_LOGO */
2404 lpfc_cmpl_adisc_adisc_issue, /* CMPL_ADISC */
2405 lpfc_disc_illegal, /* CMPL_REG_LOGIN */
2406 lpfc_device_rm_adisc_issue, /* DEVICE_RM */
2407 lpfc_device_recov_adisc_issue, /* DEVICE_RECOVERY */
2408
2409 lpfc_rcv_plogi_reglogin_issue, /* RCV_PLOGI REG_LOGIN_ISSUE */
2410 lpfc_rcv_prli_reglogin_issue, /* RCV_PLOGI */
2411 lpfc_rcv_logo_reglogin_issue, /* RCV_LOGO */
2412 lpfc_rcv_padisc_reglogin_issue, /* RCV_ADISC */
2413 lpfc_rcv_padisc_reglogin_issue, /* RCV_PDISC */
2414 lpfc_rcv_prlo_reglogin_issue, /* RCV_PRLO */
James Smart87af33f2007-10-27 13:37:43 -04002415 lpfc_cmpl_plogi_illegal, /* CMPL_PLOGI */
dea31012005-04-17 16:05:31 -05002416 lpfc_disc_illegal, /* CMPL_PRLI */
2417 lpfc_disc_illegal, /* CMPL_LOGO */
2418 lpfc_disc_illegal, /* CMPL_ADISC */
2419 lpfc_cmpl_reglogin_reglogin_issue,/* CMPL_REG_LOGIN */
2420 lpfc_device_rm_reglogin_issue, /* DEVICE_RM */
2421 lpfc_device_recov_reglogin_issue,/* DEVICE_RECOVERY */
2422
2423 lpfc_rcv_plogi_prli_issue, /* RCV_PLOGI PRLI_ISSUE */
2424 lpfc_rcv_prli_prli_issue, /* RCV_PRLI */
2425 lpfc_rcv_logo_prli_issue, /* RCV_LOGO */
2426 lpfc_rcv_padisc_prli_issue, /* RCV_ADISC */
2427 lpfc_rcv_padisc_prli_issue, /* RCV_PDISC */
2428 lpfc_rcv_prlo_prli_issue, /* RCV_PRLO */
James Smart87af33f2007-10-27 13:37:43 -04002429 lpfc_cmpl_plogi_illegal, /* CMPL_PLOGI */
dea31012005-04-17 16:05:31 -05002430 lpfc_cmpl_prli_prli_issue, /* CMPL_PRLI */
2431 lpfc_disc_illegal, /* CMPL_LOGO */
2432 lpfc_disc_illegal, /* CMPL_ADISC */
2433 lpfc_disc_illegal, /* CMPL_REG_LOGIN */
2434 lpfc_device_rm_prli_issue, /* DEVICE_RM */
2435 lpfc_device_recov_prli_issue, /* DEVICE_RECOVERY */
2436
James Smart086a3452012-08-14 14:25:21 -04002437 lpfc_rcv_plogi_logo_issue, /* RCV_PLOGI LOGO_ISSUE */
2438 lpfc_rcv_prli_logo_issue, /* RCV_PRLI */
2439 lpfc_rcv_logo_logo_issue, /* RCV_LOGO */
2440 lpfc_rcv_padisc_logo_issue, /* RCV_ADISC */
2441 lpfc_rcv_padisc_logo_issue, /* RCV_PDISC */
2442 lpfc_rcv_prlo_logo_issue, /* RCV_PRLO */
2443 lpfc_cmpl_plogi_illegal, /* CMPL_PLOGI */
2444 lpfc_disc_illegal, /* CMPL_PRLI */
2445 lpfc_cmpl_logo_logo_issue, /* CMPL_LOGO */
2446 lpfc_disc_illegal, /* CMPL_ADISC */
2447 lpfc_disc_illegal, /* CMPL_REG_LOGIN */
2448 lpfc_device_rm_logo_issue, /* DEVICE_RM */
2449 lpfc_device_recov_logo_issue, /* DEVICE_RECOVERY */
2450
dea31012005-04-17 16:05:31 -05002451 lpfc_rcv_plogi_unmap_node, /* RCV_PLOGI UNMAPPED_NODE */
2452 lpfc_rcv_prli_unmap_node, /* RCV_PRLI */
2453 lpfc_rcv_logo_unmap_node, /* RCV_LOGO */
2454 lpfc_rcv_padisc_unmap_node, /* RCV_ADISC */
2455 lpfc_rcv_padisc_unmap_node, /* RCV_PDISC */
2456 lpfc_rcv_prlo_unmap_node, /* RCV_PRLO */
2457 lpfc_disc_illegal, /* CMPL_PLOGI */
2458 lpfc_disc_illegal, /* CMPL_PRLI */
2459 lpfc_disc_illegal, /* CMPL_LOGO */
2460 lpfc_disc_illegal, /* CMPL_ADISC */
2461 lpfc_disc_illegal, /* CMPL_REG_LOGIN */
2462 lpfc_disc_illegal, /* DEVICE_RM */
2463 lpfc_device_recov_unmap_node, /* DEVICE_RECOVERY */
2464
2465 lpfc_rcv_plogi_mapped_node, /* RCV_PLOGI MAPPED_NODE */
2466 lpfc_rcv_prli_mapped_node, /* RCV_PRLI */
2467 lpfc_rcv_logo_mapped_node, /* RCV_LOGO */
2468 lpfc_rcv_padisc_mapped_node, /* RCV_ADISC */
2469 lpfc_rcv_padisc_mapped_node, /* RCV_PDISC */
2470 lpfc_rcv_prlo_mapped_node, /* RCV_PRLO */
2471 lpfc_disc_illegal, /* CMPL_PLOGI */
2472 lpfc_disc_illegal, /* CMPL_PRLI */
2473 lpfc_disc_illegal, /* CMPL_LOGO */
2474 lpfc_disc_illegal, /* CMPL_ADISC */
2475 lpfc_disc_illegal, /* CMPL_REG_LOGIN */
2476 lpfc_disc_illegal, /* DEVICE_RM */
2477 lpfc_device_recov_mapped_node, /* DEVICE_RECOVERY */
2478
2479 lpfc_rcv_plogi_npr_node, /* RCV_PLOGI NPR_NODE */
2480 lpfc_rcv_prli_npr_node, /* RCV_PRLI */
2481 lpfc_rcv_logo_npr_node, /* RCV_LOGO */
2482 lpfc_rcv_padisc_npr_node, /* RCV_ADISC */
2483 lpfc_rcv_padisc_npr_node, /* RCV_PDISC */
2484 lpfc_rcv_prlo_npr_node, /* RCV_PRLO */
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002485 lpfc_cmpl_plogi_npr_node, /* CMPL_PLOGI */
2486 lpfc_cmpl_prli_npr_node, /* CMPL_PRLI */
dea31012005-04-17 16:05:31 -05002487 lpfc_cmpl_logo_npr_node, /* CMPL_LOGO */
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002488 lpfc_cmpl_adisc_npr_node, /* CMPL_ADISC */
dea31012005-04-17 16:05:31 -05002489 lpfc_cmpl_reglogin_npr_node, /* CMPL_REG_LOGIN */
2490 lpfc_device_rm_npr_node, /* DEVICE_RM */
2491 lpfc_device_recov_npr_node, /* DEVICE_RECOVERY */
2492};
2493
2494int
James Smart2e0fef82007-06-17 19:56:36 -05002495lpfc_disc_state_machine(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
2496 void *arg, uint32_t evt)
dea31012005-04-17 16:05:31 -05002497{
2498 uint32_t cur_state, rc;
James Smart2e0fef82007-06-17 19:56:36 -05002499 uint32_t(*func) (struct lpfc_vport *, struct lpfc_nodelist *, void *,
dea31012005-04-17 16:05:31 -05002500 uint32_t);
James Smarte47c9092008-02-08 18:49:26 -05002501 uint32_t got_ndlp = 0;
dea31012005-04-17 16:05:31 -05002502
James Smarte47c9092008-02-08 18:49:26 -05002503 if (lpfc_nlp_get(ndlp))
2504 got_ndlp = 1;
2505
dea31012005-04-17 16:05:31 -05002506 cur_state = ndlp->nlp_state;
2507
2508 /* DSM in event <evt> on NPort <nlp_DID> in state <cur_state> */
James Smarte8b62012007-08-02 11:10:09 -04002509 lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
2510 "0211 DSM in event x%x on NPort x%x in "
2511 "state %d Data: x%x\n",
2512 evt, ndlp->nlp_DID, cur_state, ndlp->nlp_flag);
dea31012005-04-17 16:05:31 -05002513
James Smart858c9f62007-06-17 19:56:39 -05002514 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_DSM,
2515 "DSM in: evt:%d ste:%d did:x%x",
2516 evt, cur_state, ndlp->nlp_DID);
2517
dea31012005-04-17 16:05:31 -05002518 func = lpfc_disc_action[(cur_state * NLP_EVT_MAX_EVENT) + evt];
James Smart2e0fef82007-06-17 19:56:36 -05002519 rc = (func) (vport, ndlp, arg, evt);
dea31012005-04-17 16:05:31 -05002520
2521 /* DSM out state <rc> on NPort <nlp_DID> */
James Smarte47c9092008-02-08 18:49:26 -05002522 if (got_ndlp) {
2523 lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
James Smarte8b62012007-08-02 11:10:09 -04002524 "0212 DSM out state %d on NPort x%x Data: x%x\n",
2525 rc, ndlp->nlp_DID, ndlp->nlp_flag);
dea31012005-04-17 16:05:31 -05002526
James Smarte47c9092008-02-08 18:49:26 -05002527 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_DSM,
2528 "DSM out: ste:%d did:x%x flg:x%x",
2529 rc, ndlp->nlp_DID, ndlp->nlp_flag);
2530 /* Decrement the ndlp reference count held for this function */
2531 lpfc_nlp_put(ndlp);
2532 } else {
2533 lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
James Smartd7c255b2008-08-24 21:50:00 -04002534 "0213 DSM out state %d on NPort free\n", rc);
James Smart858c9f62007-06-17 19:56:39 -05002535
James Smarte47c9092008-02-08 18:49:26 -05002536 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_DSM,
2537 "DSM out: ste:%d did:x%x flg:x%x",
2538 rc, 0, 0);
2539 }
dea31012005-04-17 16:05:31 -05002540
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002541 return rc;
dea31012005-04-17 16:05:31 -05002542}