blob: e1c61dbb3d0f7539b0b2e0734b7ecc329aa8b4e4 [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;
185 } else {
186 icmd->un.elsreq64.bdl.bdeSize = sizeof (struct ulp_bde64);
187 icmd->ulpCommand = CMD_XMIT_ELS_RSP64_CX;
188 }
189
190 icmd->ulpBdeCount = 1;
191 icmd->ulpLe = 1;
192 icmd->ulpClass = CLASS3;
193
194 bpl = (struct ulp_bde64 *) pbuflist->virt;
195 bpl->addrLow = le32_to_cpu(putPaddrLow(pcmd->phys));
196 bpl->addrHigh = le32_to_cpu(putPaddrHigh(pcmd->phys));
197 bpl->tus.f.bdeSize = cmdSize;
198 bpl->tus.f.bdeFlags = 0;
199 bpl->tus.w = le32_to_cpu(bpl->tus.w);
200
201 if (expectRsp) {
202 bpl++;
203 bpl->addrLow = le32_to_cpu(putPaddrLow(prsp->phys));
204 bpl->addrHigh = le32_to_cpu(putPaddrHigh(prsp->phys));
205 bpl->tus.f.bdeSize = FCELSSIZE;
206 bpl->tus.f.bdeFlags = BUFF_USE_RCV;
207 bpl->tus.w = le32_to_cpu(bpl->tus.w);
208 }
209
210 /* Save for completion so we can release these resources */
211 elsiocb->context1 = (uint8_t *) ndlp;
212 elsiocb->context2 = (uint8_t *) pcmd;
213 elsiocb->context3 = (uint8_t *) pbuflist;
214 elsiocb->retry = retry;
215 elsiocb->drvrTimeout = (phba->fc_ratov << 1) + LPFC_DRVR_TIMEOUT;
216
217 if (prsp) {
218 list_add(&prsp->list, &pcmd->list);
219 }
220
221 if (expectRsp) {
222 /* Xmit ELS command <elsCmd> to remote NPORT <did> */
223 lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
224 "%d:0116 Xmit ELS command x%x to remote "
James Smart1dcb58e2007-04-25 09:51:30 -0400225 "NPORT x%x I/O tag: x%x, HBA state: x%x\n",
dea31012005-04-17 16:05:31 -0500226 phba->brd_no, elscmd,
James Smart1dcb58e2007-04-25 09:51:30 -0400227 did, elsiocb->iotag, phba->hba_state);
dea31012005-04-17 16:05:31 -0500228 } else {
229 /* Xmit ELS response <elsCmd> to remote NPORT <did> */
230 lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
231 "%d:0117 Xmit ELS response x%x to remote "
James Smart1dcb58e2007-04-25 09:51:30 -0400232 "NPORT x%x I/O tag: x%x, size: x%x\n",
dea31012005-04-17 16:05:31 -0500233 phba->brd_no, elscmd,
James Smart1dcb58e2007-04-25 09:51:30 -0400234 ndlp->nlp_DID, elsiocb->iotag, cmdSize);
dea31012005-04-17 16:05:31 -0500235 }
236
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500237 return elsiocb;
dea31012005-04-17 16:05:31 -0500238}
239
240
241static int
242lpfc_cmpl_els_flogi_fabric(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp,
243 struct serv_parm *sp, IOCB_t *irsp)
244{
245 LPFC_MBOXQ_t *mbox;
James Smart14691152006-12-02 13:34:28 -0500246 struct lpfc_dmabuf *mp;
dea31012005-04-17 16:05:31 -0500247 int rc;
248
249 spin_lock_irq(phba->host->host_lock);
250 phba->fc_flag |= FC_FABRIC;
251 spin_unlock_irq(phba->host->host_lock);
252
253 phba->fc_edtov = be32_to_cpu(sp->cmn.e_d_tov);
254 if (sp->cmn.edtovResolution) /* E_D_TOV ticks are in nanoseconds */
255 phba->fc_edtov = (phba->fc_edtov + 999999) / 1000000;
256
257 phba->fc_ratov = (be32_to_cpu(sp->cmn.w2.r_a_tov) + 999) / 1000;
258
259 if (phba->fc_topology == TOPOLOGY_LOOP) {
260 spin_lock_irq(phba->host->host_lock);
261 phba->fc_flag |= FC_PUBLIC_LOOP;
262 spin_unlock_irq(phba->host->host_lock);
263 } else {
264 /*
265 * If we are a N-port connected to a Fabric, fixup sparam's so
266 * logins to devices on remote loops work.
267 */
268 phba->fc_sparam.cmn.altBbCredit = 1;
269 }
270
271 phba->fc_myDID = irsp->un.ulpWord[4] & Mask_DID;
272 memcpy(&ndlp->nlp_portname, &sp->portName, sizeof(struct lpfc_name));
273 memcpy(&ndlp->nlp_nodename, &sp->nodeName, sizeof (struct lpfc_name));
274 ndlp->nlp_class_sup = 0;
275 if (sp->cls1.classValid)
276 ndlp->nlp_class_sup |= FC_COS_CLASS1;
277 if (sp->cls2.classValid)
278 ndlp->nlp_class_sup |= FC_COS_CLASS2;
279 if (sp->cls3.classValid)
280 ndlp->nlp_class_sup |= FC_COS_CLASS3;
281 if (sp->cls4.classValid)
282 ndlp->nlp_class_sup |= FC_COS_CLASS4;
283 ndlp->nlp_maxframe = ((sp->cmn.bbRcvSizeMsb & 0x0F) << 8) |
284 sp->cmn.bbRcvSizeLsb;
285 memcpy(&phba->fc_fabparam, sp, sizeof(struct serv_parm));
286
287 mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
288 if (!mbox)
289 goto fail;
290
291 phba->hba_state = LPFC_FABRIC_CFG_LINK;
292 lpfc_config_link(phba, mbox);
293 mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
294
295 rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT | MBX_STOP_IOCB);
296 if (rc == MBX_NOT_FINISHED)
297 goto fail_free_mbox;
298
299 mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
300 if (!mbox)
301 goto fail;
302
303 if (lpfc_reg_login(phba, Fabric_DID, (uint8_t *) sp, mbox, 0))
304 goto fail_free_mbox;
305
dea31012005-04-17 16:05:31 -0500306 mbox->mbox_cmpl = lpfc_mbx_cmpl_fabric_reg_login;
307 mbox->context2 = ndlp;
308
309 rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT | MBX_STOP_IOCB);
310 if (rc == MBX_NOT_FINISHED)
James Smart14691152006-12-02 13:34:28 -0500311 goto fail_issue_reg_login;
dea31012005-04-17 16:05:31 -0500312
313 return 0;
314
James Smart14691152006-12-02 13:34:28 -0500315 fail_issue_reg_login:
316 mp = (struct lpfc_dmabuf *) mbox->context1;
317 lpfc_mbuf_free(phba, mp->virt, mp->phys);
318 kfree(mp);
dea31012005-04-17 16:05:31 -0500319 fail_free_mbox:
320 mempool_free(mbox, phba->mbox_mem_pool);
321 fail:
322 return -ENXIO;
323}
324
325/*
326 * We FLOGIed into an NPort, initiate pt2pt protocol
327 */
328static int
329lpfc_cmpl_els_flogi_nport(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp,
330 struct serv_parm *sp)
331{
332 LPFC_MBOXQ_t *mbox;
333 int rc;
334
335 spin_lock_irq(phba->host->host_lock);
336 phba->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP);
337 spin_unlock_irq(phba->host->host_lock);
338
339 phba->fc_edtov = FF_DEF_EDTOV;
340 phba->fc_ratov = FF_DEF_RATOV;
341 rc = memcmp(&phba->fc_portname, &sp->portName,
342 sizeof(struct lpfc_name));
343 if (rc >= 0) {
344 /* This side will initiate the PLOGI */
345 spin_lock_irq(phba->host->host_lock);
346 phba->fc_flag |= FC_PT2PT_PLOGI;
347 spin_unlock_irq(phba->host->host_lock);
348
349 /*
350 * N_Port ID cannot be 0, set our to LocalID the other
351 * side will be RemoteID.
352 */
353
354 /* not equal */
355 if (rc)
356 phba->fc_myDID = PT2PT_LocalID;
357
358 mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
359 if (!mbox)
360 goto fail;
361
362 lpfc_config_link(phba, mbox);
363
364 mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
365 rc = lpfc_sli_issue_mbox(phba, mbox,
366 MBX_NOWAIT | MBX_STOP_IOCB);
367 if (rc == MBX_NOT_FINISHED) {
368 mempool_free(mbox, phba->mbox_mem_pool);
369 goto fail;
370 }
371 mempool_free(ndlp, phba->nlp_mem_pool);
372
373 ndlp = lpfc_findnode_did(phba, NLP_SEARCH_ALL, PT2PT_RemoteID);
374 if (!ndlp) {
375 /*
376 * Cannot find existing Fabric ndlp, so allocate a
377 * new one
378 */
379 ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL);
380 if (!ndlp)
381 goto fail;
382
383 lpfc_nlp_init(phba, ndlp, PT2PT_RemoteID);
384 }
385
386 memcpy(&ndlp->nlp_portname, &sp->portName,
387 sizeof(struct lpfc_name));
388 memcpy(&ndlp->nlp_nodename, &sp->nodeName,
389 sizeof(struct lpfc_name));
390 ndlp->nlp_state = NLP_STE_NPR_NODE;
391 lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST);
392 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);
585 if (ndlp && (ndlp->nlp_DID == Fabric_DID)) {
586 list_del(&iocb->list);
587 pring->txcmplq_cnt--;
588
589 if ((icmd->un.elsreq64.bdl.ulpIoTag32)) {
590 lpfc_sli_issue_abort_iotag32
591 (phba, pring, iocb);
592 }
593 if (iocb->iocb_cmpl) {
594 icmd->ulpStatus = IOSTAT_LOCAL_REJECT;
595 icmd->un.ulpWord[4] =
596 IOERR_SLI_ABORTED;
597 spin_unlock_irq(phba->host->host_lock);
598 (iocb->iocb_cmpl) (phba, iocb, iocb);
599 spin_lock_irq(phba->host->host_lock);
James Bottomley604a3e32005-10-29 10:28:33 -0500600 } else
601 lpfc_sli_release_iocbq(phba, iocb);
dea31012005-04-17 16:05:31 -0500602 }
603 }
604 }
605 spin_unlock_irq(phba->host->host_lock);
606
607 return 0;
608}
609
610int
611lpfc_initial_flogi(struct lpfc_hba * phba)
612{
613 struct lpfc_nodelist *ndlp;
614
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500615 /* First look for the Fabric ndlp */
616 ndlp = lpfc_findnode_did(phba, NLP_SEARCH_ALL, Fabric_DID);
617 if (!ndlp) {
dea31012005-04-17 16:05:31 -0500618 /* Cannot find existing Fabric ndlp, so allocate a new one */
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500619 ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL);
620 if (!ndlp)
621 return 0;
dea31012005-04-17 16:05:31 -0500622 lpfc_nlp_init(phba, ndlp, Fabric_DID);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500623 } else {
624 lpfc_nlp_list(phba, ndlp, NLP_JUST_DQ);
dea31012005-04-17 16:05:31 -0500625 }
626 if (lpfc_issue_els_flogi(phba, ndlp, 0)) {
627 mempool_free( ndlp, phba->nlp_mem_pool);
628 }
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500629 return 1;
dea31012005-04-17 16:05:31 -0500630}
631
632static void
633lpfc_more_plogi(struct lpfc_hba * phba)
634{
635 int sentplogi;
636
637 if (phba->num_disc_nodes)
638 phba->num_disc_nodes--;
639
640 /* Continue discovery with <num_disc_nodes> PLOGIs to go */
641 lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
642 "%d:0232 Continue discovery with %d PLOGIs to go "
643 "Data: x%x x%x x%x\n",
644 phba->brd_no, phba->num_disc_nodes, phba->fc_plogi_cnt,
645 phba->fc_flag, phba->hba_state);
646
647 /* Check to see if there are more PLOGIs to be sent */
648 if (phba->fc_flag & FC_NLP_MORE) {
649 /* go thru NPR list and issue any remaining ELS PLOGIs */
650 sentplogi = lpfc_els_disc_plogi(phba);
651 }
652 return;
653}
654
James Smart488d1462006-03-07 15:02:37 -0500655static struct lpfc_nodelist *
James Smart92795652006-07-06 15:50:02 -0400656lpfc_plogi_confirm_nport(struct lpfc_hba * phba, struct lpfc_dmabuf *prsp,
James Smart488d1462006-03-07 15:02:37 -0500657 struct lpfc_nodelist *ndlp)
658{
659 struct lpfc_nodelist *new_ndlp;
James Smart488d1462006-03-07 15:02:37 -0500660 uint32_t *lp;
661 struct serv_parm *sp;
662 uint8_t name[sizeof (struct lpfc_name)];
663 uint32_t rc;
664
James Smart2fb9bd82006-12-02 13:33:57 -0500665 /* Fabric nodes can have the same WWPN so we don't bother searching
666 * by WWPN. Just return the ndlp that was given to us.
667 */
668 if (ndlp->nlp_type & NLP_FABRIC)
669 return ndlp;
670
James Smart488d1462006-03-07 15:02:37 -0500671 lp = (uint32_t *) prsp->virt;
672 sp = (struct serv_parm *) ((uint8_t *) lp + sizeof (uint32_t));
James Smart92795652006-07-06 15:50:02 -0400673 memset(name, 0, sizeof (struct lpfc_name));
James Smart488d1462006-03-07 15:02:37 -0500674
675 /* Now we to find out if the NPort we are logging into, matches the WWPN
676 * we have for that ndlp. If not, we have some work to do.
677 */
678 new_ndlp = lpfc_findnode_wwpn(phba, NLP_SEARCH_ALL, &sp->portName);
679
James Smart92795652006-07-06 15:50:02 -0400680 if (new_ndlp == ndlp)
James Smart488d1462006-03-07 15:02:37 -0500681 return ndlp;
James Smart488d1462006-03-07 15:02:37 -0500682
683 if (!new_ndlp) {
James Smart92795652006-07-06 15:50:02 -0400684 rc =
685 memcmp(&ndlp->nlp_portname, name, sizeof(struct lpfc_name));
686 if (!rc)
687 return ndlp;
James Smart488d1462006-03-07 15:02:37 -0500688 new_ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_ATOMIC);
689 if (!new_ndlp)
690 return ndlp;
691
692 lpfc_nlp_init(phba, new_ndlp, ndlp->nlp_DID);
693 }
694
695 lpfc_unreg_rpi(phba, new_ndlp);
James Smart488d1462006-03-07 15:02:37 -0500696 new_ndlp->nlp_DID = ndlp->nlp_DID;
James Smart92795652006-07-06 15:50:02 -0400697 new_ndlp->nlp_prev_state = ndlp->nlp_prev_state;
698 new_ndlp->nlp_state = ndlp->nlp_state;
699 lpfc_nlp_list(phba, new_ndlp, ndlp->nlp_flag & NLP_LIST_MASK);
James Smart488d1462006-03-07 15:02:37 -0500700
701 /* Move this back to NPR list */
James Smart92795652006-07-06 15:50:02 -0400702 if (memcmp(&ndlp->nlp_portname, name, sizeof(struct lpfc_name)) == 0) {
703 lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
704 }
705 else {
706 lpfc_unreg_rpi(phba, ndlp);
707 ndlp->nlp_DID = 0; /* Two ndlps cannot have the same did */
708 ndlp->nlp_state = NLP_STE_NPR_NODE;
709 lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST);
710 }
James Smart488d1462006-03-07 15:02:37 -0500711 return new_ndlp;
712}
713
dea31012005-04-17 16:05:31 -0500714static void
715lpfc_cmpl_els_plogi(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
716 struct lpfc_iocbq * rspiocb)
717{
718 IOCB_t *irsp;
dea31012005-04-17 16:05:31 -0500719 struct lpfc_nodelist *ndlp;
James Smart92795652006-07-06 15:50:02 -0400720 struct lpfc_dmabuf *prsp;
dea31012005-04-17 16:05:31 -0500721 int disc, rc, did, type;
722
dea31012005-04-17 16:05:31 -0500723
724 /* we pass cmdiocb to state machine which needs rspiocb as well */
725 cmdiocb->context_un.rsp_iocb = rspiocb;
726
727 irsp = &rspiocb->iocb;
James Smart488d1462006-03-07 15:02:37 -0500728 ndlp = lpfc_findnode_did(phba, NLP_SEARCH_ALL,
729 irsp->un.elsreq64.remoteID);
730 if (!ndlp)
731 goto out;
dea31012005-04-17 16:05:31 -0500732
733 /* Since ndlp can be freed in the disc state machine, note if this node
734 * is being used during discovery.
735 */
736 disc = (ndlp->nlp_flag & NLP_NPR_2B_DISC);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500737 spin_lock_irq(phba->host->host_lock);
James Smart488d1462006-03-07 15:02:37 -0500738 ndlp->nlp_flag &= ~NLP_NPR_2B_DISC;
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500739 spin_unlock_irq(phba->host->host_lock);
dea31012005-04-17 16:05:31 -0500740 rc = 0;
741
742 /* PLOGI completes to NPort <nlp_DID> */
743 lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
744 "%d:0102 PLOGI completes to NPort x%x "
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500745 "Data: x%x x%x x%x x%x x%x\n",
dea31012005-04-17 16:05:31 -0500746 phba->brd_no, ndlp->nlp_DID, irsp->ulpStatus,
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500747 irsp->un.ulpWord[4], irsp->ulpTimeout, disc,
748 phba->num_disc_nodes);
dea31012005-04-17 16:05:31 -0500749
750 /* Check to see if link went down during discovery */
751 if (lpfc_els_chk_latt(phba)) {
752 spin_lock_irq(phba->host->host_lock);
753 ndlp->nlp_flag |= NLP_NPR_2B_DISC;
754 spin_unlock_irq(phba->host->host_lock);
755 goto out;
756 }
757
758 /* ndlp could be freed in DSM, save these values now */
759 type = ndlp->nlp_type;
760 did = ndlp->nlp_DID;
761
762 if (irsp->ulpStatus) {
763 /* Check for retry */
764 if (lpfc_els_retry(phba, cmdiocb, rspiocb)) {
765 /* ELS command is being retried */
766 if (disc) {
767 spin_lock_irq(phba->host->host_lock);
768 ndlp->nlp_flag |= NLP_NPR_2B_DISC;
769 spin_unlock_irq(phba->host->host_lock);
770 }
771 goto out;
772 }
773
774 /* PLOGI failed */
775 /* Do not call DSM for lpfc_els_abort'ed ELS cmds */
776 if ((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) &&
777 ((irsp->un.ulpWord[4] == IOERR_SLI_ABORTED) ||
James.Smart@Emulex.Com6281bfe2005-11-28 11:41:33 -0500778 (irsp->un.ulpWord[4] == IOERR_LINK_DOWN) ||
dea31012005-04-17 16:05:31 -0500779 (irsp->un.ulpWord[4] == IOERR_SLI_DOWN))) {
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500780 rc = NLP_STE_FREED_NODE;
Jamie Wellnitz2fe165b2006-02-28 19:25:31 -0500781 } else {
dea31012005-04-17 16:05:31 -0500782 rc = lpfc_disc_state_machine(phba, ndlp, cmdiocb,
783 NLP_EVT_CMPL_PLOGI);
784 }
785 } else {
786 /* Good status, call state machine */
James Smart92795652006-07-06 15:50:02 -0400787 prsp = list_entry(((struct lpfc_dmabuf *)
788 cmdiocb->context2)->list.next,
789 struct lpfc_dmabuf, list);
790 ndlp = lpfc_plogi_confirm_nport(phba, prsp, ndlp);
dea31012005-04-17 16:05:31 -0500791 rc = lpfc_disc_state_machine(phba, ndlp, cmdiocb,
792 NLP_EVT_CMPL_PLOGI);
793 }
794
dea31012005-04-17 16:05:31 -0500795 if (disc && phba->num_disc_nodes) {
796 /* Check to see if there are more PLOGIs to be sent */
797 lpfc_more_plogi(phba);
dea31012005-04-17 16:05:31 -0500798
James Smart10d4e952006-04-15 11:53:15 -0400799 if (phba->num_disc_nodes == 0) {
800 spin_lock_irq(phba->host->host_lock);
801 phba->fc_flag &= ~FC_NDISC_ACTIVE;
802 spin_unlock_irq(phba->host->host_lock);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500803
James Smart10d4e952006-04-15 11:53:15 -0400804 lpfc_can_disctmo(phba);
805 if (phba->fc_flag & FC_RSCN_MODE) {
806 /*
807 * Check to see if more RSCNs came in while
808 * we were processing this one.
809 */
810 if ((phba->fc_rscn_id_cnt == 0) &&
811 (!(phba->fc_flag & FC_RSCN_DISCOVERY))) {
812 spin_lock_irq(phba->host->host_lock);
813 phba->fc_flag &= ~FC_RSCN_MODE;
814 spin_unlock_irq(phba->host->host_lock);
815 } else {
816 lpfc_els_handle_rscn(phba);
817 }
dea31012005-04-17 16:05:31 -0500818 }
819 }
820 }
821
822out:
823 lpfc_els_free_iocb(phba, cmdiocb);
824 return;
825}
826
827int
James Smart488d1462006-03-07 15:02:37 -0500828lpfc_issue_els_plogi(struct lpfc_hba * phba, uint32_t did, uint8_t retry)
dea31012005-04-17 16:05:31 -0500829{
830 struct serv_parm *sp;
831 IOCB_t *icmd;
832 struct lpfc_iocbq *elsiocb;
833 struct lpfc_sli_ring *pring;
834 struct lpfc_sli *psli;
835 uint8_t *pcmd;
836 uint16_t cmdsize;
837
838 psli = &phba->sli;
839 pring = &psli->ring[LPFC_ELS_RING]; /* ELS ring */
840
841 cmdsize = (sizeof (uint32_t) + sizeof (struct serv_parm));
Randy Dunlap041976f2006-06-25 01:58:51 -0700842 elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry, NULL, did,
Jamie Wellnitz2fe165b2006-02-28 19:25:31 -0500843 ELS_CMD_PLOGI);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500844 if (!elsiocb)
845 return 1;
dea31012005-04-17 16:05:31 -0500846
847 icmd = &elsiocb->iocb;
848 pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
849
850 /* For PLOGI request, remainder of payload is service parameters */
851 *((uint32_t *) (pcmd)) = ELS_CMD_PLOGI;
852 pcmd += sizeof (uint32_t);
853 memcpy(pcmd, &phba->fc_sparam, sizeof (struct serv_parm));
854 sp = (struct serv_parm *) pcmd;
855
856 if (sp->cmn.fcphLow < FC_PH_4_3)
857 sp->cmn.fcphLow = FC_PH_4_3;
858
859 if (sp->cmn.fcphHigh < FC_PH3)
860 sp->cmn.fcphHigh = FC_PH3;
861
862 phba->fc_stat.elsXmitPLOGI++;
863 elsiocb->iocb_cmpl = lpfc_cmpl_els_plogi;
864 spin_lock_irq(phba->host->host_lock);
dea31012005-04-17 16:05:31 -0500865 if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) {
dea31012005-04-17 16:05:31 -0500866 spin_unlock_irq(phba->host->host_lock);
867 lpfc_els_free_iocb(phba, elsiocb);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500868 return 1;
dea31012005-04-17 16:05:31 -0500869 }
870 spin_unlock_irq(phba->host->host_lock);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500871 return 0;
dea31012005-04-17 16:05:31 -0500872}
873
874static void
875lpfc_cmpl_els_prli(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
876 struct lpfc_iocbq * rspiocb)
877{
878 IOCB_t *irsp;
879 struct lpfc_sli *psli;
880 struct lpfc_nodelist *ndlp;
881
882 psli = &phba->sli;
883 /* we pass cmdiocb to state machine which needs rspiocb as well */
884 cmdiocb->context_un.rsp_iocb = rspiocb;
885
886 irsp = &(rspiocb->iocb);
887 ndlp = (struct lpfc_nodelist *) cmdiocb->context1;
888 spin_lock_irq(phba->host->host_lock);
889 ndlp->nlp_flag &= ~NLP_PRLI_SND;
890 spin_unlock_irq(phba->host->host_lock);
891
892 /* PRLI completes to NPort <nlp_DID> */
893 lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
894 "%d:0103 PRLI completes to NPort x%x "
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500895 "Data: x%x x%x x%x x%x\n",
dea31012005-04-17 16:05:31 -0500896 phba->brd_no, ndlp->nlp_DID, irsp->ulpStatus,
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500897 irsp->un.ulpWord[4], irsp->ulpTimeout,
898 phba->num_disc_nodes);
dea31012005-04-17 16:05:31 -0500899
900 phba->fc_prli_sent--;
901 /* Check to see if link went down during discovery */
902 if (lpfc_els_chk_latt(phba))
903 goto out;
904
905 if (irsp->ulpStatus) {
906 /* Check for retry */
907 if (lpfc_els_retry(phba, cmdiocb, rspiocb)) {
908 /* ELS command is being retried */
909 goto out;
910 }
911 /* PRLI failed */
912 /* Do not call DSM for lpfc_els_abort'ed ELS cmds */
913 if ((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) &&
914 ((irsp->un.ulpWord[4] == IOERR_SLI_ABORTED) ||
James.Smart@Emulex.Com6281bfe2005-11-28 11:41:33 -0500915 (irsp->un.ulpWord[4] == IOERR_LINK_DOWN) ||
dea31012005-04-17 16:05:31 -0500916 (irsp->un.ulpWord[4] == IOERR_SLI_DOWN))) {
917 goto out;
Jamie Wellnitz2fe165b2006-02-28 19:25:31 -0500918 } else {
dea31012005-04-17 16:05:31 -0500919 lpfc_disc_state_machine(phba, ndlp, cmdiocb,
920 NLP_EVT_CMPL_PRLI);
921 }
922 } else {
923 /* Good status, call state machine */
924 lpfc_disc_state_machine(phba, ndlp, cmdiocb, NLP_EVT_CMPL_PRLI);
925 }
926
927out:
928 lpfc_els_free_iocb(phba, cmdiocb);
929 return;
930}
931
932int
933lpfc_issue_els_prli(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp,
934 uint8_t retry)
935{
936 PRLI *npr;
937 IOCB_t *icmd;
938 struct lpfc_iocbq *elsiocb;
939 struct lpfc_sli_ring *pring;
940 struct lpfc_sli *psli;
941 uint8_t *pcmd;
942 uint16_t cmdsize;
943
944 psli = &phba->sli;
945 pring = &psli->ring[LPFC_ELS_RING]; /* ELS ring */
946
947 cmdsize = (sizeof (uint32_t) + sizeof (PRLI));
James Smart488d1462006-03-07 15:02:37 -0500948 elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry, ndlp,
949 ndlp->nlp_DID, ELS_CMD_PRLI);
950 if (!elsiocb)
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500951 return 1;
dea31012005-04-17 16:05:31 -0500952
953 icmd = &elsiocb->iocb;
954 pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
955
956 /* For PRLI request, remainder of payload is service parameters */
957 memset(pcmd, 0, (sizeof (PRLI) + sizeof (uint32_t)));
958 *((uint32_t *) (pcmd)) = ELS_CMD_PRLI;
959 pcmd += sizeof (uint32_t);
960
961 /* For PRLI, remainder of payload is PRLI parameter page */
962 npr = (PRLI *) pcmd;
963 /*
964 * If our firmware version is 3.20 or later,
965 * set the following bits for FC-TAPE support.
966 */
967 if (phba->vpd.rev.feaLevelHigh >= 0x02) {
968 npr->ConfmComplAllowed = 1;
969 npr->Retry = 1;
970 npr->TaskRetryIdReq = 1;
971 }
972 npr->estabImagePair = 1;
973 npr->readXferRdyDis = 1;
974
975 /* For FCP support */
976 npr->prliType = PRLI_FCP_TYPE;
977 npr->initiatorFunc = 1;
978
979 phba->fc_stat.elsXmitPRLI++;
980 elsiocb->iocb_cmpl = lpfc_cmpl_els_prli;
981 spin_lock_irq(phba->host->host_lock);
982 ndlp->nlp_flag |= NLP_PRLI_SND;
983 if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) {
984 ndlp->nlp_flag &= ~NLP_PRLI_SND;
985 spin_unlock_irq(phba->host->host_lock);
986 lpfc_els_free_iocb(phba, elsiocb);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500987 return 1;
dea31012005-04-17 16:05:31 -0500988 }
989 spin_unlock_irq(phba->host->host_lock);
990 phba->fc_prli_sent++;
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500991 return 0;
dea31012005-04-17 16:05:31 -0500992}
993
994static void
995lpfc_more_adisc(struct lpfc_hba * phba)
996{
997 int sentadisc;
998
999 if (phba->num_disc_nodes)
1000 phba->num_disc_nodes--;
1001
1002 /* Continue discovery with <num_disc_nodes> ADISCs to go */
1003 lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
1004 "%d:0210 Continue discovery with %d ADISCs to go "
1005 "Data: x%x x%x x%x\n",
1006 phba->brd_no, phba->num_disc_nodes, phba->fc_adisc_cnt,
1007 phba->fc_flag, phba->hba_state);
1008
1009 /* Check to see if there are more ADISCs to be sent */
1010 if (phba->fc_flag & FC_NLP_MORE) {
1011 lpfc_set_disctmo(phba);
1012
1013 /* go thru NPR list and issue any remaining ELS ADISCs */
1014 sentadisc = lpfc_els_disc_adisc(phba);
1015 }
1016 return;
1017}
1018
1019static void
1020lpfc_rscn_disc(struct lpfc_hba * phba)
1021{
1022 /* RSCN discovery */
1023 /* go thru NPR list and issue ELS PLOGIs */
1024 if (phba->fc_npr_cnt) {
1025 if (lpfc_els_disc_plogi(phba))
1026 return;
1027 }
1028 if (phba->fc_flag & FC_RSCN_MODE) {
1029 /* Check to see if more RSCNs came in while we were
1030 * processing this one.
1031 */
1032 if ((phba->fc_rscn_id_cnt == 0) &&
1033 (!(phba->fc_flag & FC_RSCN_DISCOVERY))) {
1034 spin_lock_irq(phba->host->host_lock);
1035 phba->fc_flag &= ~FC_RSCN_MODE;
1036 spin_unlock_irq(phba->host->host_lock);
1037 } else {
1038 lpfc_els_handle_rscn(phba);
1039 }
1040 }
1041}
1042
1043static void
1044lpfc_cmpl_els_adisc(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
1045 struct lpfc_iocbq * rspiocb)
1046{
1047 IOCB_t *irsp;
1048 struct lpfc_sli *psli;
1049 struct lpfc_nodelist *ndlp;
1050 LPFC_MBOXQ_t *mbox;
1051 int disc, rc;
1052
1053 psli = &phba->sli;
1054
1055 /* we pass cmdiocb to state machine which needs rspiocb as well */
1056 cmdiocb->context_un.rsp_iocb = rspiocb;
1057
1058 irsp = &(rspiocb->iocb);
1059 ndlp = (struct lpfc_nodelist *) cmdiocb->context1;
dea31012005-04-17 16:05:31 -05001060
1061 /* Since ndlp can be freed in the disc state machine, note if this node
1062 * is being used during discovery.
1063 */
1064 disc = (ndlp->nlp_flag & NLP_NPR_2B_DISC);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001065 spin_lock_irq(phba->host->host_lock);
1066 ndlp->nlp_flag &= ~(NLP_ADISC_SND | NLP_NPR_2B_DISC);
1067 spin_unlock_irq(phba->host->host_lock);
dea31012005-04-17 16:05:31 -05001068
1069 /* ADISC completes to NPort <nlp_DID> */
1070 lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
1071 "%d:0104 ADISC completes to NPort x%x "
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001072 "Data: x%x x%x x%x x%x x%x\n",
dea31012005-04-17 16:05:31 -05001073 phba->brd_no, ndlp->nlp_DID, irsp->ulpStatus,
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001074 irsp->un.ulpWord[4], irsp->ulpTimeout, disc,
1075 phba->num_disc_nodes);
dea31012005-04-17 16:05:31 -05001076
1077 /* Check to see if link went down during discovery */
1078 if (lpfc_els_chk_latt(phba)) {
1079 spin_lock_irq(phba->host->host_lock);
1080 ndlp->nlp_flag |= NLP_NPR_2B_DISC;
1081 spin_unlock_irq(phba->host->host_lock);
1082 goto out;
1083 }
1084
1085 if (irsp->ulpStatus) {
1086 /* Check for retry */
1087 if (lpfc_els_retry(phba, cmdiocb, rspiocb)) {
1088 /* ELS command is being retried */
1089 if (disc) {
1090 spin_lock_irq(phba->host->host_lock);
1091 ndlp->nlp_flag |= NLP_NPR_2B_DISC;
1092 spin_unlock_irq(phba->host->host_lock);
1093 lpfc_set_disctmo(phba);
1094 }
1095 goto out;
1096 }
1097 /* ADISC failed */
1098 /* Do not call DSM for lpfc_els_abort'ed ELS cmds */
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001099 if ((irsp->ulpStatus != IOSTAT_LOCAL_REJECT) ||
1100 ((irsp->un.ulpWord[4] != IOERR_SLI_ABORTED) &&
1101 (irsp->un.ulpWord[4] != IOERR_LINK_DOWN) &&
1102 (irsp->un.ulpWord[4] != IOERR_SLI_DOWN))) {
dea31012005-04-17 16:05:31 -05001103 lpfc_disc_state_machine(phba, ndlp, cmdiocb,
1104 NLP_EVT_CMPL_ADISC);
1105 }
1106 } else {
1107 /* Good status, call state machine */
1108 lpfc_disc_state_machine(phba, ndlp, cmdiocb,
1109 NLP_EVT_CMPL_ADISC);
1110 }
1111
1112 if (disc && phba->num_disc_nodes) {
1113 /* Check to see if there are more ADISCs to be sent */
1114 lpfc_more_adisc(phba);
1115
1116 /* Check to see if we are done with ADISC authentication */
1117 if (phba->num_disc_nodes == 0) {
1118 lpfc_can_disctmo(phba);
1119 /* If we get here, there is nothing left to wait for */
1120 if ((phba->hba_state < LPFC_HBA_READY) &&
1121 (phba->hba_state != LPFC_CLEAR_LA)) {
1122 /* Link up discovery */
1123 if ((mbox = mempool_alloc(phba->mbox_mem_pool,
1124 GFP_KERNEL))) {
1125 phba->hba_state = LPFC_CLEAR_LA;
1126 lpfc_clear_la(phba, mbox);
1127 mbox->mbox_cmpl =
1128 lpfc_mbx_cmpl_clear_la;
1129 rc = lpfc_sli_issue_mbox
1130 (phba, mbox,
1131 (MBX_NOWAIT | MBX_STOP_IOCB));
1132 if (rc == MBX_NOT_FINISHED) {
1133 mempool_free(mbox,
1134 phba->mbox_mem_pool);
1135 lpfc_disc_flush_list(phba);
James Smarta4bc3372006-12-02 13:34:16 -05001136 psli->ring[(psli->extra_ring)].
dea31012005-04-17 16:05:31 -05001137 flag &=
1138 ~LPFC_STOP_IOCB_EVENT;
1139 psli->ring[(psli->fcp_ring)].
1140 flag &=
1141 ~LPFC_STOP_IOCB_EVENT;
1142 psli->ring[(psli->next_ring)].
1143 flag &=
1144 ~LPFC_STOP_IOCB_EVENT;
1145 phba->hba_state =
1146 LPFC_HBA_READY;
1147 }
1148 }
1149 } else {
1150 lpfc_rscn_disc(phba);
1151 }
1152 }
1153 }
dea31012005-04-17 16:05:31 -05001154out:
1155 lpfc_els_free_iocb(phba, cmdiocb);
1156 return;
1157}
1158
1159int
1160lpfc_issue_els_adisc(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp,
1161 uint8_t retry)
1162{
1163 ADISC *ap;
1164 IOCB_t *icmd;
1165 struct lpfc_iocbq *elsiocb;
1166 struct lpfc_sli_ring *pring;
1167 struct lpfc_sli *psli;
1168 uint8_t *pcmd;
1169 uint16_t cmdsize;
1170
1171 psli = &phba->sli;
1172 pring = &psli->ring[LPFC_ELS_RING]; /* ELS ring */
1173
1174 cmdsize = (sizeof (uint32_t) + sizeof (ADISC));
James Smart488d1462006-03-07 15:02:37 -05001175 elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry, ndlp,
1176 ndlp->nlp_DID, ELS_CMD_ADISC);
1177 if (!elsiocb)
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001178 return 1;
dea31012005-04-17 16:05:31 -05001179
1180 icmd = &elsiocb->iocb;
1181 pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
1182
1183 /* For ADISC request, remainder of payload is service parameters */
1184 *((uint32_t *) (pcmd)) = ELS_CMD_ADISC;
1185 pcmd += sizeof (uint32_t);
1186
1187 /* Fill in ADISC payload */
1188 ap = (ADISC *) pcmd;
1189 ap->hardAL_PA = phba->fc_pref_ALPA;
1190 memcpy(&ap->portName, &phba->fc_portname, sizeof (struct lpfc_name));
1191 memcpy(&ap->nodeName, &phba->fc_nodename, sizeof (struct lpfc_name));
1192 ap->DID = be32_to_cpu(phba->fc_myDID);
1193
1194 phba->fc_stat.elsXmitADISC++;
1195 elsiocb->iocb_cmpl = lpfc_cmpl_els_adisc;
1196 spin_lock_irq(phba->host->host_lock);
1197 ndlp->nlp_flag |= NLP_ADISC_SND;
1198 if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) {
1199 ndlp->nlp_flag &= ~NLP_ADISC_SND;
1200 spin_unlock_irq(phba->host->host_lock);
1201 lpfc_els_free_iocb(phba, elsiocb);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001202 return 1;
dea31012005-04-17 16:05:31 -05001203 }
1204 spin_unlock_irq(phba->host->host_lock);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001205 return 0;
dea31012005-04-17 16:05:31 -05001206}
1207
1208static void
1209lpfc_cmpl_els_logo(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
1210 struct lpfc_iocbq * rspiocb)
1211{
1212 IOCB_t *irsp;
1213 struct lpfc_sli *psli;
1214 struct lpfc_nodelist *ndlp;
1215
1216 psli = &phba->sli;
1217 /* we pass cmdiocb to state machine which needs rspiocb as well */
1218 cmdiocb->context_un.rsp_iocb = rspiocb;
1219
1220 irsp = &(rspiocb->iocb);
1221 ndlp = (struct lpfc_nodelist *) cmdiocb->context1;
1222 spin_lock_irq(phba->host->host_lock);
1223 ndlp->nlp_flag &= ~NLP_LOGO_SND;
1224 spin_unlock_irq(phba->host->host_lock);
1225
1226 /* LOGO completes to NPort <nlp_DID> */
1227 lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
1228 "%d:0105 LOGO completes to NPort x%x "
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001229 "Data: x%x x%x x%x x%x\n",
dea31012005-04-17 16:05:31 -05001230 phba->brd_no, ndlp->nlp_DID, irsp->ulpStatus,
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001231 irsp->un.ulpWord[4], irsp->ulpTimeout,
1232 phba->num_disc_nodes);
dea31012005-04-17 16:05:31 -05001233
1234 /* Check to see if link went down during discovery */
1235 if (lpfc_els_chk_latt(phba))
1236 goto out;
1237
1238 if (irsp->ulpStatus) {
1239 /* Check for retry */
1240 if (lpfc_els_retry(phba, cmdiocb, rspiocb)) {
1241 /* ELS command is being retried */
1242 goto out;
1243 }
1244 /* LOGO failed */
1245 /* Do not call DSM for lpfc_els_abort'ed ELS cmds */
1246 if ((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) &&
1247 ((irsp->un.ulpWord[4] == IOERR_SLI_ABORTED) ||
James.Smart@Emulex.Com6281bfe2005-11-28 11:41:33 -05001248 (irsp->un.ulpWord[4] == IOERR_LINK_DOWN) ||
dea31012005-04-17 16:05:31 -05001249 (irsp->un.ulpWord[4] == IOERR_SLI_DOWN))) {
1250 goto out;
Jamie Wellnitz2fe165b2006-02-28 19:25:31 -05001251 } else {
dea31012005-04-17 16:05:31 -05001252 lpfc_disc_state_machine(phba, ndlp, cmdiocb,
1253 NLP_EVT_CMPL_LOGO);
1254 }
1255 } else {
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05001256 /* Good status, call state machine.
1257 * This will unregister the rpi if needed.
1258 */
dea31012005-04-17 16:05:31 -05001259 lpfc_disc_state_machine(phba, ndlp, cmdiocb, NLP_EVT_CMPL_LOGO);
dea31012005-04-17 16:05:31 -05001260 }
1261
1262out:
1263 lpfc_els_free_iocb(phba, cmdiocb);
1264 return;
1265}
1266
1267int
1268lpfc_issue_els_logo(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp,
1269 uint8_t retry)
1270{
1271 IOCB_t *icmd;
1272 struct lpfc_iocbq *elsiocb;
1273 struct lpfc_sli_ring *pring;
1274 struct lpfc_sli *psli;
1275 uint8_t *pcmd;
1276 uint16_t cmdsize;
1277
1278 psli = &phba->sli;
1279 pring = &psli->ring[LPFC_ELS_RING];
1280
James Smart10d4e952006-04-15 11:53:15 -04001281 cmdsize = (2 * sizeof (uint32_t)) + sizeof (struct lpfc_name);
James Smart488d1462006-03-07 15:02:37 -05001282 elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry, ndlp,
1283 ndlp->nlp_DID, ELS_CMD_LOGO);
1284 if (!elsiocb)
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001285 return 1;
dea31012005-04-17 16:05:31 -05001286
1287 icmd = &elsiocb->iocb;
1288 pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
1289 *((uint32_t *) (pcmd)) = ELS_CMD_LOGO;
1290 pcmd += sizeof (uint32_t);
1291
1292 /* Fill in LOGO payload */
1293 *((uint32_t *) (pcmd)) = be32_to_cpu(phba->fc_myDID);
1294 pcmd += sizeof (uint32_t);
1295 memcpy(pcmd, &phba->fc_portname, sizeof (struct lpfc_name));
1296
1297 phba->fc_stat.elsXmitLOGO++;
1298 elsiocb->iocb_cmpl = lpfc_cmpl_els_logo;
1299 spin_lock_irq(phba->host->host_lock);
1300 ndlp->nlp_flag |= NLP_LOGO_SND;
1301 if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) {
1302 ndlp->nlp_flag &= ~NLP_LOGO_SND;
1303 spin_unlock_irq(phba->host->host_lock);
1304 lpfc_els_free_iocb(phba, elsiocb);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001305 return 1;
dea31012005-04-17 16:05:31 -05001306 }
1307 spin_unlock_irq(phba->host->host_lock);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001308 return 0;
dea31012005-04-17 16:05:31 -05001309}
1310
1311static void
1312lpfc_cmpl_els_cmd(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
1313 struct lpfc_iocbq * rspiocb)
1314{
1315 IOCB_t *irsp;
1316
1317 irsp = &rspiocb->iocb;
1318
1319 /* ELS cmd tag <ulpIoTag> completes */
1320 lpfc_printf_log(phba,
1321 KERN_INFO,
1322 LOG_ELS,
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001323 "%d:0106 ELS cmd tag x%x completes Data: x%x x%x x%x\n",
dea31012005-04-17 16:05:31 -05001324 phba->brd_no,
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001325 irsp->ulpIoTag, irsp->ulpStatus,
1326 irsp->un.ulpWord[4], irsp->ulpTimeout);
dea31012005-04-17 16:05:31 -05001327
1328 /* Check to see if link went down during discovery */
1329 lpfc_els_chk_latt(phba);
1330 lpfc_els_free_iocb(phba, cmdiocb);
1331 return;
1332}
1333
1334int
1335lpfc_issue_els_scr(struct lpfc_hba * phba, uint32_t nportid, uint8_t retry)
1336{
1337 IOCB_t *icmd;
1338 struct lpfc_iocbq *elsiocb;
1339 struct lpfc_sli_ring *pring;
1340 struct lpfc_sli *psli;
1341 uint8_t *pcmd;
1342 uint16_t cmdsize;
1343 struct lpfc_nodelist *ndlp;
1344
1345 psli = &phba->sli;
1346 pring = &psli->ring[LPFC_ELS_RING]; /* ELS ring */
1347 cmdsize = (sizeof (uint32_t) + sizeof (SCR));
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001348 ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL);
1349 if (!ndlp)
1350 return 1;
dea31012005-04-17 16:05:31 -05001351
1352 lpfc_nlp_init(phba, ndlp, nportid);
1353
James Smart488d1462006-03-07 15:02:37 -05001354 elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry, ndlp,
1355 ndlp->nlp_DID, ELS_CMD_SCR);
1356 if (!elsiocb) {
dea31012005-04-17 16:05:31 -05001357 mempool_free( ndlp, phba->nlp_mem_pool);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001358 return 1;
dea31012005-04-17 16:05:31 -05001359 }
1360
1361 icmd = &elsiocb->iocb;
1362 pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
1363
1364 *((uint32_t *) (pcmd)) = ELS_CMD_SCR;
1365 pcmd += sizeof (uint32_t);
1366
1367 /* For SCR, remainder of payload is SCR parameter page */
1368 memset(pcmd, 0, sizeof (SCR));
1369 ((SCR *) pcmd)->Function = SCR_FUNC_FULL;
1370
1371 phba->fc_stat.elsXmitSCR++;
1372 elsiocb->iocb_cmpl = lpfc_cmpl_els_cmd;
1373 spin_lock_irq(phba->host->host_lock);
1374 if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) {
1375 spin_unlock_irq(phba->host->host_lock);
1376 mempool_free( ndlp, phba->nlp_mem_pool);
1377 lpfc_els_free_iocb(phba, elsiocb);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001378 return 1;
dea31012005-04-17 16:05:31 -05001379 }
1380 spin_unlock_irq(phba->host->host_lock);
1381 mempool_free( ndlp, phba->nlp_mem_pool);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001382 return 0;
dea31012005-04-17 16:05:31 -05001383}
1384
1385static int
1386lpfc_issue_els_farpr(struct lpfc_hba * phba, uint32_t nportid, uint8_t retry)
1387{
1388 IOCB_t *icmd;
1389 struct lpfc_iocbq *elsiocb;
1390 struct lpfc_sli_ring *pring;
1391 struct lpfc_sli *psli;
1392 FARP *fp;
1393 uint8_t *pcmd;
1394 uint32_t *lp;
1395 uint16_t cmdsize;
1396 struct lpfc_nodelist *ondlp;
1397 struct lpfc_nodelist *ndlp;
1398
1399 psli = &phba->sli;
1400 pring = &psli->ring[LPFC_ELS_RING]; /* ELS ring */
1401 cmdsize = (sizeof (uint32_t) + sizeof (FARP));
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001402 ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL);
1403 if (!ndlp)
1404 return 1;
dea31012005-04-17 16:05:31 -05001405 lpfc_nlp_init(phba, ndlp, nportid);
1406
James Smart488d1462006-03-07 15:02:37 -05001407 elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry, ndlp,
1408 ndlp->nlp_DID, ELS_CMD_RNID);
1409 if (!elsiocb) {
dea31012005-04-17 16:05:31 -05001410 mempool_free( ndlp, phba->nlp_mem_pool);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001411 return 1;
dea31012005-04-17 16:05:31 -05001412 }
1413
1414 icmd = &elsiocb->iocb;
1415 pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
1416
1417 *((uint32_t *) (pcmd)) = ELS_CMD_FARPR;
1418 pcmd += sizeof (uint32_t);
1419
1420 /* Fill in FARPR payload */
1421 fp = (FARP *) (pcmd);
1422 memset(fp, 0, sizeof (FARP));
1423 lp = (uint32_t *) pcmd;
1424 *lp++ = be32_to_cpu(nportid);
1425 *lp++ = be32_to_cpu(phba->fc_myDID);
1426 fp->Rflags = 0;
1427 fp->Mflags = (FARP_MATCH_PORT | FARP_MATCH_NODE);
1428
1429 memcpy(&fp->RportName, &phba->fc_portname, sizeof (struct lpfc_name));
1430 memcpy(&fp->RnodeName, &phba->fc_nodename, sizeof (struct lpfc_name));
1431 if ((ondlp = lpfc_findnode_did(phba, NLP_SEARCH_ALL, nportid))) {
1432 memcpy(&fp->OportName, &ondlp->nlp_portname,
1433 sizeof (struct lpfc_name));
1434 memcpy(&fp->OnodeName, &ondlp->nlp_nodename,
1435 sizeof (struct lpfc_name));
1436 }
1437
1438 phba->fc_stat.elsXmitFARPR++;
1439 elsiocb->iocb_cmpl = lpfc_cmpl_els_cmd;
1440 spin_lock_irq(phba->host->host_lock);
1441 if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) {
1442 spin_unlock_irq(phba->host->host_lock);
1443 mempool_free( ndlp, phba->nlp_mem_pool);
1444 lpfc_els_free_iocb(phba, elsiocb);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001445 return 1;
dea31012005-04-17 16:05:31 -05001446 }
1447 spin_unlock_irq(phba->host->host_lock);
1448 mempool_free( ndlp, phba->nlp_mem_pool);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001449 return 0;
dea31012005-04-17 16:05:31 -05001450}
1451
1452void
James Smartfdcebe22006-03-07 15:04:01 -05001453lpfc_cancel_retry_delay_tmo(struct lpfc_hba *phba, struct lpfc_nodelist * nlp)
1454{
1455 nlp->nlp_flag &= ~NLP_DELAY_TMO;
1456 del_timer_sync(&nlp->nlp_delayfunc);
1457 nlp->nlp_last_elscmd = 0;
1458
1459 if (!list_empty(&nlp->els_retry_evt.evt_listp))
1460 list_del_init(&nlp->els_retry_evt.evt_listp);
1461
1462 if (nlp->nlp_flag & NLP_NPR_2B_DISC) {
1463 nlp->nlp_flag &= ~NLP_NPR_2B_DISC;
1464 if (phba->num_disc_nodes) {
1465 /* Check to see if there are more
1466 * PLOGIs to be sent
1467 */
1468 lpfc_more_plogi(phba);
James Smartfdcebe22006-03-07 15:04:01 -05001469
James Smart10d4e952006-04-15 11:53:15 -04001470 if (phba->num_disc_nodes == 0) {
1471 phba->fc_flag &= ~FC_NDISC_ACTIVE;
1472 lpfc_can_disctmo(phba);
1473 if (phba->fc_flag & FC_RSCN_MODE) {
1474 /*
1475 * Check to see if more RSCNs
1476 * came in while we were
1477 * processing this one.
1478 */
1479 if((phba->fc_rscn_id_cnt==0) &&
1480 !(phba->fc_flag & FC_RSCN_DISCOVERY)) {
1481 phba->fc_flag &= ~FC_RSCN_MODE;
1482 }
1483 else {
1484 lpfc_els_handle_rscn(phba);
1485 }
James Smartfdcebe22006-03-07 15:04:01 -05001486 }
1487 }
1488 }
1489 }
1490 return;
1491}
1492
1493void
dea31012005-04-17 16:05:31 -05001494lpfc_els_retry_delay(unsigned long ptr)
1495{
1496 struct lpfc_nodelist *ndlp;
1497 struct lpfc_hba *phba;
1498 unsigned long iflag;
1499 struct lpfc_work_evt *evtp;
1500
1501 ndlp = (struct lpfc_nodelist *)ptr;
1502 phba = ndlp->nlp_phba;
1503 evtp = &ndlp->els_retry_evt;
1504
1505 spin_lock_irqsave(phba->host->host_lock, iflag);
1506 if (!list_empty(&evtp->evt_listp)) {
1507 spin_unlock_irqrestore(phba->host->host_lock, iflag);
1508 return;
1509 }
1510
1511 evtp->evt_arg1 = ndlp;
1512 evtp->evt = LPFC_EVT_ELS_RETRY;
1513 list_add_tail(&evtp->evt_listp, &phba->work_list);
1514 if (phba->work_wait)
1515 wake_up(phba->work_wait);
1516
1517 spin_unlock_irqrestore(phba->host->host_lock, iflag);
1518 return;
1519}
1520
1521void
1522lpfc_els_retry_delay_handler(struct lpfc_nodelist *ndlp)
1523{
1524 struct lpfc_hba *phba;
1525 uint32_t cmd;
1526 uint32_t did;
1527 uint8_t retry;
1528
1529 phba = ndlp->nlp_phba;
1530 spin_lock_irq(phba->host->host_lock);
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05001531 did = ndlp->nlp_DID;
1532 cmd = ndlp->nlp_last_elscmd;
1533 ndlp->nlp_last_elscmd = 0;
dea31012005-04-17 16:05:31 -05001534
1535 if (!(ndlp->nlp_flag & NLP_DELAY_TMO)) {
1536 spin_unlock_irq(phba->host->host_lock);
1537 return;
1538 }
1539
1540 ndlp->nlp_flag &= ~NLP_DELAY_TMO;
1541 spin_unlock_irq(phba->host->host_lock);
James Smart1a169682006-03-07 15:04:06 -05001542 /*
1543 * If a discovery event readded nlp_delayfunc after timer
1544 * firing and before processing the timer, cancel the
1545 * nlp_delayfunc.
1546 */
1547 del_timer_sync(&ndlp->nlp_delayfunc);
dea31012005-04-17 16:05:31 -05001548 retry = ndlp->nlp_retry;
1549
1550 switch (cmd) {
1551 case ELS_CMD_FLOGI:
1552 lpfc_issue_els_flogi(phba, ndlp, retry);
1553 break;
1554 case ELS_CMD_PLOGI:
James Smart488d1462006-03-07 15:02:37 -05001555 if(!lpfc_issue_els_plogi(phba, ndlp->nlp_DID, retry)) {
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05001556 ndlp->nlp_prev_state = ndlp->nlp_state;
Jamie Wellnitz6ad42532006-02-28 19:25:16 -05001557 ndlp->nlp_state = NLP_STE_PLOGI_ISSUE;
1558 lpfc_nlp_list(phba, ndlp, NLP_PLOGI_LIST);
1559 }
dea31012005-04-17 16:05:31 -05001560 break;
1561 case ELS_CMD_ADISC:
Jamie Wellnitz6ad42532006-02-28 19:25:16 -05001562 if (!lpfc_issue_els_adisc(phba, ndlp, retry)) {
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05001563 ndlp->nlp_prev_state = ndlp->nlp_state;
Jamie Wellnitz6ad42532006-02-28 19:25:16 -05001564 ndlp->nlp_state = NLP_STE_ADISC_ISSUE;
1565 lpfc_nlp_list(phba, ndlp, NLP_ADISC_LIST);
1566 }
dea31012005-04-17 16:05:31 -05001567 break;
1568 case ELS_CMD_PRLI:
Jamie Wellnitz6ad42532006-02-28 19:25:16 -05001569 if (!lpfc_issue_els_prli(phba, ndlp, retry)) {
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05001570 ndlp->nlp_prev_state = ndlp->nlp_state;
Jamie Wellnitz6ad42532006-02-28 19:25:16 -05001571 ndlp->nlp_state = NLP_STE_PRLI_ISSUE;
1572 lpfc_nlp_list(phba, ndlp, NLP_PRLI_LIST);
1573 }
dea31012005-04-17 16:05:31 -05001574 break;
1575 case ELS_CMD_LOGO:
Jamie Wellnitz6ad42532006-02-28 19:25:16 -05001576 if (!lpfc_issue_els_logo(phba, ndlp, retry)) {
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05001577 ndlp->nlp_prev_state = ndlp->nlp_state;
Jamie Wellnitz6ad42532006-02-28 19:25:16 -05001578 ndlp->nlp_state = NLP_STE_NPR_NODE;
1579 lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST);
1580 }
dea31012005-04-17 16:05:31 -05001581 break;
1582 }
1583 return;
1584}
1585
1586static int
1587lpfc_els_retry(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
1588 struct lpfc_iocbq * rspiocb)
1589{
1590 IOCB_t *irsp;
1591 struct lpfc_dmabuf *pcmd;
1592 struct lpfc_nodelist *ndlp;
1593 uint32_t *elscmd;
1594 struct ls_rjt stat;
1595 int retry, maxretry;
1596 int delay;
1597 uint32_t cmd;
James Smart488d1462006-03-07 15:02:37 -05001598 uint32_t did;
dea31012005-04-17 16:05:31 -05001599
1600 retry = 0;
1601 delay = 0;
1602 maxretry = lpfc_max_els_tries;
1603 irsp = &rspiocb->iocb;
1604 ndlp = (struct lpfc_nodelist *) cmdiocb->context1;
1605 pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
1606 cmd = 0;
James Smart488d1462006-03-07 15:02:37 -05001607
dea31012005-04-17 16:05:31 -05001608 /* Note: context2 may be 0 for internal driver abort
1609 * of delays ELS command.
1610 */
1611
1612 if (pcmd && pcmd->virt) {
1613 elscmd = (uint32_t *) (pcmd->virt);
1614 cmd = *elscmd++;
1615 }
1616
James Smart488d1462006-03-07 15:02:37 -05001617 if(ndlp)
1618 did = ndlp->nlp_DID;
1619 else {
1620 /* We should only hit this case for retrying PLOGI */
1621 did = irsp->un.elsreq64.remoteID;
1622 ndlp = lpfc_findnode_did(phba, NLP_SEARCH_ALL, did);
1623 if (!ndlp && (cmd != ELS_CMD_PLOGI))
1624 return 1;
1625 }
1626
dea31012005-04-17 16:05:31 -05001627 switch (irsp->ulpStatus) {
1628 case IOSTAT_FCP_RSP_ERROR:
1629 case IOSTAT_REMOTE_STOP:
1630 break;
1631
1632 case IOSTAT_LOCAL_REJECT:
1633 switch ((irsp->un.ulpWord[4] & 0xff)) {
1634 case IOERR_LOOP_OPEN_FAILURE:
1635 if (cmd == ELS_CMD_PLOGI) {
1636 if (cmdiocb->retry == 0) {
1637 delay = 1;
1638 }
1639 }
1640 retry = 1;
1641 break;
1642
1643 case IOERR_SEQUENCE_TIMEOUT:
1644 retry = 1;
dea31012005-04-17 16:05:31 -05001645 break;
1646
1647 case IOERR_NO_RESOURCES:
1648 if (cmd == ELS_CMD_PLOGI) {
1649 delay = 1;
1650 }
1651 retry = 1;
1652 break;
1653
1654 case IOERR_INVALID_RPI:
1655 retry = 1;
1656 break;
1657 }
1658 break;
1659
1660 case IOSTAT_NPORT_RJT:
1661 case IOSTAT_FABRIC_RJT:
1662 if (irsp->un.ulpWord[4] & RJT_UNAVAIL_TEMP) {
1663 retry = 1;
1664 break;
1665 }
1666 break;
1667
1668 case IOSTAT_NPORT_BSY:
1669 case IOSTAT_FABRIC_BSY:
1670 retry = 1;
1671 break;
1672
1673 case IOSTAT_LS_RJT:
1674 stat.un.lsRjtError = be32_to_cpu(irsp->un.ulpWord[4]);
1675 /* Added for Vendor specifc support
1676 * Just keep retrying for these Rsn / Exp codes
1677 */
1678 switch (stat.un.b.lsRjtRsnCode) {
1679 case LSRJT_UNABLE_TPC:
1680 if (stat.un.b.lsRjtRsnCodeExp ==
1681 LSEXP_CMD_IN_PROGRESS) {
1682 if (cmd == ELS_CMD_PLOGI) {
1683 delay = 1;
1684 maxretry = 48;
1685 }
1686 retry = 1;
1687 break;
1688 }
1689 if (cmd == ELS_CMD_PLOGI) {
1690 delay = 1;
1691 maxretry = lpfc_max_els_tries + 1;
1692 retry = 1;
1693 break;
1694 }
1695 break;
1696
1697 case LSRJT_LOGICAL_BSY:
1698 if (cmd == ELS_CMD_PLOGI) {
1699 delay = 1;
1700 maxretry = 48;
1701 }
1702 retry = 1;
1703 break;
1704 }
1705 break;
1706
1707 case IOSTAT_INTERMED_RSP:
1708 case IOSTAT_BA_RJT:
1709 break;
1710
1711 default:
1712 break;
1713 }
1714
James Smart488d1462006-03-07 15:02:37 -05001715 if (did == FDMI_DID)
dea31012005-04-17 16:05:31 -05001716 retry = 1;
dea31012005-04-17 16:05:31 -05001717
1718 if ((++cmdiocb->retry) >= maxretry) {
1719 phba->fc_stat.elsRetryExceeded++;
1720 retry = 0;
1721 }
1722
1723 if (retry) {
1724
1725 /* Retry ELS command <elsCmd> to remote NPORT <did> */
1726 lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
1727 "%d:0107 Retry ELS command x%x to remote "
1728 "NPORT x%x Data: x%x x%x\n",
1729 phba->brd_no,
James Smart488d1462006-03-07 15:02:37 -05001730 cmd, did, cmdiocb->retry, delay);
dea31012005-04-17 16:05:31 -05001731
1732 if ((cmd == ELS_CMD_PLOGI) || (cmd == ELS_CMD_ADISC)) {
1733 /* If discovery / RSCN timer is running, reset it */
1734 if (timer_pending(&phba->fc_disctmo) ||
1735 (phba->fc_flag & FC_RSCN_MODE)) {
1736 lpfc_set_disctmo(phba);
1737 }
1738 }
1739
1740 phba->fc_stat.elsXmitRetry++;
James Smart488d1462006-03-07 15:02:37 -05001741 if (ndlp && delay) {
dea31012005-04-17 16:05:31 -05001742 phba->fc_stat.elsDelayRetry++;
1743 ndlp->nlp_retry = cmdiocb->retry;
1744
1745 mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ);
1746 ndlp->nlp_flag |= NLP_DELAY_TMO;
1747
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05001748 ndlp->nlp_prev_state = ndlp->nlp_state;
dea31012005-04-17 16:05:31 -05001749 ndlp->nlp_state = NLP_STE_NPR_NODE;
1750 lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST);
1751 ndlp->nlp_last_elscmd = cmd;
1752
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001753 return 1;
dea31012005-04-17 16:05:31 -05001754 }
1755 switch (cmd) {
1756 case ELS_CMD_FLOGI:
1757 lpfc_issue_els_flogi(phba, ndlp, cmdiocb->retry);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001758 return 1;
dea31012005-04-17 16:05:31 -05001759 case ELS_CMD_PLOGI:
James Smart488d1462006-03-07 15:02:37 -05001760 if (ndlp) {
1761 ndlp->nlp_prev_state = ndlp->nlp_state;
1762 ndlp->nlp_state = NLP_STE_PLOGI_ISSUE;
1763 lpfc_nlp_list(phba, ndlp, NLP_PLOGI_LIST);
1764 }
1765 lpfc_issue_els_plogi(phba, did, cmdiocb->retry);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001766 return 1;
dea31012005-04-17 16:05:31 -05001767 case ELS_CMD_ADISC:
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05001768 ndlp->nlp_prev_state = ndlp->nlp_state;
dea31012005-04-17 16:05:31 -05001769 ndlp->nlp_state = NLP_STE_ADISC_ISSUE;
1770 lpfc_nlp_list(phba, ndlp, NLP_ADISC_LIST);
1771 lpfc_issue_els_adisc(phba, ndlp, cmdiocb->retry);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001772 return 1;
dea31012005-04-17 16:05:31 -05001773 case ELS_CMD_PRLI:
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05001774 ndlp->nlp_prev_state = ndlp->nlp_state;
dea31012005-04-17 16:05:31 -05001775 ndlp->nlp_state = NLP_STE_PRLI_ISSUE;
1776 lpfc_nlp_list(phba, ndlp, NLP_PRLI_LIST);
1777 lpfc_issue_els_prli(phba, ndlp, cmdiocb->retry);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001778 return 1;
dea31012005-04-17 16:05:31 -05001779 case ELS_CMD_LOGO:
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05001780 ndlp->nlp_prev_state = ndlp->nlp_state;
dea31012005-04-17 16:05:31 -05001781 ndlp->nlp_state = NLP_STE_NPR_NODE;
1782 lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST);
1783 lpfc_issue_els_logo(phba, ndlp, cmdiocb->retry);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001784 return 1;
dea31012005-04-17 16:05:31 -05001785 }
1786 }
1787
1788 /* No retry ELS command <elsCmd> to remote NPORT <did> */
1789 lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
1790 "%d:0108 No retry ELS command x%x to remote NPORT x%x "
James Smart488d1462006-03-07 15:02:37 -05001791 "Data: x%x\n",
dea31012005-04-17 16:05:31 -05001792 phba->brd_no,
James Smart488d1462006-03-07 15:02:37 -05001793 cmd, did, cmdiocb->retry);
dea31012005-04-17 16:05:31 -05001794
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001795 return 0;
dea31012005-04-17 16:05:31 -05001796}
1797
1798int
1799lpfc_els_free_iocb(struct lpfc_hba * phba, struct lpfc_iocbq * elsiocb)
1800{
1801 struct lpfc_dmabuf *buf_ptr, *buf_ptr1;
1802
1803 /* context2 = cmd, context2->next = rsp, context3 = bpl */
1804 if (elsiocb->context2) {
1805 buf_ptr1 = (struct lpfc_dmabuf *) elsiocb->context2;
1806 /* Free the response before processing the command. */
1807 if (!list_empty(&buf_ptr1->list)) {
1808 list_remove_head(&buf_ptr1->list, buf_ptr,
1809 struct lpfc_dmabuf,
1810 list);
1811 lpfc_mbuf_free(phba, buf_ptr->virt, buf_ptr->phys);
1812 kfree(buf_ptr);
1813 }
1814 lpfc_mbuf_free(phba, buf_ptr1->virt, buf_ptr1->phys);
1815 kfree(buf_ptr1);
1816 }
1817
1818 if (elsiocb->context3) {
1819 buf_ptr = (struct lpfc_dmabuf *) elsiocb->context3;
1820 lpfc_mbuf_free(phba, buf_ptr->virt, buf_ptr->phys);
1821 kfree(buf_ptr);
1822 }
1823 spin_lock_irq(phba->host->host_lock);
James Bottomley604a3e32005-10-29 10:28:33 -05001824 lpfc_sli_release_iocbq(phba, elsiocb);
dea31012005-04-17 16:05:31 -05001825 spin_unlock_irq(phba->host->host_lock);
1826 return 0;
1827}
1828
1829static void
1830lpfc_cmpl_els_logo_acc(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
1831 struct lpfc_iocbq * rspiocb)
1832{
1833 struct lpfc_nodelist *ndlp;
1834
1835 ndlp = (struct lpfc_nodelist *) cmdiocb->context1;
1836
1837 /* ACC to LOGO completes to NPort <nlp_DID> */
1838 lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
1839 "%d:0109 ACC to LOGO completes to NPort x%x "
1840 "Data: x%x x%x x%x\n",
1841 phba->brd_no, ndlp->nlp_DID, ndlp->nlp_flag,
1842 ndlp->nlp_state, ndlp->nlp_rpi);
1843
dea31012005-04-17 16:05:31 -05001844 switch (ndlp->nlp_state) {
1845 case NLP_STE_UNUSED_NODE: /* node is just allocated */
1846 lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
1847 break;
1848 case NLP_STE_NPR_NODE: /* NPort Recovery mode */
1849 lpfc_unreg_rpi(phba, ndlp);
1850 break;
1851 default:
1852 break;
1853 }
1854 lpfc_els_free_iocb(phba, cmdiocb);
1855 return;
1856}
1857
1858static void
1859lpfc_cmpl_els_acc(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
1860 struct lpfc_iocbq * rspiocb)
1861{
James Smart33ccf8d2006-08-17 11:57:58 -04001862 IOCB_t *irsp;
dea31012005-04-17 16:05:31 -05001863 struct lpfc_nodelist *ndlp;
1864 LPFC_MBOXQ_t *mbox = NULL;
James Smart14691152006-12-02 13:34:28 -05001865 struct lpfc_dmabuf *mp;
dea31012005-04-17 16:05:31 -05001866
James Smart33ccf8d2006-08-17 11:57:58 -04001867 irsp = &rspiocb->iocb;
1868
dea31012005-04-17 16:05:31 -05001869 ndlp = (struct lpfc_nodelist *) cmdiocb->context1;
1870 if (cmdiocb->context_un.mbox)
1871 mbox = cmdiocb->context_un.mbox;
1872
1873
1874 /* Check to see if link went down during discovery */
1875 if ((lpfc_els_chk_latt(phba)) || !ndlp) {
1876 if (mbox) {
James Smart14691152006-12-02 13:34:28 -05001877 mp = (struct lpfc_dmabuf *) mbox->context1;
1878 if (mp) {
1879 lpfc_mbuf_free(phba, mp->virt, mp->phys);
1880 kfree(mp);
1881 }
dea31012005-04-17 16:05:31 -05001882 mempool_free( mbox, phba->mbox_mem_pool);
1883 }
1884 goto out;
1885 }
1886
1887 /* ELS response tag <ulpIoTag> completes */
1888 lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
1889 "%d:0110 ELS response tag x%x completes "
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001890 "Data: x%x x%x x%x x%x x%x x%x x%x\n",
dea31012005-04-17 16:05:31 -05001891 phba->brd_no,
1892 cmdiocb->iocb.ulpIoTag, rspiocb->iocb.ulpStatus,
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001893 rspiocb->iocb.un.ulpWord[4], rspiocb->iocb.ulpTimeout,
1894 ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state,
1895 ndlp->nlp_rpi);
dea31012005-04-17 16:05:31 -05001896
1897 if (mbox) {
1898 if ((rspiocb->iocb.ulpStatus == 0)
1899 && (ndlp->nlp_flag & NLP_ACC_REGLOGIN)) {
dea31012005-04-17 16:05:31 -05001900 lpfc_unreg_rpi(phba, ndlp);
1901 mbox->mbox_cmpl = lpfc_mbx_cmpl_reg_login;
1902 mbox->context2 = ndlp;
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05001903 ndlp->nlp_prev_state = ndlp->nlp_state;
dea31012005-04-17 16:05:31 -05001904 ndlp->nlp_state = NLP_STE_REG_LOGIN_ISSUE;
1905 lpfc_nlp_list(phba, ndlp, NLP_REGLOGIN_LIST);
1906 if (lpfc_sli_issue_mbox(phba, mbox,
1907 (MBX_NOWAIT | MBX_STOP_IOCB))
1908 != MBX_NOT_FINISHED) {
1909 goto out;
1910 }
1911 /* NOTE: we should have messages for unsuccessful
1912 reglogin */
dea31012005-04-17 16:05:31 -05001913 } else {
James Smart33ccf8d2006-08-17 11:57:58 -04001914 /* Do not call NO_LIST for lpfc_els_abort'ed ELS cmds */
1915 if (!((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) &&
1916 ((irsp->un.ulpWord[4] == IOERR_SLI_ABORTED) ||
1917 (irsp->un.ulpWord[4] == IOERR_LINK_DOWN) ||
1918 (irsp->un.ulpWord[4] == IOERR_SLI_DOWN)))) {
1919 if (ndlp->nlp_flag & NLP_ACC_REGLOGIN) {
1920 lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
1921 ndlp = NULL;
1922 }
dea31012005-04-17 16:05:31 -05001923 }
1924 }
James Smart14691152006-12-02 13:34:28 -05001925 mp = (struct lpfc_dmabuf *) mbox->context1;
1926 if (mp) {
1927 lpfc_mbuf_free(phba, mp->virt, mp->phys);
1928 kfree(mp);
1929 }
1930 mempool_free(mbox, phba->mbox_mem_pool);
dea31012005-04-17 16:05:31 -05001931 }
1932out:
1933 if (ndlp) {
1934 spin_lock_irq(phba->host->host_lock);
1935 ndlp->nlp_flag &= ~NLP_ACC_REGLOGIN;
1936 spin_unlock_irq(phba->host->host_lock);
1937 }
1938 lpfc_els_free_iocb(phba, cmdiocb);
1939 return;
1940}
1941
1942int
1943lpfc_els_rsp_acc(struct lpfc_hba * phba, uint32_t flag,
1944 struct lpfc_iocbq * oldiocb, struct lpfc_nodelist * ndlp,
1945 LPFC_MBOXQ_t * mbox, uint8_t newnode)
1946{
1947 IOCB_t *icmd;
1948 IOCB_t *oldcmd;
1949 struct lpfc_iocbq *elsiocb;
1950 struct lpfc_sli_ring *pring;
1951 struct lpfc_sli *psli;
1952 uint8_t *pcmd;
1953 uint16_t cmdsize;
1954 int rc;
James Smart82d9a2a2006-04-15 11:53:05 -04001955 ELS_PKT *els_pkt_ptr;
dea31012005-04-17 16:05:31 -05001956
1957 psli = &phba->sli;
1958 pring = &psli->ring[LPFC_ELS_RING]; /* ELS ring */
1959 oldcmd = &oldiocb->iocb;
1960
1961 switch (flag) {
1962 case ELS_CMD_ACC:
1963 cmdsize = sizeof (uint32_t);
James Smart488d1462006-03-07 15:02:37 -05001964 elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, oldiocb->retry,
1965 ndlp, ndlp->nlp_DID, ELS_CMD_ACC);
1966 if (!elsiocb) {
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05001967 ndlp->nlp_flag &= ~NLP_LOGO_ACC;
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001968 return 1;
dea31012005-04-17 16:05:31 -05001969 }
1970 icmd = &elsiocb->iocb;
1971 icmd->ulpContext = oldcmd->ulpContext; /* Xri */
1972 pcmd = (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
1973 *((uint32_t *) (pcmd)) = ELS_CMD_ACC;
1974 pcmd += sizeof (uint32_t);
1975 break;
1976 case ELS_CMD_PLOGI:
1977 cmdsize = (sizeof (struct serv_parm) + sizeof (uint32_t));
James Smart488d1462006-03-07 15:02:37 -05001978 elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, oldiocb->retry,
1979 ndlp, ndlp->nlp_DID, ELS_CMD_ACC);
1980 if (!elsiocb)
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001981 return 1;
James Smart488d1462006-03-07 15:02:37 -05001982
dea31012005-04-17 16:05:31 -05001983 icmd = &elsiocb->iocb;
1984 icmd->ulpContext = oldcmd->ulpContext; /* Xri */
1985 pcmd = (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
1986
1987 if (mbox)
1988 elsiocb->context_un.mbox = mbox;
1989
1990 *((uint32_t *) (pcmd)) = ELS_CMD_ACC;
1991 pcmd += sizeof (uint32_t);
1992 memcpy(pcmd, &phba->fc_sparam, sizeof (struct serv_parm));
1993 break;
James Smart82d9a2a2006-04-15 11:53:05 -04001994 case ELS_CMD_PRLO:
1995 cmdsize = sizeof (uint32_t) + sizeof (PRLO);
1996 elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, oldiocb->retry,
1997 ndlp, ndlp->nlp_DID, ELS_CMD_PRLO);
1998 if (!elsiocb)
1999 return 1;
2000
2001 icmd = &elsiocb->iocb;
2002 icmd->ulpContext = oldcmd->ulpContext; /* Xri */
2003 pcmd = (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
2004
2005 memcpy(pcmd, ((struct lpfc_dmabuf *) oldiocb->context2)->virt,
2006 sizeof (uint32_t) + sizeof (PRLO));
2007 *((uint32_t *) (pcmd)) = ELS_CMD_PRLO_ACC;
2008 els_pkt_ptr = (ELS_PKT *) pcmd;
2009 els_pkt_ptr->un.prlo.acceptRspCode = PRLO_REQ_EXECUTED;
2010 break;
dea31012005-04-17 16:05:31 -05002011 default:
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002012 return 1;
dea31012005-04-17 16:05:31 -05002013 }
2014
2015 if (newnode)
2016 elsiocb->context1 = NULL;
2017
2018 /* Xmit ELS ACC response tag <ulpIoTag> */
2019 lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
James Smart1dcb58e2007-04-25 09:51:30 -04002020 "%d:0128 Xmit ELS ACC response tag x%x, XRI: x%x, "
2021 "DID: x%x, nlp_flag: x%x nlp_state: x%x RPI: x%x\n",
2022 phba->brd_no, elsiocb->iotag,
dea31012005-04-17 16:05:31 -05002023 elsiocb->iocb.ulpContext, ndlp->nlp_DID,
2024 ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi);
2025
2026 if (ndlp->nlp_flag & NLP_LOGO_ACC) {
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002027 spin_lock_irq(phba->host->host_lock);
2028 ndlp->nlp_flag &= ~NLP_LOGO_ACC;
2029 spin_unlock_irq(phba->host->host_lock);
dea31012005-04-17 16:05:31 -05002030 elsiocb->iocb_cmpl = lpfc_cmpl_els_logo_acc;
2031 } else {
2032 elsiocb->iocb_cmpl = lpfc_cmpl_els_acc;
2033 }
2034
2035 phba->fc_stat.elsXmitACC++;
2036 spin_lock_irq(phba->host->host_lock);
2037 rc = lpfc_sli_issue_iocb(phba, pring, elsiocb, 0);
2038 spin_unlock_irq(phba->host->host_lock);
2039 if (rc == IOCB_ERROR) {
2040 lpfc_els_free_iocb(phba, elsiocb);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002041 return 1;
dea31012005-04-17 16:05:31 -05002042 }
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002043 return 0;
dea31012005-04-17 16:05:31 -05002044}
2045
2046int
2047lpfc_els_rsp_reject(struct lpfc_hba * phba, uint32_t rejectError,
2048 struct lpfc_iocbq * oldiocb, struct lpfc_nodelist * ndlp)
2049{
2050 IOCB_t *icmd;
2051 IOCB_t *oldcmd;
2052 struct lpfc_iocbq *elsiocb;
2053 struct lpfc_sli_ring *pring;
2054 struct lpfc_sli *psli;
2055 uint8_t *pcmd;
2056 uint16_t cmdsize;
2057 int rc;
2058
2059 psli = &phba->sli;
2060 pring = &psli->ring[LPFC_ELS_RING]; /* ELS ring */
2061
2062 cmdsize = 2 * sizeof (uint32_t);
James Smart488d1462006-03-07 15:02:37 -05002063 elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, oldiocb->retry,
2064 ndlp, ndlp->nlp_DID, ELS_CMD_LS_RJT);
2065 if (!elsiocb)
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002066 return 1;
dea31012005-04-17 16:05:31 -05002067
2068 icmd = &elsiocb->iocb;
2069 oldcmd = &oldiocb->iocb;
2070 icmd->ulpContext = oldcmd->ulpContext; /* Xri */
2071 pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
2072
2073 *((uint32_t *) (pcmd)) = ELS_CMD_LS_RJT;
2074 pcmd += sizeof (uint32_t);
2075 *((uint32_t *) (pcmd)) = rejectError;
2076
2077 /* Xmit ELS RJT <err> response tag <ulpIoTag> */
2078 lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
2079 "%d:0129 Xmit ELS RJT x%x response tag x%x "
2080 "Data: x%x x%x x%x x%x x%x\n",
2081 phba->brd_no,
2082 rejectError, elsiocb->iocb.ulpIoTag,
2083 elsiocb->iocb.ulpContext, ndlp->nlp_DID,
2084 ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi);
2085
2086 phba->fc_stat.elsXmitLSRJT++;
2087 elsiocb->iocb_cmpl = lpfc_cmpl_els_acc;
2088 spin_lock_irq(phba->host->host_lock);
2089 rc = lpfc_sli_issue_iocb(phba, pring, elsiocb, 0);
2090 spin_unlock_irq(phba->host->host_lock);
2091 if (rc == IOCB_ERROR) {
2092 lpfc_els_free_iocb(phba, elsiocb);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002093 return 1;
dea31012005-04-17 16:05:31 -05002094 }
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002095 return 0;
dea31012005-04-17 16:05:31 -05002096}
2097
2098int
2099lpfc_els_rsp_adisc_acc(struct lpfc_hba * phba,
2100 struct lpfc_iocbq * oldiocb, struct lpfc_nodelist * ndlp)
2101{
2102 ADISC *ap;
2103 IOCB_t *icmd;
2104 IOCB_t *oldcmd;
2105 struct lpfc_iocbq *elsiocb;
2106 struct lpfc_sli_ring *pring;
2107 struct lpfc_sli *psli;
2108 uint8_t *pcmd;
2109 uint16_t cmdsize;
2110 int rc;
2111
2112 psli = &phba->sli;
2113 pring = &psli->ring[LPFC_ELS_RING]; /* ELS ring */
2114
2115 cmdsize = sizeof (uint32_t) + sizeof (ADISC);
James Smart488d1462006-03-07 15:02:37 -05002116 elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, oldiocb->retry,
2117 ndlp, ndlp->nlp_DID, ELS_CMD_ACC);
2118 if (!elsiocb)
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002119 return 1;
dea31012005-04-17 16:05:31 -05002120
2121 /* Xmit ADISC ACC response tag <ulpIoTag> */
2122 lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
2123 "%d:0130 Xmit ADISC ACC response tag x%x "
2124 "Data: x%x x%x x%x x%x x%x\n",
2125 phba->brd_no,
2126 elsiocb->iocb.ulpIoTag,
2127 elsiocb->iocb.ulpContext, ndlp->nlp_DID,
2128 ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi);
2129
2130 icmd = &elsiocb->iocb;
2131 oldcmd = &oldiocb->iocb;
2132 icmd->ulpContext = oldcmd->ulpContext; /* Xri */
2133 pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
2134
2135 *((uint32_t *) (pcmd)) = ELS_CMD_ACC;
2136 pcmd += sizeof (uint32_t);
2137
2138 ap = (ADISC *) (pcmd);
2139 ap->hardAL_PA = phba->fc_pref_ALPA;
2140 memcpy(&ap->portName, &phba->fc_portname, sizeof (struct lpfc_name));
2141 memcpy(&ap->nodeName, &phba->fc_nodename, sizeof (struct lpfc_name));
2142 ap->DID = be32_to_cpu(phba->fc_myDID);
2143
2144 phba->fc_stat.elsXmitACC++;
2145 elsiocb->iocb_cmpl = lpfc_cmpl_els_acc;
2146 spin_lock_irq(phba->host->host_lock);
2147 rc = lpfc_sli_issue_iocb(phba, pring, elsiocb, 0);
2148 spin_unlock_irq(phba->host->host_lock);
2149 if (rc == IOCB_ERROR) {
2150 lpfc_els_free_iocb(phba, elsiocb);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002151 return 1;
dea31012005-04-17 16:05:31 -05002152 }
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002153 return 0;
dea31012005-04-17 16:05:31 -05002154}
2155
2156int
2157lpfc_els_rsp_prli_acc(struct lpfc_hba * phba,
2158 struct lpfc_iocbq * oldiocb, struct lpfc_nodelist * ndlp)
2159{
2160 PRLI *npr;
2161 lpfc_vpd_t *vpd;
2162 IOCB_t *icmd;
2163 IOCB_t *oldcmd;
2164 struct lpfc_iocbq *elsiocb;
2165 struct lpfc_sli_ring *pring;
2166 struct lpfc_sli *psli;
2167 uint8_t *pcmd;
2168 uint16_t cmdsize;
2169 int rc;
2170
2171 psli = &phba->sli;
2172 pring = &psli->ring[LPFC_ELS_RING]; /* ELS ring */
2173
2174 cmdsize = sizeof (uint32_t) + sizeof (PRLI);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002175 elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, oldiocb->retry, ndlp,
James Smart488d1462006-03-07 15:02:37 -05002176 ndlp->nlp_DID, (ELS_CMD_ACC | (ELS_CMD_PRLI & ~ELS_RSP_MASK)));
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002177 if (!elsiocb)
2178 return 1;
dea31012005-04-17 16:05:31 -05002179
2180 /* Xmit PRLI ACC response tag <ulpIoTag> */
2181 lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
2182 "%d:0131 Xmit PRLI ACC response tag x%x "
2183 "Data: x%x x%x x%x x%x x%x\n",
2184 phba->brd_no,
2185 elsiocb->iocb.ulpIoTag,
2186 elsiocb->iocb.ulpContext, ndlp->nlp_DID,
2187 ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi);
2188
2189 icmd = &elsiocb->iocb;
2190 oldcmd = &oldiocb->iocb;
2191 icmd->ulpContext = oldcmd->ulpContext; /* Xri */
2192 pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
2193
2194 *((uint32_t *) (pcmd)) = (ELS_CMD_ACC | (ELS_CMD_PRLI & ~ELS_RSP_MASK));
2195 pcmd += sizeof (uint32_t);
2196
2197 /* For PRLI, remainder of payload is PRLI parameter page */
2198 memset(pcmd, 0, sizeof (PRLI));
2199
2200 npr = (PRLI *) pcmd;
2201 vpd = &phba->vpd;
2202 /*
2203 * If our firmware version is 3.20 or later,
2204 * set the following bits for FC-TAPE support.
2205 */
2206 if (vpd->rev.feaLevelHigh >= 0x02) {
2207 npr->ConfmComplAllowed = 1;
2208 npr->Retry = 1;
2209 npr->TaskRetryIdReq = 1;
2210 }
2211
2212 npr->acceptRspCode = PRLI_REQ_EXECUTED;
2213 npr->estabImagePair = 1;
2214 npr->readXferRdyDis = 1;
2215 npr->ConfmComplAllowed = 1;
2216
2217 npr->prliType = PRLI_FCP_TYPE;
2218 npr->initiatorFunc = 1;
2219
2220 phba->fc_stat.elsXmitACC++;
2221 elsiocb->iocb_cmpl = lpfc_cmpl_els_acc;
2222
2223 spin_lock_irq(phba->host->host_lock);
2224 rc = lpfc_sli_issue_iocb(phba, pring, elsiocb, 0);
2225 spin_unlock_irq(phba->host->host_lock);
2226 if (rc == IOCB_ERROR) {
2227 lpfc_els_free_iocb(phba, elsiocb);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002228 return 1;
dea31012005-04-17 16:05:31 -05002229 }
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002230 return 0;
dea31012005-04-17 16:05:31 -05002231}
2232
2233static int
2234lpfc_els_rsp_rnid_acc(struct lpfc_hba * phba,
2235 uint8_t format,
2236 struct lpfc_iocbq * oldiocb, struct lpfc_nodelist * ndlp)
2237{
2238 RNID *rn;
2239 IOCB_t *icmd;
2240 IOCB_t *oldcmd;
2241 struct lpfc_iocbq *elsiocb;
2242 struct lpfc_sli_ring *pring;
2243 struct lpfc_sli *psli;
2244 uint8_t *pcmd;
2245 uint16_t cmdsize;
2246 int rc;
2247
2248 psli = &phba->sli;
2249 pring = &psli->ring[LPFC_ELS_RING];
2250
2251 cmdsize = sizeof (uint32_t) + sizeof (uint32_t)
2252 + (2 * sizeof (struct lpfc_name));
2253 if (format)
2254 cmdsize += sizeof (RNID_TOP_DISC);
2255
James Smart488d1462006-03-07 15:02:37 -05002256 elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, oldiocb->retry,
2257 ndlp, ndlp->nlp_DID, ELS_CMD_ACC);
2258 if (!elsiocb)
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002259 return 1;
dea31012005-04-17 16:05:31 -05002260
2261 /* Xmit RNID ACC response tag <ulpIoTag> */
2262 lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
2263 "%d:0132 Xmit RNID ACC response tag x%x "
2264 "Data: x%x\n",
2265 phba->brd_no,
2266 elsiocb->iocb.ulpIoTag,
2267 elsiocb->iocb.ulpContext);
2268
2269 icmd = &elsiocb->iocb;
2270 oldcmd = &oldiocb->iocb;
2271 icmd->ulpContext = oldcmd->ulpContext; /* Xri */
2272 pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
2273
2274 *((uint32_t *) (pcmd)) = ELS_CMD_ACC;
2275 pcmd += sizeof (uint32_t);
2276
2277 memset(pcmd, 0, sizeof (RNID));
2278 rn = (RNID *) (pcmd);
2279 rn->Format = format;
2280 rn->CommonLen = (2 * sizeof (struct lpfc_name));
2281 memcpy(&rn->portName, &phba->fc_portname, sizeof (struct lpfc_name));
2282 memcpy(&rn->nodeName, &phba->fc_nodename, sizeof (struct lpfc_name));
2283 switch (format) {
2284 case 0:
2285 rn->SpecificLen = 0;
2286 break;
2287 case RNID_TOPOLOGY_DISC:
2288 rn->SpecificLen = sizeof (RNID_TOP_DISC);
2289 memcpy(&rn->un.topologyDisc.portName,
2290 &phba->fc_portname, sizeof (struct lpfc_name));
2291 rn->un.topologyDisc.unitType = RNID_HBA;
2292 rn->un.topologyDisc.physPort = 0;
2293 rn->un.topologyDisc.attachedNodes = 0;
2294 break;
2295 default:
2296 rn->CommonLen = 0;
2297 rn->SpecificLen = 0;
2298 break;
2299 }
2300
2301 phba->fc_stat.elsXmitACC++;
2302 elsiocb->iocb_cmpl = lpfc_cmpl_els_acc;
2303 elsiocb->context1 = NULL; /* Don't need ndlp for cmpl,
2304 * it could be freed */
2305
2306 spin_lock_irq(phba->host->host_lock);
2307 rc = lpfc_sli_issue_iocb(phba, pring, elsiocb, 0);
2308 spin_unlock_irq(phba->host->host_lock);
2309 if (rc == IOCB_ERROR) {
2310 lpfc_els_free_iocb(phba, elsiocb);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002311 return 1;
dea31012005-04-17 16:05:31 -05002312 }
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002313 return 0;
dea31012005-04-17 16:05:31 -05002314}
2315
2316int
2317lpfc_els_disc_adisc(struct lpfc_hba * phba)
2318{
2319 int sentadisc;
2320 struct lpfc_nodelist *ndlp, *next_ndlp;
2321
2322 sentadisc = 0;
2323 /* go thru NPR list and issue any remaining ELS ADISCs */
2324 list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_npr_list,
2325 nlp_listp) {
2326 if (ndlp->nlp_flag & NLP_NPR_2B_DISC) {
2327 if (ndlp->nlp_flag & NLP_NPR_ADISC) {
2328 ndlp->nlp_flag &= ~NLP_NPR_ADISC;
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05002329 ndlp->nlp_prev_state = ndlp->nlp_state;
dea31012005-04-17 16:05:31 -05002330 ndlp->nlp_state = NLP_STE_ADISC_ISSUE;
2331 lpfc_nlp_list(phba, ndlp,
2332 NLP_ADISC_LIST);
2333 lpfc_issue_els_adisc(phba, ndlp, 0);
2334 sentadisc++;
2335 phba->num_disc_nodes++;
2336 if (phba->num_disc_nodes >=
2337 phba->cfg_discovery_threads) {
2338 spin_lock_irq(phba->host->host_lock);
2339 phba->fc_flag |= FC_NLP_MORE;
2340 spin_unlock_irq(phba->host->host_lock);
2341 break;
2342 }
2343 }
2344 }
2345 }
2346 if (sentadisc == 0) {
2347 spin_lock_irq(phba->host->host_lock);
2348 phba->fc_flag &= ~FC_NLP_MORE;
2349 spin_unlock_irq(phba->host->host_lock);
2350 }
Jamie Wellnitz2fe165b2006-02-28 19:25:31 -05002351 return sentadisc;
dea31012005-04-17 16:05:31 -05002352}
2353
2354int
2355lpfc_els_disc_plogi(struct lpfc_hba * phba)
2356{
2357 int sentplogi;
2358 struct lpfc_nodelist *ndlp, *next_ndlp;
2359
2360 sentplogi = 0;
2361 /* go thru NPR list and issue any remaining ELS PLOGIs */
2362 list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_npr_list,
2363 nlp_listp) {
2364 if ((ndlp->nlp_flag & NLP_NPR_2B_DISC) &&
2365 (!(ndlp->nlp_flag & NLP_DELAY_TMO))) {
2366 if (!(ndlp->nlp_flag & NLP_NPR_ADISC)) {
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05002367 ndlp->nlp_prev_state = ndlp->nlp_state;
dea31012005-04-17 16:05:31 -05002368 ndlp->nlp_state = NLP_STE_PLOGI_ISSUE;
2369 lpfc_nlp_list(phba, ndlp, NLP_PLOGI_LIST);
James Smart488d1462006-03-07 15:02:37 -05002370 lpfc_issue_els_plogi(phba, ndlp->nlp_DID, 0);
dea31012005-04-17 16:05:31 -05002371 sentplogi++;
2372 phba->num_disc_nodes++;
2373 if (phba->num_disc_nodes >=
2374 phba->cfg_discovery_threads) {
2375 spin_lock_irq(phba->host->host_lock);
2376 phba->fc_flag |= FC_NLP_MORE;
2377 spin_unlock_irq(phba->host->host_lock);
2378 break;
2379 }
2380 }
2381 }
2382 }
2383 if (sentplogi == 0) {
2384 spin_lock_irq(phba->host->host_lock);
2385 phba->fc_flag &= ~FC_NLP_MORE;
2386 spin_unlock_irq(phba->host->host_lock);
2387 }
Jamie Wellnitz2fe165b2006-02-28 19:25:31 -05002388 return sentplogi;
dea31012005-04-17 16:05:31 -05002389}
2390
2391int
2392lpfc_els_flush_rscn(struct lpfc_hba * phba)
2393{
2394 struct lpfc_dmabuf *mp;
2395 int i;
2396
2397 for (i = 0; i < phba->fc_rscn_id_cnt; i++) {
2398 mp = phba->fc_rscn_id_list[i];
2399 lpfc_mbuf_free(phba, mp->virt, mp->phys);
2400 kfree(mp);
2401 phba->fc_rscn_id_list[i] = NULL;
2402 }
2403 phba->fc_rscn_id_cnt = 0;
2404 spin_lock_irq(phba->host->host_lock);
2405 phba->fc_flag &= ~(FC_RSCN_MODE | FC_RSCN_DISCOVERY);
2406 spin_unlock_irq(phba->host->host_lock);
2407 lpfc_can_disctmo(phba);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002408 return 0;
dea31012005-04-17 16:05:31 -05002409}
2410
2411int
2412lpfc_rscn_payload_check(struct lpfc_hba * phba, uint32_t did)
2413{
2414 D_ID ns_did;
2415 D_ID rscn_did;
2416 struct lpfc_dmabuf *mp;
2417 uint32_t *lp;
2418 uint32_t payload_len, cmd, i, match;
2419
2420 ns_did.un.word = did;
2421 match = 0;
2422
2423 /* Never match fabric nodes for RSCNs */
2424 if ((did & Fabric_DID_MASK) == Fabric_DID_MASK)
2425 return(0);
2426
2427 /* If we are doing a FULL RSCN rediscovery, match everything */
2428 if (phba->fc_flag & FC_RSCN_DISCOVERY) {
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002429 return did;
dea31012005-04-17 16:05:31 -05002430 }
2431
2432 for (i = 0; i < phba->fc_rscn_id_cnt; i++) {
2433 mp = phba->fc_rscn_id_list[i];
2434 lp = (uint32_t *) mp->virt;
2435 cmd = *lp++;
2436 payload_len = be32_to_cpu(cmd) & 0xffff; /* payload length */
2437 payload_len -= sizeof (uint32_t); /* take off word 0 */
2438 while (payload_len) {
2439 rscn_did.un.word = *lp++;
2440 rscn_did.un.word = be32_to_cpu(rscn_did.un.word);
2441 payload_len -= sizeof (uint32_t);
2442 switch (rscn_did.un.b.resv) {
2443 case 0: /* Single N_Port ID effected */
2444 if (ns_did.un.word == rscn_did.un.word) {
2445 match = did;
2446 }
2447 break;
2448 case 1: /* Whole N_Port Area effected */
2449 if ((ns_did.un.b.domain == rscn_did.un.b.domain)
2450 && (ns_did.un.b.area == rscn_did.un.b.area))
2451 {
2452 match = did;
2453 }
2454 break;
2455 case 2: /* Whole N_Port Domain effected */
2456 if (ns_did.un.b.domain == rscn_did.un.b.domain)
2457 {
2458 match = did;
2459 }
2460 break;
2461 case 3: /* Whole Fabric effected */
2462 match = did;
2463 break;
2464 default:
2465 /* Unknown Identifier in RSCN list */
2466 lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
2467 "%d:0217 Unknown Identifier in "
2468 "RSCN payload Data: x%x\n",
2469 phba->brd_no, rscn_did.un.word);
2470 break;
2471 }
2472 if (match) {
2473 break;
2474 }
2475 }
2476 }
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002477 return match;
dea31012005-04-17 16:05:31 -05002478}
2479
2480static int
2481lpfc_rscn_recovery_check(struct lpfc_hba * phba)
2482{
2483 struct lpfc_nodelist *ndlp = NULL, *next_ndlp;
2484 struct list_head *listp;
2485 struct list_head *node_list[7];
2486 int i;
2487
2488 /* Look at all nodes effected by pending RSCNs and move
2489 * them to NPR list.
2490 */
2491 node_list[0] = &phba->fc_npr_list; /* MUST do this list first */
2492 node_list[1] = &phba->fc_nlpmap_list;
2493 node_list[2] = &phba->fc_nlpunmap_list;
2494 node_list[3] = &phba->fc_prli_list;
2495 node_list[4] = &phba->fc_reglogin_list;
2496 node_list[5] = &phba->fc_adisc_list;
2497 node_list[6] = &phba->fc_plogi_list;
2498 for (i = 0; i < 7; i++) {
2499 listp = node_list[i];
2500 if (list_empty(listp))
2501 continue;
2502
2503 list_for_each_entry_safe(ndlp, next_ndlp, listp, nlp_listp) {
2504 if (!(lpfc_rscn_payload_check(phba, ndlp->nlp_DID)))
2505 continue;
2506
2507 lpfc_disc_state_machine(phba, ndlp, NULL,
2508 NLP_EVT_DEVICE_RECOVERY);
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05002509
2510 /* Make sure NLP_DELAY_TMO is NOT running
2511 * after a device recovery event.
2512 */
James Smartfdcebe22006-03-07 15:04:01 -05002513 if (ndlp->nlp_flag & NLP_DELAY_TMO)
2514 lpfc_cancel_retry_delay_tmo(phba, ndlp);
dea31012005-04-17 16:05:31 -05002515 }
2516 }
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002517 return 0;
dea31012005-04-17 16:05:31 -05002518}
2519
2520static int
2521lpfc_els_rcv_rscn(struct lpfc_hba * phba,
2522 struct lpfc_iocbq * cmdiocb,
2523 struct lpfc_nodelist * ndlp, uint8_t newnode)
2524{
2525 struct lpfc_dmabuf *pcmd;
2526 uint32_t *lp;
2527 IOCB_t *icmd;
2528 uint32_t payload_len, cmd;
James Smartd2873e42006-08-18 17:46:43 -04002529 int i;
dea31012005-04-17 16:05:31 -05002530
2531 icmd = &cmdiocb->iocb;
2532 pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
2533 lp = (uint32_t *) pcmd->virt;
2534
2535 cmd = *lp++;
2536 payload_len = be32_to_cpu(cmd) & 0xffff; /* payload length */
2537 payload_len -= sizeof (uint32_t); /* take off word 0 */
2538 cmd &= ELS_CMD_MASK;
2539
2540 /* RSCN received */
2541 lpfc_printf_log(phba,
2542 KERN_INFO,
2543 LOG_DISCOVERY,
2544 "%d:0214 RSCN received Data: x%x x%x x%x x%x\n",
2545 phba->brd_no,
2546 phba->fc_flag, payload_len, *lp, phba->fc_rscn_id_cnt);
2547
James Smartd2873e42006-08-18 17:46:43 -04002548 for (i = 0; i < payload_len/sizeof(uint32_t); i++)
2549 fc_host_post_event(phba->host, fc_get_event_number(),
2550 FCH_EVT_RSCN, lp[i]);
2551
dea31012005-04-17 16:05:31 -05002552 /* If we are about to begin discovery, just ACC the RSCN.
2553 * Discovery processing will satisfy it.
2554 */
James Smart071fbd3d2006-04-15 11:53:20 -04002555 if (phba->hba_state <= LPFC_NS_QRY) {
dea31012005-04-17 16:05:31 -05002556 lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL,
2557 newnode);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002558 return 0;
dea31012005-04-17 16:05:31 -05002559 }
2560
2561 /* If we are already processing an RSCN, save the received
2562 * RSCN payload buffer, cmdiocb->context2 to process later.
2563 */
2564 if (phba->fc_flag & (FC_RSCN_MODE | FC_NDISC_ACTIVE)) {
2565 if ((phba->fc_rscn_id_cnt < FC_MAX_HOLD_RSCN) &&
2566 !(phba->fc_flag & FC_RSCN_DISCOVERY)) {
2567 spin_lock_irq(phba->host->host_lock);
2568 phba->fc_flag |= FC_RSCN_MODE;
2569 spin_unlock_irq(phba->host->host_lock);
2570 phba->fc_rscn_id_list[phba->fc_rscn_id_cnt++] = pcmd;
2571
2572 /* If we zero, cmdiocb->context2, the calling
2573 * routine will not try to free it.
2574 */
2575 cmdiocb->context2 = NULL;
2576
2577 /* Deferred RSCN */
2578 lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
2579 "%d:0235 Deferred RSCN "
2580 "Data: x%x x%x x%x\n",
2581 phba->brd_no, phba->fc_rscn_id_cnt,
2582 phba->fc_flag, phba->hba_state);
2583 } else {
2584 spin_lock_irq(phba->host->host_lock);
2585 phba->fc_flag |= FC_RSCN_DISCOVERY;
2586 spin_unlock_irq(phba->host->host_lock);
2587 /* ReDiscovery RSCN */
2588 lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
2589 "%d:0234 ReDiscovery RSCN "
2590 "Data: x%x x%x x%x\n",
2591 phba->brd_no, phba->fc_rscn_id_cnt,
2592 phba->fc_flag, phba->hba_state);
2593 }
2594 /* Send back ACC */
2595 lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL,
2596 newnode);
2597
2598 /* send RECOVERY event for ALL nodes that match RSCN payload */
2599 lpfc_rscn_recovery_check(phba);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002600 return 0;
dea31012005-04-17 16:05:31 -05002601 }
2602
2603 phba->fc_flag |= FC_RSCN_MODE;
2604 phba->fc_rscn_id_list[phba->fc_rscn_id_cnt++] = pcmd;
2605 /*
2606 * If we zero, cmdiocb->context2, the calling routine will
2607 * not try to free it.
2608 */
2609 cmdiocb->context2 = NULL;
2610
2611 lpfc_set_disctmo(phba);
2612
2613 /* Send back ACC */
2614 lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL, newnode);
2615
2616 /* send RECOVERY event for ALL nodes that match RSCN payload */
2617 lpfc_rscn_recovery_check(phba);
2618
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002619 return lpfc_els_handle_rscn(phba);
dea31012005-04-17 16:05:31 -05002620}
2621
2622int
2623lpfc_els_handle_rscn(struct lpfc_hba * phba)
2624{
2625 struct lpfc_nodelist *ndlp;
2626
2627 /* Start timer for RSCN processing */
2628 lpfc_set_disctmo(phba);
2629
2630 /* RSCN processed */
2631 lpfc_printf_log(phba,
2632 KERN_INFO,
2633 LOG_DISCOVERY,
2634 "%d:0215 RSCN processed Data: x%x x%x x%x x%x\n",
2635 phba->brd_no,
2636 phba->fc_flag, 0, phba->fc_rscn_id_cnt,
2637 phba->hba_state);
2638
2639 /* To process RSCN, first compare RSCN data with NameServer */
2640 phba->fc_ns_retry = 0;
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002641 ndlp = lpfc_findnode_did(phba, NLP_SEARCH_UNMAPPED, NameServer_DID);
2642 if (ndlp) {
dea31012005-04-17 16:05:31 -05002643 /* Good ndlp, issue CT Request to NameServer */
2644 if (lpfc_ns_cmd(phba, ndlp, SLI_CTNS_GID_FT) == 0) {
2645 /* Wait for NameServer query cmpl before we can
2646 continue */
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002647 return 1;
dea31012005-04-17 16:05:31 -05002648 }
2649 } else {
2650 /* If login to NameServer does not exist, issue one */
2651 /* Good status, issue PLOGI to NameServer */
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002652 ndlp = lpfc_findnode_did(phba, NLP_SEARCH_ALL, NameServer_DID);
2653 if (ndlp) {
dea31012005-04-17 16:05:31 -05002654 /* Wait for NameServer login cmpl before we can
2655 continue */
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002656 return 1;
dea31012005-04-17 16:05:31 -05002657 }
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002658 ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL);
2659 if (!ndlp) {
dea31012005-04-17 16:05:31 -05002660 lpfc_els_flush_rscn(phba);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002661 return 0;
dea31012005-04-17 16:05:31 -05002662 } else {
2663 lpfc_nlp_init(phba, ndlp, NameServer_DID);
2664 ndlp->nlp_type |= NLP_FABRIC;
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05002665 ndlp->nlp_prev_state = ndlp->nlp_state;
dea31012005-04-17 16:05:31 -05002666 ndlp->nlp_state = NLP_STE_PLOGI_ISSUE;
James Smart2fb9bd82006-12-02 13:33:57 -05002667 lpfc_nlp_list(phba, ndlp, NLP_PLOGI_LIST);
James Smart488d1462006-03-07 15:02:37 -05002668 lpfc_issue_els_plogi(phba, NameServer_DID, 0);
dea31012005-04-17 16:05:31 -05002669 /* Wait for NameServer login cmpl before we can
2670 continue */
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002671 return 1;
dea31012005-04-17 16:05:31 -05002672 }
2673 }
2674
2675 lpfc_els_flush_rscn(phba);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002676 return 0;
dea31012005-04-17 16:05:31 -05002677}
2678
2679static int
2680lpfc_els_rcv_flogi(struct lpfc_hba * phba,
2681 struct lpfc_iocbq * cmdiocb,
2682 struct lpfc_nodelist * ndlp, uint8_t newnode)
2683{
2684 struct lpfc_dmabuf *pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
2685 uint32_t *lp = (uint32_t *) pcmd->virt;
2686 IOCB_t *icmd = &cmdiocb->iocb;
2687 struct serv_parm *sp;
2688 LPFC_MBOXQ_t *mbox;
2689 struct ls_rjt stat;
2690 uint32_t cmd, did;
2691 int rc;
2692
2693 cmd = *lp++;
2694 sp = (struct serv_parm *) lp;
2695
2696 /* FLOGI received */
2697
2698 lpfc_set_disctmo(phba);
2699
2700 if (phba->fc_topology == TOPOLOGY_LOOP) {
2701 /* We should never receive a FLOGI in loop mode, ignore it */
2702 did = icmd->un.elsreq64.remoteID;
2703
2704 /* An FLOGI ELS command <elsCmd> was received from DID <did> in
2705 Loop Mode */
2706 lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
2707 "%d:0113 An FLOGI ELS command x%x was received "
2708 "from DID x%x in Loop Mode\n",
2709 phba->brd_no, cmd, did);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002710 return 1;
dea31012005-04-17 16:05:31 -05002711 }
2712
2713 did = Fabric_DID;
2714
2715 if ((lpfc_check_sparm(phba, ndlp, sp, CLASS3))) {
2716 /* For a FLOGI we accept, then if our portname is greater
2717 * then the remote portname we initiate Nport login.
2718 */
2719
2720 rc = memcmp(&phba->fc_portname, &sp->portName,
2721 sizeof (struct lpfc_name));
2722
2723 if (!rc) {
2724 if ((mbox = mempool_alloc(phba->mbox_mem_pool,
2725 GFP_KERNEL)) == 0) {
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002726 return 1;
dea31012005-04-17 16:05:31 -05002727 }
2728 lpfc_linkdown(phba);
2729 lpfc_init_link(phba, mbox,
2730 phba->cfg_topology,
2731 phba->cfg_link_speed);
2732 mbox->mb.un.varInitLnk.lipsr_AL_PA = 0;
2733 mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
2734 rc = lpfc_sli_issue_mbox
2735 (phba, mbox, (MBX_NOWAIT | MBX_STOP_IOCB));
2736 if (rc == MBX_NOT_FINISHED) {
2737 mempool_free( mbox, phba->mbox_mem_pool);
2738 }
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002739 return 1;
Jamie Wellnitz2fe165b2006-02-28 19:25:31 -05002740 } else if (rc > 0) { /* greater than */
dea31012005-04-17 16:05:31 -05002741 spin_lock_irq(phba->host->host_lock);
2742 phba->fc_flag |= FC_PT2PT_PLOGI;
2743 spin_unlock_irq(phba->host->host_lock);
2744 }
2745 phba->fc_flag |= FC_PT2PT;
2746 phba->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP);
2747 } else {
2748 /* Reject this request because invalid parameters */
2749 stat.un.b.lsRjtRsvd0 = 0;
2750 stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
2751 stat.un.b.lsRjtRsnCodeExp = LSEXP_SPARM_OPTIONS;
2752 stat.un.b.vendorUnique = 0;
2753 lpfc_els_rsp_reject(phba, stat.un.lsRjtError, cmdiocb, ndlp);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002754 return 1;
dea31012005-04-17 16:05:31 -05002755 }
2756
2757 /* Send back ACC */
2758 lpfc_els_rsp_acc(phba, ELS_CMD_PLOGI, cmdiocb, ndlp, NULL, newnode);
2759
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002760 return 0;
dea31012005-04-17 16:05:31 -05002761}
2762
2763static int
2764lpfc_els_rcv_rnid(struct lpfc_hba * phba,
2765 struct lpfc_iocbq * cmdiocb, struct lpfc_nodelist * ndlp)
2766{
2767 struct lpfc_dmabuf *pcmd;
2768 uint32_t *lp;
2769 IOCB_t *icmd;
2770 RNID *rn;
2771 struct ls_rjt stat;
2772 uint32_t cmd, did;
2773
2774 icmd = &cmdiocb->iocb;
2775 did = icmd->un.elsreq64.remoteID;
2776 pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
2777 lp = (uint32_t *) pcmd->virt;
2778
2779 cmd = *lp++;
2780 rn = (RNID *) lp;
2781
2782 /* RNID received */
2783
2784 switch (rn->Format) {
2785 case 0:
2786 case RNID_TOPOLOGY_DISC:
2787 /* Send back ACC */
2788 lpfc_els_rsp_rnid_acc(phba, rn->Format, cmdiocb, ndlp);
2789 break;
2790 default:
2791 /* Reject this request because format not supported */
2792 stat.un.b.lsRjtRsvd0 = 0;
2793 stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
2794 stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA;
2795 stat.un.b.vendorUnique = 0;
2796 lpfc_els_rsp_reject(phba, stat.un.lsRjtError, cmdiocb, ndlp);
2797 }
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002798 return 0;
dea31012005-04-17 16:05:31 -05002799}
2800
2801static int
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05002802lpfc_els_rcv_lirr(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
2803 struct lpfc_nodelist * ndlp)
2804{
2805 struct ls_rjt stat;
2806
2807 /* For now, unconditionally reject this command */
2808 stat.un.b.lsRjtRsvd0 = 0;
2809 stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
2810 stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA;
2811 stat.un.b.vendorUnique = 0;
2812 lpfc_els_rsp_reject(phba, stat.un.lsRjtError, cmdiocb, ndlp);
2813 return 0;
2814}
2815
Jamie Wellnitz082c0262006-02-28 19:25:30 -05002816static void
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05002817lpfc_els_rsp_rps_acc(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
2818{
2819 struct lpfc_sli *psli;
2820 struct lpfc_sli_ring *pring;
2821 MAILBOX_t *mb;
2822 IOCB_t *icmd;
2823 RPS_RSP *rps_rsp;
2824 uint8_t *pcmd;
2825 struct lpfc_iocbq *elsiocb;
2826 struct lpfc_nodelist *ndlp;
2827 uint16_t xri, status;
2828 uint32_t cmdsize;
2829
2830 psli = &phba->sli;
2831 pring = &psli->ring[LPFC_ELS_RING];
2832 mb = &pmb->mb;
2833
2834 ndlp = (struct lpfc_nodelist *) pmb->context2;
2835 xri = (uint16_t) ((unsigned long)(pmb->context1));
Randy Dunlap041976f2006-06-25 01:58:51 -07002836 pmb->context1 = NULL;
2837 pmb->context2 = NULL;
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05002838
2839 if (mb->mbxStatus) {
2840 mempool_free( pmb, phba->mbox_mem_pool);
2841 return;
2842 }
2843
2844 cmdsize = sizeof(RPS_RSP) + sizeof(uint32_t);
2845 mempool_free( pmb, phba->mbox_mem_pool);
James Smart488d1462006-03-07 15:02:37 -05002846 elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, lpfc_max_els_tries, ndlp,
2847 ndlp->nlp_DID, ELS_CMD_ACC);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002848 if (!elsiocb)
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05002849 return;
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05002850
2851 icmd = &elsiocb->iocb;
2852 icmd->ulpContext = xri;
2853
2854 pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
2855 *((uint32_t *) (pcmd)) = ELS_CMD_ACC;
2856 pcmd += sizeof (uint32_t); /* Skip past command */
2857 rps_rsp = (RPS_RSP *)pcmd;
2858
2859 if (phba->fc_topology != TOPOLOGY_LOOP)
2860 status = 0x10;
2861 else
2862 status = 0x8;
2863 if (phba->fc_flag & FC_FABRIC)
2864 status |= 0x4;
2865
2866 rps_rsp->rsvd1 = 0;
2867 rps_rsp->portStatus = be16_to_cpu(status);
2868 rps_rsp->linkFailureCnt = be32_to_cpu(mb->un.varRdLnk.linkFailureCnt);
2869 rps_rsp->lossSyncCnt = be32_to_cpu(mb->un.varRdLnk.lossSyncCnt);
2870 rps_rsp->lossSignalCnt = be32_to_cpu(mb->un.varRdLnk.lossSignalCnt);
2871 rps_rsp->primSeqErrCnt = be32_to_cpu(mb->un.varRdLnk.primSeqErrCnt);
2872 rps_rsp->invalidXmitWord = be32_to_cpu(mb->un.varRdLnk.invalidXmitWord);
2873 rps_rsp->crcCnt = be32_to_cpu(mb->un.varRdLnk.crcCnt);
2874
2875 /* Xmit ELS RPS ACC response tag <ulpIoTag> */
2876 lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
James Smartdca94792006-08-01 07:34:08 -04002877 "%d:0118 Xmit ELS RPS ACC response tag x%x "
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05002878 "Data: x%x x%x x%x x%x x%x\n",
2879 phba->brd_no,
2880 elsiocb->iocb.ulpIoTag,
2881 elsiocb->iocb.ulpContext, ndlp->nlp_DID,
2882 ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi);
2883
2884 elsiocb->iocb_cmpl = lpfc_cmpl_els_acc;
2885 phba->fc_stat.elsXmitACC++;
2886 if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) {
2887 lpfc_els_free_iocb(phba, elsiocb);
2888 }
2889 return;
2890}
2891
2892static int
2893lpfc_els_rcv_rps(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
2894 struct lpfc_nodelist * ndlp)
2895{
2896 uint32_t *lp;
2897 uint8_t flag;
2898 LPFC_MBOXQ_t *mbox;
2899 struct lpfc_dmabuf *pcmd;
2900 RPS *rps;
2901 struct ls_rjt stat;
2902
Jamie Wellnitz2fe165b2006-02-28 19:25:31 -05002903 if ((ndlp->nlp_state != NLP_STE_UNMAPPED_NODE) &&
2904 (ndlp->nlp_state != NLP_STE_MAPPED_NODE)) {
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05002905 stat.un.b.lsRjtRsvd0 = 0;
2906 stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
2907 stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA;
2908 stat.un.b.vendorUnique = 0;
2909 lpfc_els_rsp_reject(phba, stat.un.lsRjtError, cmdiocb, ndlp);
2910 }
2911
2912 pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
2913 lp = (uint32_t *) pcmd->virt;
2914 flag = (be32_to_cpu(*lp++) & 0xf);
2915 rps = (RPS *) lp;
2916
2917 if ((flag == 0) ||
2918 ((flag == 1) && (be32_to_cpu(rps->un.portNum) == 0)) ||
2919 ((flag == 2) && (memcmp(&rps->un.portName, &phba->fc_portname,
2920 sizeof (struct lpfc_name)) == 0))) {
2921 if ((mbox = mempool_alloc(phba->mbox_mem_pool, GFP_ATOMIC))) {
2922 lpfc_read_lnk_stat(phba, mbox);
2923 mbox->context1 =
2924 (void *)((unsigned long)cmdiocb->iocb.ulpContext);
2925 mbox->context2 = ndlp;
2926 mbox->mbox_cmpl = lpfc_els_rsp_rps_acc;
2927 if (lpfc_sli_issue_mbox (phba, mbox,
2928 (MBX_NOWAIT | MBX_STOP_IOCB)) != MBX_NOT_FINISHED) {
2929 /* Mbox completion will send ELS Response */
2930 return 0;
2931 }
2932 mempool_free(mbox, phba->mbox_mem_pool);
2933 }
2934 }
2935 stat.un.b.lsRjtRsvd0 = 0;
2936 stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
2937 stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA;
2938 stat.un.b.vendorUnique = 0;
2939 lpfc_els_rsp_reject(phba, stat.un.lsRjtError, cmdiocb, ndlp);
2940 return 0;
2941}
2942
Jamie Wellnitz082c0262006-02-28 19:25:30 -05002943static int
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05002944lpfc_els_rsp_rpl_acc(struct lpfc_hba * phba, uint16_t cmdsize,
2945 struct lpfc_iocbq * oldiocb, struct lpfc_nodelist * ndlp)
2946{
2947 IOCB_t *icmd;
2948 IOCB_t *oldcmd;
2949 RPL_RSP rpl_rsp;
2950 struct lpfc_iocbq *elsiocb;
2951 struct lpfc_sli_ring *pring;
2952 struct lpfc_sli *psli;
2953 uint8_t *pcmd;
2954
2955 psli = &phba->sli;
2956 pring = &psli->ring[LPFC_ELS_RING]; /* ELS ring */
2957
James Smart488d1462006-03-07 15:02:37 -05002958 elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, oldiocb->retry,
2959 ndlp, ndlp->nlp_DID, ELS_CMD_ACC);
2960 if (!elsiocb)
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05002961 return 1;
James Smart488d1462006-03-07 15:02:37 -05002962
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05002963 icmd = &elsiocb->iocb;
2964 oldcmd = &oldiocb->iocb;
2965 icmd->ulpContext = oldcmd->ulpContext; /* Xri */
2966
2967 pcmd = (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
2968 *((uint32_t *) (pcmd)) = ELS_CMD_ACC;
2969 pcmd += sizeof (uint16_t);
2970 *((uint16_t *)(pcmd)) = be16_to_cpu(cmdsize);
2971 pcmd += sizeof(uint16_t);
2972
2973 /* Setup the RPL ACC payload */
2974 rpl_rsp.listLen = be32_to_cpu(1);
2975 rpl_rsp.index = 0;
2976 rpl_rsp.port_num_blk.portNum = 0;
2977 rpl_rsp.port_num_blk.portID = be32_to_cpu(phba->fc_myDID);
2978 memcpy(&rpl_rsp.port_num_blk.portName, &phba->fc_portname,
2979 sizeof(struct lpfc_name));
2980
2981 memcpy(pcmd, &rpl_rsp, cmdsize - sizeof(uint32_t));
2982
2983
2984 /* Xmit ELS RPL ACC response tag <ulpIoTag> */
2985 lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
James Smartdca94792006-08-01 07:34:08 -04002986 "%d:0120 Xmit ELS RPL ACC response tag x%x "
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05002987 "Data: x%x x%x x%x x%x x%x\n",
2988 phba->brd_no,
2989 elsiocb->iocb.ulpIoTag,
2990 elsiocb->iocb.ulpContext, ndlp->nlp_DID,
2991 ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi);
2992
2993 elsiocb->iocb_cmpl = lpfc_cmpl_els_acc;
2994
2995 phba->fc_stat.elsXmitACC++;
2996 if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) {
2997 lpfc_els_free_iocb(phba, elsiocb);
2998 return 1;
2999 }
3000 return 0;
3001}
3002
3003static int
3004lpfc_els_rcv_rpl(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
dea31012005-04-17 16:05:31 -05003005 struct lpfc_nodelist * ndlp)
3006{
3007 struct lpfc_dmabuf *pcmd;
3008 uint32_t *lp;
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05003009 uint32_t maxsize;
3010 uint16_t cmdsize;
3011 RPL *rpl;
3012 struct ls_rjt stat;
dea31012005-04-17 16:05:31 -05003013
Jamie Wellnitz2fe165b2006-02-28 19:25:31 -05003014 if ((ndlp->nlp_state != NLP_STE_UNMAPPED_NODE) &&
3015 (ndlp->nlp_state != NLP_STE_MAPPED_NODE)) {
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05003016 stat.un.b.lsRjtRsvd0 = 0;
3017 stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
3018 stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA;
3019 stat.un.b.vendorUnique = 0;
3020 lpfc_els_rsp_reject(phba, stat.un.lsRjtError, cmdiocb, ndlp);
dea31012005-04-17 16:05:31 -05003021 }
3022
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05003023 pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
3024 lp = (uint32_t *) pcmd->virt;
3025 rpl = (RPL *) (lp + 1);
3026
3027 maxsize = be32_to_cpu(rpl->maxsize);
3028
3029 /* We support only one port */
3030 if ((rpl->index == 0) &&
3031 ((maxsize == 0) ||
3032 ((maxsize * sizeof(uint32_t)) >= sizeof(RPL_RSP)))) {
3033 cmdsize = sizeof(uint32_t) + sizeof(RPL_RSP);
Jamie Wellnitz2fe165b2006-02-28 19:25:31 -05003034 } else {
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05003035 cmdsize = sizeof(uint32_t) + maxsize * sizeof(uint32_t);
3036 }
3037 lpfc_els_rsp_rpl_acc(phba, cmdsize, cmdiocb, ndlp);
dea31012005-04-17 16:05:31 -05003038
3039 return 0;
3040}
3041
3042static int
3043lpfc_els_rcv_farp(struct lpfc_hba * phba,
3044 struct lpfc_iocbq * cmdiocb, struct lpfc_nodelist * ndlp)
3045{
3046 struct lpfc_dmabuf *pcmd;
3047 uint32_t *lp;
3048 IOCB_t *icmd;
3049 FARP *fp;
3050 uint32_t cmd, cnt, did;
3051
3052 icmd = &cmdiocb->iocb;
3053 did = icmd->un.elsreq64.remoteID;
3054 pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
3055 lp = (uint32_t *) pcmd->virt;
3056
3057 cmd = *lp++;
3058 fp = (FARP *) lp;
3059
3060 /* FARP-REQ received from DID <did> */
3061 lpfc_printf_log(phba,
3062 KERN_INFO,
James Smarta4bc3372006-12-02 13:34:16 -05003063 LOG_ELS,
dea31012005-04-17 16:05:31 -05003064 "%d:0601 FARP-REQ received from DID x%x\n",
3065 phba->brd_no, did);
3066
3067 /* We will only support match on WWPN or WWNN */
3068 if (fp->Mflags & ~(FARP_MATCH_NODE | FARP_MATCH_PORT)) {
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05003069 return 0;
dea31012005-04-17 16:05:31 -05003070 }
3071
3072 cnt = 0;
3073 /* If this FARP command is searching for my portname */
3074 if (fp->Mflags & FARP_MATCH_PORT) {
3075 if (memcmp(&fp->RportName, &phba->fc_portname,
3076 sizeof (struct lpfc_name)) == 0)
3077 cnt = 1;
3078 }
3079
3080 /* If this FARP command is searching for my nodename */
3081 if (fp->Mflags & FARP_MATCH_NODE) {
3082 if (memcmp(&fp->RnodeName, &phba->fc_nodename,
3083 sizeof (struct lpfc_name)) == 0)
3084 cnt = 1;
3085 }
3086
3087 if (cnt) {
3088 if ((ndlp->nlp_state == NLP_STE_UNMAPPED_NODE) ||
3089 (ndlp->nlp_state == NLP_STE_MAPPED_NODE)) {
3090 /* Log back into the node before sending the FARP. */
3091 if (fp->Rflags & FARP_REQUEST_PLOGI) {
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05003092 ndlp->nlp_prev_state = ndlp->nlp_state;
dea31012005-04-17 16:05:31 -05003093 ndlp->nlp_state = NLP_STE_PLOGI_ISSUE;
3094 lpfc_nlp_list(phba, ndlp, NLP_PLOGI_LIST);
James Smart488d1462006-03-07 15:02:37 -05003095 lpfc_issue_els_plogi(phba, ndlp->nlp_DID, 0);
dea31012005-04-17 16:05:31 -05003096 }
3097
3098 /* Send a FARP response to that node */
3099 if (fp->Rflags & FARP_REQUEST_FARPR) {
3100 lpfc_issue_els_farpr(phba, did, 0);
3101 }
3102 }
3103 }
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05003104 return 0;
dea31012005-04-17 16:05:31 -05003105}
3106
3107static int
3108lpfc_els_rcv_farpr(struct lpfc_hba * phba,
3109 struct lpfc_iocbq * cmdiocb, struct lpfc_nodelist * ndlp)
3110{
3111 struct lpfc_dmabuf *pcmd;
3112 uint32_t *lp;
3113 IOCB_t *icmd;
3114 uint32_t cmd, did;
3115
3116 icmd = &cmdiocb->iocb;
3117 did = icmd->un.elsreq64.remoteID;
3118 pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
3119 lp = (uint32_t *) pcmd->virt;
3120
3121 cmd = *lp++;
3122 /* FARP-RSP received from DID <did> */
3123 lpfc_printf_log(phba,
3124 KERN_INFO,
James Smarta4bc3372006-12-02 13:34:16 -05003125 LOG_ELS,
dea31012005-04-17 16:05:31 -05003126 "%d:0600 FARP-RSP received from DID x%x\n",
3127 phba->brd_no, did);
3128
3129 /* ACCEPT the Farp resp request */
3130 lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0);
3131
3132 return 0;
3133}
3134
3135static int
3136lpfc_els_rcv_fan(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05003137 struct lpfc_nodelist * fan_ndlp)
dea31012005-04-17 16:05:31 -05003138{
3139 struct lpfc_dmabuf *pcmd;
3140 uint32_t *lp;
3141 IOCB_t *icmd;
dea31012005-04-17 16:05:31 -05003142 uint32_t cmd, did;
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05003143 FAN *fp;
3144 struct lpfc_nodelist *ndlp, *next_ndlp;
3145
3146 /* FAN received */
James Smartdca94792006-08-01 07:34:08 -04003147 lpfc_printf_log(phba, KERN_INFO, LOG_ELS, "%d:0265 FAN received\n",
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05003148 phba->brd_no);
dea31012005-04-17 16:05:31 -05003149
3150 icmd = &cmdiocb->iocb;
3151 did = icmd->un.elsreq64.remoteID;
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05003152 pcmd = (struct lpfc_dmabuf *)cmdiocb->context2;
3153 lp = (uint32_t *)pcmd->virt;
dea31012005-04-17 16:05:31 -05003154
3155 cmd = *lp++;
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05003156 fp = (FAN *)lp;
dea31012005-04-17 16:05:31 -05003157
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05003158 /* FAN received; Fan does not have a reply sequence */
dea31012005-04-17 16:05:31 -05003159
3160 if (phba->hba_state == LPFC_LOCAL_CFG_LINK) {
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05003161 if ((memcmp(&phba->fc_fabparam.nodeName, &fp->FnodeName,
3162 sizeof(struct lpfc_name)) != 0) ||
3163 (memcmp(&phba->fc_fabparam.portName, &fp->FportName,
3164 sizeof(struct lpfc_name)) != 0)) {
3165 /*
3166 * This node has switched fabrics. FLOGI is required
3167 * Clean up the old rpi's
dea31012005-04-17 16:05:31 -05003168 */
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05003169
3170 list_for_each_entry_safe(ndlp, next_ndlp,
3171 &phba->fc_npr_list, nlp_listp) {
3172
3173 if (ndlp->nlp_type & NLP_FABRIC) {
3174 /*
3175 * Clean up old Fabric, Nameserver and
3176 * other NLP_FABRIC logins
3177 */
3178 lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
Jamie Wellnitz2fe165b2006-02-28 19:25:31 -05003179 } else if (!(ndlp->nlp_flag & NLP_NPR_ADISC)) {
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05003180 /* Fail outstanding I/O now since this
3181 * device is marked for PLOGI
3182 */
3183 lpfc_unreg_rpi(phba, ndlp);
3184 }
3185 }
3186
3187 phba->hba_state = LPFC_FLOGI;
3188 lpfc_set_disctmo(phba);
3189 lpfc_initial_flogi(phba);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05003190 return 0;
dea31012005-04-17 16:05:31 -05003191 }
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05003192 /* Discovery not needed,
3193 * move the nodes to their original state.
3194 */
3195 list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_npr_list,
3196 nlp_listp) {
dea31012005-04-17 16:05:31 -05003197
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05003198 switch (ndlp->nlp_prev_state) {
3199 case NLP_STE_UNMAPPED_NODE:
3200 ndlp->nlp_prev_state = NLP_STE_NPR_NODE;
3201 ndlp->nlp_state = NLP_STE_UNMAPPED_NODE;
3202 lpfc_nlp_list(phba, ndlp, NLP_UNMAPPED_LIST);
3203 break;
3204
3205 case NLP_STE_MAPPED_NODE:
3206 ndlp->nlp_prev_state = NLP_STE_NPR_NODE;
3207 ndlp->nlp_state = NLP_STE_MAPPED_NODE;
3208 lpfc_nlp_list(phba, ndlp, NLP_MAPPED_LIST);
3209 break;
3210
3211 default:
3212 break;
3213 }
3214 }
3215
3216 /* Start discovery - this should just do CLEAR_LA */
dea31012005-04-17 16:05:31 -05003217 lpfc_disc_start(phba);
3218 }
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05003219 return 0;
dea31012005-04-17 16:05:31 -05003220}
3221
3222void
3223lpfc_els_timeout(unsigned long ptr)
3224{
3225 struct lpfc_hba *phba;
3226 unsigned long iflag;
3227
3228 phba = (struct lpfc_hba *)ptr;
3229 if (phba == 0)
3230 return;
3231 spin_lock_irqsave(phba->host->host_lock, iflag);
3232 if (!(phba->work_hba_events & WORKER_ELS_TMO)) {
3233 phba->work_hba_events |= WORKER_ELS_TMO;
3234 if (phba->work_wait)
3235 wake_up(phba->work_wait);
3236 }
3237 spin_unlock_irqrestore(phba->host->host_lock, iflag);
3238 return;
3239}
3240
3241void
3242lpfc_els_timeout_handler(struct lpfc_hba *phba)
3243{
3244 struct lpfc_sli_ring *pring;
3245 struct lpfc_iocbq *tmp_iocb, *piocb;
3246 IOCB_t *cmd = NULL;
3247 struct lpfc_dmabuf *pcmd;
3248 struct list_head *dlp;
3249 uint32_t *elscmd;
3250 uint32_t els_command;
3251 uint32_t timeout;
3252 uint32_t remote_ID;
3253
3254 if (phba == 0)
3255 return;
3256 spin_lock_irq(phba->host->host_lock);
3257 /* If the timer is already canceled do nothing */
3258 if (!(phba->work_hba_events & WORKER_ELS_TMO)) {
3259 spin_unlock_irq(phba->host->host_lock);
3260 return;
3261 }
3262 timeout = (uint32_t)(phba->fc_ratov << 1);
3263
3264 pring = &phba->sli.ring[LPFC_ELS_RING];
3265 dlp = &pring->txcmplq;
3266
3267 list_for_each_entry_safe(piocb, tmp_iocb, &pring->txcmplq, list) {
3268 cmd = &piocb->iocb;
3269
3270 if (piocb->iocb_flag & LPFC_IO_LIBDFC) {
3271 continue;
3272 }
3273 pcmd = (struct lpfc_dmabuf *) piocb->context2;
3274 elscmd = (uint32_t *) (pcmd->virt);
3275 els_command = *elscmd;
3276
3277 if ((els_command == ELS_CMD_FARP)
3278 || (els_command == ELS_CMD_FARPR)) {
3279 continue;
3280 }
3281
3282 if (piocb->drvrTimeout > 0) {
3283 if (piocb->drvrTimeout >= timeout) {
3284 piocb->drvrTimeout -= timeout;
3285 } else {
3286 piocb->drvrTimeout = 0;
3287 }
3288 continue;
3289 }
3290
3291 list_del(&piocb->list);
3292 pring->txcmplq_cnt--;
3293
3294 if (cmd->ulpCommand == CMD_GEN_REQUEST64_CR) {
3295 struct lpfc_nodelist *ndlp;
Jamie Wellnitz66a9ed62006-02-28 22:33:10 -05003296 spin_unlock_irq(phba->host->host_lock);
dea31012005-04-17 16:05:31 -05003297 ndlp = lpfc_findnode_rpi(phba, cmd->ulpContext);
Jamie Wellnitz66a9ed62006-02-28 22:33:10 -05003298 spin_lock_irq(phba->host->host_lock);
dea31012005-04-17 16:05:31 -05003299 remote_ID = ndlp->nlp_DID;
3300 if (cmd->un.elsreq64.bdl.ulpIoTag32) {
3301 lpfc_sli_issue_abort_iotag32(phba,
3302 pring, piocb);
3303 }
3304 } else {
3305 remote_ID = cmd->un.elsreq64.remoteID;
3306 }
3307
3308 lpfc_printf_log(phba,
3309 KERN_ERR,
3310 LOG_ELS,
3311 "%d:0127 ELS timeout Data: x%x x%x x%x x%x\n",
3312 phba->brd_no, els_command,
3313 remote_ID, cmd->ulpCommand, cmd->ulpIoTag);
3314
3315 /*
3316 * The iocb has timed out; abort it.
3317 */
3318 if (piocb->iocb_cmpl) {
3319 cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
3320 cmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
3321 spin_unlock_irq(phba->host->host_lock);
3322 (piocb->iocb_cmpl) (phba, piocb, piocb);
3323 spin_lock_irq(phba->host->host_lock);
James Bottomley604a3e32005-10-29 10:28:33 -05003324 } else
3325 lpfc_sli_release_iocbq(phba, piocb);
dea31012005-04-17 16:05:31 -05003326 }
James Smart5a0e3262006-07-06 15:49:16 -04003327 if (phba->sli.ring[LPFC_ELS_RING].txcmplq_cnt)
3328 mod_timer(&phba->els_tmofunc, jiffies + HZ * timeout);
3329
dea31012005-04-17 16:05:31 -05003330 spin_unlock_irq(phba->host->host_lock);
3331}
3332
3333void
3334lpfc_els_flush_cmd(struct lpfc_hba * phba)
3335{
3336 struct lpfc_sli_ring *pring;
3337 struct lpfc_iocbq *tmp_iocb, *piocb;
3338 IOCB_t *cmd = NULL;
3339 struct lpfc_dmabuf *pcmd;
3340 uint32_t *elscmd;
3341 uint32_t els_command;
dea31012005-04-17 16:05:31 -05003342
3343 pring = &phba->sli.ring[LPFC_ELS_RING];
3344 spin_lock_irq(phba->host->host_lock);
3345 list_for_each_entry_safe(piocb, tmp_iocb, &pring->txq, list) {
3346 cmd = &piocb->iocb;
3347
3348 if (piocb->iocb_flag & LPFC_IO_LIBDFC) {
3349 continue;
3350 }
3351
3352 /* Do not flush out the QUE_RING and ABORT/CLOSE iocbs */
3353 if ((cmd->ulpCommand == CMD_QUE_RING_BUF_CN) ||
3354 (cmd->ulpCommand == CMD_QUE_RING_BUF64_CN) ||
3355 (cmd->ulpCommand == CMD_CLOSE_XRI_CN) ||
3356 (cmd->ulpCommand == CMD_ABORT_XRI_CN)) {
3357 continue;
3358 }
3359
3360 pcmd = (struct lpfc_dmabuf *) piocb->context2;
3361 elscmd = (uint32_t *) (pcmd->virt);
3362 els_command = *elscmd;
3363
dea31012005-04-17 16:05:31 -05003364 list_del(&piocb->list);
James Smart1dcb58e2007-04-25 09:51:30 -04003365 pring->txq_cnt--;
dea31012005-04-17 16:05:31 -05003366
3367 cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
3368 cmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
3369
3370 if (piocb->iocb_cmpl) {
3371 spin_unlock_irq(phba->host->host_lock);
3372 (piocb->iocb_cmpl) (phba, piocb, piocb);
3373 spin_lock_irq(phba->host->host_lock);
Jamie Wellnitz2fe165b2006-02-28 19:25:31 -05003374 } else
James Bottomley604a3e32005-10-29 10:28:33 -05003375 lpfc_sli_release_iocbq(phba, piocb);
dea31012005-04-17 16:05:31 -05003376 }
3377
3378 list_for_each_entry_safe(piocb, tmp_iocb, &pring->txcmplq, list) {
3379 cmd = &piocb->iocb;
3380
3381 if (piocb->iocb_flag & LPFC_IO_LIBDFC) {
3382 continue;
3383 }
3384 pcmd = (struct lpfc_dmabuf *) piocb->context2;
3385 elscmd = (uint32_t *) (pcmd->virt);
3386 els_command = *elscmd;
3387
dea31012005-04-17 16:05:31 -05003388 list_del(&piocb->list);
3389 pring->txcmplq_cnt--;
3390
3391 cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
3392 cmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
3393
3394 if (piocb->iocb_cmpl) {
3395 spin_unlock_irq(phba->host->host_lock);
3396 (piocb->iocb_cmpl) (phba, piocb, piocb);
3397 spin_lock_irq(phba->host->host_lock);
Jamie Wellnitz2fe165b2006-02-28 19:25:31 -05003398 } else
James Bottomley604a3e32005-10-29 10:28:33 -05003399 lpfc_sli_release_iocbq(phba, piocb);
dea31012005-04-17 16:05:31 -05003400 }
3401 spin_unlock_irq(phba->host->host_lock);
3402 return;
3403}
3404
3405void
3406lpfc_els_unsol_event(struct lpfc_hba * phba,
3407 struct lpfc_sli_ring * pring, struct lpfc_iocbq * elsiocb)
3408{
3409 struct lpfc_sli *psli;
3410 struct lpfc_nodelist *ndlp;
3411 struct lpfc_dmabuf *mp;
3412 uint32_t *lp;
3413 IOCB_t *icmd;
3414 struct ls_rjt stat;
3415 uint32_t cmd;
3416 uint32_t did;
3417 uint32_t newnode;
3418 uint32_t drop_cmd = 0; /* by default do NOT drop received cmd */
3419 uint32_t rjt_err = 0;
3420
3421 psli = &phba->sli;
3422 icmd = &elsiocb->iocb;
3423
3424 if ((icmd->ulpStatus == IOSTAT_LOCAL_REJECT) &&
3425 ((icmd->un.ulpWord[4] & 0xff) == IOERR_RCV_BUFFER_WAITING)) {
3426 /* Not enough posted buffers; Try posting more buffers */
3427 phba->fc_stat.NoRcvBuf++;
3428 lpfc_post_buffer(phba, pring, 0, 1);
3429 return;
3430 }
3431
3432 /* If there are no BDEs associated with this IOCB,
3433 * there is nothing to do.
3434 */
3435 if (icmd->ulpBdeCount == 0)
3436 return;
3437
3438 /* type of ELS cmd is first 32bit word in packet */
3439 mp = lpfc_sli_ringpostbuf_get(phba, pring, getPaddr(icmd->un.
3440 cont64[0].
3441 addrHigh,
3442 icmd->un.
3443 cont64[0].addrLow));
3444 if (mp == 0) {
3445 drop_cmd = 1;
3446 goto dropit;
3447 }
3448
3449 newnode = 0;
3450 lp = (uint32_t *) mp->virt;
3451 cmd = *lp++;
3452 lpfc_post_buffer(phba, &psli->ring[LPFC_ELS_RING], 1, 1);
3453
3454 if (icmd->ulpStatus) {
3455 lpfc_mbuf_free(phba, mp->virt, mp->phys);
3456 kfree(mp);
3457 drop_cmd = 1;
3458 goto dropit;
3459 }
3460
3461 /* Check to see if link went down during discovery */
3462 if (lpfc_els_chk_latt(phba)) {
3463 lpfc_mbuf_free(phba, mp->virt, mp->phys);
3464 kfree(mp);
3465 drop_cmd = 1;
3466 goto dropit;
3467 }
3468
3469 did = icmd->un.rcvels.remoteID;
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05003470 ndlp = lpfc_findnode_did(phba, NLP_SEARCH_ALL, did);
3471 if (!ndlp) {
dea31012005-04-17 16:05:31 -05003472 /* Cannot find existing Fabric ndlp, so allocate a new one */
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05003473 ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL);
3474 if (!ndlp) {
dea31012005-04-17 16:05:31 -05003475 lpfc_mbuf_free(phba, mp->virt, mp->phys);
3476 kfree(mp);
3477 drop_cmd = 1;
3478 goto dropit;
3479 }
3480
3481 lpfc_nlp_init(phba, ndlp, did);
3482 newnode = 1;
3483 if ((did & Fabric_DID_MASK) == Fabric_DID_MASK) {
3484 ndlp->nlp_type |= NLP_FABRIC;
3485 }
James Smart92795652006-07-06 15:50:02 -04003486 ndlp->nlp_state = NLP_STE_UNUSED_NODE;
3487 lpfc_nlp_list(phba, ndlp, NLP_UNUSED_LIST);
dea31012005-04-17 16:05:31 -05003488 }
3489
3490 phba->fc_stat.elsRcvFrame++;
3491 elsiocb->context1 = ndlp;
3492 elsiocb->context2 = mp;
3493
3494 if ((cmd & ELS_CMD_MASK) == ELS_CMD_RSCN) {
3495 cmd &= ELS_CMD_MASK;
3496 }
3497 /* ELS command <elsCmd> received from NPORT <did> */
3498 lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
3499 "%d:0112 ELS command x%x received from NPORT x%x "
3500 "Data: x%x\n", phba->brd_no, cmd, did, phba->hba_state);
3501
3502 switch (cmd) {
3503 case ELS_CMD_PLOGI:
3504 phba->fc_stat.elsRcvPLOGI++;
3505 if (phba->hba_state < LPFC_DISC_AUTH) {
James.Smart@Emulex.Com1f679ca2005-06-25 10:34:27 -04003506 rjt_err = 1;
dea31012005-04-17 16:05:31 -05003507 break;
3508 }
James Smart92795652006-07-06 15:50:02 -04003509 ndlp = lpfc_plogi_confirm_nport(phba, mp, ndlp);
dea31012005-04-17 16:05:31 -05003510 lpfc_disc_state_machine(phba, ndlp, elsiocb, NLP_EVT_RCV_PLOGI);
3511 break;
3512 case ELS_CMD_FLOGI:
3513 phba->fc_stat.elsRcvFLOGI++;
3514 lpfc_els_rcv_flogi(phba, elsiocb, ndlp, newnode);
3515 if (newnode) {
James Smart92795652006-07-06 15:50:02 -04003516 lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
dea31012005-04-17 16:05:31 -05003517 }
3518 break;
3519 case ELS_CMD_LOGO:
3520 phba->fc_stat.elsRcvLOGO++;
3521 if (phba->hba_state < LPFC_DISC_AUTH) {
James.Smart@Emulex.Com1f679ca2005-06-25 10:34:27 -04003522 rjt_err = 1;
dea31012005-04-17 16:05:31 -05003523 break;
3524 }
3525 lpfc_disc_state_machine(phba, ndlp, elsiocb, NLP_EVT_RCV_LOGO);
3526 break;
3527 case ELS_CMD_PRLO:
3528 phba->fc_stat.elsRcvPRLO++;
3529 if (phba->hba_state < LPFC_DISC_AUTH) {
James.Smart@Emulex.Com1f679ca2005-06-25 10:34:27 -04003530 rjt_err = 1;
dea31012005-04-17 16:05:31 -05003531 break;
3532 }
3533 lpfc_disc_state_machine(phba, ndlp, elsiocb, NLP_EVT_RCV_PRLO);
3534 break;
3535 case ELS_CMD_RSCN:
3536 phba->fc_stat.elsRcvRSCN++;
3537 lpfc_els_rcv_rscn(phba, elsiocb, ndlp, newnode);
3538 if (newnode) {
James Smart92795652006-07-06 15:50:02 -04003539 lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
dea31012005-04-17 16:05:31 -05003540 }
3541 break;
3542 case ELS_CMD_ADISC:
3543 phba->fc_stat.elsRcvADISC++;
3544 if (phba->hba_state < LPFC_DISC_AUTH) {
James.Smart@Emulex.Com1f679ca2005-06-25 10:34:27 -04003545 rjt_err = 1;
dea31012005-04-17 16:05:31 -05003546 break;
3547 }
3548 lpfc_disc_state_machine(phba, ndlp, elsiocb, NLP_EVT_RCV_ADISC);
3549 break;
3550 case ELS_CMD_PDISC:
3551 phba->fc_stat.elsRcvPDISC++;
3552 if (phba->hba_state < LPFC_DISC_AUTH) {
James.Smart@Emulex.Com1f679ca2005-06-25 10:34:27 -04003553 rjt_err = 1;
dea31012005-04-17 16:05:31 -05003554 break;
3555 }
3556 lpfc_disc_state_machine(phba, ndlp, elsiocb, NLP_EVT_RCV_PDISC);
3557 break;
3558 case ELS_CMD_FARPR:
3559 phba->fc_stat.elsRcvFARPR++;
3560 lpfc_els_rcv_farpr(phba, elsiocb, ndlp);
3561 break;
3562 case ELS_CMD_FARP:
3563 phba->fc_stat.elsRcvFARP++;
3564 lpfc_els_rcv_farp(phba, elsiocb, ndlp);
3565 break;
3566 case ELS_CMD_FAN:
3567 phba->fc_stat.elsRcvFAN++;
3568 lpfc_els_rcv_fan(phba, elsiocb, ndlp);
3569 break;
dea31012005-04-17 16:05:31 -05003570 case ELS_CMD_PRLI:
3571 phba->fc_stat.elsRcvPRLI++;
3572 if (phba->hba_state < LPFC_DISC_AUTH) {
James.Smart@Emulex.Com1f679ca2005-06-25 10:34:27 -04003573 rjt_err = 1;
dea31012005-04-17 16:05:31 -05003574 break;
3575 }
3576 lpfc_disc_state_machine(phba, ndlp, elsiocb, NLP_EVT_RCV_PRLI);
3577 break;
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05003578 case ELS_CMD_LIRR:
3579 phba->fc_stat.elsRcvLIRR++;
3580 lpfc_els_rcv_lirr(phba, elsiocb, ndlp);
3581 if (newnode) {
James Smart92795652006-07-06 15:50:02 -04003582 lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05003583 }
3584 break;
3585 case ELS_CMD_RPS:
3586 phba->fc_stat.elsRcvRPS++;
3587 lpfc_els_rcv_rps(phba, elsiocb, ndlp);
3588 if (newnode) {
James Smart92795652006-07-06 15:50:02 -04003589 lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05003590 }
3591 break;
3592 case ELS_CMD_RPL:
3593 phba->fc_stat.elsRcvRPL++;
3594 lpfc_els_rcv_rpl(phba, elsiocb, ndlp);
3595 if (newnode) {
James Smart92795652006-07-06 15:50:02 -04003596 lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05003597 }
3598 break;
dea31012005-04-17 16:05:31 -05003599 case ELS_CMD_RNID:
3600 phba->fc_stat.elsRcvRNID++;
3601 lpfc_els_rcv_rnid(phba, elsiocb, ndlp);
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05003602 if (newnode) {
James Smart92795652006-07-06 15:50:02 -04003603 lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05003604 }
dea31012005-04-17 16:05:31 -05003605 break;
3606 default:
3607 /* Unsupported ELS command, reject */
James.Smart@Emulex.Com1f679ca2005-06-25 10:34:27 -04003608 rjt_err = 1;
dea31012005-04-17 16:05:31 -05003609
3610 /* Unknown ELS command <elsCmd> received from NPORT <did> */
3611 lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
3612 "%d:0115 Unknown ELS command x%x received from "
3613 "NPORT x%x\n", phba->brd_no, cmd, did);
3614 if (newnode) {
James Smart92795652006-07-06 15:50:02 -04003615 lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
dea31012005-04-17 16:05:31 -05003616 }
3617 break;
3618 }
3619
3620 /* check if need to LS_RJT received ELS cmd */
3621 if (rjt_err) {
3622 stat.un.b.lsRjtRsvd0 = 0;
3623 stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
James.Smart@Emulex.Com1f679ca2005-06-25 10:34:27 -04003624 stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE;
dea31012005-04-17 16:05:31 -05003625 stat.un.b.vendorUnique = 0;
3626 lpfc_els_rsp_reject(phba, stat.un.lsRjtError, elsiocb, ndlp);
3627 }
3628
3629 if (elsiocb->context2) {
3630 lpfc_mbuf_free(phba, mp->virt, mp->phys);
3631 kfree(mp);
3632 }
3633dropit:
3634 /* check if need to drop received ELS cmd */
3635 if (drop_cmd == 1) {
3636 lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
3637 "%d:0111 Dropping received ELS cmd "
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05003638 "Data: x%x x%x x%x\n", phba->brd_no,
3639 icmd->ulpStatus, icmd->un.ulpWord[4],
3640 icmd->ulpTimeout);
dea31012005-04-17 16:05:31 -05003641 phba->fc_stat.elsRcvDrop++;
3642 }
3643 return;
3644}