~ubuntu-branches/ubuntu/precise/linux-lowlatency/precise

« back to all changes in this revision

Viewing changes to drivers/scsi/lpfc/lpfc_nportdisc.c

  • Committer: Package Import Robot
  • Author(s): Alessio Igor Bogani
  • Date: 2011-10-26 11:13:05 UTC
  • Revision ID: package-import@ubuntu.com-20111026111305-tz023xykf0i6eosh
Tags: upstream-3.2.0
ImportĀ upstreamĀ versionĀ 3.2.0

Show diffs side-by-side

added added

removed removed

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