blob: 14d204ba8a3946e6c91bb419e2ed5a1938070fa3 [file] [log] [blame]
dea31012005-04-17 16:05:31 -05001/*******************************************************************
2 * This file is part of the Emulex Linux Device Driver for *
James.Smart@Emulex.Comc44ce172005-06-25 10:34:39 -04003 * Fibre Channel Host Bus Adapters. *
Jamie Wellnitz2fe165b2006-02-28 19:25:31 -05004 * Copyright (C) 2004-2006 Emulex. All rights reserved. *
James.Smart@Emulex.Comc44ce172005-06-25 10:34:39 -04005 * EMULEX and SLI are trademarks of Emulex. *
dea31012005-04-17 16:05:31 -05006 * www.emulex.com *
James.Smart@Emulex.Comc44ce172005-06-25 10:34:39 -04007 * Portions Copyright (C) 2004-2005 Christoph Hellwig *
dea31012005-04-17 16:05:31 -05008 * *
9 * This program is free software; you can redistribute it and/or *
James.Smart@Emulex.Comc44ce172005-06-25 10:34:39 -040010 * modify it under the terms of version 2 of the GNU General *
11 * Public License as published by the Free Software Foundation. *
12 * This program is distributed in the hope that it will be useful. *
13 * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND *
14 * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, *
15 * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE *
16 * DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD *
17 * TO BE LEGALLY INVALID. See the GNU General Public License for *
18 * more details, a copy of which can be found in the file COPYING *
19 * included with this package. *
dea31012005-04-17 16:05:31 -050020 *******************************************************************/
21
dea31012005-04-17 16:05:31 -050022#include <linux/blkdev.h>
23#include <linux/pci.h>
24#include <linux/interrupt.h>
25
James.Smart@Emulex.Com91886522005-08-10 15:03:09 -040026#include <scsi/scsi.h>
dea31012005-04-17 16:05:31 -050027#include <scsi/scsi_device.h>
28#include <scsi/scsi_host.h>
29#include <scsi/scsi_transport_fc.h>
30
31#include "lpfc_hw.h"
32#include "lpfc_sli.h"
33#include "lpfc_disc.h"
34#include "lpfc_scsi.h"
35#include "lpfc.h"
36#include "lpfc_logmsg.h"
37#include "lpfc_crtn.h"
38
39static int lpfc_els_retry(struct lpfc_hba *, struct lpfc_iocbq *,
40 struct lpfc_iocbq *);
41static int lpfc_max_els_tries = 3;
42
43static int
44lpfc_els_chk_latt(struct lpfc_hba * phba)
45{
46 struct lpfc_sli *psli;
47 LPFC_MBOXQ_t *mbox;
48 uint32_t ha_copy;
49 int rc;
50
51 psli = &phba->sli;
52
53 if ((phba->hba_state >= LPFC_HBA_READY) ||
54 (phba->hba_state == LPFC_LINK_DOWN))
55 return 0;
56
57 /* Read the HBA Host Attention Register */
58 spin_lock_irq(phba->host->host_lock);
59 ha_copy = readl(phba->HAregaddr);
60 spin_unlock_irq(phba->host->host_lock);
61
62 if (!(ha_copy & HA_LATT))
63 return 0;
64
65 /* Pending Link Event during Discovery */
66 lpfc_printf_log(phba, KERN_WARNING, LOG_DISCOVERY,
67 "%d:0237 Pending Link Event during "
68 "Discovery: State x%x\n",
69 phba->brd_no, phba->hba_state);
70
71 /* CLEAR_LA should re-enable link attention events and
72 * we should then imediately take a LATT event. The
73 * LATT processing should call lpfc_linkdown() which
74 * will cleanup any left over in-progress discovery
75 * events.
76 */
77 spin_lock_irq(phba->host->host_lock);
78 phba->fc_flag |= FC_ABORT_DISCOVERY;
79 spin_unlock_irq(phba->host->host_lock);
80
81 if (phba->hba_state != LPFC_CLEAR_LA) {
82 if ((mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL))) {
83 phba->hba_state = LPFC_CLEAR_LA;
84 lpfc_clear_la(phba, mbox);
85 mbox->mbox_cmpl = lpfc_mbx_cmpl_clear_la;
86 rc = lpfc_sli_issue_mbox (phba, mbox,
87 (MBX_NOWAIT | MBX_STOP_IOCB));
88 if (rc == MBX_NOT_FINISHED) {
89 mempool_free(mbox, phba->mbox_mem_pool);
90 phba->hba_state = LPFC_HBA_ERROR;
91 }
92 }
93 }
94
Jamie Wellnitzc9f87352006-02-28 19:25:23 -050095 return 1;
dea31012005-04-17 16:05:31 -050096
97}
98
99static struct lpfc_iocbq *
James Smart488d1462006-03-07 15:02:37 -0500100lpfc_prep_els_iocb(struct lpfc_hba * phba, uint8_t expectRsp,
101 uint16_t cmdSize, uint8_t retry, struct lpfc_nodelist * ndlp,
102 uint32_t did, uint32_t elscmd)
dea31012005-04-17 16:05:31 -0500103{
dea31012005-04-17 16:05:31 -0500104 struct lpfc_sli_ring *pring;
James.Smart@Emulex.Com0bd4ca22005-10-28 20:30:02 -0400105 struct lpfc_iocbq *elsiocb;
dea31012005-04-17 16:05:31 -0500106 struct lpfc_dmabuf *pcmd, *prsp, *pbuflist;
107 struct ulp_bde64 *bpl;
108 IOCB_t *icmd;
109
110 pring = &phba->sli.ring[LPFC_ELS_RING];
111
112 if (phba->hba_state < LPFC_LINK_UP)
113 return NULL;
114
dea31012005-04-17 16:05:31 -0500115 /* Allocate buffer for command iocb */
116 spin_lock_irq(phba->host->host_lock);
James.Smart@Emulex.Com0bd4ca22005-10-28 20:30:02 -0400117 elsiocb = lpfc_sli_get_iocbq(phba);
dea31012005-04-17 16:05:31 -0500118 spin_unlock_irq(phba->host->host_lock);
119
120 if (elsiocb == NULL)
121 return NULL;
dea31012005-04-17 16:05:31 -0500122 icmd = &elsiocb->iocb;
123
124 /* fill in BDEs for command */
125 /* Allocate buffer for command payload */
126 if (((pcmd = kmalloc(sizeof (struct lpfc_dmabuf), GFP_KERNEL)) == 0) ||
127 ((pcmd->virt = lpfc_mbuf_alloc(phba,
128 MEM_PRI, &(pcmd->phys))) == 0)) {
Jesper Juhlc9475cb2005-11-07 01:01:26 -0800129 kfree(pcmd);
dea31012005-04-17 16:05:31 -0500130
James Bottomley604a3e32005-10-29 10:28:33 -0500131 spin_lock_irq(phba->host->host_lock);
132 lpfc_sli_release_iocbq(phba, elsiocb);
133 spin_unlock_irq(phba->host->host_lock);
dea31012005-04-17 16:05:31 -0500134 return NULL;
135 }
136
137 INIT_LIST_HEAD(&pcmd->list);
138
139 /* Allocate buffer for response payload */
140 if (expectRsp) {
141 prsp = kmalloc(sizeof (struct lpfc_dmabuf), GFP_KERNEL);
142 if (prsp)
143 prsp->virt = lpfc_mbuf_alloc(phba, MEM_PRI,
144 &prsp->phys);
145 if (prsp == 0 || prsp->virt == 0) {
Jesper Juhlc9475cb2005-11-07 01:01:26 -0800146 kfree(prsp);
dea31012005-04-17 16:05:31 -0500147 lpfc_mbuf_free(phba, pcmd->virt, pcmd->phys);
148 kfree(pcmd);
James Bottomley604a3e32005-10-29 10:28:33 -0500149 spin_lock_irq(phba->host->host_lock);
150 lpfc_sli_release_iocbq(phba, elsiocb);
151 spin_unlock_irq(phba->host->host_lock);
dea31012005-04-17 16:05:31 -0500152 return NULL;
153 }
154 INIT_LIST_HEAD(&prsp->list);
155 } else {
156 prsp = NULL;
157 }
158
159 /* Allocate buffer for Buffer ptr list */
160 pbuflist = kmalloc(sizeof (struct lpfc_dmabuf), GFP_KERNEL);
161 if (pbuflist)
162 pbuflist->virt = lpfc_mbuf_alloc(phba, MEM_PRI,
163 &pbuflist->phys);
164 if (pbuflist == 0 || pbuflist->virt == 0) {
James Bottomley604a3e32005-10-29 10:28:33 -0500165 spin_lock_irq(phba->host->host_lock);
166 lpfc_sli_release_iocbq(phba, elsiocb);
167 spin_unlock_irq(phba->host->host_lock);
dea31012005-04-17 16:05:31 -0500168 lpfc_mbuf_free(phba, pcmd->virt, pcmd->phys);
169 lpfc_mbuf_free(phba, prsp->virt, prsp->phys);
170 kfree(pcmd);
171 kfree(prsp);
Jesper Juhlc9475cb2005-11-07 01:01:26 -0800172 kfree(pbuflist);
dea31012005-04-17 16:05:31 -0500173 return NULL;
174 }
175
176 INIT_LIST_HEAD(&pbuflist->list);
177
178 icmd->un.elsreq64.bdl.addrHigh = putPaddrHigh(pbuflist->phys);
179 icmd->un.elsreq64.bdl.addrLow = putPaddrLow(pbuflist->phys);
180 icmd->un.elsreq64.bdl.bdeFlags = BUFF_TYPE_BDL;
181 if (expectRsp) {
182 icmd->un.elsreq64.bdl.bdeSize = (2 * sizeof (struct ulp_bde64));
James Smart488d1462006-03-07 15:02:37 -0500183 icmd->un.elsreq64.remoteID = did; /* DID */
dea31012005-04-17 16:05:31 -0500184 icmd->ulpCommand = CMD_ELS_REQUEST64_CR;
James Smart2680eea2007-04-25 09:52:55 -0400185 icmd->ulpTimeout = phba->fc_ratov * 2;
dea31012005-04-17 16:05:31 -0500186 } else {
187 icmd->un.elsreq64.bdl.bdeSize = sizeof (struct ulp_bde64);
188 icmd->ulpCommand = CMD_XMIT_ELS_RSP64_CX;
189 }
190
191 icmd->ulpBdeCount = 1;
192 icmd->ulpLe = 1;
193 icmd->ulpClass = CLASS3;
194
195 bpl = (struct ulp_bde64 *) pbuflist->virt;
196 bpl->addrLow = le32_to_cpu(putPaddrLow(pcmd->phys));
197 bpl->addrHigh = le32_to_cpu(putPaddrHigh(pcmd->phys));
198 bpl->tus.f.bdeSize = cmdSize;
199 bpl->tus.f.bdeFlags = 0;
200 bpl->tus.w = le32_to_cpu(bpl->tus.w);
201
202 if (expectRsp) {
203 bpl++;
204 bpl->addrLow = le32_to_cpu(putPaddrLow(prsp->phys));
205 bpl->addrHigh = le32_to_cpu(putPaddrHigh(prsp->phys));
206 bpl->tus.f.bdeSize = FCELSSIZE;
207 bpl->tus.f.bdeFlags = BUFF_USE_RCV;
208 bpl->tus.w = le32_to_cpu(bpl->tus.w);
209 }
210
211 /* Save for completion so we can release these resources */
212 elsiocb->context1 = (uint8_t *) ndlp;
213 elsiocb->context2 = (uint8_t *) pcmd;
214 elsiocb->context3 = (uint8_t *) pbuflist;
215 elsiocb->retry = retry;
216 elsiocb->drvrTimeout = (phba->fc_ratov << 1) + LPFC_DRVR_TIMEOUT;
217
218 if (prsp) {
219 list_add(&prsp->list, &pcmd->list);
220 }
221
222 if (expectRsp) {
223 /* Xmit ELS command <elsCmd> to remote NPORT <did> */
224 lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
225 "%d:0116 Xmit ELS command x%x to remote "
James Smart1dcb58e2007-04-25 09:51:30 -0400226 "NPORT x%x I/O tag: x%x, HBA state: x%x\n",
dea31012005-04-17 16:05:31 -0500227 phba->brd_no, elscmd,
James Smart1dcb58e2007-04-25 09:51:30 -0400228 did, elsiocb->iotag, phba->hba_state);
dea31012005-04-17 16:05:31 -0500229 } else {
230 /* Xmit ELS response <elsCmd> to remote NPORT <did> */
231 lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
232 "%d:0117 Xmit ELS response x%x to remote "
James Smart1dcb58e2007-04-25 09:51:30 -0400233 "NPORT x%x I/O tag: x%x, size: x%x\n",
dea31012005-04-17 16:05:31 -0500234 phba->brd_no, elscmd,
James Smart1dcb58e2007-04-25 09:51:30 -0400235 ndlp->nlp_DID, elsiocb->iotag, cmdSize);
dea31012005-04-17 16:05:31 -0500236 }
237
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500238 return elsiocb;
dea31012005-04-17 16:05:31 -0500239}
240
241
242static int
243lpfc_cmpl_els_flogi_fabric(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp,
244 struct serv_parm *sp, IOCB_t *irsp)
245{
246 LPFC_MBOXQ_t *mbox;
James Smart14691152006-12-02 13:34:28 -0500247 struct lpfc_dmabuf *mp;
dea31012005-04-17 16:05:31 -0500248 int rc;
249
250 spin_lock_irq(phba->host->host_lock);
251 phba->fc_flag |= FC_FABRIC;
252 spin_unlock_irq(phba->host->host_lock);
253
254 phba->fc_edtov = be32_to_cpu(sp->cmn.e_d_tov);
255 if (sp->cmn.edtovResolution) /* E_D_TOV ticks are in nanoseconds */
256 phba->fc_edtov = (phba->fc_edtov + 999999) / 1000000;
257
258 phba->fc_ratov = (be32_to_cpu(sp->cmn.w2.r_a_tov) + 999) / 1000;
259
260 if (phba->fc_topology == TOPOLOGY_LOOP) {
261 spin_lock_irq(phba->host->host_lock);
262 phba->fc_flag |= FC_PUBLIC_LOOP;
263 spin_unlock_irq(phba->host->host_lock);
264 } else {
265 /*
266 * If we are a N-port connected to a Fabric, fixup sparam's so
267 * logins to devices on remote loops work.
268 */
269 phba->fc_sparam.cmn.altBbCredit = 1;
270 }
271
272 phba->fc_myDID = irsp->un.ulpWord[4] & Mask_DID;
273 memcpy(&ndlp->nlp_portname, &sp->portName, sizeof(struct lpfc_name));
274 memcpy(&ndlp->nlp_nodename, &sp->nodeName, sizeof (struct lpfc_name));
275 ndlp->nlp_class_sup = 0;
276 if (sp->cls1.classValid)
277 ndlp->nlp_class_sup |= FC_COS_CLASS1;
278 if (sp->cls2.classValid)
279 ndlp->nlp_class_sup |= FC_COS_CLASS2;
280 if (sp->cls3.classValid)
281 ndlp->nlp_class_sup |= FC_COS_CLASS3;
282 if (sp->cls4.classValid)
283 ndlp->nlp_class_sup |= FC_COS_CLASS4;
284 ndlp->nlp_maxframe = ((sp->cmn.bbRcvSizeMsb & 0x0F) << 8) |
285 sp->cmn.bbRcvSizeLsb;
286 memcpy(&phba->fc_fabparam, sp, sizeof(struct serv_parm));
287
288 mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
289 if (!mbox)
290 goto fail;
291
292 phba->hba_state = LPFC_FABRIC_CFG_LINK;
293 lpfc_config_link(phba, mbox);
294 mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
295
296 rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT | MBX_STOP_IOCB);
297 if (rc == MBX_NOT_FINISHED)
298 goto fail_free_mbox;
299
300 mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
301 if (!mbox)
302 goto fail;
303
304 if (lpfc_reg_login(phba, Fabric_DID, (uint8_t *) sp, mbox, 0))
305 goto fail_free_mbox;
306
dea31012005-04-17 16:05:31 -0500307 mbox->mbox_cmpl = lpfc_mbx_cmpl_fabric_reg_login;
308 mbox->context2 = ndlp;
309
310 rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT | MBX_STOP_IOCB);
311 if (rc == MBX_NOT_FINISHED)
James Smart14691152006-12-02 13:34:28 -0500312 goto fail_issue_reg_login;
dea31012005-04-17 16:05:31 -0500313
314 return 0;
315
James Smart14691152006-12-02 13:34:28 -0500316 fail_issue_reg_login:
317 mp = (struct lpfc_dmabuf *) mbox->context1;
318 lpfc_mbuf_free(phba, mp->virt, mp->phys);
319 kfree(mp);
dea31012005-04-17 16:05:31 -0500320 fail_free_mbox:
321 mempool_free(mbox, phba->mbox_mem_pool);
322 fail:
323 return -ENXIO;
324}
325
326/*
327 * We FLOGIed into an NPort, initiate pt2pt protocol
328 */
329static int
330lpfc_cmpl_els_flogi_nport(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp,
331 struct serv_parm *sp)
332{
333 LPFC_MBOXQ_t *mbox;
334 int rc;
335
336 spin_lock_irq(phba->host->host_lock);
337 phba->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP);
338 spin_unlock_irq(phba->host->host_lock);
339
340 phba->fc_edtov = FF_DEF_EDTOV;
341 phba->fc_ratov = FF_DEF_RATOV;
342 rc = memcmp(&phba->fc_portname, &sp->portName,
343 sizeof(struct lpfc_name));
344 if (rc >= 0) {
345 /* This side will initiate the PLOGI */
346 spin_lock_irq(phba->host->host_lock);
347 phba->fc_flag |= FC_PT2PT_PLOGI;
348 spin_unlock_irq(phba->host->host_lock);
349
350 /*
351 * N_Port ID cannot be 0, set our to LocalID the other
352 * side will be RemoteID.
353 */
354
355 /* not equal */
356 if (rc)
357 phba->fc_myDID = PT2PT_LocalID;
358
359 mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
360 if (!mbox)
361 goto fail;
362
363 lpfc_config_link(phba, mbox);
364
365 mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
366 rc = lpfc_sli_issue_mbox(phba, mbox,
367 MBX_NOWAIT | MBX_STOP_IOCB);
368 if (rc == MBX_NOT_FINISHED) {
369 mempool_free(mbox, phba->mbox_mem_pool);
370 goto fail;
371 }
372 mempool_free(ndlp, phba->nlp_mem_pool);
373
374 ndlp = lpfc_findnode_did(phba, NLP_SEARCH_ALL, PT2PT_RemoteID);
375 if (!ndlp) {
376 /*
377 * Cannot find existing Fabric ndlp, so allocate a
378 * new one
379 */
380 ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL);
381 if (!ndlp)
382 goto fail;
383
384 lpfc_nlp_init(phba, ndlp, PT2PT_RemoteID);
385 }
386
387 memcpy(&ndlp->nlp_portname, &sp->portName,
388 sizeof(struct lpfc_name));
389 memcpy(&ndlp->nlp_nodename, &sp->nodeName,
390 sizeof(struct lpfc_name));
James Smartde0c5b32007-04-25 09:52:27 -0400391 lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
dea31012005-04-17 16:05:31 -0500392 ndlp->nlp_flag |= NLP_NPR_2B_DISC;
393 } else {
394 /* This side will wait for the PLOGI */
395 mempool_free( ndlp, phba->nlp_mem_pool);
396 }
397
398 spin_lock_irq(phba->host->host_lock);
399 phba->fc_flag |= FC_PT2PT;
400 spin_unlock_irq(phba->host->host_lock);
401
402 /* Start discovery - this should just do CLEAR_LA */
403 lpfc_disc_start(phba);
404 return 0;
405 fail:
406 return -ENXIO;
407}
408
409static void
410lpfc_cmpl_els_flogi(struct lpfc_hba * phba,
411 struct lpfc_iocbq * cmdiocb, struct lpfc_iocbq * rspiocb)
412{
413 IOCB_t *irsp = &rspiocb->iocb;
414 struct lpfc_nodelist *ndlp = cmdiocb->context1;
415 struct lpfc_dmabuf *pcmd = cmdiocb->context2, *prsp;
416 struct serv_parm *sp;
417 int rc;
418
419 /* Check to see if link went down during discovery */
420 if (lpfc_els_chk_latt(phba)) {
421 lpfc_nlp_remove(phba, ndlp);
422 goto out;
423 }
424
425 if (irsp->ulpStatus) {
426 /* Check for retry */
427 if (lpfc_els_retry(phba, cmdiocb, rspiocb)) {
428 /* ELS command is being retried */
429 goto out;
430 }
431 /* FLOGI failed, so there is no fabric */
432 spin_lock_irq(phba->host->host_lock);
433 phba->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP);
434 spin_unlock_irq(phba->host->host_lock);
435
436 /* If private loop, then allow max outstandting els to be
437 * LPFC_MAX_DISC_THREADS (32). Scanning in the case of no
438 * alpa map would take too long otherwise.
439 */
440 if (phba->alpa_map[0] == 0) {
441 phba->cfg_discovery_threads =
442 LPFC_MAX_DISC_THREADS;
443 }
444
445 /* FLOGI failure */
446 lpfc_printf_log(phba,
447 KERN_INFO,
448 LOG_ELS,
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500449 "%d:0100 FLOGI failure Data: x%x x%x x%x\n",
dea31012005-04-17 16:05:31 -0500450 phba->brd_no,
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500451 irsp->ulpStatus, irsp->un.ulpWord[4],
452 irsp->ulpTimeout);
dea31012005-04-17 16:05:31 -0500453 goto flogifail;
454 }
455
456 /*
457 * The FLogI succeeded. Sync the data for the CPU before
458 * accessing it.
459 */
460 prsp = list_get_first(&pcmd->list, struct lpfc_dmabuf, list);
461
462 sp = prsp->virt + sizeof(uint32_t);
463
464 /* FLOGI completes successfully */
465 lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
466 "%d:0101 FLOGI completes sucessfully "
467 "Data: x%x x%x x%x x%x\n",
468 phba->brd_no,
469 irsp->un.ulpWord[4], sp->cmn.e_d_tov,
470 sp->cmn.w2.r_a_tov, sp->cmn.edtovResolution);
471
472 if (phba->hba_state == LPFC_FLOGI) {
473 /*
474 * If Common Service Parameters indicate Nport
475 * we are point to point, if Fport we are Fabric.
476 */
477 if (sp->cmn.fPort)
478 rc = lpfc_cmpl_els_flogi_fabric(phba, ndlp, sp, irsp);
479 else
480 rc = lpfc_cmpl_els_flogi_nport(phba, ndlp, sp);
481
482 if (!rc)
483 goto out;
484 }
485
486flogifail:
487 lpfc_nlp_remove(phba, ndlp);
488
489 if (irsp->ulpStatus != IOSTAT_LOCAL_REJECT ||
490 (irsp->un.ulpWord[4] != IOERR_SLI_ABORTED &&
491 irsp->un.ulpWord[4] != IOERR_SLI_DOWN)) {
492 /* FLOGI failed, so just use loop map to make discovery list */
493 lpfc_disc_list_loopmap(phba);
494
495 /* Start discovery */
496 lpfc_disc_start(phba);
497 }
498
499out:
500 lpfc_els_free_iocb(phba, cmdiocb);
501}
502
503static int
504lpfc_issue_els_flogi(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp,
505 uint8_t retry)
506{
507 struct serv_parm *sp;
508 IOCB_t *icmd;
509 struct lpfc_iocbq *elsiocb;
510 struct lpfc_sli_ring *pring;
511 uint8_t *pcmd;
512 uint16_t cmdsize;
513 uint32_t tmo;
514 int rc;
515
516 pring = &phba->sli.ring[LPFC_ELS_RING];
517
518 cmdsize = (sizeof (uint32_t) + sizeof (struct serv_parm));
James Smart488d1462006-03-07 15:02:37 -0500519 elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry, ndlp,
520 ndlp->nlp_DID, ELS_CMD_FLOGI);
521 if (!elsiocb)
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500522 return 1;
dea31012005-04-17 16:05:31 -0500523
524 icmd = &elsiocb->iocb;
525 pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
526
527 /* For FLOGI request, remainder of payload is service parameters */
528 *((uint32_t *) (pcmd)) = ELS_CMD_FLOGI;
529 pcmd += sizeof (uint32_t);
530 memcpy(pcmd, &phba->fc_sparam, sizeof (struct serv_parm));
531 sp = (struct serv_parm *) pcmd;
532
533 /* Setup CSPs accordingly for Fabric */
534 sp->cmn.e_d_tov = 0;
535 sp->cmn.w2.r_a_tov = 0;
536 sp->cls1.classValid = 0;
537 sp->cls2.seqDelivery = 1;
538 sp->cls3.seqDelivery = 1;
539 if (sp->cmn.fcphLow < FC_PH3)
540 sp->cmn.fcphLow = FC_PH3;
541 if (sp->cmn.fcphHigh < FC_PH3)
542 sp->cmn.fcphHigh = FC_PH3;
543
544 tmo = phba->fc_ratov;
545 phba->fc_ratov = LPFC_DISC_FLOGI_TMO;
546 lpfc_set_disctmo(phba);
547 phba->fc_ratov = tmo;
548
549 phba->fc_stat.elsXmitFLOGI++;
550 elsiocb->iocb_cmpl = lpfc_cmpl_els_flogi;
551 spin_lock_irq(phba->host->host_lock);
552 rc = lpfc_sli_issue_iocb(phba, pring, elsiocb, 0);
553 spin_unlock_irq(phba->host->host_lock);
554 if (rc == IOCB_ERROR) {
555 lpfc_els_free_iocb(phba, elsiocb);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500556 return 1;
dea31012005-04-17 16:05:31 -0500557 }
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500558 return 0;
dea31012005-04-17 16:05:31 -0500559}
560
561int
562lpfc_els_abort_flogi(struct lpfc_hba * phba)
563{
564 struct lpfc_sli_ring *pring;
565 struct lpfc_iocbq *iocb, *next_iocb;
566 struct lpfc_nodelist *ndlp;
567 IOCB_t *icmd;
568
569 /* Abort outstanding I/O on NPort <nlp_DID> */
570 lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
571 "%d:0201 Abort outstanding I/O on NPort x%x\n",
572 phba->brd_no, Fabric_DID);
573
574 pring = &phba->sli.ring[LPFC_ELS_RING];
575
576 /*
577 * Check the txcmplq for an iocb that matches the nport the driver is
578 * searching for.
579 */
580 spin_lock_irq(phba->host->host_lock);
581 list_for_each_entry_safe(iocb, next_iocb, &pring->txcmplq, list) {
582 icmd = &iocb->iocb;
583 if (icmd->ulpCommand == CMD_ELS_REQUEST64_CR) {
584 ndlp = (struct lpfc_nodelist *)(iocb->context1);
James Smart07951072007-04-25 09:51:38 -0400585 if (ndlp && (ndlp->nlp_DID == Fabric_DID))
586 lpfc_sli_issue_abort_iotag(phba, pring, iocb);
dea31012005-04-17 16:05:31 -0500587 }
588 }
589 spin_unlock_irq(phba->host->host_lock);
590
591 return 0;
592}
593
594int
595lpfc_initial_flogi(struct lpfc_hba * phba)
596{
597 struct lpfc_nodelist *ndlp;
598
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500599 /* First look for the Fabric ndlp */
600 ndlp = lpfc_findnode_did(phba, NLP_SEARCH_ALL, Fabric_DID);
601 if (!ndlp) {
dea31012005-04-17 16:05:31 -0500602 /* Cannot find existing Fabric ndlp, so allocate a new one */
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500603 ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL);
604 if (!ndlp)
605 return 0;
dea31012005-04-17 16:05:31 -0500606 lpfc_nlp_init(phba, ndlp, Fabric_DID);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500607 } else {
James Smartde0c5b32007-04-25 09:52:27 -0400608 lpfc_dequeue_node(phba, ndlp);
dea31012005-04-17 16:05:31 -0500609 }
610 if (lpfc_issue_els_flogi(phba, ndlp, 0)) {
611 mempool_free( ndlp, phba->nlp_mem_pool);
612 }
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500613 return 1;
dea31012005-04-17 16:05:31 -0500614}
615
616static void
617lpfc_more_plogi(struct lpfc_hba * phba)
618{
619 int sentplogi;
620
621 if (phba->num_disc_nodes)
622 phba->num_disc_nodes--;
623
624 /* Continue discovery with <num_disc_nodes> PLOGIs to go */
625 lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
626 "%d:0232 Continue discovery with %d PLOGIs to go "
627 "Data: x%x x%x x%x\n",
628 phba->brd_no, phba->num_disc_nodes, phba->fc_plogi_cnt,
629 phba->fc_flag, phba->hba_state);
630
631 /* Check to see if there are more PLOGIs to be sent */
632 if (phba->fc_flag & FC_NLP_MORE) {
633 /* go thru NPR list and issue any remaining ELS PLOGIs */
634 sentplogi = lpfc_els_disc_plogi(phba);
635 }
636 return;
637}
638
James Smart488d1462006-03-07 15:02:37 -0500639static struct lpfc_nodelist *
James Smart92795652006-07-06 15:50:02 -0400640lpfc_plogi_confirm_nport(struct lpfc_hba * phba, struct lpfc_dmabuf *prsp,
James Smart488d1462006-03-07 15:02:37 -0500641 struct lpfc_nodelist *ndlp)
642{
643 struct lpfc_nodelist *new_ndlp;
James Smart488d1462006-03-07 15:02:37 -0500644 uint32_t *lp;
645 struct serv_parm *sp;
646 uint8_t name[sizeof (struct lpfc_name)];
647 uint32_t rc;
648
James Smart2fb9bd82006-12-02 13:33:57 -0500649 /* Fabric nodes can have the same WWPN so we don't bother searching
650 * by WWPN. Just return the ndlp that was given to us.
651 */
652 if (ndlp->nlp_type & NLP_FABRIC)
653 return ndlp;
654
James Smart488d1462006-03-07 15:02:37 -0500655 lp = (uint32_t *) prsp->virt;
656 sp = (struct serv_parm *) ((uint8_t *) lp + sizeof (uint32_t));
James Smart92795652006-07-06 15:50:02 -0400657 memset(name, 0, sizeof (struct lpfc_name));
James Smart488d1462006-03-07 15:02:37 -0500658
659 /* Now we to find out if the NPort we are logging into, matches the WWPN
660 * we have for that ndlp. If not, we have some work to do.
661 */
662 new_ndlp = lpfc_findnode_wwpn(phba, NLP_SEARCH_ALL, &sp->portName);
663
James Smart92795652006-07-06 15:50:02 -0400664 if (new_ndlp == ndlp)
James Smart488d1462006-03-07 15:02:37 -0500665 return ndlp;
James Smart488d1462006-03-07 15:02:37 -0500666
667 if (!new_ndlp) {
James Smart92795652006-07-06 15:50:02 -0400668 rc =
669 memcmp(&ndlp->nlp_portname, name, sizeof(struct lpfc_name));
670 if (!rc)
671 return ndlp;
James Smart488d1462006-03-07 15:02:37 -0500672 new_ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_ATOMIC);
673 if (!new_ndlp)
674 return ndlp;
675
676 lpfc_nlp_init(phba, new_ndlp, ndlp->nlp_DID);
677 }
678
679 lpfc_unreg_rpi(phba, new_ndlp);
James Smart488d1462006-03-07 15:02:37 -0500680 new_ndlp->nlp_DID = ndlp->nlp_DID;
James Smart92795652006-07-06 15:50:02 -0400681 new_ndlp->nlp_prev_state = ndlp->nlp_prev_state;
James Smartde0c5b32007-04-25 09:52:27 -0400682 lpfc_nlp_set_state(phba, new_ndlp, ndlp->nlp_state);
James Smart488d1462006-03-07 15:02:37 -0500683
684 /* Move this back to NPR list */
James Smartde0c5b32007-04-25 09:52:27 -0400685 if (memcmp(&ndlp->nlp_portname, name, sizeof(struct lpfc_name)) == 0)
686 lpfc_drop_node(phba, ndlp);
James Smart92795652006-07-06 15:50:02 -0400687 else {
688 lpfc_unreg_rpi(phba, ndlp);
689 ndlp->nlp_DID = 0; /* Two ndlps cannot have the same did */
James Smartde0c5b32007-04-25 09:52:27 -0400690 lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
James Smart92795652006-07-06 15:50:02 -0400691 }
James Smart488d1462006-03-07 15:02:37 -0500692 return new_ndlp;
693}
694
dea31012005-04-17 16:05:31 -0500695static void
696lpfc_cmpl_els_plogi(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
697 struct lpfc_iocbq * rspiocb)
698{
699 IOCB_t *irsp;
dea31012005-04-17 16:05:31 -0500700 struct lpfc_nodelist *ndlp;
James Smart92795652006-07-06 15:50:02 -0400701 struct lpfc_dmabuf *prsp;
dea31012005-04-17 16:05:31 -0500702 int disc, rc, did, type;
703
dea31012005-04-17 16:05:31 -0500704 /* we pass cmdiocb to state machine which needs rspiocb as well */
705 cmdiocb->context_un.rsp_iocb = rspiocb;
706
707 irsp = &rspiocb->iocb;
James Smart488d1462006-03-07 15:02:37 -0500708 ndlp = lpfc_findnode_did(phba, NLP_SEARCH_ALL,
709 irsp->un.elsreq64.remoteID);
710 if (!ndlp)
711 goto out;
dea31012005-04-17 16:05:31 -0500712
713 /* Since ndlp can be freed in the disc state machine, note if this node
714 * is being used during discovery.
715 */
716 disc = (ndlp->nlp_flag & NLP_NPR_2B_DISC);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500717 spin_lock_irq(phba->host->host_lock);
James Smart488d1462006-03-07 15:02:37 -0500718 ndlp->nlp_flag &= ~NLP_NPR_2B_DISC;
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500719 spin_unlock_irq(phba->host->host_lock);
dea31012005-04-17 16:05:31 -0500720 rc = 0;
721
722 /* PLOGI completes to NPort <nlp_DID> */
723 lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
724 "%d:0102 PLOGI completes to NPort x%x "
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500725 "Data: x%x x%x x%x x%x x%x\n",
dea31012005-04-17 16:05:31 -0500726 phba->brd_no, ndlp->nlp_DID, irsp->ulpStatus,
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500727 irsp->un.ulpWord[4], irsp->ulpTimeout, disc,
728 phba->num_disc_nodes);
dea31012005-04-17 16:05:31 -0500729
730 /* Check to see if link went down during discovery */
731 if (lpfc_els_chk_latt(phba)) {
732 spin_lock_irq(phba->host->host_lock);
733 ndlp->nlp_flag |= NLP_NPR_2B_DISC;
734 spin_unlock_irq(phba->host->host_lock);
735 goto out;
736 }
737
738 /* ndlp could be freed in DSM, save these values now */
739 type = ndlp->nlp_type;
740 did = ndlp->nlp_DID;
741
742 if (irsp->ulpStatus) {
743 /* Check for retry */
744 if (lpfc_els_retry(phba, cmdiocb, rspiocb)) {
745 /* ELS command is being retried */
746 if (disc) {
747 spin_lock_irq(phba->host->host_lock);
748 ndlp->nlp_flag |= NLP_NPR_2B_DISC;
749 spin_unlock_irq(phba->host->host_lock);
750 }
751 goto out;
752 }
753
754 /* PLOGI failed */
755 /* Do not call DSM for lpfc_els_abort'ed ELS cmds */
756 if ((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) &&
757 ((irsp->un.ulpWord[4] == IOERR_SLI_ABORTED) ||
James.Smart@Emulex.Com6281bfe2005-11-28 11:41:33 -0500758 (irsp->un.ulpWord[4] == IOERR_LINK_DOWN) ||
dea31012005-04-17 16:05:31 -0500759 (irsp->un.ulpWord[4] == IOERR_SLI_DOWN))) {
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500760 rc = NLP_STE_FREED_NODE;
Jamie Wellnitz2fe165b2006-02-28 19:25:31 -0500761 } else {
dea31012005-04-17 16:05:31 -0500762 rc = lpfc_disc_state_machine(phba, ndlp, cmdiocb,
763 NLP_EVT_CMPL_PLOGI);
764 }
765 } else {
766 /* Good status, call state machine */
James Smart92795652006-07-06 15:50:02 -0400767 prsp = list_entry(((struct lpfc_dmabuf *)
768 cmdiocb->context2)->list.next,
769 struct lpfc_dmabuf, list);
770 ndlp = lpfc_plogi_confirm_nport(phba, prsp, ndlp);
dea31012005-04-17 16:05:31 -0500771 rc = lpfc_disc_state_machine(phba, ndlp, cmdiocb,
772 NLP_EVT_CMPL_PLOGI);
773 }
774
dea31012005-04-17 16:05:31 -0500775 if (disc && phba->num_disc_nodes) {
776 /* Check to see if there are more PLOGIs to be sent */
777 lpfc_more_plogi(phba);
dea31012005-04-17 16:05:31 -0500778
James Smart10d4e952006-04-15 11:53:15 -0400779 if (phba->num_disc_nodes == 0) {
780 spin_lock_irq(phba->host->host_lock);
781 phba->fc_flag &= ~FC_NDISC_ACTIVE;
782 spin_unlock_irq(phba->host->host_lock);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500783
James Smart10d4e952006-04-15 11:53:15 -0400784 lpfc_can_disctmo(phba);
785 if (phba->fc_flag & FC_RSCN_MODE) {
786 /*
787 * Check to see if more RSCNs came in while
788 * we were processing this one.
789 */
790 if ((phba->fc_rscn_id_cnt == 0) &&
791 (!(phba->fc_flag & FC_RSCN_DISCOVERY))) {
792 spin_lock_irq(phba->host->host_lock);
793 phba->fc_flag &= ~FC_RSCN_MODE;
794 spin_unlock_irq(phba->host->host_lock);
795 } else {
796 lpfc_els_handle_rscn(phba);
797 }
dea31012005-04-17 16:05:31 -0500798 }
799 }
800 }
801
802out:
803 lpfc_els_free_iocb(phba, cmdiocb);
804 return;
805}
806
807int
James Smart488d1462006-03-07 15:02:37 -0500808lpfc_issue_els_plogi(struct lpfc_hba * phba, uint32_t did, uint8_t retry)
dea31012005-04-17 16:05:31 -0500809{
810 struct serv_parm *sp;
811 IOCB_t *icmd;
812 struct lpfc_iocbq *elsiocb;
813 struct lpfc_sli_ring *pring;
814 struct lpfc_sli *psli;
815 uint8_t *pcmd;
816 uint16_t cmdsize;
817
818 psli = &phba->sli;
819 pring = &psli->ring[LPFC_ELS_RING]; /* ELS ring */
820
821 cmdsize = (sizeof (uint32_t) + sizeof (struct serv_parm));
Randy Dunlap041976f2006-06-25 01:58:51 -0700822 elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry, NULL, did,
Jamie Wellnitz2fe165b2006-02-28 19:25:31 -0500823 ELS_CMD_PLOGI);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500824 if (!elsiocb)
825 return 1;
dea31012005-04-17 16:05:31 -0500826
827 icmd = &elsiocb->iocb;
828 pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
829
830 /* For PLOGI request, remainder of payload is service parameters */
831 *((uint32_t *) (pcmd)) = ELS_CMD_PLOGI;
832 pcmd += sizeof (uint32_t);
833 memcpy(pcmd, &phba->fc_sparam, sizeof (struct serv_parm));
834 sp = (struct serv_parm *) pcmd;
835
836 if (sp->cmn.fcphLow < FC_PH_4_3)
837 sp->cmn.fcphLow = FC_PH_4_3;
838
839 if (sp->cmn.fcphHigh < FC_PH3)
840 sp->cmn.fcphHigh = FC_PH3;
841
842 phba->fc_stat.elsXmitPLOGI++;
843 elsiocb->iocb_cmpl = lpfc_cmpl_els_plogi;
844 spin_lock_irq(phba->host->host_lock);
dea31012005-04-17 16:05:31 -0500845 if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) {
dea31012005-04-17 16:05:31 -0500846 spin_unlock_irq(phba->host->host_lock);
847 lpfc_els_free_iocb(phba, elsiocb);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500848 return 1;
dea31012005-04-17 16:05:31 -0500849 }
850 spin_unlock_irq(phba->host->host_lock);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500851 return 0;
dea31012005-04-17 16:05:31 -0500852}
853
854static void
855lpfc_cmpl_els_prli(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
856 struct lpfc_iocbq * rspiocb)
857{
858 IOCB_t *irsp;
859 struct lpfc_sli *psli;
860 struct lpfc_nodelist *ndlp;
861
862 psli = &phba->sli;
863 /* we pass cmdiocb to state machine which needs rspiocb as well */
864 cmdiocb->context_un.rsp_iocb = rspiocb;
865
866 irsp = &(rspiocb->iocb);
867 ndlp = (struct lpfc_nodelist *) cmdiocb->context1;
868 spin_lock_irq(phba->host->host_lock);
869 ndlp->nlp_flag &= ~NLP_PRLI_SND;
870 spin_unlock_irq(phba->host->host_lock);
871
872 /* PRLI completes to NPort <nlp_DID> */
873 lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
874 "%d:0103 PRLI completes to NPort x%x "
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500875 "Data: x%x x%x x%x x%x\n",
dea31012005-04-17 16:05:31 -0500876 phba->brd_no, ndlp->nlp_DID, irsp->ulpStatus,
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500877 irsp->un.ulpWord[4], irsp->ulpTimeout,
878 phba->num_disc_nodes);
dea31012005-04-17 16:05:31 -0500879
880 phba->fc_prli_sent--;
881 /* Check to see if link went down during discovery */
882 if (lpfc_els_chk_latt(phba))
883 goto out;
884
885 if (irsp->ulpStatus) {
886 /* Check for retry */
887 if (lpfc_els_retry(phba, cmdiocb, rspiocb)) {
888 /* ELS command is being retried */
889 goto out;
890 }
891 /* PRLI failed */
892 /* Do not call DSM for lpfc_els_abort'ed ELS cmds */
893 if ((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) &&
894 ((irsp->un.ulpWord[4] == IOERR_SLI_ABORTED) ||
James.Smart@Emulex.Com6281bfe2005-11-28 11:41:33 -0500895 (irsp->un.ulpWord[4] == IOERR_LINK_DOWN) ||
dea31012005-04-17 16:05:31 -0500896 (irsp->un.ulpWord[4] == IOERR_SLI_DOWN))) {
897 goto out;
Jamie Wellnitz2fe165b2006-02-28 19:25:31 -0500898 } else {
dea31012005-04-17 16:05:31 -0500899 lpfc_disc_state_machine(phba, ndlp, cmdiocb,
900 NLP_EVT_CMPL_PRLI);
901 }
902 } else {
903 /* Good status, call state machine */
904 lpfc_disc_state_machine(phba, ndlp, cmdiocb, NLP_EVT_CMPL_PRLI);
905 }
906
907out:
908 lpfc_els_free_iocb(phba, cmdiocb);
909 return;
910}
911
912int
913lpfc_issue_els_prli(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp,
914 uint8_t retry)
915{
916 PRLI *npr;
917 IOCB_t *icmd;
918 struct lpfc_iocbq *elsiocb;
919 struct lpfc_sli_ring *pring;
920 struct lpfc_sli *psli;
921 uint8_t *pcmd;
922 uint16_t cmdsize;
923
924 psli = &phba->sli;
925 pring = &psli->ring[LPFC_ELS_RING]; /* ELS ring */
926
927 cmdsize = (sizeof (uint32_t) + sizeof (PRLI));
James Smart488d1462006-03-07 15:02:37 -0500928 elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry, ndlp,
929 ndlp->nlp_DID, ELS_CMD_PRLI);
930 if (!elsiocb)
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500931 return 1;
dea31012005-04-17 16:05:31 -0500932
933 icmd = &elsiocb->iocb;
934 pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
935
936 /* For PRLI request, remainder of payload is service parameters */
937 memset(pcmd, 0, (sizeof (PRLI) + sizeof (uint32_t)));
938 *((uint32_t *) (pcmd)) = ELS_CMD_PRLI;
939 pcmd += sizeof (uint32_t);
940
941 /* For PRLI, remainder of payload is PRLI parameter page */
942 npr = (PRLI *) pcmd;
943 /*
944 * If our firmware version is 3.20 or later,
945 * set the following bits for FC-TAPE support.
946 */
947 if (phba->vpd.rev.feaLevelHigh >= 0x02) {
948 npr->ConfmComplAllowed = 1;
949 npr->Retry = 1;
950 npr->TaskRetryIdReq = 1;
951 }
952 npr->estabImagePair = 1;
953 npr->readXferRdyDis = 1;
954
955 /* For FCP support */
956 npr->prliType = PRLI_FCP_TYPE;
957 npr->initiatorFunc = 1;
958
959 phba->fc_stat.elsXmitPRLI++;
960 elsiocb->iocb_cmpl = lpfc_cmpl_els_prli;
961 spin_lock_irq(phba->host->host_lock);
962 ndlp->nlp_flag |= NLP_PRLI_SND;
963 if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) {
964 ndlp->nlp_flag &= ~NLP_PRLI_SND;
965 spin_unlock_irq(phba->host->host_lock);
966 lpfc_els_free_iocb(phba, elsiocb);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500967 return 1;
dea31012005-04-17 16:05:31 -0500968 }
969 spin_unlock_irq(phba->host->host_lock);
970 phba->fc_prli_sent++;
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500971 return 0;
dea31012005-04-17 16:05:31 -0500972}
973
974static void
975lpfc_more_adisc(struct lpfc_hba * phba)
976{
977 int sentadisc;
978
979 if (phba->num_disc_nodes)
980 phba->num_disc_nodes--;
981
982 /* Continue discovery with <num_disc_nodes> ADISCs to go */
983 lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
984 "%d:0210 Continue discovery with %d ADISCs to go "
985 "Data: x%x x%x x%x\n",
986 phba->brd_no, phba->num_disc_nodes, phba->fc_adisc_cnt,
987 phba->fc_flag, phba->hba_state);
988
989 /* Check to see if there are more ADISCs to be sent */
990 if (phba->fc_flag & FC_NLP_MORE) {
991 lpfc_set_disctmo(phba);
992
993 /* go thru NPR list and issue any remaining ELS ADISCs */
994 sentadisc = lpfc_els_disc_adisc(phba);
995 }
996 return;
997}
998
999static void
1000lpfc_rscn_disc(struct lpfc_hba * phba)
1001{
1002 /* RSCN discovery */
1003 /* go thru NPR list and issue ELS PLOGIs */
1004 if (phba->fc_npr_cnt) {
1005 if (lpfc_els_disc_plogi(phba))
1006 return;
1007 }
1008 if (phba->fc_flag & FC_RSCN_MODE) {
1009 /* Check to see if more RSCNs came in while we were
1010 * processing this one.
1011 */
1012 if ((phba->fc_rscn_id_cnt == 0) &&
1013 (!(phba->fc_flag & FC_RSCN_DISCOVERY))) {
1014 spin_lock_irq(phba->host->host_lock);
1015 phba->fc_flag &= ~FC_RSCN_MODE;
1016 spin_unlock_irq(phba->host->host_lock);
1017 } else {
1018 lpfc_els_handle_rscn(phba);
1019 }
1020 }
1021}
1022
1023static void
1024lpfc_cmpl_els_adisc(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
1025 struct lpfc_iocbq * rspiocb)
1026{
1027 IOCB_t *irsp;
1028 struct lpfc_sli *psli;
1029 struct lpfc_nodelist *ndlp;
1030 LPFC_MBOXQ_t *mbox;
1031 int disc, rc;
1032
1033 psli = &phba->sli;
1034
1035 /* we pass cmdiocb to state machine which needs rspiocb as well */
1036 cmdiocb->context_un.rsp_iocb = rspiocb;
1037
1038 irsp = &(rspiocb->iocb);
1039 ndlp = (struct lpfc_nodelist *) cmdiocb->context1;
dea31012005-04-17 16:05:31 -05001040
1041 /* Since ndlp can be freed in the disc state machine, note if this node
1042 * is being used during discovery.
1043 */
1044 disc = (ndlp->nlp_flag & NLP_NPR_2B_DISC);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001045 spin_lock_irq(phba->host->host_lock);
1046 ndlp->nlp_flag &= ~(NLP_ADISC_SND | NLP_NPR_2B_DISC);
1047 spin_unlock_irq(phba->host->host_lock);
dea31012005-04-17 16:05:31 -05001048
1049 /* ADISC completes to NPort <nlp_DID> */
1050 lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
1051 "%d:0104 ADISC completes to NPort x%x "
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001052 "Data: x%x x%x x%x x%x x%x\n",
dea31012005-04-17 16:05:31 -05001053 phba->brd_no, ndlp->nlp_DID, irsp->ulpStatus,
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001054 irsp->un.ulpWord[4], irsp->ulpTimeout, disc,
1055 phba->num_disc_nodes);
dea31012005-04-17 16:05:31 -05001056
1057 /* Check to see if link went down during discovery */
1058 if (lpfc_els_chk_latt(phba)) {
1059 spin_lock_irq(phba->host->host_lock);
1060 ndlp->nlp_flag |= NLP_NPR_2B_DISC;
1061 spin_unlock_irq(phba->host->host_lock);
1062 goto out;
1063 }
1064
1065 if (irsp->ulpStatus) {
1066 /* Check for retry */
1067 if (lpfc_els_retry(phba, cmdiocb, rspiocb)) {
1068 /* ELS command is being retried */
1069 if (disc) {
1070 spin_lock_irq(phba->host->host_lock);
1071 ndlp->nlp_flag |= NLP_NPR_2B_DISC;
1072 spin_unlock_irq(phba->host->host_lock);
1073 lpfc_set_disctmo(phba);
1074 }
1075 goto out;
1076 }
1077 /* ADISC failed */
1078 /* Do not call DSM for lpfc_els_abort'ed ELS cmds */
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001079 if ((irsp->ulpStatus != IOSTAT_LOCAL_REJECT) ||
1080 ((irsp->un.ulpWord[4] != IOERR_SLI_ABORTED) &&
1081 (irsp->un.ulpWord[4] != IOERR_LINK_DOWN) &&
1082 (irsp->un.ulpWord[4] != IOERR_SLI_DOWN))) {
dea31012005-04-17 16:05:31 -05001083 lpfc_disc_state_machine(phba, ndlp, cmdiocb,
1084 NLP_EVT_CMPL_ADISC);
1085 }
1086 } else {
1087 /* Good status, call state machine */
1088 lpfc_disc_state_machine(phba, ndlp, cmdiocb,
1089 NLP_EVT_CMPL_ADISC);
1090 }
1091
1092 if (disc && phba->num_disc_nodes) {
1093 /* Check to see if there are more ADISCs to be sent */
1094 lpfc_more_adisc(phba);
1095
1096 /* Check to see if we are done with ADISC authentication */
1097 if (phba->num_disc_nodes == 0) {
1098 lpfc_can_disctmo(phba);
1099 /* If we get here, there is nothing left to wait for */
1100 if ((phba->hba_state < LPFC_HBA_READY) &&
1101 (phba->hba_state != LPFC_CLEAR_LA)) {
1102 /* Link up discovery */
1103 if ((mbox = mempool_alloc(phba->mbox_mem_pool,
1104 GFP_KERNEL))) {
1105 phba->hba_state = LPFC_CLEAR_LA;
1106 lpfc_clear_la(phba, mbox);
1107 mbox->mbox_cmpl =
1108 lpfc_mbx_cmpl_clear_la;
1109 rc = lpfc_sli_issue_mbox
1110 (phba, mbox,
1111 (MBX_NOWAIT | MBX_STOP_IOCB));
1112 if (rc == MBX_NOT_FINISHED) {
1113 mempool_free(mbox,
1114 phba->mbox_mem_pool);
1115 lpfc_disc_flush_list(phba);
James Smarta4bc3372006-12-02 13:34:16 -05001116 psli->ring[(psli->extra_ring)].
dea31012005-04-17 16:05:31 -05001117 flag &=
1118 ~LPFC_STOP_IOCB_EVENT;
1119 psli->ring[(psli->fcp_ring)].
1120 flag &=
1121 ~LPFC_STOP_IOCB_EVENT;
1122 psli->ring[(psli->next_ring)].
1123 flag &=
1124 ~LPFC_STOP_IOCB_EVENT;
1125 phba->hba_state =
1126 LPFC_HBA_READY;
1127 }
1128 }
1129 } else {
1130 lpfc_rscn_disc(phba);
1131 }
1132 }
1133 }
dea31012005-04-17 16:05:31 -05001134out:
1135 lpfc_els_free_iocb(phba, cmdiocb);
1136 return;
1137}
1138
1139int
1140lpfc_issue_els_adisc(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp,
1141 uint8_t retry)
1142{
1143 ADISC *ap;
1144 IOCB_t *icmd;
1145 struct lpfc_iocbq *elsiocb;
1146 struct lpfc_sli_ring *pring;
1147 struct lpfc_sli *psli;
1148 uint8_t *pcmd;
1149 uint16_t cmdsize;
1150
1151 psli = &phba->sli;
1152 pring = &psli->ring[LPFC_ELS_RING]; /* ELS ring */
1153
1154 cmdsize = (sizeof (uint32_t) + sizeof (ADISC));
James Smart488d1462006-03-07 15:02:37 -05001155 elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry, ndlp,
1156 ndlp->nlp_DID, ELS_CMD_ADISC);
1157 if (!elsiocb)
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001158 return 1;
dea31012005-04-17 16:05:31 -05001159
1160 icmd = &elsiocb->iocb;
1161 pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
1162
1163 /* For ADISC request, remainder of payload is service parameters */
1164 *((uint32_t *) (pcmd)) = ELS_CMD_ADISC;
1165 pcmd += sizeof (uint32_t);
1166
1167 /* Fill in ADISC payload */
1168 ap = (ADISC *) pcmd;
1169 ap->hardAL_PA = phba->fc_pref_ALPA;
1170 memcpy(&ap->portName, &phba->fc_portname, sizeof (struct lpfc_name));
1171 memcpy(&ap->nodeName, &phba->fc_nodename, sizeof (struct lpfc_name));
1172 ap->DID = be32_to_cpu(phba->fc_myDID);
1173
1174 phba->fc_stat.elsXmitADISC++;
1175 elsiocb->iocb_cmpl = lpfc_cmpl_els_adisc;
1176 spin_lock_irq(phba->host->host_lock);
1177 ndlp->nlp_flag |= NLP_ADISC_SND;
1178 if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) {
1179 ndlp->nlp_flag &= ~NLP_ADISC_SND;
1180 spin_unlock_irq(phba->host->host_lock);
1181 lpfc_els_free_iocb(phba, elsiocb);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001182 return 1;
dea31012005-04-17 16:05:31 -05001183 }
1184 spin_unlock_irq(phba->host->host_lock);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001185 return 0;
dea31012005-04-17 16:05:31 -05001186}
1187
1188static void
1189lpfc_cmpl_els_logo(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
1190 struct lpfc_iocbq * rspiocb)
1191{
1192 IOCB_t *irsp;
1193 struct lpfc_sli *psli;
1194 struct lpfc_nodelist *ndlp;
1195
1196 psli = &phba->sli;
1197 /* we pass cmdiocb to state machine which needs rspiocb as well */
1198 cmdiocb->context_un.rsp_iocb = rspiocb;
1199
1200 irsp = &(rspiocb->iocb);
1201 ndlp = (struct lpfc_nodelist *) cmdiocb->context1;
1202 spin_lock_irq(phba->host->host_lock);
1203 ndlp->nlp_flag &= ~NLP_LOGO_SND;
1204 spin_unlock_irq(phba->host->host_lock);
1205
1206 /* LOGO completes to NPort <nlp_DID> */
1207 lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
1208 "%d:0105 LOGO completes to NPort x%x "
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001209 "Data: x%x x%x x%x x%x\n",
dea31012005-04-17 16:05:31 -05001210 phba->brd_no, ndlp->nlp_DID, irsp->ulpStatus,
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001211 irsp->un.ulpWord[4], irsp->ulpTimeout,
1212 phba->num_disc_nodes);
dea31012005-04-17 16:05:31 -05001213
1214 /* Check to see if link went down during discovery */
1215 if (lpfc_els_chk_latt(phba))
1216 goto out;
1217
1218 if (irsp->ulpStatus) {
1219 /* Check for retry */
1220 if (lpfc_els_retry(phba, cmdiocb, rspiocb)) {
1221 /* ELS command is being retried */
1222 goto out;
1223 }
1224 /* LOGO failed */
1225 /* Do not call DSM for lpfc_els_abort'ed ELS cmds */
1226 if ((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) &&
1227 ((irsp->un.ulpWord[4] == IOERR_SLI_ABORTED) ||
James.Smart@Emulex.Com6281bfe2005-11-28 11:41:33 -05001228 (irsp->un.ulpWord[4] == IOERR_LINK_DOWN) ||
dea31012005-04-17 16:05:31 -05001229 (irsp->un.ulpWord[4] == IOERR_SLI_DOWN))) {
1230 goto out;
Jamie Wellnitz2fe165b2006-02-28 19:25:31 -05001231 } else {
dea31012005-04-17 16:05:31 -05001232 lpfc_disc_state_machine(phba, ndlp, cmdiocb,
1233 NLP_EVT_CMPL_LOGO);
1234 }
1235 } else {
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05001236 /* Good status, call state machine.
1237 * This will unregister the rpi if needed.
1238 */
dea31012005-04-17 16:05:31 -05001239 lpfc_disc_state_machine(phba, ndlp, cmdiocb, NLP_EVT_CMPL_LOGO);
dea31012005-04-17 16:05:31 -05001240 }
1241
1242out:
1243 lpfc_els_free_iocb(phba, cmdiocb);
1244 return;
1245}
1246
1247int
1248lpfc_issue_els_logo(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp,
1249 uint8_t retry)
1250{
1251 IOCB_t *icmd;
1252 struct lpfc_iocbq *elsiocb;
1253 struct lpfc_sli_ring *pring;
1254 struct lpfc_sli *psli;
1255 uint8_t *pcmd;
1256 uint16_t cmdsize;
1257
1258 psli = &phba->sli;
1259 pring = &psli->ring[LPFC_ELS_RING];
1260
James Smart10d4e952006-04-15 11:53:15 -04001261 cmdsize = (2 * sizeof (uint32_t)) + sizeof (struct lpfc_name);
James Smart488d1462006-03-07 15:02:37 -05001262 elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry, ndlp,
1263 ndlp->nlp_DID, ELS_CMD_LOGO);
1264 if (!elsiocb)
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001265 return 1;
dea31012005-04-17 16:05:31 -05001266
1267 icmd = &elsiocb->iocb;
1268 pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
1269 *((uint32_t *) (pcmd)) = ELS_CMD_LOGO;
1270 pcmd += sizeof (uint32_t);
1271
1272 /* Fill in LOGO payload */
1273 *((uint32_t *) (pcmd)) = be32_to_cpu(phba->fc_myDID);
1274 pcmd += sizeof (uint32_t);
1275 memcpy(pcmd, &phba->fc_portname, sizeof (struct lpfc_name));
1276
1277 phba->fc_stat.elsXmitLOGO++;
1278 elsiocb->iocb_cmpl = lpfc_cmpl_els_logo;
1279 spin_lock_irq(phba->host->host_lock);
1280 ndlp->nlp_flag |= NLP_LOGO_SND;
1281 if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) {
1282 ndlp->nlp_flag &= ~NLP_LOGO_SND;
1283 spin_unlock_irq(phba->host->host_lock);
1284 lpfc_els_free_iocb(phba, elsiocb);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001285 return 1;
dea31012005-04-17 16:05:31 -05001286 }
1287 spin_unlock_irq(phba->host->host_lock);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001288 return 0;
dea31012005-04-17 16:05:31 -05001289}
1290
1291static void
1292lpfc_cmpl_els_cmd(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
1293 struct lpfc_iocbq * rspiocb)
1294{
1295 IOCB_t *irsp;
1296
1297 irsp = &rspiocb->iocb;
1298
1299 /* ELS cmd tag <ulpIoTag> completes */
1300 lpfc_printf_log(phba,
1301 KERN_INFO,
1302 LOG_ELS,
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001303 "%d:0106 ELS cmd tag x%x completes Data: x%x x%x x%x\n",
dea31012005-04-17 16:05:31 -05001304 phba->brd_no,
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001305 irsp->ulpIoTag, irsp->ulpStatus,
1306 irsp->un.ulpWord[4], irsp->ulpTimeout);
dea31012005-04-17 16:05:31 -05001307
1308 /* Check to see if link went down during discovery */
1309 lpfc_els_chk_latt(phba);
1310 lpfc_els_free_iocb(phba, cmdiocb);
1311 return;
1312}
1313
1314int
1315lpfc_issue_els_scr(struct lpfc_hba * phba, uint32_t nportid, uint8_t retry)
1316{
1317 IOCB_t *icmd;
1318 struct lpfc_iocbq *elsiocb;
1319 struct lpfc_sli_ring *pring;
1320 struct lpfc_sli *psli;
1321 uint8_t *pcmd;
1322 uint16_t cmdsize;
1323 struct lpfc_nodelist *ndlp;
1324
1325 psli = &phba->sli;
1326 pring = &psli->ring[LPFC_ELS_RING]; /* ELS ring */
1327 cmdsize = (sizeof (uint32_t) + sizeof (SCR));
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001328 ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL);
1329 if (!ndlp)
1330 return 1;
dea31012005-04-17 16:05:31 -05001331
1332 lpfc_nlp_init(phba, ndlp, nportid);
1333
James Smart488d1462006-03-07 15:02:37 -05001334 elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry, ndlp,
1335 ndlp->nlp_DID, ELS_CMD_SCR);
1336 if (!elsiocb) {
dea31012005-04-17 16:05:31 -05001337 mempool_free( ndlp, phba->nlp_mem_pool);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001338 return 1;
dea31012005-04-17 16:05:31 -05001339 }
1340
1341 icmd = &elsiocb->iocb;
1342 pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
1343
1344 *((uint32_t *) (pcmd)) = ELS_CMD_SCR;
1345 pcmd += sizeof (uint32_t);
1346
1347 /* For SCR, remainder of payload is SCR parameter page */
1348 memset(pcmd, 0, sizeof (SCR));
1349 ((SCR *) pcmd)->Function = SCR_FUNC_FULL;
1350
1351 phba->fc_stat.elsXmitSCR++;
1352 elsiocb->iocb_cmpl = lpfc_cmpl_els_cmd;
1353 spin_lock_irq(phba->host->host_lock);
1354 if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) {
1355 spin_unlock_irq(phba->host->host_lock);
1356 mempool_free( ndlp, phba->nlp_mem_pool);
1357 lpfc_els_free_iocb(phba, elsiocb);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001358 return 1;
dea31012005-04-17 16:05:31 -05001359 }
1360 spin_unlock_irq(phba->host->host_lock);
1361 mempool_free( ndlp, phba->nlp_mem_pool);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001362 return 0;
dea31012005-04-17 16:05:31 -05001363}
1364
1365static int
1366lpfc_issue_els_farpr(struct lpfc_hba * phba, uint32_t nportid, uint8_t retry)
1367{
1368 IOCB_t *icmd;
1369 struct lpfc_iocbq *elsiocb;
1370 struct lpfc_sli_ring *pring;
1371 struct lpfc_sli *psli;
1372 FARP *fp;
1373 uint8_t *pcmd;
1374 uint32_t *lp;
1375 uint16_t cmdsize;
1376 struct lpfc_nodelist *ondlp;
1377 struct lpfc_nodelist *ndlp;
1378
1379 psli = &phba->sli;
1380 pring = &psli->ring[LPFC_ELS_RING]; /* ELS ring */
1381 cmdsize = (sizeof (uint32_t) + sizeof (FARP));
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001382 ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL);
1383 if (!ndlp)
1384 return 1;
dea31012005-04-17 16:05:31 -05001385 lpfc_nlp_init(phba, ndlp, nportid);
1386
James Smart488d1462006-03-07 15:02:37 -05001387 elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry, ndlp,
1388 ndlp->nlp_DID, ELS_CMD_RNID);
1389 if (!elsiocb) {
dea31012005-04-17 16:05:31 -05001390 mempool_free( ndlp, phba->nlp_mem_pool);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001391 return 1;
dea31012005-04-17 16:05:31 -05001392 }
1393
1394 icmd = &elsiocb->iocb;
1395 pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
1396
1397 *((uint32_t *) (pcmd)) = ELS_CMD_FARPR;
1398 pcmd += sizeof (uint32_t);
1399
1400 /* Fill in FARPR payload */
1401 fp = (FARP *) (pcmd);
1402 memset(fp, 0, sizeof (FARP));
1403 lp = (uint32_t *) pcmd;
1404 *lp++ = be32_to_cpu(nportid);
1405 *lp++ = be32_to_cpu(phba->fc_myDID);
1406 fp->Rflags = 0;
1407 fp->Mflags = (FARP_MATCH_PORT | FARP_MATCH_NODE);
1408
1409 memcpy(&fp->RportName, &phba->fc_portname, sizeof (struct lpfc_name));
1410 memcpy(&fp->RnodeName, &phba->fc_nodename, sizeof (struct lpfc_name));
1411 if ((ondlp = lpfc_findnode_did(phba, NLP_SEARCH_ALL, nportid))) {
1412 memcpy(&fp->OportName, &ondlp->nlp_portname,
1413 sizeof (struct lpfc_name));
1414 memcpy(&fp->OnodeName, &ondlp->nlp_nodename,
1415 sizeof (struct lpfc_name));
1416 }
1417
1418 phba->fc_stat.elsXmitFARPR++;
1419 elsiocb->iocb_cmpl = lpfc_cmpl_els_cmd;
1420 spin_lock_irq(phba->host->host_lock);
1421 if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) {
1422 spin_unlock_irq(phba->host->host_lock);
1423 mempool_free( ndlp, phba->nlp_mem_pool);
1424 lpfc_els_free_iocb(phba, elsiocb);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001425 return 1;
dea31012005-04-17 16:05:31 -05001426 }
1427 spin_unlock_irq(phba->host->host_lock);
1428 mempool_free( ndlp, phba->nlp_mem_pool);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001429 return 0;
dea31012005-04-17 16:05:31 -05001430}
1431
1432void
James Smartfdcebe22006-03-07 15:04:01 -05001433lpfc_cancel_retry_delay_tmo(struct lpfc_hba *phba, struct lpfc_nodelist * nlp)
1434{
1435 nlp->nlp_flag &= ~NLP_DELAY_TMO;
1436 del_timer_sync(&nlp->nlp_delayfunc);
1437 nlp->nlp_last_elscmd = 0;
1438
1439 if (!list_empty(&nlp->els_retry_evt.evt_listp))
1440 list_del_init(&nlp->els_retry_evt.evt_listp);
1441
1442 if (nlp->nlp_flag & NLP_NPR_2B_DISC) {
1443 nlp->nlp_flag &= ~NLP_NPR_2B_DISC;
1444 if (phba->num_disc_nodes) {
1445 /* Check to see if there are more
1446 * PLOGIs to be sent
1447 */
1448 lpfc_more_plogi(phba);
James Smartfdcebe22006-03-07 15:04:01 -05001449
James Smart10d4e952006-04-15 11:53:15 -04001450 if (phba->num_disc_nodes == 0) {
1451 phba->fc_flag &= ~FC_NDISC_ACTIVE;
1452 lpfc_can_disctmo(phba);
1453 if (phba->fc_flag & FC_RSCN_MODE) {
1454 /*
1455 * Check to see if more RSCNs
1456 * came in while we were
1457 * processing this one.
1458 */
1459 if((phba->fc_rscn_id_cnt==0) &&
1460 !(phba->fc_flag & FC_RSCN_DISCOVERY)) {
1461 phba->fc_flag &= ~FC_RSCN_MODE;
1462 }
1463 else {
1464 lpfc_els_handle_rscn(phba);
1465 }
James Smartfdcebe22006-03-07 15:04:01 -05001466 }
1467 }
1468 }
1469 }
1470 return;
1471}
1472
1473void
dea31012005-04-17 16:05:31 -05001474lpfc_els_retry_delay(unsigned long ptr)
1475{
1476 struct lpfc_nodelist *ndlp;
1477 struct lpfc_hba *phba;
1478 unsigned long iflag;
1479 struct lpfc_work_evt *evtp;
1480
1481 ndlp = (struct lpfc_nodelist *)ptr;
1482 phba = ndlp->nlp_phba;
1483 evtp = &ndlp->els_retry_evt;
1484
1485 spin_lock_irqsave(phba->host->host_lock, iflag);
1486 if (!list_empty(&evtp->evt_listp)) {
1487 spin_unlock_irqrestore(phba->host->host_lock, iflag);
1488 return;
1489 }
1490
1491 evtp->evt_arg1 = ndlp;
1492 evtp->evt = LPFC_EVT_ELS_RETRY;
1493 list_add_tail(&evtp->evt_listp, &phba->work_list);
1494 if (phba->work_wait)
1495 wake_up(phba->work_wait);
1496
1497 spin_unlock_irqrestore(phba->host->host_lock, iflag);
1498 return;
1499}
1500
1501void
1502lpfc_els_retry_delay_handler(struct lpfc_nodelist *ndlp)
1503{
1504 struct lpfc_hba *phba;
1505 uint32_t cmd;
1506 uint32_t did;
1507 uint8_t retry;
1508
1509 phba = ndlp->nlp_phba;
1510 spin_lock_irq(phba->host->host_lock);
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05001511 did = ndlp->nlp_DID;
1512 cmd = ndlp->nlp_last_elscmd;
1513 ndlp->nlp_last_elscmd = 0;
dea31012005-04-17 16:05:31 -05001514
1515 if (!(ndlp->nlp_flag & NLP_DELAY_TMO)) {
1516 spin_unlock_irq(phba->host->host_lock);
1517 return;
1518 }
1519
1520 ndlp->nlp_flag &= ~NLP_DELAY_TMO;
1521 spin_unlock_irq(phba->host->host_lock);
James Smart1a169682006-03-07 15:04:06 -05001522 /*
1523 * If a discovery event readded nlp_delayfunc after timer
1524 * firing and before processing the timer, cancel the
1525 * nlp_delayfunc.
1526 */
1527 del_timer_sync(&ndlp->nlp_delayfunc);
dea31012005-04-17 16:05:31 -05001528 retry = ndlp->nlp_retry;
1529
1530 switch (cmd) {
1531 case ELS_CMD_FLOGI:
1532 lpfc_issue_els_flogi(phba, ndlp, retry);
1533 break;
1534 case ELS_CMD_PLOGI:
James Smart488d1462006-03-07 15:02:37 -05001535 if(!lpfc_issue_els_plogi(phba, ndlp->nlp_DID, retry)) {
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05001536 ndlp->nlp_prev_state = ndlp->nlp_state;
James Smartde0c5b32007-04-25 09:52:27 -04001537 lpfc_nlp_set_state(phba, ndlp, NLP_STE_PLOGI_ISSUE);
Jamie Wellnitz6ad42532006-02-28 19:25:16 -05001538 }
dea31012005-04-17 16:05:31 -05001539 break;
1540 case ELS_CMD_ADISC:
Jamie Wellnitz6ad42532006-02-28 19:25:16 -05001541 if (!lpfc_issue_els_adisc(phba, ndlp, retry)) {
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05001542 ndlp->nlp_prev_state = ndlp->nlp_state;
James Smartde0c5b32007-04-25 09:52:27 -04001543 lpfc_nlp_set_state(phba, ndlp, NLP_STE_ADISC_ISSUE);
Jamie Wellnitz6ad42532006-02-28 19:25:16 -05001544 }
dea31012005-04-17 16:05:31 -05001545 break;
1546 case ELS_CMD_PRLI:
Jamie Wellnitz6ad42532006-02-28 19:25:16 -05001547 if (!lpfc_issue_els_prli(phba, ndlp, retry)) {
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05001548 ndlp->nlp_prev_state = ndlp->nlp_state;
James Smartde0c5b32007-04-25 09:52:27 -04001549 lpfc_nlp_set_state(phba, ndlp, NLP_STE_PRLI_ISSUE);
Jamie Wellnitz6ad42532006-02-28 19:25:16 -05001550 }
dea31012005-04-17 16:05:31 -05001551 break;
1552 case ELS_CMD_LOGO:
Jamie Wellnitz6ad42532006-02-28 19:25:16 -05001553 if (!lpfc_issue_els_logo(phba, ndlp, retry)) {
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05001554 ndlp->nlp_prev_state = ndlp->nlp_state;
James Smartde0c5b32007-04-25 09:52:27 -04001555 lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
Jamie Wellnitz6ad42532006-02-28 19:25:16 -05001556 }
dea31012005-04-17 16:05:31 -05001557 break;
1558 }
1559 return;
1560}
1561
1562static int
1563lpfc_els_retry(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
1564 struct lpfc_iocbq * rspiocb)
1565{
1566 IOCB_t *irsp;
1567 struct lpfc_dmabuf *pcmd;
1568 struct lpfc_nodelist *ndlp;
1569 uint32_t *elscmd;
1570 struct ls_rjt stat;
1571 int retry, maxretry;
1572 int delay;
1573 uint32_t cmd;
James Smart488d1462006-03-07 15:02:37 -05001574 uint32_t did;
dea31012005-04-17 16:05:31 -05001575
1576 retry = 0;
1577 delay = 0;
1578 maxretry = lpfc_max_els_tries;
1579 irsp = &rspiocb->iocb;
1580 ndlp = (struct lpfc_nodelist *) cmdiocb->context1;
1581 pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
1582 cmd = 0;
James Smart488d1462006-03-07 15:02:37 -05001583
dea31012005-04-17 16:05:31 -05001584 /* Note: context2 may be 0 for internal driver abort
1585 * of delays ELS command.
1586 */
1587
1588 if (pcmd && pcmd->virt) {
1589 elscmd = (uint32_t *) (pcmd->virt);
1590 cmd = *elscmd++;
1591 }
1592
James Smart488d1462006-03-07 15:02:37 -05001593 if(ndlp)
1594 did = ndlp->nlp_DID;
1595 else {
1596 /* We should only hit this case for retrying PLOGI */
1597 did = irsp->un.elsreq64.remoteID;
1598 ndlp = lpfc_findnode_did(phba, NLP_SEARCH_ALL, did);
1599 if (!ndlp && (cmd != ELS_CMD_PLOGI))
1600 return 1;
1601 }
1602
dea31012005-04-17 16:05:31 -05001603 switch (irsp->ulpStatus) {
1604 case IOSTAT_FCP_RSP_ERROR:
1605 case IOSTAT_REMOTE_STOP:
1606 break;
1607
1608 case IOSTAT_LOCAL_REJECT:
1609 switch ((irsp->un.ulpWord[4] & 0xff)) {
1610 case IOERR_LOOP_OPEN_FAILURE:
1611 if (cmd == ELS_CMD_PLOGI) {
1612 if (cmdiocb->retry == 0) {
1613 delay = 1;
1614 }
1615 }
1616 retry = 1;
1617 break;
1618
1619 case IOERR_SEQUENCE_TIMEOUT:
1620 retry = 1;
dea31012005-04-17 16:05:31 -05001621 break;
1622
1623 case IOERR_NO_RESOURCES:
1624 if (cmd == ELS_CMD_PLOGI) {
1625 delay = 1;
1626 }
1627 retry = 1;
1628 break;
1629
1630 case IOERR_INVALID_RPI:
1631 retry = 1;
1632 break;
1633 }
1634 break;
1635
1636 case IOSTAT_NPORT_RJT:
1637 case IOSTAT_FABRIC_RJT:
1638 if (irsp->un.ulpWord[4] & RJT_UNAVAIL_TEMP) {
1639 retry = 1;
1640 break;
1641 }
1642 break;
1643
1644 case IOSTAT_NPORT_BSY:
1645 case IOSTAT_FABRIC_BSY:
1646 retry = 1;
1647 break;
1648
1649 case IOSTAT_LS_RJT:
1650 stat.un.lsRjtError = be32_to_cpu(irsp->un.ulpWord[4]);
1651 /* Added for Vendor specifc support
1652 * Just keep retrying for these Rsn / Exp codes
1653 */
1654 switch (stat.un.b.lsRjtRsnCode) {
1655 case LSRJT_UNABLE_TPC:
1656 if (stat.un.b.lsRjtRsnCodeExp ==
1657 LSEXP_CMD_IN_PROGRESS) {
1658 if (cmd == ELS_CMD_PLOGI) {
1659 delay = 1;
1660 maxretry = 48;
1661 }
1662 retry = 1;
1663 break;
1664 }
1665 if (cmd == ELS_CMD_PLOGI) {
1666 delay = 1;
1667 maxretry = lpfc_max_els_tries + 1;
1668 retry = 1;
1669 break;
1670 }
1671 break;
1672
1673 case LSRJT_LOGICAL_BSY:
1674 if (cmd == ELS_CMD_PLOGI) {
1675 delay = 1;
1676 maxretry = 48;
1677 }
1678 retry = 1;
1679 break;
1680 }
1681 break;
1682
1683 case IOSTAT_INTERMED_RSP:
1684 case IOSTAT_BA_RJT:
1685 break;
1686
1687 default:
1688 break;
1689 }
1690
James Smart488d1462006-03-07 15:02:37 -05001691 if (did == FDMI_DID)
dea31012005-04-17 16:05:31 -05001692 retry = 1;
dea31012005-04-17 16:05:31 -05001693
1694 if ((++cmdiocb->retry) >= maxretry) {
1695 phba->fc_stat.elsRetryExceeded++;
1696 retry = 0;
1697 }
1698
1699 if (retry) {
1700
1701 /* Retry ELS command <elsCmd> to remote NPORT <did> */
1702 lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
1703 "%d:0107 Retry ELS command x%x to remote "
1704 "NPORT x%x Data: x%x x%x\n",
1705 phba->brd_no,
James Smart488d1462006-03-07 15:02:37 -05001706 cmd, did, cmdiocb->retry, delay);
dea31012005-04-17 16:05:31 -05001707
1708 if ((cmd == ELS_CMD_PLOGI) || (cmd == ELS_CMD_ADISC)) {
1709 /* If discovery / RSCN timer is running, reset it */
1710 if (timer_pending(&phba->fc_disctmo) ||
1711 (phba->fc_flag & FC_RSCN_MODE)) {
1712 lpfc_set_disctmo(phba);
1713 }
1714 }
1715
1716 phba->fc_stat.elsXmitRetry++;
James Smart488d1462006-03-07 15:02:37 -05001717 if (ndlp && delay) {
dea31012005-04-17 16:05:31 -05001718 phba->fc_stat.elsDelayRetry++;
1719 ndlp->nlp_retry = cmdiocb->retry;
1720
1721 mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ);
1722 ndlp->nlp_flag |= NLP_DELAY_TMO;
1723
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05001724 ndlp->nlp_prev_state = ndlp->nlp_state;
James Smartde0c5b32007-04-25 09:52:27 -04001725 lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
dea31012005-04-17 16:05:31 -05001726 ndlp->nlp_last_elscmd = cmd;
1727
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001728 return 1;
dea31012005-04-17 16:05:31 -05001729 }
1730 switch (cmd) {
1731 case ELS_CMD_FLOGI:
1732 lpfc_issue_els_flogi(phba, ndlp, cmdiocb->retry);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001733 return 1;
dea31012005-04-17 16:05:31 -05001734 case ELS_CMD_PLOGI:
James Smart488d1462006-03-07 15:02:37 -05001735 if (ndlp) {
1736 ndlp->nlp_prev_state = ndlp->nlp_state;
James Smartde0c5b32007-04-25 09:52:27 -04001737 lpfc_nlp_set_state(phba, ndlp,
1738 NLP_STE_PLOGI_ISSUE);
James Smart488d1462006-03-07 15:02:37 -05001739 }
1740 lpfc_issue_els_plogi(phba, did, cmdiocb->retry);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001741 return 1;
dea31012005-04-17 16:05:31 -05001742 case ELS_CMD_ADISC:
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05001743 ndlp->nlp_prev_state = ndlp->nlp_state;
James Smartde0c5b32007-04-25 09:52:27 -04001744 lpfc_nlp_set_state(phba, ndlp, NLP_STE_ADISC_ISSUE);
dea31012005-04-17 16:05:31 -05001745 lpfc_issue_els_adisc(phba, ndlp, cmdiocb->retry);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001746 return 1;
dea31012005-04-17 16:05:31 -05001747 case ELS_CMD_PRLI:
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05001748 ndlp->nlp_prev_state = ndlp->nlp_state;
James Smartde0c5b32007-04-25 09:52:27 -04001749 lpfc_nlp_set_state(phba, ndlp, NLP_STE_PRLI_ISSUE);
dea31012005-04-17 16:05:31 -05001750 lpfc_issue_els_prli(phba, ndlp, cmdiocb->retry);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001751 return 1;
dea31012005-04-17 16:05:31 -05001752 case ELS_CMD_LOGO:
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05001753 ndlp->nlp_prev_state = ndlp->nlp_state;
James Smartde0c5b32007-04-25 09:52:27 -04001754 lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
dea31012005-04-17 16:05:31 -05001755 lpfc_issue_els_logo(phba, ndlp, cmdiocb->retry);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001756 return 1;
dea31012005-04-17 16:05:31 -05001757 }
1758 }
1759
1760 /* No retry ELS command <elsCmd> to remote NPORT <did> */
1761 lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
1762 "%d:0108 No retry ELS command x%x to remote NPORT x%x "
James Smart488d1462006-03-07 15:02:37 -05001763 "Data: x%x\n",
dea31012005-04-17 16:05:31 -05001764 phba->brd_no,
James Smart488d1462006-03-07 15:02:37 -05001765 cmd, did, cmdiocb->retry);
dea31012005-04-17 16:05:31 -05001766
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001767 return 0;
dea31012005-04-17 16:05:31 -05001768}
1769
1770int
1771lpfc_els_free_iocb(struct lpfc_hba * phba, struct lpfc_iocbq * elsiocb)
1772{
1773 struct lpfc_dmabuf *buf_ptr, *buf_ptr1;
1774
1775 /* context2 = cmd, context2->next = rsp, context3 = bpl */
1776 if (elsiocb->context2) {
1777 buf_ptr1 = (struct lpfc_dmabuf *) elsiocb->context2;
1778 /* Free the response before processing the command. */
1779 if (!list_empty(&buf_ptr1->list)) {
1780 list_remove_head(&buf_ptr1->list, buf_ptr,
1781 struct lpfc_dmabuf,
1782 list);
1783 lpfc_mbuf_free(phba, buf_ptr->virt, buf_ptr->phys);
1784 kfree(buf_ptr);
1785 }
1786 lpfc_mbuf_free(phba, buf_ptr1->virt, buf_ptr1->phys);
1787 kfree(buf_ptr1);
1788 }
1789
1790 if (elsiocb->context3) {
1791 buf_ptr = (struct lpfc_dmabuf *) elsiocb->context3;
1792 lpfc_mbuf_free(phba, buf_ptr->virt, buf_ptr->phys);
1793 kfree(buf_ptr);
1794 }
1795 spin_lock_irq(phba->host->host_lock);
James Bottomley604a3e32005-10-29 10:28:33 -05001796 lpfc_sli_release_iocbq(phba, elsiocb);
dea31012005-04-17 16:05:31 -05001797 spin_unlock_irq(phba->host->host_lock);
1798 return 0;
1799}
1800
1801static void
1802lpfc_cmpl_els_logo_acc(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
1803 struct lpfc_iocbq * rspiocb)
1804{
1805 struct lpfc_nodelist *ndlp;
1806
1807 ndlp = (struct lpfc_nodelist *) cmdiocb->context1;
1808
1809 /* ACC to LOGO completes to NPort <nlp_DID> */
1810 lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
1811 "%d:0109 ACC to LOGO completes to NPort x%x "
1812 "Data: x%x x%x x%x\n",
1813 phba->brd_no, ndlp->nlp_DID, ndlp->nlp_flag,
1814 ndlp->nlp_state, ndlp->nlp_rpi);
1815
dea31012005-04-17 16:05:31 -05001816 switch (ndlp->nlp_state) {
1817 case NLP_STE_UNUSED_NODE: /* node is just allocated */
James Smartde0c5b32007-04-25 09:52:27 -04001818 lpfc_drop_node(phba, ndlp);
dea31012005-04-17 16:05:31 -05001819 break;
1820 case NLP_STE_NPR_NODE: /* NPort Recovery mode */
1821 lpfc_unreg_rpi(phba, ndlp);
1822 break;
1823 default:
1824 break;
1825 }
1826 lpfc_els_free_iocb(phba, cmdiocb);
1827 return;
1828}
1829
1830static void
1831lpfc_cmpl_els_acc(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
1832 struct lpfc_iocbq * rspiocb)
1833{
James Smart33ccf8d2006-08-17 11:57:58 -04001834 IOCB_t *irsp;
dea31012005-04-17 16:05:31 -05001835 struct lpfc_nodelist *ndlp;
1836 LPFC_MBOXQ_t *mbox = NULL;
James Smart14691152006-12-02 13:34:28 -05001837 struct lpfc_dmabuf *mp;
dea31012005-04-17 16:05:31 -05001838
James Smart33ccf8d2006-08-17 11:57:58 -04001839 irsp = &rspiocb->iocb;
1840
dea31012005-04-17 16:05:31 -05001841 ndlp = (struct lpfc_nodelist *) cmdiocb->context1;
1842 if (cmdiocb->context_un.mbox)
1843 mbox = cmdiocb->context_un.mbox;
1844
1845
1846 /* Check to see if link went down during discovery */
1847 if ((lpfc_els_chk_latt(phba)) || !ndlp) {
1848 if (mbox) {
James Smart14691152006-12-02 13:34:28 -05001849 mp = (struct lpfc_dmabuf *) mbox->context1;
1850 if (mp) {
1851 lpfc_mbuf_free(phba, mp->virt, mp->phys);
1852 kfree(mp);
1853 }
dea31012005-04-17 16:05:31 -05001854 mempool_free( mbox, phba->mbox_mem_pool);
1855 }
1856 goto out;
1857 }
1858
1859 /* ELS response tag <ulpIoTag> completes */
1860 lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
1861 "%d:0110 ELS response tag x%x completes "
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001862 "Data: x%x x%x x%x x%x x%x x%x x%x\n",
dea31012005-04-17 16:05:31 -05001863 phba->brd_no,
1864 cmdiocb->iocb.ulpIoTag, rspiocb->iocb.ulpStatus,
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001865 rspiocb->iocb.un.ulpWord[4], rspiocb->iocb.ulpTimeout,
1866 ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state,
1867 ndlp->nlp_rpi);
dea31012005-04-17 16:05:31 -05001868
1869 if (mbox) {
1870 if ((rspiocb->iocb.ulpStatus == 0)
1871 && (ndlp->nlp_flag & NLP_ACC_REGLOGIN)) {
dea31012005-04-17 16:05:31 -05001872 lpfc_unreg_rpi(phba, ndlp);
1873 mbox->mbox_cmpl = lpfc_mbx_cmpl_reg_login;
1874 mbox->context2 = ndlp;
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05001875 ndlp->nlp_prev_state = ndlp->nlp_state;
James Smartde0c5b32007-04-25 09:52:27 -04001876 lpfc_nlp_set_state(phba, ndlp, NLP_STE_REG_LOGIN_ISSUE);
dea31012005-04-17 16:05:31 -05001877 if (lpfc_sli_issue_mbox(phba, mbox,
1878 (MBX_NOWAIT | MBX_STOP_IOCB))
1879 != MBX_NOT_FINISHED) {
1880 goto out;
1881 }
1882 /* NOTE: we should have messages for unsuccessful
1883 reglogin */
dea31012005-04-17 16:05:31 -05001884 } else {
James Smart33ccf8d2006-08-17 11:57:58 -04001885 /* Do not call NO_LIST for lpfc_els_abort'ed ELS cmds */
1886 if (!((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) &&
1887 ((irsp->un.ulpWord[4] == IOERR_SLI_ABORTED) ||
1888 (irsp->un.ulpWord[4] == IOERR_LINK_DOWN) ||
1889 (irsp->un.ulpWord[4] == IOERR_SLI_DOWN)))) {
1890 if (ndlp->nlp_flag & NLP_ACC_REGLOGIN) {
James Smartde0c5b32007-04-25 09:52:27 -04001891 lpfc_drop_node(phba, ndlp);
James Smart33ccf8d2006-08-17 11:57:58 -04001892 ndlp = NULL;
1893 }
dea31012005-04-17 16:05:31 -05001894 }
1895 }
James Smart14691152006-12-02 13:34:28 -05001896 mp = (struct lpfc_dmabuf *) mbox->context1;
1897 if (mp) {
1898 lpfc_mbuf_free(phba, mp->virt, mp->phys);
1899 kfree(mp);
1900 }
1901 mempool_free(mbox, phba->mbox_mem_pool);
dea31012005-04-17 16:05:31 -05001902 }
1903out:
1904 if (ndlp) {
1905 spin_lock_irq(phba->host->host_lock);
1906 ndlp->nlp_flag &= ~NLP_ACC_REGLOGIN;
1907 spin_unlock_irq(phba->host->host_lock);
1908 }
1909 lpfc_els_free_iocb(phba, cmdiocb);
1910 return;
1911}
1912
1913int
1914lpfc_els_rsp_acc(struct lpfc_hba * phba, uint32_t flag,
1915 struct lpfc_iocbq * oldiocb, struct lpfc_nodelist * ndlp,
1916 LPFC_MBOXQ_t * mbox, uint8_t newnode)
1917{
1918 IOCB_t *icmd;
1919 IOCB_t *oldcmd;
1920 struct lpfc_iocbq *elsiocb;
1921 struct lpfc_sli_ring *pring;
1922 struct lpfc_sli *psli;
1923 uint8_t *pcmd;
1924 uint16_t cmdsize;
1925 int rc;
James Smart82d9a2a2006-04-15 11:53:05 -04001926 ELS_PKT *els_pkt_ptr;
dea31012005-04-17 16:05:31 -05001927
1928 psli = &phba->sli;
1929 pring = &psli->ring[LPFC_ELS_RING]; /* ELS ring */
1930 oldcmd = &oldiocb->iocb;
1931
1932 switch (flag) {
1933 case ELS_CMD_ACC:
1934 cmdsize = sizeof (uint32_t);
James Smart488d1462006-03-07 15:02:37 -05001935 elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, oldiocb->retry,
1936 ndlp, ndlp->nlp_DID, ELS_CMD_ACC);
1937 if (!elsiocb) {
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05001938 ndlp->nlp_flag &= ~NLP_LOGO_ACC;
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001939 return 1;
dea31012005-04-17 16:05:31 -05001940 }
1941 icmd = &elsiocb->iocb;
1942 icmd->ulpContext = oldcmd->ulpContext; /* Xri */
1943 pcmd = (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
1944 *((uint32_t *) (pcmd)) = ELS_CMD_ACC;
1945 pcmd += sizeof (uint32_t);
1946 break;
1947 case ELS_CMD_PLOGI:
1948 cmdsize = (sizeof (struct serv_parm) + sizeof (uint32_t));
James Smart488d1462006-03-07 15:02:37 -05001949 elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, oldiocb->retry,
1950 ndlp, ndlp->nlp_DID, ELS_CMD_ACC);
1951 if (!elsiocb)
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001952 return 1;
James Smart488d1462006-03-07 15:02:37 -05001953
dea31012005-04-17 16:05:31 -05001954 icmd = &elsiocb->iocb;
1955 icmd->ulpContext = oldcmd->ulpContext; /* Xri */
1956 pcmd = (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
1957
1958 if (mbox)
1959 elsiocb->context_un.mbox = mbox;
1960
1961 *((uint32_t *) (pcmd)) = ELS_CMD_ACC;
1962 pcmd += sizeof (uint32_t);
1963 memcpy(pcmd, &phba->fc_sparam, sizeof (struct serv_parm));
1964 break;
James Smart82d9a2a2006-04-15 11:53:05 -04001965 case ELS_CMD_PRLO:
1966 cmdsize = sizeof (uint32_t) + sizeof (PRLO);
1967 elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, oldiocb->retry,
1968 ndlp, ndlp->nlp_DID, ELS_CMD_PRLO);
1969 if (!elsiocb)
1970 return 1;
1971
1972 icmd = &elsiocb->iocb;
1973 icmd->ulpContext = oldcmd->ulpContext; /* Xri */
1974 pcmd = (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
1975
1976 memcpy(pcmd, ((struct lpfc_dmabuf *) oldiocb->context2)->virt,
1977 sizeof (uint32_t) + sizeof (PRLO));
1978 *((uint32_t *) (pcmd)) = ELS_CMD_PRLO_ACC;
1979 els_pkt_ptr = (ELS_PKT *) pcmd;
1980 els_pkt_ptr->un.prlo.acceptRspCode = PRLO_REQ_EXECUTED;
1981 break;
dea31012005-04-17 16:05:31 -05001982 default:
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001983 return 1;
dea31012005-04-17 16:05:31 -05001984 }
1985
1986 if (newnode)
1987 elsiocb->context1 = NULL;
1988
1989 /* Xmit ELS ACC response tag <ulpIoTag> */
1990 lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
James Smart1dcb58e2007-04-25 09:51:30 -04001991 "%d:0128 Xmit ELS ACC response tag x%x, XRI: x%x, "
1992 "DID: x%x, nlp_flag: x%x nlp_state: x%x RPI: x%x\n",
1993 phba->brd_no, elsiocb->iotag,
dea31012005-04-17 16:05:31 -05001994 elsiocb->iocb.ulpContext, ndlp->nlp_DID,
1995 ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi);
1996
1997 if (ndlp->nlp_flag & NLP_LOGO_ACC) {
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001998 spin_lock_irq(phba->host->host_lock);
1999 ndlp->nlp_flag &= ~NLP_LOGO_ACC;
2000 spin_unlock_irq(phba->host->host_lock);
dea31012005-04-17 16:05:31 -05002001 elsiocb->iocb_cmpl = lpfc_cmpl_els_logo_acc;
2002 } else {
2003 elsiocb->iocb_cmpl = lpfc_cmpl_els_acc;
2004 }
2005
2006 phba->fc_stat.elsXmitACC++;
2007 spin_lock_irq(phba->host->host_lock);
2008 rc = lpfc_sli_issue_iocb(phba, pring, elsiocb, 0);
2009 spin_unlock_irq(phba->host->host_lock);
2010 if (rc == IOCB_ERROR) {
2011 lpfc_els_free_iocb(phba, elsiocb);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002012 return 1;
dea31012005-04-17 16:05:31 -05002013 }
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002014 return 0;
dea31012005-04-17 16:05:31 -05002015}
2016
2017int
2018lpfc_els_rsp_reject(struct lpfc_hba * phba, uint32_t rejectError,
2019 struct lpfc_iocbq * oldiocb, struct lpfc_nodelist * ndlp)
2020{
2021 IOCB_t *icmd;
2022 IOCB_t *oldcmd;
2023 struct lpfc_iocbq *elsiocb;
2024 struct lpfc_sli_ring *pring;
2025 struct lpfc_sli *psli;
2026 uint8_t *pcmd;
2027 uint16_t cmdsize;
2028 int rc;
2029
2030 psli = &phba->sli;
2031 pring = &psli->ring[LPFC_ELS_RING]; /* ELS ring */
2032
2033 cmdsize = 2 * sizeof (uint32_t);
James Smart488d1462006-03-07 15:02:37 -05002034 elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, oldiocb->retry,
2035 ndlp, ndlp->nlp_DID, ELS_CMD_LS_RJT);
2036 if (!elsiocb)
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002037 return 1;
dea31012005-04-17 16:05:31 -05002038
2039 icmd = &elsiocb->iocb;
2040 oldcmd = &oldiocb->iocb;
2041 icmd->ulpContext = oldcmd->ulpContext; /* Xri */
2042 pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
2043
2044 *((uint32_t *) (pcmd)) = ELS_CMD_LS_RJT;
2045 pcmd += sizeof (uint32_t);
2046 *((uint32_t *) (pcmd)) = rejectError;
2047
2048 /* Xmit ELS RJT <err> response tag <ulpIoTag> */
2049 lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
James Smart5b8bd0c2007-04-25 09:52:49 -04002050 "%d:0129 Xmit ELS RJT x%x response tag x%x xri x%x, "
2051 "did x%x, nlp_flag x%x, nlp_state x%x, rpi x%x\n",
2052 phba->brd_no, rejectError, elsiocb->iotag,
dea31012005-04-17 16:05:31 -05002053 elsiocb->iocb.ulpContext, ndlp->nlp_DID,
2054 ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi);
2055
2056 phba->fc_stat.elsXmitLSRJT++;
2057 elsiocb->iocb_cmpl = lpfc_cmpl_els_acc;
2058 spin_lock_irq(phba->host->host_lock);
2059 rc = lpfc_sli_issue_iocb(phba, pring, elsiocb, 0);
2060 spin_unlock_irq(phba->host->host_lock);
2061 if (rc == IOCB_ERROR) {
2062 lpfc_els_free_iocb(phba, elsiocb);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002063 return 1;
dea31012005-04-17 16:05:31 -05002064 }
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002065 return 0;
dea31012005-04-17 16:05:31 -05002066}
2067
2068int
2069lpfc_els_rsp_adisc_acc(struct lpfc_hba * phba,
2070 struct lpfc_iocbq * oldiocb, struct lpfc_nodelist * ndlp)
2071{
2072 ADISC *ap;
2073 IOCB_t *icmd;
2074 IOCB_t *oldcmd;
2075 struct lpfc_iocbq *elsiocb;
2076 struct lpfc_sli_ring *pring;
2077 struct lpfc_sli *psli;
2078 uint8_t *pcmd;
2079 uint16_t cmdsize;
2080 int rc;
2081
2082 psli = &phba->sli;
2083 pring = &psli->ring[LPFC_ELS_RING]; /* ELS ring */
2084
2085 cmdsize = sizeof (uint32_t) + sizeof (ADISC);
James Smart488d1462006-03-07 15:02:37 -05002086 elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, oldiocb->retry,
2087 ndlp, ndlp->nlp_DID, ELS_CMD_ACC);
2088 if (!elsiocb)
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002089 return 1;
dea31012005-04-17 16:05:31 -05002090
dea31012005-04-17 16:05:31 -05002091 icmd = &elsiocb->iocb;
2092 oldcmd = &oldiocb->iocb;
2093 icmd->ulpContext = oldcmd->ulpContext; /* Xri */
James Smart5b8bd0c2007-04-25 09:52:49 -04002094
2095 /* Xmit ADISC ACC response tag <ulpIoTag> */
2096 lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
2097 "%d:0130 Xmit ADISC ACC response iotag x%x xri: "
2098 "x%x, did x%x, nlp_flag x%x, nlp_state x%x rpi x%x\n",
2099 phba->brd_no, elsiocb->iotag,
2100 elsiocb->iocb.ulpContext, ndlp->nlp_DID,
2101 ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi);
2102
dea31012005-04-17 16:05:31 -05002103 pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
2104
2105 *((uint32_t *) (pcmd)) = ELS_CMD_ACC;
2106 pcmd += sizeof (uint32_t);
2107
2108 ap = (ADISC *) (pcmd);
2109 ap->hardAL_PA = phba->fc_pref_ALPA;
2110 memcpy(&ap->portName, &phba->fc_portname, sizeof (struct lpfc_name));
2111 memcpy(&ap->nodeName, &phba->fc_nodename, sizeof (struct lpfc_name));
2112 ap->DID = be32_to_cpu(phba->fc_myDID);
2113
2114 phba->fc_stat.elsXmitACC++;
2115 elsiocb->iocb_cmpl = lpfc_cmpl_els_acc;
2116 spin_lock_irq(phba->host->host_lock);
2117 rc = lpfc_sli_issue_iocb(phba, pring, elsiocb, 0);
2118 spin_unlock_irq(phba->host->host_lock);
2119 if (rc == IOCB_ERROR) {
2120 lpfc_els_free_iocb(phba, elsiocb);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002121 return 1;
dea31012005-04-17 16:05:31 -05002122 }
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002123 return 0;
dea31012005-04-17 16:05:31 -05002124}
2125
2126int
James Smart5b8bd0c2007-04-25 09:52:49 -04002127lpfc_els_rsp_prli_acc(struct lpfc_hba *phba, struct lpfc_iocbq *oldiocb,
2128 struct lpfc_nodelist *ndlp)
dea31012005-04-17 16:05:31 -05002129{
2130 PRLI *npr;
2131 lpfc_vpd_t *vpd;
2132 IOCB_t *icmd;
2133 IOCB_t *oldcmd;
2134 struct lpfc_iocbq *elsiocb;
2135 struct lpfc_sli_ring *pring;
2136 struct lpfc_sli *psli;
2137 uint8_t *pcmd;
2138 uint16_t cmdsize;
2139 int rc;
2140
2141 psli = &phba->sli;
2142 pring = &psli->ring[LPFC_ELS_RING]; /* ELS ring */
2143
2144 cmdsize = sizeof (uint32_t) + sizeof (PRLI);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002145 elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, oldiocb->retry, ndlp,
James Smart488d1462006-03-07 15:02:37 -05002146 ndlp->nlp_DID, (ELS_CMD_ACC | (ELS_CMD_PRLI & ~ELS_RSP_MASK)));
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002147 if (!elsiocb)
2148 return 1;
dea31012005-04-17 16:05:31 -05002149
dea31012005-04-17 16:05:31 -05002150 icmd = &elsiocb->iocb;
2151 oldcmd = &oldiocb->iocb;
2152 icmd->ulpContext = oldcmd->ulpContext; /* Xri */
James Smart5b8bd0c2007-04-25 09:52:49 -04002153
2154 /* Xmit PRLI ACC response tag <ulpIoTag> */
2155 lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
2156 "%d:0131 Xmit PRLI ACC response tag x%x xri x%x, "
2157 "did x%x, nlp_flag x%x, nlp_state x%x, rpi x%x\n",
2158 phba->brd_no, elsiocb->iotag,
2159 elsiocb->iocb.ulpContext, ndlp->nlp_DID,
2160 ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi);
2161
dea31012005-04-17 16:05:31 -05002162 pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
2163
2164 *((uint32_t *) (pcmd)) = (ELS_CMD_ACC | (ELS_CMD_PRLI & ~ELS_RSP_MASK));
2165 pcmd += sizeof (uint32_t);
2166
2167 /* For PRLI, remainder of payload is PRLI parameter page */
2168 memset(pcmd, 0, sizeof (PRLI));
2169
2170 npr = (PRLI *) pcmd;
2171 vpd = &phba->vpd;
2172 /*
2173 * If our firmware version is 3.20 or later,
2174 * set the following bits for FC-TAPE support.
2175 */
2176 if (vpd->rev.feaLevelHigh >= 0x02) {
2177 npr->ConfmComplAllowed = 1;
2178 npr->Retry = 1;
2179 npr->TaskRetryIdReq = 1;
2180 }
2181
2182 npr->acceptRspCode = PRLI_REQ_EXECUTED;
2183 npr->estabImagePair = 1;
2184 npr->readXferRdyDis = 1;
2185 npr->ConfmComplAllowed = 1;
2186
2187 npr->prliType = PRLI_FCP_TYPE;
2188 npr->initiatorFunc = 1;
2189
2190 phba->fc_stat.elsXmitACC++;
2191 elsiocb->iocb_cmpl = lpfc_cmpl_els_acc;
2192
2193 spin_lock_irq(phba->host->host_lock);
2194 rc = lpfc_sli_issue_iocb(phba, pring, elsiocb, 0);
2195 spin_unlock_irq(phba->host->host_lock);
2196 if (rc == IOCB_ERROR) {
2197 lpfc_els_free_iocb(phba, elsiocb);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002198 return 1;
dea31012005-04-17 16:05:31 -05002199 }
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002200 return 0;
dea31012005-04-17 16:05:31 -05002201}
2202
2203static int
2204lpfc_els_rsp_rnid_acc(struct lpfc_hba * phba,
2205 uint8_t format,
2206 struct lpfc_iocbq * oldiocb, struct lpfc_nodelist * ndlp)
2207{
2208 RNID *rn;
2209 IOCB_t *icmd;
2210 IOCB_t *oldcmd;
2211 struct lpfc_iocbq *elsiocb;
2212 struct lpfc_sli_ring *pring;
2213 struct lpfc_sli *psli;
2214 uint8_t *pcmd;
2215 uint16_t cmdsize;
2216 int rc;
2217
2218 psli = &phba->sli;
2219 pring = &psli->ring[LPFC_ELS_RING];
2220
2221 cmdsize = sizeof (uint32_t) + sizeof (uint32_t)
2222 + (2 * sizeof (struct lpfc_name));
2223 if (format)
2224 cmdsize += sizeof (RNID_TOP_DISC);
2225
James Smart488d1462006-03-07 15:02:37 -05002226 elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, oldiocb->retry,
2227 ndlp, ndlp->nlp_DID, ELS_CMD_ACC);
2228 if (!elsiocb)
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002229 return 1;
dea31012005-04-17 16:05:31 -05002230
dea31012005-04-17 16:05:31 -05002231 icmd = &elsiocb->iocb;
2232 oldcmd = &oldiocb->iocb;
2233 icmd->ulpContext = oldcmd->ulpContext; /* Xri */
James Smart5b8bd0c2007-04-25 09:52:49 -04002234
2235 /* Xmit RNID ACC response tag <ulpIoTag> */
2236 lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
2237 "%d:0132 Xmit RNID ACC response tag x%x "
2238 "xri x%x\n",
2239 phba->brd_no, elsiocb->iotag,
2240 elsiocb->iocb.ulpContext);
2241
dea31012005-04-17 16:05:31 -05002242 pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
2243
2244 *((uint32_t *) (pcmd)) = ELS_CMD_ACC;
2245 pcmd += sizeof (uint32_t);
2246
2247 memset(pcmd, 0, sizeof (RNID));
2248 rn = (RNID *) (pcmd);
2249 rn->Format = format;
2250 rn->CommonLen = (2 * sizeof (struct lpfc_name));
2251 memcpy(&rn->portName, &phba->fc_portname, sizeof (struct lpfc_name));
2252 memcpy(&rn->nodeName, &phba->fc_nodename, sizeof (struct lpfc_name));
2253 switch (format) {
2254 case 0:
2255 rn->SpecificLen = 0;
2256 break;
2257 case RNID_TOPOLOGY_DISC:
2258 rn->SpecificLen = sizeof (RNID_TOP_DISC);
2259 memcpy(&rn->un.topologyDisc.portName,
2260 &phba->fc_portname, sizeof (struct lpfc_name));
2261 rn->un.topologyDisc.unitType = RNID_HBA;
2262 rn->un.topologyDisc.physPort = 0;
2263 rn->un.topologyDisc.attachedNodes = 0;
2264 break;
2265 default:
2266 rn->CommonLen = 0;
2267 rn->SpecificLen = 0;
2268 break;
2269 }
2270
2271 phba->fc_stat.elsXmitACC++;
2272 elsiocb->iocb_cmpl = lpfc_cmpl_els_acc;
2273 elsiocb->context1 = NULL; /* Don't need ndlp for cmpl,
2274 * it could be freed */
2275
2276 spin_lock_irq(phba->host->host_lock);
2277 rc = lpfc_sli_issue_iocb(phba, pring, elsiocb, 0);
2278 spin_unlock_irq(phba->host->host_lock);
2279 if (rc == IOCB_ERROR) {
2280 lpfc_els_free_iocb(phba, elsiocb);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002281 return 1;
dea31012005-04-17 16:05:31 -05002282 }
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002283 return 0;
dea31012005-04-17 16:05:31 -05002284}
2285
2286int
2287lpfc_els_disc_adisc(struct lpfc_hba * phba)
2288{
2289 int sentadisc;
2290 struct lpfc_nodelist *ndlp, *next_ndlp;
2291
2292 sentadisc = 0;
2293 /* go thru NPR list and issue any remaining ELS ADISCs */
2294 list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_npr_list,
2295 nlp_listp) {
2296 if (ndlp->nlp_flag & NLP_NPR_2B_DISC) {
2297 if (ndlp->nlp_flag & NLP_NPR_ADISC) {
2298 ndlp->nlp_flag &= ~NLP_NPR_ADISC;
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05002299 ndlp->nlp_prev_state = ndlp->nlp_state;
James Smartde0c5b32007-04-25 09:52:27 -04002300 lpfc_nlp_set_state(phba, ndlp,
2301 NLP_STE_ADISC_ISSUE);
dea31012005-04-17 16:05:31 -05002302 lpfc_issue_els_adisc(phba, ndlp, 0);
2303 sentadisc++;
2304 phba->num_disc_nodes++;
2305 if (phba->num_disc_nodes >=
2306 phba->cfg_discovery_threads) {
2307 spin_lock_irq(phba->host->host_lock);
2308 phba->fc_flag |= FC_NLP_MORE;
2309 spin_unlock_irq(phba->host->host_lock);
2310 break;
2311 }
2312 }
2313 }
2314 }
2315 if (sentadisc == 0) {
2316 spin_lock_irq(phba->host->host_lock);
2317 phba->fc_flag &= ~FC_NLP_MORE;
2318 spin_unlock_irq(phba->host->host_lock);
2319 }
Jamie Wellnitz2fe165b2006-02-28 19:25:31 -05002320 return sentadisc;
dea31012005-04-17 16:05:31 -05002321}
2322
2323int
2324lpfc_els_disc_plogi(struct lpfc_hba * phba)
2325{
2326 int sentplogi;
2327 struct lpfc_nodelist *ndlp, *next_ndlp;
2328
2329 sentplogi = 0;
2330 /* go thru NPR list and issue any remaining ELS PLOGIs */
2331 list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_npr_list,
2332 nlp_listp) {
2333 if ((ndlp->nlp_flag & NLP_NPR_2B_DISC) &&
2334 (!(ndlp->nlp_flag & NLP_DELAY_TMO))) {
2335 if (!(ndlp->nlp_flag & NLP_NPR_ADISC)) {
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05002336 ndlp->nlp_prev_state = ndlp->nlp_state;
James Smartde0c5b32007-04-25 09:52:27 -04002337 lpfc_nlp_set_state(phba, ndlp,
2338 NLP_STE_PLOGI_ISSUE);
James Smart488d1462006-03-07 15:02:37 -05002339 lpfc_issue_els_plogi(phba, ndlp->nlp_DID, 0);
dea31012005-04-17 16:05:31 -05002340 sentplogi++;
2341 phba->num_disc_nodes++;
2342 if (phba->num_disc_nodes >=
2343 phba->cfg_discovery_threads) {
2344 spin_lock_irq(phba->host->host_lock);
2345 phba->fc_flag |= FC_NLP_MORE;
2346 spin_unlock_irq(phba->host->host_lock);
2347 break;
2348 }
2349 }
2350 }
2351 }
2352 if (sentplogi == 0) {
2353 spin_lock_irq(phba->host->host_lock);
2354 phba->fc_flag &= ~FC_NLP_MORE;
2355 spin_unlock_irq(phba->host->host_lock);
2356 }
Jamie Wellnitz2fe165b2006-02-28 19:25:31 -05002357 return sentplogi;
dea31012005-04-17 16:05:31 -05002358}
2359
2360int
2361lpfc_els_flush_rscn(struct lpfc_hba * phba)
2362{
2363 struct lpfc_dmabuf *mp;
2364 int i;
2365
2366 for (i = 0; i < phba->fc_rscn_id_cnt; i++) {
2367 mp = phba->fc_rscn_id_list[i];
2368 lpfc_mbuf_free(phba, mp->virt, mp->phys);
2369 kfree(mp);
2370 phba->fc_rscn_id_list[i] = NULL;
2371 }
2372 phba->fc_rscn_id_cnt = 0;
2373 spin_lock_irq(phba->host->host_lock);
2374 phba->fc_flag &= ~(FC_RSCN_MODE | FC_RSCN_DISCOVERY);
2375 spin_unlock_irq(phba->host->host_lock);
2376 lpfc_can_disctmo(phba);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002377 return 0;
dea31012005-04-17 16:05:31 -05002378}
2379
2380int
2381lpfc_rscn_payload_check(struct lpfc_hba * phba, uint32_t did)
2382{
2383 D_ID ns_did;
2384 D_ID rscn_did;
2385 struct lpfc_dmabuf *mp;
2386 uint32_t *lp;
2387 uint32_t payload_len, cmd, i, match;
2388
2389 ns_did.un.word = did;
2390 match = 0;
2391
2392 /* Never match fabric nodes for RSCNs */
2393 if ((did & Fabric_DID_MASK) == Fabric_DID_MASK)
2394 return(0);
2395
2396 /* If we are doing a FULL RSCN rediscovery, match everything */
2397 if (phba->fc_flag & FC_RSCN_DISCOVERY) {
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002398 return did;
dea31012005-04-17 16:05:31 -05002399 }
2400
2401 for (i = 0; i < phba->fc_rscn_id_cnt; i++) {
2402 mp = phba->fc_rscn_id_list[i];
2403 lp = (uint32_t *) mp->virt;
2404 cmd = *lp++;
2405 payload_len = be32_to_cpu(cmd) & 0xffff; /* payload length */
2406 payload_len -= sizeof (uint32_t); /* take off word 0 */
2407 while (payload_len) {
2408 rscn_did.un.word = *lp++;
2409 rscn_did.un.word = be32_to_cpu(rscn_did.un.word);
2410 payload_len -= sizeof (uint32_t);
2411 switch (rscn_did.un.b.resv) {
2412 case 0: /* Single N_Port ID effected */
2413 if (ns_did.un.word == rscn_did.un.word) {
2414 match = did;
2415 }
2416 break;
2417 case 1: /* Whole N_Port Area effected */
2418 if ((ns_did.un.b.domain == rscn_did.un.b.domain)
2419 && (ns_did.un.b.area == rscn_did.un.b.area))
2420 {
2421 match = did;
2422 }
2423 break;
2424 case 2: /* Whole N_Port Domain effected */
2425 if (ns_did.un.b.domain == rscn_did.un.b.domain)
2426 {
2427 match = did;
2428 }
2429 break;
2430 case 3: /* Whole Fabric effected */
2431 match = did;
2432 break;
2433 default:
2434 /* Unknown Identifier in RSCN list */
2435 lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
2436 "%d:0217 Unknown Identifier in "
2437 "RSCN payload Data: x%x\n",
2438 phba->brd_no, rscn_did.un.word);
2439 break;
2440 }
2441 if (match) {
2442 break;
2443 }
2444 }
2445 }
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002446 return match;
dea31012005-04-17 16:05:31 -05002447}
2448
2449static int
2450lpfc_rscn_recovery_check(struct lpfc_hba * phba)
2451{
2452 struct lpfc_nodelist *ndlp = NULL, *next_ndlp;
2453 struct list_head *listp;
2454 struct list_head *node_list[7];
2455 int i;
2456
2457 /* Look at all nodes effected by pending RSCNs and move
2458 * them to NPR list.
2459 */
2460 node_list[0] = &phba->fc_npr_list; /* MUST do this list first */
2461 node_list[1] = &phba->fc_nlpmap_list;
2462 node_list[2] = &phba->fc_nlpunmap_list;
2463 node_list[3] = &phba->fc_prli_list;
2464 node_list[4] = &phba->fc_reglogin_list;
2465 node_list[5] = &phba->fc_adisc_list;
2466 node_list[6] = &phba->fc_plogi_list;
2467 for (i = 0; i < 7; i++) {
2468 listp = node_list[i];
2469 if (list_empty(listp))
2470 continue;
2471
2472 list_for_each_entry_safe(ndlp, next_ndlp, listp, nlp_listp) {
2473 if (!(lpfc_rscn_payload_check(phba, ndlp->nlp_DID)))
2474 continue;
2475
2476 lpfc_disc_state_machine(phba, ndlp, NULL,
2477 NLP_EVT_DEVICE_RECOVERY);
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05002478
2479 /* Make sure NLP_DELAY_TMO is NOT running
2480 * after a device recovery event.
2481 */
James Smartfdcebe22006-03-07 15:04:01 -05002482 if (ndlp->nlp_flag & NLP_DELAY_TMO)
2483 lpfc_cancel_retry_delay_tmo(phba, ndlp);
dea31012005-04-17 16:05:31 -05002484 }
2485 }
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002486 return 0;
dea31012005-04-17 16:05:31 -05002487}
2488
2489static int
2490lpfc_els_rcv_rscn(struct lpfc_hba * phba,
2491 struct lpfc_iocbq * cmdiocb,
2492 struct lpfc_nodelist * ndlp, uint8_t newnode)
2493{
2494 struct lpfc_dmabuf *pcmd;
2495 uint32_t *lp;
2496 IOCB_t *icmd;
2497 uint32_t payload_len, cmd;
James Smartd2873e42006-08-18 17:46:43 -04002498 int i;
dea31012005-04-17 16:05:31 -05002499
2500 icmd = &cmdiocb->iocb;
2501 pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
2502 lp = (uint32_t *) pcmd->virt;
2503
2504 cmd = *lp++;
2505 payload_len = be32_to_cpu(cmd) & 0xffff; /* payload length */
2506 payload_len -= sizeof (uint32_t); /* take off word 0 */
2507 cmd &= ELS_CMD_MASK;
2508
2509 /* RSCN received */
2510 lpfc_printf_log(phba,
2511 KERN_INFO,
2512 LOG_DISCOVERY,
2513 "%d:0214 RSCN received Data: x%x x%x x%x x%x\n",
2514 phba->brd_no,
2515 phba->fc_flag, payload_len, *lp, phba->fc_rscn_id_cnt);
2516
James Smartd2873e42006-08-18 17:46:43 -04002517 for (i = 0; i < payload_len/sizeof(uint32_t); i++)
2518 fc_host_post_event(phba->host, fc_get_event_number(),
2519 FCH_EVT_RSCN, lp[i]);
2520
dea31012005-04-17 16:05:31 -05002521 /* If we are about to begin discovery, just ACC the RSCN.
2522 * Discovery processing will satisfy it.
2523 */
James Smart071fbd3d2006-04-15 11:53:20 -04002524 if (phba->hba_state <= LPFC_NS_QRY) {
dea31012005-04-17 16:05:31 -05002525 lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL,
2526 newnode);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002527 return 0;
dea31012005-04-17 16:05:31 -05002528 }
2529
2530 /* If we are already processing an RSCN, save the received
2531 * RSCN payload buffer, cmdiocb->context2 to process later.
2532 */
2533 if (phba->fc_flag & (FC_RSCN_MODE | FC_NDISC_ACTIVE)) {
2534 if ((phba->fc_rscn_id_cnt < FC_MAX_HOLD_RSCN) &&
2535 !(phba->fc_flag & FC_RSCN_DISCOVERY)) {
2536 spin_lock_irq(phba->host->host_lock);
2537 phba->fc_flag |= FC_RSCN_MODE;
2538 spin_unlock_irq(phba->host->host_lock);
2539 phba->fc_rscn_id_list[phba->fc_rscn_id_cnt++] = pcmd;
2540
2541 /* If we zero, cmdiocb->context2, the calling
2542 * routine will not try to free it.
2543 */
2544 cmdiocb->context2 = NULL;
2545
2546 /* Deferred RSCN */
2547 lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
2548 "%d:0235 Deferred RSCN "
2549 "Data: x%x x%x x%x\n",
2550 phba->brd_no, phba->fc_rscn_id_cnt,
2551 phba->fc_flag, phba->hba_state);
2552 } else {
2553 spin_lock_irq(phba->host->host_lock);
2554 phba->fc_flag |= FC_RSCN_DISCOVERY;
2555 spin_unlock_irq(phba->host->host_lock);
2556 /* ReDiscovery RSCN */
2557 lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
2558 "%d:0234 ReDiscovery RSCN "
2559 "Data: x%x x%x x%x\n",
2560 phba->brd_no, phba->fc_rscn_id_cnt,
2561 phba->fc_flag, phba->hba_state);
2562 }
2563 /* Send back ACC */
2564 lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL,
2565 newnode);
2566
2567 /* send RECOVERY event for ALL nodes that match RSCN payload */
2568 lpfc_rscn_recovery_check(phba);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002569 return 0;
dea31012005-04-17 16:05:31 -05002570 }
2571
2572 phba->fc_flag |= FC_RSCN_MODE;
2573 phba->fc_rscn_id_list[phba->fc_rscn_id_cnt++] = pcmd;
2574 /*
2575 * If we zero, cmdiocb->context2, the calling routine will
2576 * not try to free it.
2577 */
2578 cmdiocb->context2 = NULL;
2579
2580 lpfc_set_disctmo(phba);
2581
2582 /* Send back ACC */
2583 lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL, newnode);
2584
2585 /* send RECOVERY event for ALL nodes that match RSCN payload */
2586 lpfc_rscn_recovery_check(phba);
2587
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002588 return lpfc_els_handle_rscn(phba);
dea31012005-04-17 16:05:31 -05002589}
2590
2591int
2592lpfc_els_handle_rscn(struct lpfc_hba * phba)
2593{
2594 struct lpfc_nodelist *ndlp;
2595
2596 /* Start timer for RSCN processing */
2597 lpfc_set_disctmo(phba);
2598
2599 /* RSCN processed */
2600 lpfc_printf_log(phba,
2601 KERN_INFO,
2602 LOG_DISCOVERY,
2603 "%d:0215 RSCN processed Data: x%x x%x x%x x%x\n",
2604 phba->brd_no,
2605 phba->fc_flag, 0, phba->fc_rscn_id_cnt,
2606 phba->hba_state);
2607
2608 /* To process RSCN, first compare RSCN data with NameServer */
2609 phba->fc_ns_retry = 0;
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002610 ndlp = lpfc_findnode_did(phba, NLP_SEARCH_UNMAPPED, NameServer_DID);
2611 if (ndlp) {
dea31012005-04-17 16:05:31 -05002612 /* Good ndlp, issue CT Request to NameServer */
2613 if (lpfc_ns_cmd(phba, ndlp, SLI_CTNS_GID_FT) == 0) {
2614 /* Wait for NameServer query cmpl before we can
2615 continue */
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002616 return 1;
dea31012005-04-17 16:05:31 -05002617 }
2618 } else {
2619 /* If login to NameServer does not exist, issue one */
2620 /* Good status, issue PLOGI to NameServer */
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002621 ndlp = lpfc_findnode_did(phba, NLP_SEARCH_ALL, NameServer_DID);
2622 if (ndlp) {
dea31012005-04-17 16:05:31 -05002623 /* Wait for NameServer login cmpl before we can
2624 continue */
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002625 return 1;
dea31012005-04-17 16:05:31 -05002626 }
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002627 ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL);
2628 if (!ndlp) {
dea31012005-04-17 16:05:31 -05002629 lpfc_els_flush_rscn(phba);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002630 return 0;
dea31012005-04-17 16:05:31 -05002631 } else {
2632 lpfc_nlp_init(phba, ndlp, NameServer_DID);
2633 ndlp->nlp_type |= NLP_FABRIC;
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05002634 ndlp->nlp_prev_state = ndlp->nlp_state;
James Smartde0c5b32007-04-25 09:52:27 -04002635 lpfc_nlp_set_state(phba, ndlp, NLP_STE_PLOGI_ISSUE);
James Smart488d1462006-03-07 15:02:37 -05002636 lpfc_issue_els_plogi(phba, NameServer_DID, 0);
dea31012005-04-17 16:05:31 -05002637 /* Wait for NameServer login cmpl before we can
2638 continue */
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002639 return 1;
dea31012005-04-17 16:05:31 -05002640 }
2641 }
2642
2643 lpfc_els_flush_rscn(phba);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002644 return 0;
dea31012005-04-17 16:05:31 -05002645}
2646
2647static int
2648lpfc_els_rcv_flogi(struct lpfc_hba * phba,
2649 struct lpfc_iocbq * cmdiocb,
2650 struct lpfc_nodelist * ndlp, uint8_t newnode)
2651{
2652 struct lpfc_dmabuf *pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
2653 uint32_t *lp = (uint32_t *) pcmd->virt;
2654 IOCB_t *icmd = &cmdiocb->iocb;
2655 struct serv_parm *sp;
2656 LPFC_MBOXQ_t *mbox;
2657 struct ls_rjt stat;
2658 uint32_t cmd, did;
2659 int rc;
2660
2661 cmd = *lp++;
2662 sp = (struct serv_parm *) lp;
2663
2664 /* FLOGI received */
2665
2666 lpfc_set_disctmo(phba);
2667
2668 if (phba->fc_topology == TOPOLOGY_LOOP) {
2669 /* We should never receive a FLOGI in loop mode, ignore it */
2670 did = icmd->un.elsreq64.remoteID;
2671
2672 /* An FLOGI ELS command <elsCmd> was received from DID <did> in
2673 Loop Mode */
2674 lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
2675 "%d:0113 An FLOGI ELS command x%x was received "
2676 "from DID x%x in Loop Mode\n",
2677 phba->brd_no, cmd, did);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002678 return 1;
dea31012005-04-17 16:05:31 -05002679 }
2680
2681 did = Fabric_DID;
2682
2683 if ((lpfc_check_sparm(phba, ndlp, sp, CLASS3))) {
2684 /* For a FLOGI we accept, then if our portname is greater
2685 * then the remote portname we initiate Nport login.
2686 */
2687
2688 rc = memcmp(&phba->fc_portname, &sp->portName,
2689 sizeof (struct lpfc_name));
2690
2691 if (!rc) {
2692 if ((mbox = mempool_alloc(phba->mbox_mem_pool,
2693 GFP_KERNEL)) == 0) {
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002694 return 1;
dea31012005-04-17 16:05:31 -05002695 }
2696 lpfc_linkdown(phba);
2697 lpfc_init_link(phba, mbox,
2698 phba->cfg_topology,
2699 phba->cfg_link_speed);
2700 mbox->mb.un.varInitLnk.lipsr_AL_PA = 0;
2701 mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
2702 rc = lpfc_sli_issue_mbox
2703 (phba, mbox, (MBX_NOWAIT | MBX_STOP_IOCB));
James Smart5b8bd0c2007-04-25 09:52:49 -04002704 lpfc_set_loopback_flag(phba);
dea31012005-04-17 16:05:31 -05002705 if (rc == MBX_NOT_FINISHED) {
2706 mempool_free( mbox, phba->mbox_mem_pool);
2707 }
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002708 return 1;
Jamie Wellnitz2fe165b2006-02-28 19:25:31 -05002709 } else if (rc > 0) { /* greater than */
dea31012005-04-17 16:05:31 -05002710 spin_lock_irq(phba->host->host_lock);
2711 phba->fc_flag |= FC_PT2PT_PLOGI;
2712 spin_unlock_irq(phba->host->host_lock);
2713 }
2714 phba->fc_flag |= FC_PT2PT;
2715 phba->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP);
2716 } else {
2717 /* Reject this request because invalid parameters */
2718 stat.un.b.lsRjtRsvd0 = 0;
2719 stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
2720 stat.un.b.lsRjtRsnCodeExp = LSEXP_SPARM_OPTIONS;
2721 stat.un.b.vendorUnique = 0;
2722 lpfc_els_rsp_reject(phba, stat.un.lsRjtError, cmdiocb, ndlp);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002723 return 1;
dea31012005-04-17 16:05:31 -05002724 }
2725
2726 /* Send back ACC */
2727 lpfc_els_rsp_acc(phba, ELS_CMD_PLOGI, cmdiocb, ndlp, NULL, newnode);
2728
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002729 return 0;
dea31012005-04-17 16:05:31 -05002730}
2731
2732static int
2733lpfc_els_rcv_rnid(struct lpfc_hba * phba,
2734 struct lpfc_iocbq * cmdiocb, struct lpfc_nodelist * ndlp)
2735{
2736 struct lpfc_dmabuf *pcmd;
2737 uint32_t *lp;
2738 IOCB_t *icmd;
2739 RNID *rn;
2740 struct ls_rjt stat;
2741 uint32_t cmd, did;
2742
2743 icmd = &cmdiocb->iocb;
2744 did = icmd->un.elsreq64.remoteID;
2745 pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
2746 lp = (uint32_t *) pcmd->virt;
2747
2748 cmd = *lp++;
2749 rn = (RNID *) lp;
2750
2751 /* RNID received */
2752
2753 switch (rn->Format) {
2754 case 0:
2755 case RNID_TOPOLOGY_DISC:
2756 /* Send back ACC */
2757 lpfc_els_rsp_rnid_acc(phba, rn->Format, cmdiocb, ndlp);
2758 break;
2759 default:
2760 /* Reject this request because format not supported */
2761 stat.un.b.lsRjtRsvd0 = 0;
2762 stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
2763 stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA;
2764 stat.un.b.vendorUnique = 0;
2765 lpfc_els_rsp_reject(phba, stat.un.lsRjtError, cmdiocb, ndlp);
2766 }
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002767 return 0;
dea31012005-04-17 16:05:31 -05002768}
2769
2770static int
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05002771lpfc_els_rcv_lirr(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
2772 struct lpfc_nodelist * ndlp)
2773{
2774 struct ls_rjt stat;
2775
2776 /* For now, unconditionally reject this command */
2777 stat.un.b.lsRjtRsvd0 = 0;
2778 stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
2779 stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA;
2780 stat.un.b.vendorUnique = 0;
2781 lpfc_els_rsp_reject(phba, stat.un.lsRjtError, cmdiocb, ndlp);
2782 return 0;
2783}
2784
Jamie Wellnitz082c0262006-02-28 19:25:30 -05002785static void
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05002786lpfc_els_rsp_rps_acc(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
2787{
2788 struct lpfc_sli *psli;
2789 struct lpfc_sli_ring *pring;
2790 MAILBOX_t *mb;
2791 IOCB_t *icmd;
2792 RPS_RSP *rps_rsp;
2793 uint8_t *pcmd;
2794 struct lpfc_iocbq *elsiocb;
2795 struct lpfc_nodelist *ndlp;
2796 uint16_t xri, status;
2797 uint32_t cmdsize;
2798
2799 psli = &phba->sli;
2800 pring = &psli->ring[LPFC_ELS_RING];
2801 mb = &pmb->mb;
2802
2803 ndlp = (struct lpfc_nodelist *) pmb->context2;
2804 xri = (uint16_t) ((unsigned long)(pmb->context1));
Randy Dunlap041976f2006-06-25 01:58:51 -07002805 pmb->context1 = NULL;
2806 pmb->context2 = NULL;
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05002807
2808 if (mb->mbxStatus) {
2809 mempool_free( pmb, phba->mbox_mem_pool);
2810 return;
2811 }
2812
2813 cmdsize = sizeof(RPS_RSP) + sizeof(uint32_t);
2814 mempool_free( pmb, phba->mbox_mem_pool);
James Smart488d1462006-03-07 15:02:37 -05002815 elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, lpfc_max_els_tries, ndlp,
2816 ndlp->nlp_DID, ELS_CMD_ACC);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002817 if (!elsiocb)
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05002818 return;
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05002819
2820 icmd = &elsiocb->iocb;
2821 icmd->ulpContext = xri;
2822
2823 pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
2824 *((uint32_t *) (pcmd)) = ELS_CMD_ACC;
2825 pcmd += sizeof (uint32_t); /* Skip past command */
2826 rps_rsp = (RPS_RSP *)pcmd;
2827
2828 if (phba->fc_topology != TOPOLOGY_LOOP)
2829 status = 0x10;
2830 else
2831 status = 0x8;
2832 if (phba->fc_flag & FC_FABRIC)
2833 status |= 0x4;
2834
2835 rps_rsp->rsvd1 = 0;
2836 rps_rsp->portStatus = be16_to_cpu(status);
2837 rps_rsp->linkFailureCnt = be32_to_cpu(mb->un.varRdLnk.linkFailureCnt);
2838 rps_rsp->lossSyncCnt = be32_to_cpu(mb->un.varRdLnk.lossSyncCnt);
2839 rps_rsp->lossSignalCnt = be32_to_cpu(mb->un.varRdLnk.lossSignalCnt);
2840 rps_rsp->primSeqErrCnt = be32_to_cpu(mb->un.varRdLnk.primSeqErrCnt);
2841 rps_rsp->invalidXmitWord = be32_to_cpu(mb->un.varRdLnk.invalidXmitWord);
2842 rps_rsp->crcCnt = be32_to_cpu(mb->un.varRdLnk.crcCnt);
2843
2844 /* Xmit ELS RPS ACC response tag <ulpIoTag> */
2845 lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
James Smart5b8bd0c2007-04-25 09:52:49 -04002846 "%d:0118 Xmit ELS RPS ACC response tag x%x xri x%x, "
2847 "did x%x, nlp_flag x%x, nlp_state x%x, rpi x%x\n",
2848 phba->brd_no, elsiocb->iotag,
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05002849 elsiocb->iocb.ulpContext, ndlp->nlp_DID,
2850 ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi);
2851
2852 elsiocb->iocb_cmpl = lpfc_cmpl_els_acc;
2853 phba->fc_stat.elsXmitACC++;
2854 if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) {
2855 lpfc_els_free_iocb(phba, elsiocb);
2856 }
2857 return;
2858}
2859
2860static int
2861lpfc_els_rcv_rps(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
2862 struct lpfc_nodelist * ndlp)
2863{
2864 uint32_t *lp;
2865 uint8_t flag;
2866 LPFC_MBOXQ_t *mbox;
2867 struct lpfc_dmabuf *pcmd;
2868 RPS *rps;
2869 struct ls_rjt stat;
2870
Jamie Wellnitz2fe165b2006-02-28 19:25:31 -05002871 if ((ndlp->nlp_state != NLP_STE_UNMAPPED_NODE) &&
2872 (ndlp->nlp_state != NLP_STE_MAPPED_NODE)) {
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05002873 stat.un.b.lsRjtRsvd0 = 0;
2874 stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
2875 stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA;
2876 stat.un.b.vendorUnique = 0;
2877 lpfc_els_rsp_reject(phba, stat.un.lsRjtError, cmdiocb, ndlp);
2878 }
2879
2880 pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
2881 lp = (uint32_t *) pcmd->virt;
2882 flag = (be32_to_cpu(*lp++) & 0xf);
2883 rps = (RPS *) lp;
2884
2885 if ((flag == 0) ||
2886 ((flag == 1) && (be32_to_cpu(rps->un.portNum) == 0)) ||
2887 ((flag == 2) && (memcmp(&rps->un.portName, &phba->fc_portname,
2888 sizeof (struct lpfc_name)) == 0))) {
2889 if ((mbox = mempool_alloc(phba->mbox_mem_pool, GFP_ATOMIC))) {
2890 lpfc_read_lnk_stat(phba, mbox);
2891 mbox->context1 =
2892 (void *)((unsigned long)cmdiocb->iocb.ulpContext);
2893 mbox->context2 = ndlp;
2894 mbox->mbox_cmpl = lpfc_els_rsp_rps_acc;
2895 if (lpfc_sli_issue_mbox (phba, mbox,
2896 (MBX_NOWAIT | MBX_STOP_IOCB)) != MBX_NOT_FINISHED) {
2897 /* Mbox completion will send ELS Response */
2898 return 0;
2899 }
2900 mempool_free(mbox, phba->mbox_mem_pool);
2901 }
2902 }
2903 stat.un.b.lsRjtRsvd0 = 0;
2904 stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
2905 stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA;
2906 stat.un.b.vendorUnique = 0;
2907 lpfc_els_rsp_reject(phba, stat.un.lsRjtError, cmdiocb, ndlp);
2908 return 0;
2909}
2910
Jamie Wellnitz082c0262006-02-28 19:25:30 -05002911static int
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05002912lpfc_els_rsp_rpl_acc(struct lpfc_hba * phba, uint16_t cmdsize,
2913 struct lpfc_iocbq * oldiocb, struct lpfc_nodelist * ndlp)
2914{
2915 IOCB_t *icmd;
2916 IOCB_t *oldcmd;
2917 RPL_RSP rpl_rsp;
2918 struct lpfc_iocbq *elsiocb;
2919 struct lpfc_sli_ring *pring;
2920 struct lpfc_sli *psli;
2921 uint8_t *pcmd;
2922
2923 psli = &phba->sli;
2924 pring = &psli->ring[LPFC_ELS_RING]; /* ELS ring */
2925
James Smart488d1462006-03-07 15:02:37 -05002926 elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, oldiocb->retry,
2927 ndlp, ndlp->nlp_DID, ELS_CMD_ACC);
2928 if (!elsiocb)
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05002929 return 1;
James Smart488d1462006-03-07 15:02:37 -05002930
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05002931 icmd = &elsiocb->iocb;
2932 oldcmd = &oldiocb->iocb;
2933 icmd->ulpContext = oldcmd->ulpContext; /* Xri */
2934
2935 pcmd = (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
2936 *((uint32_t *) (pcmd)) = ELS_CMD_ACC;
2937 pcmd += sizeof (uint16_t);
2938 *((uint16_t *)(pcmd)) = be16_to_cpu(cmdsize);
2939 pcmd += sizeof(uint16_t);
2940
2941 /* Setup the RPL ACC payload */
2942 rpl_rsp.listLen = be32_to_cpu(1);
2943 rpl_rsp.index = 0;
2944 rpl_rsp.port_num_blk.portNum = 0;
2945 rpl_rsp.port_num_blk.portID = be32_to_cpu(phba->fc_myDID);
2946 memcpy(&rpl_rsp.port_num_blk.portName, &phba->fc_portname,
2947 sizeof(struct lpfc_name));
2948
2949 memcpy(pcmd, &rpl_rsp, cmdsize - sizeof(uint32_t));
2950
2951
2952 /* Xmit ELS RPL ACC response tag <ulpIoTag> */
2953 lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
James Smart5b8bd0c2007-04-25 09:52:49 -04002954 "%d:0120 Xmit ELS RPL ACC response tag x%x xri x%x, "
2955 "did x%x, nlp_flag x%x, nlp_state x%x, rpi x%x\n",
2956 phba->brd_no, elsiocb->iotag,
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05002957 elsiocb->iocb.ulpContext, ndlp->nlp_DID,
2958 ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi);
2959
2960 elsiocb->iocb_cmpl = lpfc_cmpl_els_acc;
2961
2962 phba->fc_stat.elsXmitACC++;
2963 if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) {
2964 lpfc_els_free_iocb(phba, elsiocb);
2965 return 1;
2966 }
2967 return 0;
2968}
2969
2970static int
2971lpfc_els_rcv_rpl(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
dea31012005-04-17 16:05:31 -05002972 struct lpfc_nodelist * ndlp)
2973{
2974 struct lpfc_dmabuf *pcmd;
2975 uint32_t *lp;
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05002976 uint32_t maxsize;
2977 uint16_t cmdsize;
2978 RPL *rpl;
2979 struct ls_rjt stat;
dea31012005-04-17 16:05:31 -05002980
Jamie Wellnitz2fe165b2006-02-28 19:25:31 -05002981 if ((ndlp->nlp_state != NLP_STE_UNMAPPED_NODE) &&
2982 (ndlp->nlp_state != NLP_STE_MAPPED_NODE)) {
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05002983 stat.un.b.lsRjtRsvd0 = 0;
2984 stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
2985 stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA;
2986 stat.un.b.vendorUnique = 0;
2987 lpfc_els_rsp_reject(phba, stat.un.lsRjtError, cmdiocb, ndlp);
dea31012005-04-17 16:05:31 -05002988 }
2989
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05002990 pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
2991 lp = (uint32_t *) pcmd->virt;
2992 rpl = (RPL *) (lp + 1);
2993
2994 maxsize = be32_to_cpu(rpl->maxsize);
2995
2996 /* We support only one port */
2997 if ((rpl->index == 0) &&
2998 ((maxsize == 0) ||
2999 ((maxsize * sizeof(uint32_t)) >= sizeof(RPL_RSP)))) {
3000 cmdsize = sizeof(uint32_t) + sizeof(RPL_RSP);
Jamie Wellnitz2fe165b2006-02-28 19:25:31 -05003001 } else {
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05003002 cmdsize = sizeof(uint32_t) + maxsize * sizeof(uint32_t);
3003 }
3004 lpfc_els_rsp_rpl_acc(phba, cmdsize, cmdiocb, ndlp);
dea31012005-04-17 16:05:31 -05003005
3006 return 0;
3007}
3008
3009static int
3010lpfc_els_rcv_farp(struct lpfc_hba * phba,
3011 struct lpfc_iocbq * cmdiocb, struct lpfc_nodelist * ndlp)
3012{
3013 struct lpfc_dmabuf *pcmd;
3014 uint32_t *lp;
3015 IOCB_t *icmd;
3016 FARP *fp;
3017 uint32_t cmd, cnt, did;
3018
3019 icmd = &cmdiocb->iocb;
3020 did = icmd->un.elsreq64.remoteID;
3021 pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
3022 lp = (uint32_t *) pcmd->virt;
3023
3024 cmd = *lp++;
3025 fp = (FARP *) lp;
3026
3027 /* FARP-REQ received from DID <did> */
3028 lpfc_printf_log(phba,
3029 KERN_INFO,
James Smarta4bc3372006-12-02 13:34:16 -05003030 LOG_ELS,
dea31012005-04-17 16:05:31 -05003031 "%d:0601 FARP-REQ received from DID x%x\n",
3032 phba->brd_no, did);
3033
3034 /* We will only support match on WWPN or WWNN */
3035 if (fp->Mflags & ~(FARP_MATCH_NODE | FARP_MATCH_PORT)) {
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05003036 return 0;
dea31012005-04-17 16:05:31 -05003037 }
3038
3039 cnt = 0;
3040 /* If this FARP command is searching for my portname */
3041 if (fp->Mflags & FARP_MATCH_PORT) {
3042 if (memcmp(&fp->RportName, &phba->fc_portname,
3043 sizeof (struct lpfc_name)) == 0)
3044 cnt = 1;
3045 }
3046
3047 /* If this FARP command is searching for my nodename */
3048 if (fp->Mflags & FARP_MATCH_NODE) {
3049 if (memcmp(&fp->RnodeName, &phba->fc_nodename,
3050 sizeof (struct lpfc_name)) == 0)
3051 cnt = 1;
3052 }
3053
3054 if (cnt) {
3055 if ((ndlp->nlp_state == NLP_STE_UNMAPPED_NODE) ||
3056 (ndlp->nlp_state == NLP_STE_MAPPED_NODE)) {
3057 /* Log back into the node before sending the FARP. */
3058 if (fp->Rflags & FARP_REQUEST_PLOGI) {
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05003059 ndlp->nlp_prev_state = ndlp->nlp_state;
James Smartde0c5b32007-04-25 09:52:27 -04003060 lpfc_nlp_set_state(phba, ndlp,
3061 NLP_STE_PLOGI_ISSUE);
James Smart488d1462006-03-07 15:02:37 -05003062 lpfc_issue_els_plogi(phba, ndlp->nlp_DID, 0);
dea31012005-04-17 16:05:31 -05003063 }
3064
3065 /* Send a FARP response to that node */
3066 if (fp->Rflags & FARP_REQUEST_FARPR) {
3067 lpfc_issue_els_farpr(phba, did, 0);
3068 }
3069 }
3070 }
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05003071 return 0;
dea31012005-04-17 16:05:31 -05003072}
3073
3074static int
3075lpfc_els_rcv_farpr(struct lpfc_hba * phba,
3076 struct lpfc_iocbq * cmdiocb, struct lpfc_nodelist * ndlp)
3077{
3078 struct lpfc_dmabuf *pcmd;
3079 uint32_t *lp;
3080 IOCB_t *icmd;
3081 uint32_t cmd, did;
3082
3083 icmd = &cmdiocb->iocb;
3084 did = icmd->un.elsreq64.remoteID;
3085 pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
3086 lp = (uint32_t *) pcmd->virt;
3087
3088 cmd = *lp++;
3089 /* FARP-RSP received from DID <did> */
3090 lpfc_printf_log(phba,
3091 KERN_INFO,
James Smarta4bc3372006-12-02 13:34:16 -05003092 LOG_ELS,
dea31012005-04-17 16:05:31 -05003093 "%d:0600 FARP-RSP received from DID x%x\n",
3094 phba->brd_no, did);
3095
3096 /* ACCEPT the Farp resp request */
3097 lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0);
3098
3099 return 0;
3100}
3101
3102static int
3103lpfc_els_rcv_fan(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05003104 struct lpfc_nodelist * fan_ndlp)
dea31012005-04-17 16:05:31 -05003105{
3106 struct lpfc_dmabuf *pcmd;
3107 uint32_t *lp;
3108 IOCB_t *icmd;
dea31012005-04-17 16:05:31 -05003109 uint32_t cmd, did;
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05003110 FAN *fp;
3111 struct lpfc_nodelist *ndlp, *next_ndlp;
3112
3113 /* FAN received */
James Smartdca94792006-08-01 07:34:08 -04003114 lpfc_printf_log(phba, KERN_INFO, LOG_ELS, "%d:0265 FAN received\n",
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05003115 phba->brd_no);
dea31012005-04-17 16:05:31 -05003116
3117 icmd = &cmdiocb->iocb;
3118 did = icmd->un.elsreq64.remoteID;
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05003119 pcmd = (struct lpfc_dmabuf *)cmdiocb->context2;
3120 lp = (uint32_t *)pcmd->virt;
dea31012005-04-17 16:05:31 -05003121
3122 cmd = *lp++;
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05003123 fp = (FAN *)lp;
dea31012005-04-17 16:05:31 -05003124
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05003125 /* FAN received; Fan does not have a reply sequence */
dea31012005-04-17 16:05:31 -05003126
3127 if (phba->hba_state == LPFC_LOCAL_CFG_LINK) {
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05003128 if ((memcmp(&phba->fc_fabparam.nodeName, &fp->FnodeName,
3129 sizeof(struct lpfc_name)) != 0) ||
3130 (memcmp(&phba->fc_fabparam.portName, &fp->FportName,
3131 sizeof(struct lpfc_name)) != 0)) {
3132 /*
3133 * This node has switched fabrics. FLOGI is required
3134 * Clean up the old rpi's
dea31012005-04-17 16:05:31 -05003135 */
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05003136
3137 list_for_each_entry_safe(ndlp, next_ndlp,
3138 &phba->fc_npr_list, nlp_listp) {
3139
3140 if (ndlp->nlp_type & NLP_FABRIC) {
3141 /*
3142 * Clean up old Fabric, Nameserver and
3143 * other NLP_FABRIC logins
3144 */
James Smartde0c5b32007-04-25 09:52:27 -04003145 lpfc_drop_node(phba, ndlp);
Jamie Wellnitz2fe165b2006-02-28 19:25:31 -05003146 } else if (!(ndlp->nlp_flag & NLP_NPR_ADISC)) {
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05003147 /* Fail outstanding I/O now since this
3148 * device is marked for PLOGI
3149 */
3150 lpfc_unreg_rpi(phba, ndlp);
3151 }
3152 }
3153
3154 phba->hba_state = LPFC_FLOGI;
3155 lpfc_set_disctmo(phba);
3156 lpfc_initial_flogi(phba);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05003157 return 0;
dea31012005-04-17 16:05:31 -05003158 }
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05003159 /* Discovery not needed,
3160 * move the nodes to their original state.
3161 */
3162 list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_npr_list,
3163 nlp_listp) {
dea31012005-04-17 16:05:31 -05003164
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05003165 switch (ndlp->nlp_prev_state) {
3166 case NLP_STE_UNMAPPED_NODE:
3167 ndlp->nlp_prev_state = NLP_STE_NPR_NODE;
James Smartde0c5b32007-04-25 09:52:27 -04003168 lpfc_nlp_set_state(phba, ndlp,
3169 NLP_STE_UNMAPPED_NODE);
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05003170 break;
3171
3172 case NLP_STE_MAPPED_NODE:
3173 ndlp->nlp_prev_state = NLP_STE_NPR_NODE;
James Smartde0c5b32007-04-25 09:52:27 -04003174 lpfc_nlp_set_state(phba, ndlp,
3175 NLP_STE_MAPPED_NODE);
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05003176 break;
3177
3178 default:
3179 break;
3180 }
3181 }
3182
3183 /* Start discovery - this should just do CLEAR_LA */
dea31012005-04-17 16:05:31 -05003184 lpfc_disc_start(phba);
3185 }
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05003186 return 0;
dea31012005-04-17 16:05:31 -05003187}
3188
3189void
3190lpfc_els_timeout(unsigned long ptr)
3191{
3192 struct lpfc_hba *phba;
3193 unsigned long iflag;
3194
3195 phba = (struct lpfc_hba *)ptr;
3196 if (phba == 0)
3197 return;
3198 spin_lock_irqsave(phba->host->host_lock, iflag);
3199 if (!(phba->work_hba_events & WORKER_ELS_TMO)) {
3200 phba->work_hba_events |= WORKER_ELS_TMO;
3201 if (phba->work_wait)
3202 wake_up(phba->work_wait);
3203 }
3204 spin_unlock_irqrestore(phba->host->host_lock, iflag);
3205 return;
3206}
3207
3208void
3209lpfc_els_timeout_handler(struct lpfc_hba *phba)
3210{
3211 struct lpfc_sli_ring *pring;
3212 struct lpfc_iocbq *tmp_iocb, *piocb;
3213 IOCB_t *cmd = NULL;
3214 struct lpfc_dmabuf *pcmd;
dea31012005-04-17 16:05:31 -05003215 uint32_t *elscmd;
James Smart7054a602007-04-25 09:52:34 -04003216 uint32_t els_command=0;
dea31012005-04-17 16:05:31 -05003217 uint32_t timeout;
3218 uint32_t remote_ID;
3219
3220 if (phba == 0)
3221 return;
3222 spin_lock_irq(phba->host->host_lock);
3223 /* If the timer is already canceled do nothing */
3224 if (!(phba->work_hba_events & WORKER_ELS_TMO)) {
3225 spin_unlock_irq(phba->host->host_lock);
3226 return;
3227 }
3228 timeout = (uint32_t)(phba->fc_ratov << 1);
3229
3230 pring = &phba->sli.ring[LPFC_ELS_RING];
dea31012005-04-17 16:05:31 -05003231
3232 list_for_each_entry_safe(piocb, tmp_iocb, &pring->txcmplq, list) {
3233 cmd = &piocb->iocb;
3234
James Smart7054a602007-04-25 09:52:34 -04003235 if ((piocb->iocb_flag & LPFC_IO_LIBDFC) ||
3236 (piocb->iocb.ulpCommand == CMD_ABORT_XRI_CN) ||
3237 (piocb->iocb.ulpCommand == CMD_CLOSE_XRI_CN)) {
dea31012005-04-17 16:05:31 -05003238 continue;
3239 }
3240 pcmd = (struct lpfc_dmabuf *) piocb->context2;
James Smart7054a602007-04-25 09:52:34 -04003241 if (pcmd) {
3242 elscmd = (uint32_t *) (pcmd->virt);
3243 els_command = *elscmd;
3244 }
dea31012005-04-17 16:05:31 -05003245
3246 if ((els_command == ELS_CMD_FARP)
3247 || (els_command == ELS_CMD_FARPR)) {
3248 continue;
3249 }
3250
3251 if (piocb->drvrTimeout > 0) {
3252 if (piocb->drvrTimeout >= timeout) {
3253 piocb->drvrTimeout -= timeout;
3254 } else {
3255 piocb->drvrTimeout = 0;
3256 }
3257 continue;
3258 }
3259
dea31012005-04-17 16:05:31 -05003260 if (cmd->ulpCommand == CMD_GEN_REQUEST64_CR) {
3261 struct lpfc_nodelist *ndlp;
James Smart2534ba72007-04-25 09:52:20 -04003262 ndlp = __lpfc_findnode_rpi(phba, cmd->ulpContext);
dea31012005-04-17 16:05:31 -05003263 remote_ID = ndlp->nlp_DID;
dea31012005-04-17 16:05:31 -05003264 } else {
3265 remote_ID = cmd->un.elsreq64.remoteID;
3266 }
3267
3268 lpfc_printf_log(phba,
3269 KERN_ERR,
3270 LOG_ELS,
3271 "%d:0127 ELS timeout Data: x%x x%x x%x x%x\n",
3272 phba->brd_no, els_command,
3273 remote_ID, cmd->ulpCommand, cmd->ulpIoTag);
3274
James Smart07951072007-04-25 09:51:38 -04003275 lpfc_sli_issue_abort_iotag(phba, pring, piocb);
dea31012005-04-17 16:05:31 -05003276 }
James Smart5a0e3262006-07-06 15:49:16 -04003277 if (phba->sli.ring[LPFC_ELS_RING].txcmplq_cnt)
3278 mod_timer(&phba->els_tmofunc, jiffies + HZ * timeout);
3279
dea31012005-04-17 16:05:31 -05003280 spin_unlock_irq(phba->host->host_lock);
3281}
3282
3283void
3284lpfc_els_flush_cmd(struct lpfc_hba * phba)
3285{
James Smart2534ba72007-04-25 09:52:20 -04003286 LIST_HEAD(completions);
dea31012005-04-17 16:05:31 -05003287 struct lpfc_sli_ring *pring;
3288 struct lpfc_iocbq *tmp_iocb, *piocb;
3289 IOCB_t *cmd = NULL;
dea31012005-04-17 16:05:31 -05003290
3291 pring = &phba->sli.ring[LPFC_ELS_RING];
3292 spin_lock_irq(phba->host->host_lock);
3293 list_for_each_entry_safe(piocb, tmp_iocb, &pring->txq, list) {
3294 cmd = &piocb->iocb;
3295
3296 if (piocb->iocb_flag & LPFC_IO_LIBDFC) {
3297 continue;
3298 }
3299
3300 /* Do not flush out the QUE_RING and ABORT/CLOSE iocbs */
3301 if ((cmd->ulpCommand == CMD_QUE_RING_BUF_CN) ||
3302 (cmd->ulpCommand == CMD_QUE_RING_BUF64_CN) ||
3303 (cmd->ulpCommand == CMD_CLOSE_XRI_CN) ||
3304 (cmd->ulpCommand == CMD_ABORT_XRI_CN)) {
3305 continue;
3306 }
3307
James Smart2534ba72007-04-25 09:52:20 -04003308 list_move_tail(&piocb->list, &completions);
James Smart1dcb58e2007-04-25 09:51:30 -04003309 pring->txq_cnt--;
dea31012005-04-17 16:05:31 -05003310
dea31012005-04-17 16:05:31 -05003311 }
3312
3313 list_for_each_entry_safe(piocb, tmp_iocb, &pring->txcmplq, list) {
3314 cmd = &piocb->iocb;
3315
3316 if (piocb->iocb_flag & LPFC_IO_LIBDFC) {
3317 continue;
3318 }
dea31012005-04-17 16:05:31 -05003319
James Smart07951072007-04-25 09:51:38 -04003320 lpfc_sli_issue_abort_iotag(phba, pring, piocb);
dea31012005-04-17 16:05:31 -05003321 }
3322 spin_unlock_irq(phba->host->host_lock);
James Smart2534ba72007-04-25 09:52:20 -04003323
3324 while(!list_empty(&completions)) {
3325 piocb = list_get_first(&completions, struct lpfc_iocbq, list);
3326 cmd = &piocb->iocb;
3327 list_del(&piocb->list);
3328
3329 if (piocb->iocb_cmpl) {
3330 cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
3331 cmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
3332 (piocb->iocb_cmpl) (phba, piocb, piocb);
3333 } else
3334 lpfc_sli_release_iocbq(phba, piocb);
3335 }
3336
dea31012005-04-17 16:05:31 -05003337 return;
3338}
3339
3340void
3341lpfc_els_unsol_event(struct lpfc_hba * phba,
3342 struct lpfc_sli_ring * pring, struct lpfc_iocbq * elsiocb)
3343{
3344 struct lpfc_sli *psli;
3345 struct lpfc_nodelist *ndlp;
3346 struct lpfc_dmabuf *mp;
3347 uint32_t *lp;
3348 IOCB_t *icmd;
3349 struct ls_rjt stat;
3350 uint32_t cmd;
3351 uint32_t did;
3352 uint32_t newnode;
3353 uint32_t drop_cmd = 0; /* by default do NOT drop received cmd */
3354 uint32_t rjt_err = 0;
3355
3356 psli = &phba->sli;
3357 icmd = &elsiocb->iocb;
3358
3359 if ((icmd->ulpStatus == IOSTAT_LOCAL_REJECT) &&
3360 ((icmd->un.ulpWord[4] & 0xff) == IOERR_RCV_BUFFER_WAITING)) {
3361 /* Not enough posted buffers; Try posting more buffers */
3362 phba->fc_stat.NoRcvBuf++;
3363 lpfc_post_buffer(phba, pring, 0, 1);
3364 return;
3365 }
3366
3367 /* If there are no BDEs associated with this IOCB,
3368 * there is nothing to do.
3369 */
3370 if (icmd->ulpBdeCount == 0)
3371 return;
3372
3373 /* type of ELS cmd is first 32bit word in packet */
3374 mp = lpfc_sli_ringpostbuf_get(phba, pring, getPaddr(icmd->un.
3375 cont64[0].
3376 addrHigh,
3377 icmd->un.
3378 cont64[0].addrLow));
3379 if (mp == 0) {
3380 drop_cmd = 1;
3381 goto dropit;
3382 }
3383
3384 newnode = 0;
3385 lp = (uint32_t *) mp->virt;
3386 cmd = *lp++;
3387 lpfc_post_buffer(phba, &psli->ring[LPFC_ELS_RING], 1, 1);
3388
3389 if (icmd->ulpStatus) {
3390 lpfc_mbuf_free(phba, mp->virt, mp->phys);
3391 kfree(mp);
3392 drop_cmd = 1;
3393 goto dropit;
3394 }
3395
3396 /* Check to see if link went down during discovery */
3397 if (lpfc_els_chk_latt(phba)) {
3398 lpfc_mbuf_free(phba, mp->virt, mp->phys);
3399 kfree(mp);
3400 drop_cmd = 1;
3401 goto dropit;
3402 }
3403
3404 did = icmd->un.rcvels.remoteID;
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05003405 ndlp = lpfc_findnode_did(phba, NLP_SEARCH_ALL, did);
3406 if (!ndlp) {
dea31012005-04-17 16:05:31 -05003407 /* Cannot find existing Fabric ndlp, so allocate a new one */
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05003408 ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL);
3409 if (!ndlp) {
dea31012005-04-17 16:05:31 -05003410 lpfc_mbuf_free(phba, mp->virt, mp->phys);
3411 kfree(mp);
3412 drop_cmd = 1;
3413 goto dropit;
3414 }
3415
3416 lpfc_nlp_init(phba, ndlp, did);
3417 newnode = 1;
3418 if ((did & Fabric_DID_MASK) == Fabric_DID_MASK) {
3419 ndlp->nlp_type |= NLP_FABRIC;
3420 }
James Smartde0c5b32007-04-25 09:52:27 -04003421 lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNUSED_NODE);
dea31012005-04-17 16:05:31 -05003422 }
3423
3424 phba->fc_stat.elsRcvFrame++;
3425 elsiocb->context1 = ndlp;
3426 elsiocb->context2 = mp;
3427
3428 if ((cmd & ELS_CMD_MASK) == ELS_CMD_RSCN) {
3429 cmd &= ELS_CMD_MASK;
3430 }
3431 /* ELS command <elsCmd> received from NPORT <did> */
3432 lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
3433 "%d:0112 ELS command x%x received from NPORT x%x "
3434 "Data: x%x\n", phba->brd_no, cmd, did, phba->hba_state);
3435
3436 switch (cmd) {
3437 case ELS_CMD_PLOGI:
3438 phba->fc_stat.elsRcvPLOGI++;
3439 if (phba->hba_state < LPFC_DISC_AUTH) {
James.Smart@Emulex.Com1f679ca2005-06-25 10:34:27 -04003440 rjt_err = 1;
dea31012005-04-17 16:05:31 -05003441 break;
3442 }
James Smart92795652006-07-06 15:50:02 -04003443 ndlp = lpfc_plogi_confirm_nport(phba, mp, ndlp);
dea31012005-04-17 16:05:31 -05003444 lpfc_disc_state_machine(phba, ndlp, elsiocb, NLP_EVT_RCV_PLOGI);
3445 break;
3446 case ELS_CMD_FLOGI:
3447 phba->fc_stat.elsRcvFLOGI++;
3448 lpfc_els_rcv_flogi(phba, elsiocb, ndlp, newnode);
James Smartde0c5b32007-04-25 09:52:27 -04003449 if (newnode)
3450 lpfc_drop_node(phba, ndlp);
dea31012005-04-17 16:05:31 -05003451 break;
3452 case ELS_CMD_LOGO:
3453 phba->fc_stat.elsRcvLOGO++;
3454 if (phba->hba_state < LPFC_DISC_AUTH) {
James.Smart@Emulex.Com1f679ca2005-06-25 10:34:27 -04003455 rjt_err = 1;
dea31012005-04-17 16:05:31 -05003456 break;
3457 }
3458 lpfc_disc_state_machine(phba, ndlp, elsiocb, NLP_EVT_RCV_LOGO);
3459 break;
3460 case ELS_CMD_PRLO:
3461 phba->fc_stat.elsRcvPRLO++;
3462 if (phba->hba_state < LPFC_DISC_AUTH) {
James.Smart@Emulex.Com1f679ca2005-06-25 10:34:27 -04003463 rjt_err = 1;
dea31012005-04-17 16:05:31 -05003464 break;
3465 }
3466 lpfc_disc_state_machine(phba, ndlp, elsiocb, NLP_EVT_RCV_PRLO);
3467 break;
3468 case ELS_CMD_RSCN:
3469 phba->fc_stat.elsRcvRSCN++;
3470 lpfc_els_rcv_rscn(phba, elsiocb, ndlp, newnode);
James Smartde0c5b32007-04-25 09:52:27 -04003471 if (newnode)
3472 lpfc_drop_node(phba, ndlp);
dea31012005-04-17 16:05:31 -05003473 break;
3474 case ELS_CMD_ADISC:
3475 phba->fc_stat.elsRcvADISC++;
3476 if (phba->hba_state < LPFC_DISC_AUTH) {
James.Smart@Emulex.Com1f679ca2005-06-25 10:34:27 -04003477 rjt_err = 1;
dea31012005-04-17 16:05:31 -05003478 break;
3479 }
3480 lpfc_disc_state_machine(phba, ndlp, elsiocb, NLP_EVT_RCV_ADISC);
3481 break;
3482 case ELS_CMD_PDISC:
3483 phba->fc_stat.elsRcvPDISC++;
3484 if (phba->hba_state < LPFC_DISC_AUTH) {
James.Smart@Emulex.Com1f679ca2005-06-25 10:34:27 -04003485 rjt_err = 1;
dea31012005-04-17 16:05:31 -05003486 break;
3487 }
3488 lpfc_disc_state_machine(phba, ndlp, elsiocb, NLP_EVT_RCV_PDISC);
3489 break;
3490 case ELS_CMD_FARPR:
3491 phba->fc_stat.elsRcvFARPR++;
3492 lpfc_els_rcv_farpr(phba, elsiocb, ndlp);
3493 break;
3494 case ELS_CMD_FARP:
3495 phba->fc_stat.elsRcvFARP++;
3496 lpfc_els_rcv_farp(phba, elsiocb, ndlp);
3497 break;
3498 case ELS_CMD_FAN:
3499 phba->fc_stat.elsRcvFAN++;
3500 lpfc_els_rcv_fan(phba, elsiocb, ndlp);
3501 break;
dea31012005-04-17 16:05:31 -05003502 case ELS_CMD_PRLI:
3503 phba->fc_stat.elsRcvPRLI++;
3504 if (phba->hba_state < LPFC_DISC_AUTH) {
James.Smart@Emulex.Com1f679ca2005-06-25 10:34:27 -04003505 rjt_err = 1;
dea31012005-04-17 16:05:31 -05003506 break;
3507 }
3508 lpfc_disc_state_machine(phba, ndlp, elsiocb, NLP_EVT_RCV_PRLI);
3509 break;
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05003510 case ELS_CMD_LIRR:
3511 phba->fc_stat.elsRcvLIRR++;
3512 lpfc_els_rcv_lirr(phba, elsiocb, ndlp);
James Smartde0c5b32007-04-25 09:52:27 -04003513 if (newnode)
3514 lpfc_drop_node(phba, ndlp);
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05003515 break;
3516 case ELS_CMD_RPS:
3517 phba->fc_stat.elsRcvRPS++;
3518 lpfc_els_rcv_rps(phba, elsiocb, ndlp);
James Smartde0c5b32007-04-25 09:52:27 -04003519 if (newnode)
3520 lpfc_drop_node(phba, ndlp);
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05003521 break;
3522 case ELS_CMD_RPL:
3523 phba->fc_stat.elsRcvRPL++;
3524 lpfc_els_rcv_rpl(phba, elsiocb, ndlp);
James Smartde0c5b32007-04-25 09:52:27 -04003525 if (newnode)
3526 lpfc_drop_node(phba, ndlp);
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05003527 break;
dea31012005-04-17 16:05:31 -05003528 case ELS_CMD_RNID:
3529 phba->fc_stat.elsRcvRNID++;
3530 lpfc_els_rcv_rnid(phba, elsiocb, ndlp);
James Smartde0c5b32007-04-25 09:52:27 -04003531 if (newnode)
3532 lpfc_drop_node(phba, ndlp);
dea31012005-04-17 16:05:31 -05003533 break;
3534 default:
3535 /* Unsupported ELS command, reject */
James.Smart@Emulex.Com1f679ca2005-06-25 10:34:27 -04003536 rjt_err = 1;
dea31012005-04-17 16:05:31 -05003537
3538 /* Unknown ELS command <elsCmd> received from NPORT <did> */
3539 lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
3540 "%d:0115 Unknown ELS command x%x received from "
3541 "NPORT x%x\n", phba->brd_no, cmd, did);
James Smartde0c5b32007-04-25 09:52:27 -04003542 if (newnode)
3543 lpfc_drop_node(phba, ndlp);
dea31012005-04-17 16:05:31 -05003544 break;
3545 }
3546
3547 /* check if need to LS_RJT received ELS cmd */
3548 if (rjt_err) {
3549 stat.un.b.lsRjtRsvd0 = 0;
3550 stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
James.Smart@Emulex.Com1f679ca2005-06-25 10:34:27 -04003551 stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE;
dea31012005-04-17 16:05:31 -05003552 stat.un.b.vendorUnique = 0;
3553 lpfc_els_rsp_reject(phba, stat.un.lsRjtError, elsiocb, ndlp);
3554 }
3555
3556 if (elsiocb->context2) {
3557 lpfc_mbuf_free(phba, mp->virt, mp->phys);
3558 kfree(mp);
3559 }
3560dropit:
3561 /* check if need to drop received ELS cmd */
3562 if (drop_cmd == 1) {
3563 lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
3564 "%d:0111 Dropping received ELS cmd "
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05003565 "Data: x%x x%x x%x\n", phba->brd_no,
3566 icmd->ulpStatus, icmd->un.ulpWord[4],
3567 icmd->ulpTimeout);
dea31012005-04-17 16:05:31 -05003568 phba->fc_stat.elsRcvDrop++;
3569 }
3570 return;
3571}