blob: cb63c350c2157024ea6dba1a772ba14aa02d3d13 [file] [log] [blame]
dea31012005-04-17 16:05:31 -05001/*******************************************************************
2 * This file is part of the Emulex Linux Device Driver for *
James.Smart@Emulex.Comc44ce172005-06-25 10:34:39 -04003 * Fibre Channel Host Bus Adapters. *
Jamie Wellnitz2fe165b2006-02-28 19:25:31 -05004 * Copyright (C) 2004-2006 Emulex. All rights reserved. *
James.Smart@Emulex.Comc44ce172005-06-25 10:34:39 -04005 * EMULEX and SLI are trademarks of Emulex. *
dea31012005-04-17 16:05:31 -05006 * www.emulex.com *
James.Smart@Emulex.Comc44ce172005-06-25 10:34:39 -04007 * Portions Copyright (C) 2004-2005 Christoph Hellwig *
dea31012005-04-17 16:05:31 -05008 * *
9 * This program is free software; you can redistribute it and/or *
James.Smart@Emulex.Comc44ce172005-06-25 10:34:39 -040010 * modify it under the terms of version 2 of the GNU General *
11 * Public License as published by the Free Software Foundation. *
12 * This program is distributed in the hope that it will be useful. *
13 * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND *
14 * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, *
15 * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE *
16 * DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD *
17 * TO BE LEGALLY INVALID. See the GNU General Public License for *
18 * more details, a copy of which can be found in the file COPYING *
19 * included with this package. *
dea31012005-04-17 16:05:31 -050020 *******************************************************************/
21
dea31012005-04-17 16:05:31 -050022#include <linux/blkdev.h>
23#include <linux/pci.h>
24#include <linux/interrupt.h>
25
James.Smart@Emulex.Com91886522005-08-10 15:03:09 -040026#include <scsi/scsi.h>
dea31012005-04-17 16:05:31 -050027#include <scsi/scsi_device.h>
28#include <scsi/scsi_host.h>
29#include <scsi/scsi_transport_fc.h>
30
31#include "lpfc_hw.h"
32#include "lpfc_sli.h"
33#include "lpfc_disc.h"
34#include "lpfc_scsi.h"
35#include "lpfc.h"
36#include "lpfc_logmsg.h"
37#include "lpfc_crtn.h"
38
39static int lpfc_els_retry(struct lpfc_hba *, struct lpfc_iocbq *,
40 struct lpfc_iocbq *);
41static int lpfc_max_els_tries = 3;
42
43static int
44lpfc_els_chk_latt(struct lpfc_hba * phba)
45{
46 struct lpfc_sli *psli;
47 LPFC_MBOXQ_t *mbox;
48 uint32_t ha_copy;
49 int rc;
50
51 psli = &phba->sli;
52
53 if ((phba->hba_state >= LPFC_HBA_READY) ||
54 (phba->hba_state == LPFC_LINK_DOWN))
55 return 0;
56
57 /* Read the HBA Host Attention Register */
58 spin_lock_irq(phba->host->host_lock);
59 ha_copy = readl(phba->HAregaddr);
60 spin_unlock_irq(phba->host->host_lock);
61
62 if (!(ha_copy & HA_LATT))
63 return 0;
64
65 /* Pending Link Event during Discovery */
66 lpfc_printf_log(phba, KERN_WARNING, LOG_DISCOVERY,
67 "%d:0237 Pending Link Event during "
68 "Discovery: State x%x\n",
69 phba->brd_no, phba->hba_state);
70
71 /* CLEAR_LA should re-enable link attention events and
72 * we should then imediately take a LATT event. The
73 * LATT processing should call lpfc_linkdown() which
74 * will cleanup any left over in-progress discovery
75 * events.
76 */
77 spin_lock_irq(phba->host->host_lock);
78 phba->fc_flag |= FC_ABORT_DISCOVERY;
79 spin_unlock_irq(phba->host->host_lock);
80
81 if (phba->hba_state != LPFC_CLEAR_LA) {
82 if ((mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL))) {
83 phba->hba_state = LPFC_CLEAR_LA;
84 lpfc_clear_la(phba, mbox);
85 mbox->mbox_cmpl = lpfc_mbx_cmpl_clear_la;
86 rc = lpfc_sli_issue_mbox (phba, mbox,
87 (MBX_NOWAIT | MBX_STOP_IOCB));
88 if (rc == MBX_NOT_FINISHED) {
89 mempool_free(mbox, phba->mbox_mem_pool);
90 phba->hba_state = LPFC_HBA_ERROR;
91 }
92 }
93 }
94
Jamie Wellnitzc9f87352006-02-28 19:25:23 -050095 return 1;
dea31012005-04-17 16:05:31 -050096
97}
98
99static struct lpfc_iocbq *
James Smart488d1462006-03-07 15:02:37 -0500100lpfc_prep_els_iocb(struct lpfc_hba * phba, uint8_t expectRsp,
101 uint16_t cmdSize, uint8_t retry, struct lpfc_nodelist * ndlp,
102 uint32_t did, uint32_t elscmd)
dea31012005-04-17 16:05:31 -0500103{
dea31012005-04-17 16:05:31 -0500104 struct lpfc_sli_ring *pring;
James.Smart@Emulex.Com0bd4ca22005-10-28 20:30:02 -0400105 struct lpfc_iocbq *elsiocb;
dea31012005-04-17 16:05:31 -0500106 struct lpfc_dmabuf *pcmd, *prsp, *pbuflist;
107 struct ulp_bde64 *bpl;
108 IOCB_t *icmd;
109
110 pring = &phba->sli.ring[LPFC_ELS_RING];
111
112 if (phba->hba_state < LPFC_LINK_UP)
113 return NULL;
114
dea31012005-04-17 16:05:31 -0500115 /* Allocate buffer for command iocb */
116 spin_lock_irq(phba->host->host_lock);
James.Smart@Emulex.Com0bd4ca22005-10-28 20:30:02 -0400117 elsiocb = lpfc_sli_get_iocbq(phba);
dea31012005-04-17 16:05:31 -0500118 spin_unlock_irq(phba->host->host_lock);
119
120 if (elsiocb == NULL)
121 return NULL;
dea31012005-04-17 16:05:31 -0500122 icmd = &elsiocb->iocb;
123
124 /* fill in BDEs for command */
125 /* Allocate buffer for command payload */
126 if (((pcmd = kmalloc(sizeof (struct lpfc_dmabuf), GFP_KERNEL)) == 0) ||
127 ((pcmd->virt = lpfc_mbuf_alloc(phba,
128 MEM_PRI, &(pcmd->phys))) == 0)) {
Jesper Juhlc9475cb2005-11-07 01:01:26 -0800129 kfree(pcmd);
dea31012005-04-17 16:05:31 -0500130
James Bottomley604a3e32005-10-29 10:28:33 -0500131 spin_lock_irq(phba->host->host_lock);
132 lpfc_sli_release_iocbq(phba, elsiocb);
133 spin_unlock_irq(phba->host->host_lock);
dea31012005-04-17 16:05:31 -0500134 return NULL;
135 }
136
137 INIT_LIST_HEAD(&pcmd->list);
138
139 /* Allocate buffer for response payload */
140 if (expectRsp) {
141 prsp = kmalloc(sizeof (struct lpfc_dmabuf), GFP_KERNEL);
142 if (prsp)
143 prsp->virt = lpfc_mbuf_alloc(phba, MEM_PRI,
144 &prsp->phys);
145 if (prsp == 0 || prsp->virt == 0) {
Jesper Juhlc9475cb2005-11-07 01:01:26 -0800146 kfree(prsp);
dea31012005-04-17 16:05:31 -0500147 lpfc_mbuf_free(phba, pcmd->virt, pcmd->phys);
148 kfree(pcmd);
James Bottomley604a3e32005-10-29 10:28:33 -0500149 spin_lock_irq(phba->host->host_lock);
150 lpfc_sli_release_iocbq(phba, elsiocb);
151 spin_unlock_irq(phba->host->host_lock);
dea31012005-04-17 16:05:31 -0500152 return NULL;
153 }
154 INIT_LIST_HEAD(&prsp->list);
155 } else {
156 prsp = NULL;
157 }
158
159 /* Allocate buffer for Buffer ptr list */
160 pbuflist = kmalloc(sizeof (struct lpfc_dmabuf), GFP_KERNEL);
161 if (pbuflist)
162 pbuflist->virt = lpfc_mbuf_alloc(phba, MEM_PRI,
163 &pbuflist->phys);
164 if (pbuflist == 0 || pbuflist->virt == 0) {
James Bottomley604a3e32005-10-29 10:28:33 -0500165 spin_lock_irq(phba->host->host_lock);
166 lpfc_sli_release_iocbq(phba, elsiocb);
167 spin_unlock_irq(phba->host->host_lock);
dea31012005-04-17 16:05:31 -0500168 lpfc_mbuf_free(phba, pcmd->virt, pcmd->phys);
169 lpfc_mbuf_free(phba, prsp->virt, prsp->phys);
170 kfree(pcmd);
171 kfree(prsp);
Jesper Juhlc9475cb2005-11-07 01:01:26 -0800172 kfree(pbuflist);
dea31012005-04-17 16:05:31 -0500173 return NULL;
174 }
175
176 INIT_LIST_HEAD(&pbuflist->list);
177
178 icmd->un.elsreq64.bdl.addrHigh = putPaddrHigh(pbuflist->phys);
179 icmd->un.elsreq64.bdl.addrLow = putPaddrLow(pbuflist->phys);
180 icmd->un.elsreq64.bdl.bdeFlags = BUFF_TYPE_BDL;
181 if (expectRsp) {
182 icmd->un.elsreq64.bdl.bdeSize = (2 * sizeof (struct ulp_bde64));
James Smart488d1462006-03-07 15:02:37 -0500183 icmd->un.elsreq64.remoteID = did; /* DID */
dea31012005-04-17 16:05:31 -0500184 icmd->ulpCommand = CMD_ELS_REQUEST64_CR;
James Smart2680eea2007-04-25 09:52:55 -0400185 icmd->ulpTimeout = phba->fc_ratov * 2;
dea31012005-04-17 16:05:31 -0500186 } else {
187 icmd->un.elsreq64.bdl.bdeSize = sizeof (struct ulp_bde64);
188 icmd->ulpCommand = CMD_XMIT_ELS_RSP64_CX;
189 }
190
191 icmd->ulpBdeCount = 1;
192 icmd->ulpLe = 1;
193 icmd->ulpClass = CLASS3;
194
195 bpl = (struct ulp_bde64 *) pbuflist->virt;
196 bpl->addrLow = le32_to_cpu(putPaddrLow(pcmd->phys));
197 bpl->addrHigh = le32_to_cpu(putPaddrHigh(pcmd->phys));
198 bpl->tus.f.bdeSize = cmdSize;
199 bpl->tus.f.bdeFlags = 0;
200 bpl->tus.w = le32_to_cpu(bpl->tus.w);
201
202 if (expectRsp) {
203 bpl++;
204 bpl->addrLow = le32_to_cpu(putPaddrLow(prsp->phys));
205 bpl->addrHigh = le32_to_cpu(putPaddrHigh(prsp->phys));
206 bpl->tus.f.bdeSize = FCELSSIZE;
207 bpl->tus.f.bdeFlags = BUFF_USE_RCV;
208 bpl->tus.w = le32_to_cpu(bpl->tus.w);
209 }
210
211 /* Save for completion so we can release these resources */
James Smart329f9bc2007-04-25 09:53:01 -0400212 elsiocb->context1 = lpfc_nlp_get(ndlp);
213 elsiocb->context2 = pcmd;
214 elsiocb->context3 = pbuflist;
dea31012005-04-17 16:05:31 -0500215 elsiocb->retry = retry;
216 elsiocb->drvrTimeout = (phba->fc_ratov << 1) + LPFC_DRVR_TIMEOUT;
217
218 if (prsp) {
219 list_add(&prsp->list, &pcmd->list);
220 }
221
222 if (expectRsp) {
223 /* Xmit ELS command <elsCmd> to remote NPORT <did> */
224 lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
225 "%d:0116 Xmit ELS command x%x to remote "
James Smart1dcb58e2007-04-25 09:51:30 -0400226 "NPORT x%x I/O tag: x%x, HBA state: x%x\n",
dea31012005-04-17 16:05:31 -0500227 phba->brd_no, elscmd,
James Smart1dcb58e2007-04-25 09:51:30 -0400228 did, elsiocb->iotag, phba->hba_state);
dea31012005-04-17 16:05:31 -0500229 } else {
230 /* Xmit ELS response <elsCmd> to remote NPORT <did> */
231 lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
232 "%d:0117 Xmit ELS response x%x to remote "
James Smart1dcb58e2007-04-25 09:51:30 -0400233 "NPORT x%x I/O tag: x%x, size: x%x\n",
dea31012005-04-17 16:05:31 -0500234 phba->brd_no, elscmd,
James Smart1dcb58e2007-04-25 09:51:30 -0400235 ndlp->nlp_DID, elsiocb->iotag, cmdSize);
dea31012005-04-17 16:05:31 -0500236 }
237
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500238 return elsiocb;
dea31012005-04-17 16:05:31 -0500239}
240
241
242static int
243lpfc_cmpl_els_flogi_fabric(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp,
244 struct serv_parm *sp, IOCB_t *irsp)
245{
246 LPFC_MBOXQ_t *mbox;
James Smart14691152006-12-02 13:34:28 -0500247 struct lpfc_dmabuf *mp;
dea31012005-04-17 16:05:31 -0500248 int rc;
249
250 spin_lock_irq(phba->host->host_lock);
251 phba->fc_flag |= FC_FABRIC;
252 spin_unlock_irq(phba->host->host_lock);
253
254 phba->fc_edtov = be32_to_cpu(sp->cmn.e_d_tov);
255 if (sp->cmn.edtovResolution) /* E_D_TOV ticks are in nanoseconds */
256 phba->fc_edtov = (phba->fc_edtov + 999999) / 1000000;
257
258 phba->fc_ratov = (be32_to_cpu(sp->cmn.w2.r_a_tov) + 999) / 1000;
259
260 if (phba->fc_topology == TOPOLOGY_LOOP) {
261 spin_lock_irq(phba->host->host_lock);
262 phba->fc_flag |= FC_PUBLIC_LOOP;
263 spin_unlock_irq(phba->host->host_lock);
264 } else {
265 /*
266 * If we are a N-port connected to a Fabric, fixup sparam's so
267 * logins to devices on remote loops work.
268 */
269 phba->fc_sparam.cmn.altBbCredit = 1;
270 }
271
272 phba->fc_myDID = irsp->un.ulpWord[4] & Mask_DID;
273 memcpy(&ndlp->nlp_portname, &sp->portName, sizeof(struct lpfc_name));
274 memcpy(&ndlp->nlp_nodename, &sp->nodeName, sizeof (struct lpfc_name));
275 ndlp->nlp_class_sup = 0;
276 if (sp->cls1.classValid)
277 ndlp->nlp_class_sup |= FC_COS_CLASS1;
278 if (sp->cls2.classValid)
279 ndlp->nlp_class_sup |= FC_COS_CLASS2;
280 if (sp->cls3.classValid)
281 ndlp->nlp_class_sup |= FC_COS_CLASS3;
282 if (sp->cls4.classValid)
283 ndlp->nlp_class_sup |= FC_COS_CLASS4;
284 ndlp->nlp_maxframe = ((sp->cmn.bbRcvSizeMsb & 0x0F) << 8) |
285 sp->cmn.bbRcvSizeLsb;
286 memcpy(&phba->fc_fabparam, sp, sizeof(struct serv_parm));
287
288 mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
289 if (!mbox)
290 goto fail;
291
292 phba->hba_state = LPFC_FABRIC_CFG_LINK;
293 lpfc_config_link(phba, mbox);
294 mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
295
296 rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT | MBX_STOP_IOCB);
297 if (rc == MBX_NOT_FINISHED)
298 goto fail_free_mbox;
299
300 mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
301 if (!mbox)
302 goto fail;
303
304 if (lpfc_reg_login(phba, Fabric_DID, (uint8_t *) sp, mbox, 0))
305 goto fail_free_mbox;
306
dea31012005-04-17 16:05:31 -0500307 mbox->mbox_cmpl = lpfc_mbx_cmpl_fabric_reg_login;
James Smart329f9bc2007-04-25 09:53:01 -0400308 mbox->context2 = lpfc_nlp_get(ndlp);
dea31012005-04-17 16:05:31 -0500309
310 rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT | MBX_STOP_IOCB);
311 if (rc == MBX_NOT_FINISHED)
James Smart14691152006-12-02 13:34:28 -0500312 goto fail_issue_reg_login;
dea31012005-04-17 16:05:31 -0500313
314 return 0;
315
James Smart14691152006-12-02 13:34:28 -0500316 fail_issue_reg_login:
James Smart329f9bc2007-04-25 09:53:01 -0400317 lpfc_nlp_put(ndlp);
James Smart14691152006-12-02 13:34:28 -0500318 mp = (struct lpfc_dmabuf *) mbox->context1;
319 lpfc_mbuf_free(phba, mp->virt, mp->phys);
320 kfree(mp);
dea31012005-04-17 16:05:31 -0500321 fail_free_mbox:
322 mempool_free(mbox, phba->mbox_mem_pool);
323 fail:
324 return -ENXIO;
325}
326
327/*
328 * We FLOGIed into an NPort, initiate pt2pt protocol
329 */
330static int
331lpfc_cmpl_els_flogi_nport(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp,
332 struct serv_parm *sp)
333{
334 LPFC_MBOXQ_t *mbox;
335 int rc;
336
337 spin_lock_irq(phba->host->host_lock);
338 phba->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP);
339 spin_unlock_irq(phba->host->host_lock);
340
341 phba->fc_edtov = FF_DEF_EDTOV;
342 phba->fc_ratov = FF_DEF_RATOV;
343 rc = memcmp(&phba->fc_portname, &sp->portName,
344 sizeof(struct lpfc_name));
345 if (rc >= 0) {
346 /* This side will initiate the PLOGI */
347 spin_lock_irq(phba->host->host_lock);
348 phba->fc_flag |= FC_PT2PT_PLOGI;
349 spin_unlock_irq(phba->host->host_lock);
350
351 /*
352 * N_Port ID cannot be 0, set our to LocalID the other
353 * side will be RemoteID.
354 */
355
356 /* not equal */
357 if (rc)
358 phba->fc_myDID = PT2PT_LocalID;
359
360 mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
361 if (!mbox)
362 goto fail;
363
364 lpfc_config_link(phba, mbox);
365
366 mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
367 rc = lpfc_sli_issue_mbox(phba, mbox,
368 MBX_NOWAIT | MBX_STOP_IOCB);
369 if (rc == MBX_NOT_FINISHED) {
370 mempool_free(mbox, phba->mbox_mem_pool);
371 goto fail;
372 }
James Smart329f9bc2007-04-25 09:53:01 -0400373 lpfc_nlp_put(ndlp);
dea31012005-04-17 16:05:31 -0500374
375 ndlp = lpfc_findnode_did(phba, NLP_SEARCH_ALL, PT2PT_RemoteID);
376 if (!ndlp) {
377 /*
378 * Cannot find existing Fabric ndlp, so allocate a
379 * new one
380 */
381 ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL);
382 if (!ndlp)
383 goto fail;
384
385 lpfc_nlp_init(phba, ndlp, PT2PT_RemoteID);
386 }
387
388 memcpy(&ndlp->nlp_portname, &sp->portName,
389 sizeof(struct lpfc_name));
390 memcpy(&ndlp->nlp_nodename, &sp->nodeName,
391 sizeof(struct lpfc_name));
James Smartde0c5b32007-04-25 09:52:27 -0400392 lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
dea31012005-04-17 16:05:31 -0500393 ndlp->nlp_flag |= NLP_NPR_2B_DISC;
394 } else {
395 /* This side will wait for the PLOGI */
James Smart329f9bc2007-04-25 09:53:01 -0400396 lpfc_nlp_put(ndlp);
dea31012005-04-17 16:05:31 -0500397 }
398
399 spin_lock_irq(phba->host->host_lock);
400 phba->fc_flag |= FC_PT2PT;
401 spin_unlock_irq(phba->host->host_lock);
402
403 /* Start discovery - this should just do CLEAR_LA */
404 lpfc_disc_start(phba);
405 return 0;
406 fail:
407 return -ENXIO;
408}
409
410static void
James Smart329f9bc2007-04-25 09:53:01 -0400411lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
412 struct lpfc_iocbq *rspiocb)
dea31012005-04-17 16:05:31 -0500413{
414 IOCB_t *irsp = &rspiocb->iocb;
415 struct lpfc_nodelist *ndlp = cmdiocb->context1;
416 struct lpfc_dmabuf *pcmd = cmdiocb->context2, *prsp;
417 struct serv_parm *sp;
418 int rc;
419
420 /* Check to see if link went down during discovery */
421 if (lpfc_els_chk_latt(phba)) {
James Smart329f9bc2007-04-25 09:53:01 -0400422 lpfc_nlp_put(ndlp);
dea31012005-04-17 16:05:31 -0500423 goto out;
424 }
425
426 if (irsp->ulpStatus) {
427 /* Check for retry */
428 if (lpfc_els_retry(phba, cmdiocb, rspiocb)) {
429 /* ELS command is being retried */
430 goto out;
431 }
432 /* FLOGI failed, so there is no fabric */
433 spin_lock_irq(phba->host->host_lock);
434 phba->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP);
435 spin_unlock_irq(phba->host->host_lock);
436
James Smart329f9bc2007-04-25 09:53:01 -0400437 /* If private loop, then allow max outstanding els to be
dea31012005-04-17 16:05:31 -0500438 * LPFC_MAX_DISC_THREADS (32). Scanning in the case of no
439 * alpa map would take too long otherwise.
440 */
441 if (phba->alpa_map[0] == 0) {
James Smart329f9bc2007-04-25 09:53:01 -0400442 phba->cfg_discovery_threads = LPFC_MAX_DISC_THREADS;
dea31012005-04-17 16:05:31 -0500443 }
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:
James Smart329f9bc2007-04-25 09:53:01 -0400487 lpfc_nlp_put(ndlp);
dea31012005-04-17 16:05:31 -0500488
489 if (irsp->ulpStatus != IOSTAT_LOCAL_REJECT ||
490 (irsp->un.ulpWord[4] != IOERR_SLI_ABORTED &&
491 irsp->un.ulpWord[4] != IOERR_SLI_DOWN)) {
492 /* FLOGI failed, so just use loop map to make discovery list */
493 lpfc_disc_list_loopmap(phba);
494
495 /* Start discovery */
496 lpfc_disc_start(phba);
497 }
498
499out:
500 lpfc_els_free_iocb(phba, cmdiocb);
501}
502
503static int
504lpfc_issue_els_flogi(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp,
505 uint8_t retry)
506{
507 struct serv_parm *sp;
508 IOCB_t *icmd;
509 struct lpfc_iocbq *elsiocb;
510 struct lpfc_sli_ring *pring;
511 uint8_t *pcmd;
512 uint16_t cmdsize;
513 uint32_t tmo;
514 int rc;
515
516 pring = &phba->sli.ring[LPFC_ELS_RING];
517
518 cmdsize = (sizeof (uint32_t) + sizeof (struct serv_parm));
James Smart488d1462006-03-07 15:02:37 -0500519 elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry, ndlp,
520 ndlp->nlp_DID, ELS_CMD_FLOGI);
521 if (!elsiocb)
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500522 return 1;
dea31012005-04-17 16:05:31 -0500523
524 icmd = &elsiocb->iocb;
525 pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
526
527 /* For FLOGI request, remainder of payload is service parameters */
528 *((uint32_t *) (pcmd)) = ELS_CMD_FLOGI;
529 pcmd += sizeof (uint32_t);
530 memcpy(pcmd, &phba->fc_sparam, sizeof (struct serv_parm));
531 sp = (struct serv_parm *) pcmd;
532
533 /* Setup CSPs accordingly for Fabric */
534 sp->cmn.e_d_tov = 0;
535 sp->cmn.w2.r_a_tov = 0;
536 sp->cls1.classValid = 0;
537 sp->cls2.seqDelivery = 1;
538 sp->cls3.seqDelivery = 1;
539 if (sp->cmn.fcphLow < FC_PH3)
540 sp->cmn.fcphLow = FC_PH3;
541 if (sp->cmn.fcphHigh < FC_PH3)
542 sp->cmn.fcphHigh = FC_PH3;
543
544 tmo = phba->fc_ratov;
545 phba->fc_ratov = LPFC_DISC_FLOGI_TMO;
546 lpfc_set_disctmo(phba);
547 phba->fc_ratov = tmo;
548
549 phba->fc_stat.elsXmitFLOGI++;
550 elsiocb->iocb_cmpl = lpfc_cmpl_els_flogi;
551 spin_lock_irq(phba->host->host_lock);
552 rc = lpfc_sli_issue_iocb(phba, pring, elsiocb, 0);
553 spin_unlock_irq(phba->host->host_lock);
554 if (rc == IOCB_ERROR) {
555 lpfc_els_free_iocb(phba, elsiocb);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500556 return 1;
dea31012005-04-17 16:05:31 -0500557 }
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500558 return 0;
dea31012005-04-17 16:05:31 -0500559}
560
561int
562lpfc_els_abort_flogi(struct lpfc_hba * phba)
563{
564 struct lpfc_sli_ring *pring;
565 struct lpfc_iocbq *iocb, *next_iocb;
566 struct lpfc_nodelist *ndlp;
567 IOCB_t *icmd;
568
569 /* Abort outstanding I/O on NPort <nlp_DID> */
570 lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
571 "%d:0201 Abort outstanding I/O on NPort x%x\n",
572 phba->brd_no, Fabric_DID);
573
574 pring = &phba->sli.ring[LPFC_ELS_RING];
575
576 /*
577 * Check the txcmplq for an iocb that matches the nport the driver is
578 * searching for.
579 */
580 spin_lock_irq(phba->host->host_lock);
581 list_for_each_entry_safe(iocb, next_iocb, &pring->txcmplq, list) {
582 icmd = &iocb->iocb;
583 if (icmd->ulpCommand == CMD_ELS_REQUEST64_CR) {
584 ndlp = (struct lpfc_nodelist *)(iocb->context1);
James Smart07951072007-04-25 09:51:38 -0400585 if (ndlp && (ndlp->nlp_DID == Fabric_DID))
586 lpfc_sli_issue_abort_iotag(phba, pring, iocb);
dea31012005-04-17 16:05:31 -0500587 }
588 }
589 spin_unlock_irq(phba->host->host_lock);
590
591 return 0;
592}
593
594int
595lpfc_initial_flogi(struct lpfc_hba * phba)
596{
597 struct lpfc_nodelist *ndlp;
598
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500599 /* First look for the Fabric ndlp */
600 ndlp = lpfc_findnode_did(phba, NLP_SEARCH_ALL, Fabric_DID);
601 if (!ndlp) {
dea31012005-04-17 16:05:31 -0500602 /* Cannot find existing Fabric ndlp, so allocate a new one */
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500603 ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL);
604 if (!ndlp)
605 return 0;
dea31012005-04-17 16:05:31 -0500606 lpfc_nlp_init(phba, ndlp, Fabric_DID);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500607 } else {
James Smartde0c5b32007-04-25 09:52:27 -0400608 lpfc_dequeue_node(phba, ndlp);
dea31012005-04-17 16:05:31 -0500609 }
610 if (lpfc_issue_els_flogi(phba, ndlp, 0)) {
James Smart329f9bc2007-04-25 09:53:01 -0400611 lpfc_nlp_put(ndlp);
dea31012005-04-17 16:05:31 -0500612 }
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500613 return 1;
dea31012005-04-17 16:05:31 -0500614}
615
616static void
617lpfc_more_plogi(struct lpfc_hba * phba)
618{
619 int sentplogi;
620
621 if (phba->num_disc_nodes)
622 phba->num_disc_nodes--;
623
624 /* Continue discovery with <num_disc_nodes> PLOGIs to go */
625 lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
626 "%d:0232 Continue discovery with %d PLOGIs to go "
627 "Data: x%x x%x x%x\n",
628 phba->brd_no, phba->num_disc_nodes, phba->fc_plogi_cnt,
629 phba->fc_flag, phba->hba_state);
630
631 /* Check to see if there are more PLOGIs to be sent */
632 if (phba->fc_flag & FC_NLP_MORE) {
633 /* go thru NPR list and issue any remaining ELS PLOGIs */
634 sentplogi = lpfc_els_disc_plogi(phba);
635 }
636 return;
637}
638
James Smart488d1462006-03-07 15:02:37 -0500639static struct lpfc_nodelist *
James Smart92795652006-07-06 15:50:02 -0400640lpfc_plogi_confirm_nport(struct lpfc_hba * phba, struct lpfc_dmabuf *prsp,
James Smart488d1462006-03-07 15:02:37 -0500641 struct lpfc_nodelist *ndlp)
642{
643 struct lpfc_nodelist *new_ndlp;
James Smart488d1462006-03-07 15:02:37 -0500644 uint32_t *lp;
645 struct serv_parm *sp;
646 uint8_t name[sizeof (struct lpfc_name)];
647 uint32_t rc;
648
James Smart2fb9bd82006-12-02 13:33:57 -0500649 /* Fabric nodes can have the same WWPN so we don't bother searching
650 * by WWPN. Just return the ndlp that was given to us.
651 */
652 if (ndlp->nlp_type & NLP_FABRIC)
653 return ndlp;
654
James Smart488d1462006-03-07 15:02:37 -0500655 lp = (uint32_t *) prsp->virt;
656 sp = (struct serv_parm *) ((uint8_t *) lp + sizeof (uint32_t));
James Smart92795652006-07-06 15:50:02 -0400657 memset(name, 0, sizeof (struct lpfc_name));
James Smart488d1462006-03-07 15:02:37 -0500658
659 /* Now we to find out if the NPort we are logging into, matches the WWPN
660 * we have for that ndlp. If not, we have some work to do.
661 */
662 new_ndlp = lpfc_findnode_wwpn(phba, NLP_SEARCH_ALL, &sp->portName);
663
James Smart92795652006-07-06 15:50:02 -0400664 if (new_ndlp == ndlp)
James Smart488d1462006-03-07 15:02:37 -0500665 return ndlp;
James Smart488d1462006-03-07 15:02:37 -0500666
667 if (!new_ndlp) {
James Smart92795652006-07-06 15:50:02 -0400668 rc =
669 memcmp(&ndlp->nlp_portname, name, sizeof(struct lpfc_name));
670 if (!rc)
671 return ndlp;
James Smart488d1462006-03-07 15:02:37 -0500672 new_ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_ATOMIC);
673 if (!new_ndlp)
674 return ndlp;
675
676 lpfc_nlp_init(phba, new_ndlp, ndlp->nlp_DID);
677 }
678
679 lpfc_unreg_rpi(phba, new_ndlp);
James Smart488d1462006-03-07 15:02:37 -0500680 new_ndlp->nlp_DID = ndlp->nlp_DID;
James Smart92795652006-07-06 15:50:02 -0400681 new_ndlp->nlp_prev_state = ndlp->nlp_prev_state;
James Smartde0c5b32007-04-25 09:52:27 -0400682 lpfc_nlp_set_state(phba, new_ndlp, ndlp->nlp_state);
James Smart488d1462006-03-07 15:02:37 -0500683
684 /* Move this back to NPR list */
James Smartde0c5b32007-04-25 09:52:27 -0400685 if (memcmp(&ndlp->nlp_portname, name, sizeof(struct lpfc_name)) == 0)
686 lpfc_drop_node(phba, ndlp);
James Smart92795652006-07-06 15:50:02 -0400687 else {
688 lpfc_unreg_rpi(phba, ndlp);
689 ndlp->nlp_DID = 0; /* Two ndlps cannot have the same did */
James Smartde0c5b32007-04-25 09:52:27 -0400690 lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
James Smart92795652006-07-06 15:50:02 -0400691 }
James Smart488d1462006-03-07 15:02:37 -0500692 return new_ndlp;
693}
694
dea31012005-04-17 16:05:31 -0500695static void
696lpfc_cmpl_els_plogi(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
697 struct lpfc_iocbq * rspiocb)
698{
699 IOCB_t *irsp;
dea31012005-04-17 16:05:31 -0500700 struct lpfc_nodelist *ndlp;
James Smart92795652006-07-06 15:50:02 -0400701 struct lpfc_dmabuf *prsp;
dea31012005-04-17 16:05:31 -0500702 int disc, rc, did, type;
703
dea31012005-04-17 16:05:31 -0500704 /* we pass cmdiocb to state machine which needs rspiocb as well */
705 cmdiocb->context_un.rsp_iocb = rspiocb;
706
707 irsp = &rspiocb->iocb;
James Smart488d1462006-03-07 15:02:37 -0500708 ndlp = lpfc_findnode_did(phba, NLP_SEARCH_ALL,
709 irsp->un.elsreq64.remoteID);
710 if (!ndlp)
711 goto out;
dea31012005-04-17 16:05:31 -0500712
713 /* Since ndlp can be freed in the disc state machine, note if this node
714 * is being used during discovery.
715 */
716 disc = (ndlp->nlp_flag & NLP_NPR_2B_DISC);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500717 spin_lock_irq(phba->host->host_lock);
James Smart488d1462006-03-07 15:02:37 -0500718 ndlp->nlp_flag &= ~NLP_NPR_2B_DISC;
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500719 spin_unlock_irq(phba->host->host_lock);
dea31012005-04-17 16:05:31 -0500720 rc = 0;
721
722 /* PLOGI completes to NPort <nlp_DID> */
723 lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
724 "%d:0102 PLOGI completes to NPort x%x "
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500725 "Data: x%x x%x x%x x%x x%x\n",
dea31012005-04-17 16:05:31 -0500726 phba->brd_no, ndlp->nlp_DID, irsp->ulpStatus,
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500727 irsp->un.ulpWord[4], irsp->ulpTimeout, disc,
728 phba->num_disc_nodes);
dea31012005-04-17 16:05:31 -0500729
730 /* Check to see if link went down during discovery */
731 if (lpfc_els_chk_latt(phba)) {
732 spin_lock_irq(phba->host->host_lock);
733 ndlp->nlp_flag |= NLP_NPR_2B_DISC;
734 spin_unlock_irq(phba->host->host_lock);
735 goto out;
736 }
737
738 /* ndlp could be freed in DSM, save these values now */
739 type = ndlp->nlp_type;
740 did = ndlp->nlp_DID;
741
742 if (irsp->ulpStatus) {
743 /* Check for retry */
744 if (lpfc_els_retry(phba, cmdiocb, rspiocb)) {
745 /* ELS command is being retried */
746 if (disc) {
747 spin_lock_irq(phba->host->host_lock);
748 ndlp->nlp_flag |= NLP_NPR_2B_DISC;
749 spin_unlock_irq(phba->host->host_lock);
750 }
751 goto out;
752 }
753
754 /* PLOGI failed */
755 /* Do not call DSM for lpfc_els_abort'ed ELS cmds */
756 if ((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) &&
757 ((irsp->un.ulpWord[4] == IOERR_SLI_ABORTED) ||
James.Smart@Emulex.Com6281bfe2005-11-28 11:41:33 -0500758 (irsp->un.ulpWord[4] == IOERR_LINK_DOWN) ||
dea31012005-04-17 16:05:31 -0500759 (irsp->un.ulpWord[4] == IOERR_SLI_DOWN))) {
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500760 rc = NLP_STE_FREED_NODE;
Jamie Wellnitz2fe165b2006-02-28 19:25:31 -0500761 } else {
dea31012005-04-17 16:05:31 -0500762 rc = lpfc_disc_state_machine(phba, ndlp, cmdiocb,
763 NLP_EVT_CMPL_PLOGI);
764 }
765 } else {
766 /* Good status, call state machine */
James Smart92795652006-07-06 15:50:02 -0400767 prsp = list_entry(((struct lpfc_dmabuf *)
768 cmdiocb->context2)->list.next,
769 struct lpfc_dmabuf, list);
770 ndlp = lpfc_plogi_confirm_nport(phba, prsp, ndlp);
dea31012005-04-17 16:05:31 -0500771 rc = lpfc_disc_state_machine(phba, ndlp, cmdiocb,
772 NLP_EVT_CMPL_PLOGI);
773 }
774
dea31012005-04-17 16:05:31 -0500775 if (disc && phba->num_disc_nodes) {
776 /* Check to see if there are more PLOGIs to be sent */
777 lpfc_more_plogi(phba);
dea31012005-04-17 16:05:31 -0500778
James Smart10d4e952006-04-15 11:53:15 -0400779 if (phba->num_disc_nodes == 0) {
780 spin_lock_irq(phba->host->host_lock);
781 phba->fc_flag &= ~FC_NDISC_ACTIVE;
782 spin_unlock_irq(phba->host->host_lock);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500783
James Smart10d4e952006-04-15 11:53:15 -0400784 lpfc_can_disctmo(phba);
785 if (phba->fc_flag & FC_RSCN_MODE) {
786 /*
787 * Check to see if more RSCNs came in while
788 * we were processing this one.
789 */
790 if ((phba->fc_rscn_id_cnt == 0) &&
791 (!(phba->fc_flag & FC_RSCN_DISCOVERY))) {
792 spin_lock_irq(phba->host->host_lock);
793 phba->fc_flag &= ~FC_RSCN_MODE;
794 spin_unlock_irq(phba->host->host_lock);
795 } else {
796 lpfc_els_handle_rscn(phba);
797 }
dea31012005-04-17 16:05:31 -0500798 }
799 }
800 }
801
802out:
803 lpfc_els_free_iocb(phba, cmdiocb);
804 return;
805}
806
807int
James Smart488d1462006-03-07 15:02:37 -0500808lpfc_issue_els_plogi(struct lpfc_hba * phba, uint32_t did, uint8_t retry)
dea31012005-04-17 16:05:31 -0500809{
810 struct serv_parm *sp;
811 IOCB_t *icmd;
812 struct lpfc_iocbq *elsiocb;
813 struct lpfc_sli_ring *pring;
814 struct lpfc_sli *psli;
815 uint8_t *pcmd;
816 uint16_t cmdsize;
817
818 psli = &phba->sli;
819 pring = &psli->ring[LPFC_ELS_RING]; /* ELS ring */
820
821 cmdsize = (sizeof (uint32_t) + sizeof (struct serv_parm));
Randy Dunlap041976f2006-06-25 01:58:51 -0700822 elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry, NULL, did,
Jamie Wellnitz2fe165b2006-02-28 19:25:31 -0500823 ELS_CMD_PLOGI);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500824 if (!elsiocb)
825 return 1;
dea31012005-04-17 16:05:31 -0500826
827 icmd = &elsiocb->iocb;
828 pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
829
830 /* For PLOGI request, remainder of payload is service parameters */
831 *((uint32_t *) (pcmd)) = ELS_CMD_PLOGI;
832 pcmd += sizeof (uint32_t);
833 memcpy(pcmd, &phba->fc_sparam, sizeof (struct serv_parm));
834 sp = (struct serv_parm *) pcmd;
835
836 if (sp->cmn.fcphLow < FC_PH_4_3)
837 sp->cmn.fcphLow = FC_PH_4_3;
838
839 if (sp->cmn.fcphHigh < FC_PH3)
840 sp->cmn.fcphHigh = FC_PH3;
841
842 phba->fc_stat.elsXmitPLOGI++;
843 elsiocb->iocb_cmpl = lpfc_cmpl_els_plogi;
844 spin_lock_irq(phba->host->host_lock);
dea31012005-04-17 16:05:31 -0500845 if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) {
dea31012005-04-17 16:05:31 -0500846 spin_unlock_irq(phba->host->host_lock);
847 lpfc_els_free_iocb(phba, elsiocb);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500848 return 1;
dea31012005-04-17 16:05:31 -0500849 }
850 spin_unlock_irq(phba->host->host_lock);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500851 return 0;
dea31012005-04-17 16:05:31 -0500852}
853
854static void
855lpfc_cmpl_els_prli(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
856 struct lpfc_iocbq * rspiocb)
857{
858 IOCB_t *irsp;
859 struct lpfc_sli *psli;
860 struct lpfc_nodelist *ndlp;
861
862 psli = &phba->sli;
863 /* we pass cmdiocb to state machine which needs rspiocb as well */
864 cmdiocb->context_un.rsp_iocb = rspiocb;
865
866 irsp = &(rspiocb->iocb);
867 ndlp = (struct lpfc_nodelist *) cmdiocb->context1;
868 spin_lock_irq(phba->host->host_lock);
869 ndlp->nlp_flag &= ~NLP_PRLI_SND;
870 spin_unlock_irq(phba->host->host_lock);
871
872 /* PRLI completes to NPort <nlp_DID> */
873 lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
874 "%d:0103 PRLI completes to NPort x%x "
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500875 "Data: x%x x%x x%x x%x\n",
dea31012005-04-17 16:05:31 -0500876 phba->brd_no, ndlp->nlp_DID, irsp->ulpStatus,
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500877 irsp->un.ulpWord[4], irsp->ulpTimeout,
878 phba->num_disc_nodes);
dea31012005-04-17 16:05:31 -0500879
880 phba->fc_prli_sent--;
881 /* Check to see if link went down during discovery */
882 if (lpfc_els_chk_latt(phba))
883 goto out;
884
885 if (irsp->ulpStatus) {
886 /* Check for retry */
887 if (lpfc_els_retry(phba, cmdiocb, rspiocb)) {
888 /* ELS command is being retried */
889 goto out;
890 }
891 /* PRLI failed */
892 /* Do not call DSM for lpfc_els_abort'ed ELS cmds */
893 if ((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) &&
894 ((irsp->un.ulpWord[4] == IOERR_SLI_ABORTED) ||
James.Smart@Emulex.Com6281bfe2005-11-28 11:41:33 -0500895 (irsp->un.ulpWord[4] == IOERR_LINK_DOWN) ||
dea31012005-04-17 16:05:31 -0500896 (irsp->un.ulpWord[4] == IOERR_SLI_DOWN))) {
897 goto out;
Jamie Wellnitz2fe165b2006-02-28 19:25:31 -0500898 } else {
dea31012005-04-17 16:05:31 -0500899 lpfc_disc_state_machine(phba, ndlp, cmdiocb,
900 NLP_EVT_CMPL_PRLI);
901 }
902 } else {
903 /* Good status, call state machine */
904 lpfc_disc_state_machine(phba, ndlp, cmdiocb, NLP_EVT_CMPL_PRLI);
905 }
906
907out:
908 lpfc_els_free_iocb(phba, cmdiocb);
909 return;
910}
911
912int
913lpfc_issue_els_prli(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp,
914 uint8_t retry)
915{
916 PRLI *npr;
917 IOCB_t *icmd;
918 struct lpfc_iocbq *elsiocb;
919 struct lpfc_sli_ring *pring;
920 struct lpfc_sli *psli;
921 uint8_t *pcmd;
922 uint16_t cmdsize;
923
924 psli = &phba->sli;
925 pring = &psli->ring[LPFC_ELS_RING]; /* ELS ring */
926
927 cmdsize = (sizeof (uint32_t) + sizeof (PRLI));
James Smart488d1462006-03-07 15:02:37 -0500928 elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry, ndlp,
929 ndlp->nlp_DID, ELS_CMD_PRLI);
930 if (!elsiocb)
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500931 return 1;
dea31012005-04-17 16:05:31 -0500932
933 icmd = &elsiocb->iocb;
934 pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
935
936 /* For PRLI request, remainder of payload is service parameters */
937 memset(pcmd, 0, (sizeof (PRLI) + sizeof (uint32_t)));
938 *((uint32_t *) (pcmd)) = ELS_CMD_PRLI;
939 pcmd += sizeof (uint32_t);
940
941 /* For PRLI, remainder of payload is PRLI parameter page */
942 npr = (PRLI *) pcmd;
943 /*
944 * If our firmware version is 3.20 or later,
945 * set the following bits for FC-TAPE support.
946 */
947 if (phba->vpd.rev.feaLevelHigh >= 0x02) {
948 npr->ConfmComplAllowed = 1;
949 npr->Retry = 1;
950 npr->TaskRetryIdReq = 1;
951 }
952 npr->estabImagePair = 1;
953 npr->readXferRdyDis = 1;
954
955 /* For FCP support */
956 npr->prliType = PRLI_FCP_TYPE;
957 npr->initiatorFunc = 1;
958
959 phba->fc_stat.elsXmitPRLI++;
960 elsiocb->iocb_cmpl = lpfc_cmpl_els_prli;
961 spin_lock_irq(phba->host->host_lock);
962 ndlp->nlp_flag |= NLP_PRLI_SND;
963 if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) {
964 ndlp->nlp_flag &= ~NLP_PRLI_SND;
965 spin_unlock_irq(phba->host->host_lock);
966 lpfc_els_free_iocb(phba, elsiocb);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500967 return 1;
dea31012005-04-17 16:05:31 -0500968 }
969 spin_unlock_irq(phba->host->host_lock);
970 phba->fc_prli_sent++;
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500971 return 0;
dea31012005-04-17 16:05:31 -0500972}
973
974static void
975lpfc_more_adisc(struct lpfc_hba * phba)
976{
977 int sentadisc;
978
979 if (phba->num_disc_nodes)
980 phba->num_disc_nodes--;
981
982 /* Continue discovery with <num_disc_nodes> ADISCs to go */
983 lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
984 "%d:0210 Continue discovery with %d ADISCs to go "
985 "Data: x%x x%x x%x\n",
986 phba->brd_no, phba->num_disc_nodes, phba->fc_adisc_cnt,
987 phba->fc_flag, phba->hba_state);
988
989 /* Check to see if there are more ADISCs to be sent */
990 if (phba->fc_flag & FC_NLP_MORE) {
991 lpfc_set_disctmo(phba);
992
993 /* go thru NPR list and issue any remaining ELS ADISCs */
994 sentadisc = lpfc_els_disc_adisc(phba);
995 }
996 return;
997}
998
999static void
1000lpfc_rscn_disc(struct lpfc_hba * phba)
1001{
1002 /* RSCN discovery */
1003 /* go thru NPR list and issue ELS PLOGIs */
1004 if (phba->fc_npr_cnt) {
1005 if (lpfc_els_disc_plogi(phba))
1006 return;
1007 }
1008 if (phba->fc_flag & FC_RSCN_MODE) {
1009 /* Check to see if more RSCNs came in while we were
1010 * processing this one.
1011 */
1012 if ((phba->fc_rscn_id_cnt == 0) &&
1013 (!(phba->fc_flag & FC_RSCN_DISCOVERY))) {
1014 spin_lock_irq(phba->host->host_lock);
1015 phba->fc_flag &= ~FC_RSCN_MODE;
1016 spin_unlock_irq(phba->host->host_lock);
1017 } else {
1018 lpfc_els_handle_rscn(phba);
1019 }
1020 }
1021}
1022
1023static void
1024lpfc_cmpl_els_adisc(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
1025 struct lpfc_iocbq * rspiocb)
1026{
1027 IOCB_t *irsp;
1028 struct lpfc_sli *psli;
1029 struct lpfc_nodelist *ndlp;
1030 LPFC_MBOXQ_t *mbox;
1031 int disc, rc;
1032
1033 psli = &phba->sli;
1034
1035 /* we pass cmdiocb to state machine which needs rspiocb as well */
1036 cmdiocb->context_un.rsp_iocb = rspiocb;
1037
1038 irsp = &(rspiocb->iocb);
1039 ndlp = (struct lpfc_nodelist *) cmdiocb->context1;
dea31012005-04-17 16:05:31 -05001040
1041 /* Since ndlp can be freed in the disc state machine, note if this node
1042 * is being used during discovery.
1043 */
1044 disc = (ndlp->nlp_flag & NLP_NPR_2B_DISC);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001045 spin_lock_irq(phba->host->host_lock);
1046 ndlp->nlp_flag &= ~(NLP_ADISC_SND | NLP_NPR_2B_DISC);
1047 spin_unlock_irq(phba->host->host_lock);
dea31012005-04-17 16:05:31 -05001048
1049 /* ADISC completes to NPort <nlp_DID> */
1050 lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
1051 "%d:0104 ADISC completes to NPort x%x "
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001052 "Data: x%x x%x x%x x%x x%x\n",
dea31012005-04-17 16:05:31 -05001053 phba->brd_no, ndlp->nlp_DID, irsp->ulpStatus,
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001054 irsp->un.ulpWord[4], irsp->ulpTimeout, disc,
1055 phba->num_disc_nodes);
dea31012005-04-17 16:05:31 -05001056
1057 /* Check to see if link went down during discovery */
1058 if (lpfc_els_chk_latt(phba)) {
1059 spin_lock_irq(phba->host->host_lock);
1060 ndlp->nlp_flag |= NLP_NPR_2B_DISC;
1061 spin_unlock_irq(phba->host->host_lock);
1062 goto out;
1063 }
1064
1065 if (irsp->ulpStatus) {
1066 /* Check for retry */
1067 if (lpfc_els_retry(phba, cmdiocb, rspiocb)) {
1068 /* ELS command is being retried */
1069 if (disc) {
1070 spin_lock_irq(phba->host->host_lock);
1071 ndlp->nlp_flag |= NLP_NPR_2B_DISC;
1072 spin_unlock_irq(phba->host->host_lock);
1073 lpfc_set_disctmo(phba);
1074 }
1075 goto out;
1076 }
1077 /* ADISC failed */
1078 /* Do not call DSM for lpfc_els_abort'ed ELS cmds */
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001079 if ((irsp->ulpStatus != IOSTAT_LOCAL_REJECT) ||
1080 ((irsp->un.ulpWord[4] != IOERR_SLI_ABORTED) &&
1081 (irsp->un.ulpWord[4] != IOERR_LINK_DOWN) &&
1082 (irsp->un.ulpWord[4] != IOERR_SLI_DOWN))) {
dea31012005-04-17 16:05:31 -05001083 lpfc_disc_state_machine(phba, ndlp, cmdiocb,
1084 NLP_EVT_CMPL_ADISC);
1085 }
1086 } else {
1087 /* Good status, call state machine */
1088 lpfc_disc_state_machine(phba, ndlp, cmdiocb,
1089 NLP_EVT_CMPL_ADISC);
1090 }
1091
1092 if (disc && phba->num_disc_nodes) {
1093 /* Check to see if there are more ADISCs to be sent */
1094 lpfc_more_adisc(phba);
1095
1096 /* Check to see if we are done with ADISC authentication */
1097 if (phba->num_disc_nodes == 0) {
1098 lpfc_can_disctmo(phba);
1099 /* If we get here, there is nothing left to wait for */
1100 if ((phba->hba_state < LPFC_HBA_READY) &&
1101 (phba->hba_state != LPFC_CLEAR_LA)) {
1102 /* Link up discovery */
1103 if ((mbox = mempool_alloc(phba->mbox_mem_pool,
1104 GFP_KERNEL))) {
1105 phba->hba_state = LPFC_CLEAR_LA;
1106 lpfc_clear_la(phba, mbox);
1107 mbox->mbox_cmpl =
1108 lpfc_mbx_cmpl_clear_la;
1109 rc = lpfc_sli_issue_mbox
1110 (phba, mbox,
1111 (MBX_NOWAIT | MBX_STOP_IOCB));
1112 if (rc == MBX_NOT_FINISHED) {
1113 mempool_free(mbox,
1114 phba->mbox_mem_pool);
1115 lpfc_disc_flush_list(phba);
James Smarta4bc3372006-12-02 13:34:16 -05001116 psli->ring[(psli->extra_ring)].
dea31012005-04-17 16:05:31 -05001117 flag &=
1118 ~LPFC_STOP_IOCB_EVENT;
1119 psli->ring[(psli->fcp_ring)].
1120 flag &=
1121 ~LPFC_STOP_IOCB_EVENT;
1122 psli->ring[(psli->next_ring)].
1123 flag &=
1124 ~LPFC_STOP_IOCB_EVENT;
1125 phba->hba_state =
1126 LPFC_HBA_READY;
1127 }
1128 }
1129 } else {
1130 lpfc_rscn_disc(phba);
1131 }
1132 }
1133 }
dea31012005-04-17 16:05:31 -05001134out:
1135 lpfc_els_free_iocb(phba, cmdiocb);
1136 return;
1137}
1138
1139int
1140lpfc_issue_els_adisc(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp,
1141 uint8_t retry)
1142{
1143 ADISC *ap;
1144 IOCB_t *icmd;
1145 struct lpfc_iocbq *elsiocb;
1146 struct lpfc_sli_ring *pring;
1147 struct lpfc_sli *psli;
1148 uint8_t *pcmd;
1149 uint16_t cmdsize;
1150
1151 psli = &phba->sli;
1152 pring = &psli->ring[LPFC_ELS_RING]; /* ELS ring */
1153
1154 cmdsize = (sizeof (uint32_t) + sizeof (ADISC));
James Smart488d1462006-03-07 15:02:37 -05001155 elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry, ndlp,
1156 ndlp->nlp_DID, ELS_CMD_ADISC);
1157 if (!elsiocb)
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001158 return 1;
dea31012005-04-17 16:05:31 -05001159
1160 icmd = &elsiocb->iocb;
1161 pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
1162
1163 /* For ADISC request, remainder of payload is service parameters */
1164 *((uint32_t *) (pcmd)) = ELS_CMD_ADISC;
1165 pcmd += sizeof (uint32_t);
1166
1167 /* Fill in ADISC payload */
1168 ap = (ADISC *) pcmd;
1169 ap->hardAL_PA = phba->fc_pref_ALPA;
1170 memcpy(&ap->portName, &phba->fc_portname, sizeof (struct lpfc_name));
1171 memcpy(&ap->nodeName, &phba->fc_nodename, sizeof (struct lpfc_name));
1172 ap->DID = be32_to_cpu(phba->fc_myDID);
1173
1174 phba->fc_stat.elsXmitADISC++;
1175 elsiocb->iocb_cmpl = lpfc_cmpl_els_adisc;
1176 spin_lock_irq(phba->host->host_lock);
1177 ndlp->nlp_flag |= NLP_ADISC_SND;
1178 if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) {
1179 ndlp->nlp_flag &= ~NLP_ADISC_SND;
1180 spin_unlock_irq(phba->host->host_lock);
1181 lpfc_els_free_iocb(phba, elsiocb);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001182 return 1;
dea31012005-04-17 16:05:31 -05001183 }
1184 spin_unlock_irq(phba->host->host_lock);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001185 return 0;
dea31012005-04-17 16:05:31 -05001186}
1187
1188static void
1189lpfc_cmpl_els_logo(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
1190 struct lpfc_iocbq * rspiocb)
1191{
1192 IOCB_t *irsp;
1193 struct lpfc_sli *psli;
1194 struct lpfc_nodelist *ndlp;
1195
1196 psli = &phba->sli;
1197 /* we pass cmdiocb to state machine which needs rspiocb as well */
1198 cmdiocb->context_un.rsp_iocb = rspiocb;
1199
1200 irsp = &(rspiocb->iocb);
1201 ndlp = (struct lpfc_nodelist *) cmdiocb->context1;
1202 spin_lock_irq(phba->host->host_lock);
1203 ndlp->nlp_flag &= ~NLP_LOGO_SND;
1204 spin_unlock_irq(phba->host->host_lock);
1205
1206 /* LOGO completes to NPort <nlp_DID> */
1207 lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
1208 "%d:0105 LOGO completes to NPort x%x "
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001209 "Data: x%x x%x x%x x%x\n",
dea31012005-04-17 16:05:31 -05001210 phba->brd_no, ndlp->nlp_DID, irsp->ulpStatus,
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001211 irsp->un.ulpWord[4], irsp->ulpTimeout,
1212 phba->num_disc_nodes);
dea31012005-04-17 16:05:31 -05001213
1214 /* Check to see if link went down during discovery */
1215 if (lpfc_els_chk_latt(phba))
1216 goto out;
1217
1218 if (irsp->ulpStatus) {
1219 /* Check for retry */
1220 if (lpfc_els_retry(phba, cmdiocb, rspiocb)) {
1221 /* ELS command is being retried */
1222 goto out;
1223 }
1224 /* LOGO failed */
1225 /* Do not call DSM for lpfc_els_abort'ed ELS cmds */
1226 if ((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) &&
1227 ((irsp->un.ulpWord[4] == IOERR_SLI_ABORTED) ||
James.Smart@Emulex.Com6281bfe2005-11-28 11:41:33 -05001228 (irsp->un.ulpWord[4] == IOERR_LINK_DOWN) ||
dea31012005-04-17 16:05:31 -05001229 (irsp->un.ulpWord[4] == IOERR_SLI_DOWN))) {
1230 goto out;
Jamie Wellnitz2fe165b2006-02-28 19:25:31 -05001231 } else {
dea31012005-04-17 16:05:31 -05001232 lpfc_disc_state_machine(phba, ndlp, cmdiocb,
1233 NLP_EVT_CMPL_LOGO);
1234 }
1235 } else {
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05001236 /* Good status, call state machine.
1237 * This will unregister the rpi if needed.
1238 */
dea31012005-04-17 16:05:31 -05001239 lpfc_disc_state_machine(phba, ndlp, cmdiocb, NLP_EVT_CMPL_LOGO);
dea31012005-04-17 16:05:31 -05001240 }
1241
1242out:
1243 lpfc_els_free_iocb(phba, cmdiocb);
1244 return;
1245}
1246
1247int
1248lpfc_issue_els_logo(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp,
1249 uint8_t retry)
1250{
1251 IOCB_t *icmd;
1252 struct lpfc_iocbq *elsiocb;
1253 struct lpfc_sli_ring *pring;
1254 struct lpfc_sli *psli;
1255 uint8_t *pcmd;
1256 uint16_t cmdsize;
1257
1258 psli = &phba->sli;
1259 pring = &psli->ring[LPFC_ELS_RING];
1260
James Smart10d4e952006-04-15 11:53:15 -04001261 cmdsize = (2 * sizeof (uint32_t)) + sizeof (struct lpfc_name);
James Smart488d1462006-03-07 15:02:37 -05001262 elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry, ndlp,
1263 ndlp->nlp_DID, ELS_CMD_LOGO);
1264 if (!elsiocb)
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001265 return 1;
dea31012005-04-17 16:05:31 -05001266
1267 icmd = &elsiocb->iocb;
1268 pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
1269 *((uint32_t *) (pcmd)) = ELS_CMD_LOGO;
1270 pcmd += sizeof (uint32_t);
1271
1272 /* Fill in LOGO payload */
1273 *((uint32_t *) (pcmd)) = be32_to_cpu(phba->fc_myDID);
1274 pcmd += sizeof (uint32_t);
1275 memcpy(pcmd, &phba->fc_portname, sizeof (struct lpfc_name));
1276
1277 phba->fc_stat.elsXmitLOGO++;
1278 elsiocb->iocb_cmpl = lpfc_cmpl_els_logo;
1279 spin_lock_irq(phba->host->host_lock);
1280 ndlp->nlp_flag |= NLP_LOGO_SND;
1281 if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) {
1282 ndlp->nlp_flag &= ~NLP_LOGO_SND;
1283 spin_unlock_irq(phba->host->host_lock);
1284 lpfc_els_free_iocb(phba, elsiocb);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001285 return 1;
dea31012005-04-17 16:05:31 -05001286 }
1287 spin_unlock_irq(phba->host->host_lock);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001288 return 0;
dea31012005-04-17 16:05:31 -05001289}
1290
1291static void
1292lpfc_cmpl_els_cmd(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
1293 struct lpfc_iocbq * rspiocb)
1294{
1295 IOCB_t *irsp;
1296
1297 irsp = &rspiocb->iocb;
1298
1299 /* ELS cmd tag <ulpIoTag> completes */
1300 lpfc_printf_log(phba,
1301 KERN_INFO,
1302 LOG_ELS,
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001303 "%d:0106 ELS cmd tag x%x completes Data: x%x x%x x%x\n",
dea31012005-04-17 16:05:31 -05001304 phba->brd_no,
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001305 irsp->ulpIoTag, irsp->ulpStatus,
1306 irsp->un.ulpWord[4], irsp->ulpTimeout);
dea31012005-04-17 16:05:31 -05001307
1308 /* Check to see if link went down during discovery */
1309 lpfc_els_chk_latt(phba);
1310 lpfc_els_free_iocb(phba, cmdiocb);
1311 return;
1312}
1313
1314int
1315lpfc_issue_els_scr(struct lpfc_hba * phba, uint32_t nportid, uint8_t retry)
1316{
1317 IOCB_t *icmd;
1318 struct lpfc_iocbq *elsiocb;
1319 struct lpfc_sli_ring *pring;
1320 struct lpfc_sli *psli;
1321 uint8_t *pcmd;
1322 uint16_t cmdsize;
1323 struct lpfc_nodelist *ndlp;
1324
1325 psli = &phba->sli;
1326 pring = &psli->ring[LPFC_ELS_RING]; /* ELS ring */
1327 cmdsize = (sizeof (uint32_t) + sizeof (SCR));
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001328 ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL);
1329 if (!ndlp)
1330 return 1;
dea31012005-04-17 16:05:31 -05001331
1332 lpfc_nlp_init(phba, ndlp, nportid);
1333
James Smart488d1462006-03-07 15:02:37 -05001334 elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry, ndlp,
1335 ndlp->nlp_DID, ELS_CMD_SCR);
1336 if (!elsiocb) {
James Smart329f9bc2007-04-25 09:53:01 -04001337 lpfc_nlp_put(ndlp);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001338 return 1;
dea31012005-04-17 16:05:31 -05001339 }
1340
1341 icmd = &elsiocb->iocb;
1342 pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
1343
1344 *((uint32_t *) (pcmd)) = ELS_CMD_SCR;
1345 pcmd += sizeof (uint32_t);
1346
1347 /* For SCR, remainder of payload is SCR parameter page */
1348 memset(pcmd, 0, sizeof (SCR));
1349 ((SCR *) pcmd)->Function = SCR_FUNC_FULL;
1350
1351 phba->fc_stat.elsXmitSCR++;
1352 elsiocb->iocb_cmpl = lpfc_cmpl_els_cmd;
1353 spin_lock_irq(phba->host->host_lock);
1354 if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) {
1355 spin_unlock_irq(phba->host->host_lock);
James Smart329f9bc2007-04-25 09:53:01 -04001356 lpfc_nlp_put(ndlp);
dea31012005-04-17 16:05:31 -05001357 lpfc_els_free_iocb(phba, elsiocb);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001358 return 1;
dea31012005-04-17 16:05:31 -05001359 }
1360 spin_unlock_irq(phba->host->host_lock);
James Smart329f9bc2007-04-25 09:53:01 -04001361 lpfc_nlp_put(ndlp);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001362 return 0;
dea31012005-04-17 16:05:31 -05001363}
1364
1365static int
1366lpfc_issue_els_farpr(struct lpfc_hba * phba, uint32_t nportid, uint8_t retry)
1367{
1368 IOCB_t *icmd;
1369 struct lpfc_iocbq *elsiocb;
1370 struct lpfc_sli_ring *pring;
1371 struct lpfc_sli *psli;
1372 FARP *fp;
1373 uint8_t *pcmd;
1374 uint32_t *lp;
1375 uint16_t cmdsize;
1376 struct lpfc_nodelist *ondlp;
1377 struct lpfc_nodelist *ndlp;
1378
1379 psli = &phba->sli;
1380 pring = &psli->ring[LPFC_ELS_RING]; /* ELS ring */
1381 cmdsize = (sizeof (uint32_t) + sizeof (FARP));
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001382 ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL);
1383 if (!ndlp)
1384 return 1;
dea31012005-04-17 16:05:31 -05001385 lpfc_nlp_init(phba, ndlp, nportid);
1386
James Smart488d1462006-03-07 15:02:37 -05001387 elsiocb = lpfc_prep_els_iocb(phba, 1, cmdsize, retry, ndlp,
1388 ndlp->nlp_DID, ELS_CMD_RNID);
1389 if (!elsiocb) {
James Smart329f9bc2007-04-25 09:53:01 -04001390 lpfc_nlp_put(ndlp);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001391 return 1;
dea31012005-04-17 16:05:31 -05001392 }
1393
1394 icmd = &elsiocb->iocb;
1395 pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
1396
1397 *((uint32_t *) (pcmd)) = ELS_CMD_FARPR;
1398 pcmd += sizeof (uint32_t);
1399
1400 /* Fill in FARPR payload */
1401 fp = (FARP *) (pcmd);
1402 memset(fp, 0, sizeof (FARP));
1403 lp = (uint32_t *) pcmd;
1404 *lp++ = be32_to_cpu(nportid);
1405 *lp++ = be32_to_cpu(phba->fc_myDID);
1406 fp->Rflags = 0;
1407 fp->Mflags = (FARP_MATCH_PORT | FARP_MATCH_NODE);
1408
1409 memcpy(&fp->RportName, &phba->fc_portname, sizeof (struct lpfc_name));
1410 memcpy(&fp->RnodeName, &phba->fc_nodename, sizeof (struct lpfc_name));
1411 if ((ondlp = lpfc_findnode_did(phba, NLP_SEARCH_ALL, nportid))) {
1412 memcpy(&fp->OportName, &ondlp->nlp_portname,
1413 sizeof (struct lpfc_name));
1414 memcpy(&fp->OnodeName, &ondlp->nlp_nodename,
1415 sizeof (struct lpfc_name));
1416 }
1417
1418 phba->fc_stat.elsXmitFARPR++;
1419 elsiocb->iocb_cmpl = lpfc_cmpl_els_cmd;
1420 spin_lock_irq(phba->host->host_lock);
1421 if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) {
1422 spin_unlock_irq(phba->host->host_lock);
James Smart329f9bc2007-04-25 09:53:01 -04001423 lpfc_nlp_put(ndlp);
dea31012005-04-17 16:05:31 -05001424 lpfc_els_free_iocb(phba, elsiocb);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001425 return 1;
dea31012005-04-17 16:05:31 -05001426 }
1427 spin_unlock_irq(phba->host->host_lock);
James Smart329f9bc2007-04-25 09:53:01 -04001428 lpfc_nlp_put(ndlp);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001429 return 0;
dea31012005-04-17 16:05:31 -05001430}
1431
1432void
James Smartfdcebe22006-03-07 15:04:01 -05001433lpfc_cancel_retry_delay_tmo(struct lpfc_hba *phba, struct lpfc_nodelist * nlp)
1434{
1435 nlp->nlp_flag &= ~NLP_DELAY_TMO;
1436 del_timer_sync(&nlp->nlp_delayfunc);
1437 nlp->nlp_last_elscmd = 0;
1438
1439 if (!list_empty(&nlp->els_retry_evt.evt_listp))
1440 list_del_init(&nlp->els_retry_evt.evt_listp);
1441
1442 if (nlp->nlp_flag & NLP_NPR_2B_DISC) {
1443 nlp->nlp_flag &= ~NLP_NPR_2B_DISC;
1444 if (phba->num_disc_nodes) {
1445 /* Check to see if there are more
1446 * PLOGIs to be sent
1447 */
1448 lpfc_more_plogi(phba);
James Smartfdcebe22006-03-07 15:04:01 -05001449
James Smart10d4e952006-04-15 11:53:15 -04001450 if (phba->num_disc_nodes == 0) {
1451 phba->fc_flag &= ~FC_NDISC_ACTIVE;
1452 lpfc_can_disctmo(phba);
1453 if (phba->fc_flag & FC_RSCN_MODE) {
1454 /*
1455 * Check to see if more RSCNs
1456 * came in while we were
1457 * processing this one.
1458 */
1459 if((phba->fc_rscn_id_cnt==0) &&
1460 !(phba->fc_flag & FC_RSCN_DISCOVERY)) {
1461 phba->fc_flag &= ~FC_RSCN_MODE;
1462 }
1463 else {
1464 lpfc_els_handle_rscn(phba);
1465 }
James Smartfdcebe22006-03-07 15:04:01 -05001466 }
1467 }
1468 }
1469 }
1470 return;
1471}
1472
1473void
dea31012005-04-17 16:05:31 -05001474lpfc_els_retry_delay(unsigned long ptr)
1475{
1476 struct lpfc_nodelist *ndlp;
1477 struct lpfc_hba *phba;
1478 unsigned long iflag;
1479 struct lpfc_work_evt *evtp;
1480
1481 ndlp = (struct lpfc_nodelist *)ptr;
1482 phba = ndlp->nlp_phba;
1483 evtp = &ndlp->els_retry_evt;
1484
1485 spin_lock_irqsave(phba->host->host_lock, iflag);
1486 if (!list_empty(&evtp->evt_listp)) {
1487 spin_unlock_irqrestore(phba->host->host_lock, iflag);
1488 return;
1489 }
1490
1491 evtp->evt_arg1 = ndlp;
1492 evtp->evt = LPFC_EVT_ELS_RETRY;
1493 list_add_tail(&evtp->evt_listp, &phba->work_list);
1494 if (phba->work_wait)
1495 wake_up(phba->work_wait);
1496
1497 spin_unlock_irqrestore(phba->host->host_lock, iflag);
1498 return;
1499}
1500
1501void
1502lpfc_els_retry_delay_handler(struct lpfc_nodelist *ndlp)
1503{
1504 struct lpfc_hba *phba;
1505 uint32_t cmd;
1506 uint32_t did;
1507 uint8_t retry;
1508
1509 phba = ndlp->nlp_phba;
1510 spin_lock_irq(phba->host->host_lock);
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05001511 did = ndlp->nlp_DID;
1512 cmd = ndlp->nlp_last_elscmd;
1513 ndlp->nlp_last_elscmd = 0;
dea31012005-04-17 16:05:31 -05001514
1515 if (!(ndlp->nlp_flag & NLP_DELAY_TMO)) {
1516 spin_unlock_irq(phba->host->host_lock);
1517 return;
1518 }
1519
1520 ndlp->nlp_flag &= ~NLP_DELAY_TMO;
1521 spin_unlock_irq(phba->host->host_lock);
James Smart1a169682006-03-07 15:04:06 -05001522 /*
1523 * If a discovery event readded nlp_delayfunc after timer
1524 * firing and before processing the timer, cancel the
1525 * nlp_delayfunc.
1526 */
1527 del_timer_sync(&ndlp->nlp_delayfunc);
dea31012005-04-17 16:05:31 -05001528 retry = ndlp->nlp_retry;
1529
1530 switch (cmd) {
1531 case ELS_CMD_FLOGI:
1532 lpfc_issue_els_flogi(phba, ndlp, retry);
1533 break;
1534 case ELS_CMD_PLOGI:
James Smart488d1462006-03-07 15:02:37 -05001535 if(!lpfc_issue_els_plogi(phba, ndlp->nlp_DID, retry)) {
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05001536 ndlp->nlp_prev_state = ndlp->nlp_state;
James Smartde0c5b32007-04-25 09:52:27 -04001537 lpfc_nlp_set_state(phba, ndlp, NLP_STE_PLOGI_ISSUE);
Jamie Wellnitz6ad42532006-02-28 19:25:16 -05001538 }
dea31012005-04-17 16:05:31 -05001539 break;
1540 case ELS_CMD_ADISC:
Jamie Wellnitz6ad42532006-02-28 19:25:16 -05001541 if (!lpfc_issue_els_adisc(phba, ndlp, retry)) {
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05001542 ndlp->nlp_prev_state = ndlp->nlp_state;
James Smartde0c5b32007-04-25 09:52:27 -04001543 lpfc_nlp_set_state(phba, ndlp, NLP_STE_ADISC_ISSUE);
Jamie Wellnitz6ad42532006-02-28 19:25:16 -05001544 }
dea31012005-04-17 16:05:31 -05001545 break;
1546 case ELS_CMD_PRLI:
Jamie Wellnitz6ad42532006-02-28 19:25:16 -05001547 if (!lpfc_issue_els_prli(phba, ndlp, retry)) {
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05001548 ndlp->nlp_prev_state = ndlp->nlp_state;
James Smartde0c5b32007-04-25 09:52:27 -04001549 lpfc_nlp_set_state(phba, ndlp, NLP_STE_PRLI_ISSUE);
Jamie Wellnitz6ad42532006-02-28 19:25:16 -05001550 }
dea31012005-04-17 16:05:31 -05001551 break;
1552 case ELS_CMD_LOGO:
Jamie Wellnitz6ad42532006-02-28 19:25:16 -05001553 if (!lpfc_issue_els_logo(phba, ndlp, retry)) {
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05001554 ndlp->nlp_prev_state = ndlp->nlp_state;
James Smartde0c5b32007-04-25 09:52:27 -04001555 lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
Jamie Wellnitz6ad42532006-02-28 19:25:16 -05001556 }
dea31012005-04-17 16:05:31 -05001557 break;
1558 }
1559 return;
1560}
1561
1562static int
1563lpfc_els_retry(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
1564 struct lpfc_iocbq * rspiocb)
1565{
1566 IOCB_t *irsp;
1567 struct lpfc_dmabuf *pcmd;
1568 struct lpfc_nodelist *ndlp;
1569 uint32_t *elscmd;
1570 struct ls_rjt stat;
1571 int retry, maxretry;
1572 int delay;
1573 uint32_t cmd;
James Smart488d1462006-03-07 15:02:37 -05001574 uint32_t did;
dea31012005-04-17 16:05:31 -05001575
1576 retry = 0;
1577 delay = 0;
1578 maxretry = lpfc_max_els_tries;
1579 irsp = &rspiocb->iocb;
1580 ndlp = (struct lpfc_nodelist *) cmdiocb->context1;
1581 pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
1582 cmd = 0;
James Smart488d1462006-03-07 15:02:37 -05001583
dea31012005-04-17 16:05:31 -05001584 /* Note: context2 may be 0 for internal driver abort
1585 * of delays ELS command.
1586 */
1587
1588 if (pcmd && pcmd->virt) {
1589 elscmd = (uint32_t *) (pcmd->virt);
1590 cmd = *elscmd++;
1591 }
1592
James Smart329f9bc2007-04-25 09:53:01 -04001593 if (ndlp)
James Smart488d1462006-03-07 15:02:37 -05001594 did = ndlp->nlp_DID;
1595 else {
1596 /* We should only hit this case for retrying PLOGI */
1597 did = irsp->un.elsreq64.remoteID;
1598 ndlp = lpfc_findnode_did(phba, NLP_SEARCH_ALL, did);
1599 if (!ndlp && (cmd != ELS_CMD_PLOGI))
1600 return 1;
1601 }
1602
dea31012005-04-17 16:05:31 -05001603 switch (irsp->ulpStatus) {
1604 case IOSTAT_FCP_RSP_ERROR:
1605 case IOSTAT_REMOTE_STOP:
1606 break;
1607
1608 case IOSTAT_LOCAL_REJECT:
1609 switch ((irsp->un.ulpWord[4] & 0xff)) {
1610 case IOERR_LOOP_OPEN_FAILURE:
1611 if (cmd == ELS_CMD_PLOGI) {
1612 if (cmdiocb->retry == 0) {
1613 delay = 1;
1614 }
1615 }
1616 retry = 1;
1617 break;
1618
1619 case IOERR_SEQUENCE_TIMEOUT:
1620 retry = 1;
dea31012005-04-17 16:05:31 -05001621 break;
1622
1623 case IOERR_NO_RESOURCES:
1624 if (cmd == ELS_CMD_PLOGI) {
1625 delay = 1;
1626 }
1627 retry = 1;
1628 break;
1629
1630 case IOERR_INVALID_RPI:
1631 retry = 1;
1632 break;
1633 }
1634 break;
1635
1636 case IOSTAT_NPORT_RJT:
1637 case IOSTAT_FABRIC_RJT:
1638 if (irsp->un.ulpWord[4] & RJT_UNAVAIL_TEMP) {
1639 retry = 1;
1640 break;
1641 }
1642 break;
1643
1644 case IOSTAT_NPORT_BSY:
1645 case IOSTAT_FABRIC_BSY:
1646 retry = 1;
1647 break;
1648
1649 case IOSTAT_LS_RJT:
1650 stat.un.lsRjtError = be32_to_cpu(irsp->un.ulpWord[4]);
1651 /* Added for Vendor specifc support
1652 * Just keep retrying for these Rsn / Exp codes
1653 */
1654 switch (stat.un.b.lsRjtRsnCode) {
1655 case LSRJT_UNABLE_TPC:
1656 if (stat.un.b.lsRjtRsnCodeExp ==
1657 LSEXP_CMD_IN_PROGRESS) {
1658 if (cmd == ELS_CMD_PLOGI) {
1659 delay = 1;
1660 maxretry = 48;
1661 }
1662 retry = 1;
1663 break;
1664 }
1665 if (cmd == ELS_CMD_PLOGI) {
1666 delay = 1;
1667 maxretry = lpfc_max_els_tries + 1;
1668 retry = 1;
1669 break;
1670 }
1671 break;
1672
1673 case LSRJT_LOGICAL_BSY:
1674 if (cmd == ELS_CMD_PLOGI) {
1675 delay = 1;
1676 maxretry = 48;
1677 }
1678 retry = 1;
1679 break;
1680 }
1681 break;
1682
1683 case IOSTAT_INTERMED_RSP:
1684 case IOSTAT_BA_RJT:
1685 break;
1686
1687 default:
1688 break;
1689 }
1690
James Smart488d1462006-03-07 15:02:37 -05001691 if (did == FDMI_DID)
dea31012005-04-17 16:05:31 -05001692 retry = 1;
dea31012005-04-17 16:05:31 -05001693
1694 if ((++cmdiocb->retry) >= maxretry) {
1695 phba->fc_stat.elsRetryExceeded++;
1696 retry = 0;
1697 }
1698
1699 if (retry) {
1700
1701 /* Retry ELS command <elsCmd> to remote NPORT <did> */
1702 lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
1703 "%d:0107 Retry ELS command x%x to remote "
1704 "NPORT x%x Data: x%x x%x\n",
1705 phba->brd_no,
James Smart488d1462006-03-07 15:02:37 -05001706 cmd, did, cmdiocb->retry, delay);
dea31012005-04-17 16:05:31 -05001707
1708 if ((cmd == ELS_CMD_PLOGI) || (cmd == ELS_CMD_ADISC)) {
1709 /* If discovery / RSCN timer is running, reset it */
1710 if (timer_pending(&phba->fc_disctmo) ||
1711 (phba->fc_flag & FC_RSCN_MODE)) {
1712 lpfc_set_disctmo(phba);
1713 }
1714 }
1715
1716 phba->fc_stat.elsXmitRetry++;
James Smart488d1462006-03-07 15:02:37 -05001717 if (ndlp && delay) {
dea31012005-04-17 16:05:31 -05001718 phba->fc_stat.elsDelayRetry++;
1719 ndlp->nlp_retry = cmdiocb->retry;
1720
1721 mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ);
1722 ndlp->nlp_flag |= NLP_DELAY_TMO;
1723
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05001724 ndlp->nlp_prev_state = ndlp->nlp_state;
James Smartde0c5b32007-04-25 09:52:27 -04001725 lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
dea31012005-04-17 16:05:31 -05001726 ndlp->nlp_last_elscmd = cmd;
1727
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001728 return 1;
dea31012005-04-17 16:05:31 -05001729 }
1730 switch (cmd) {
1731 case ELS_CMD_FLOGI:
1732 lpfc_issue_els_flogi(phba, ndlp, cmdiocb->retry);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001733 return 1;
dea31012005-04-17 16:05:31 -05001734 case ELS_CMD_PLOGI:
James Smart488d1462006-03-07 15:02:37 -05001735 if (ndlp) {
1736 ndlp->nlp_prev_state = ndlp->nlp_state;
James Smartde0c5b32007-04-25 09:52:27 -04001737 lpfc_nlp_set_state(phba, ndlp,
1738 NLP_STE_PLOGI_ISSUE);
James Smart488d1462006-03-07 15:02:37 -05001739 }
1740 lpfc_issue_els_plogi(phba, did, cmdiocb->retry);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001741 return 1;
dea31012005-04-17 16:05:31 -05001742 case ELS_CMD_ADISC:
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05001743 ndlp->nlp_prev_state = ndlp->nlp_state;
James Smartde0c5b32007-04-25 09:52:27 -04001744 lpfc_nlp_set_state(phba, ndlp, NLP_STE_ADISC_ISSUE);
dea31012005-04-17 16:05:31 -05001745 lpfc_issue_els_adisc(phba, ndlp, cmdiocb->retry);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001746 return 1;
dea31012005-04-17 16:05:31 -05001747 case ELS_CMD_PRLI:
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05001748 ndlp->nlp_prev_state = ndlp->nlp_state;
James Smartde0c5b32007-04-25 09:52:27 -04001749 lpfc_nlp_set_state(phba, ndlp, NLP_STE_PRLI_ISSUE);
dea31012005-04-17 16:05:31 -05001750 lpfc_issue_els_prli(phba, ndlp, cmdiocb->retry);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001751 return 1;
dea31012005-04-17 16:05:31 -05001752 case ELS_CMD_LOGO:
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05001753 ndlp->nlp_prev_state = ndlp->nlp_state;
James Smartde0c5b32007-04-25 09:52:27 -04001754 lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
dea31012005-04-17 16:05:31 -05001755 lpfc_issue_els_logo(phba, ndlp, cmdiocb->retry);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001756 return 1;
dea31012005-04-17 16:05:31 -05001757 }
1758 }
1759
1760 /* No retry ELS command <elsCmd> to remote NPORT <did> */
1761 lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
1762 "%d:0108 No retry ELS command x%x to remote NPORT x%x "
James Smart488d1462006-03-07 15:02:37 -05001763 "Data: x%x\n",
dea31012005-04-17 16:05:31 -05001764 phba->brd_no,
James Smart488d1462006-03-07 15:02:37 -05001765 cmd, did, cmdiocb->retry);
dea31012005-04-17 16:05:31 -05001766
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001767 return 0;
dea31012005-04-17 16:05:31 -05001768}
1769
1770int
James Smart329f9bc2007-04-25 09:53:01 -04001771lpfc_els_free_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *elsiocb)
dea31012005-04-17 16:05:31 -05001772{
1773 struct lpfc_dmabuf *buf_ptr, *buf_ptr1;
1774
James Smart329f9bc2007-04-25 09:53:01 -04001775 if (elsiocb->context1) {
1776 lpfc_nlp_put(elsiocb->context1);
1777 elsiocb->context1 = NULL;
1778 }
dea31012005-04-17 16:05:31 -05001779 /* context2 = cmd, context2->next = rsp, context3 = bpl */
1780 if (elsiocb->context2) {
1781 buf_ptr1 = (struct lpfc_dmabuf *) elsiocb->context2;
1782 /* Free the response before processing the command. */
1783 if (!list_empty(&buf_ptr1->list)) {
1784 list_remove_head(&buf_ptr1->list, buf_ptr,
1785 struct lpfc_dmabuf,
1786 list);
1787 lpfc_mbuf_free(phba, buf_ptr->virt, buf_ptr->phys);
1788 kfree(buf_ptr);
1789 }
1790 lpfc_mbuf_free(phba, buf_ptr1->virt, buf_ptr1->phys);
1791 kfree(buf_ptr1);
1792 }
1793
1794 if (elsiocb->context3) {
1795 buf_ptr = (struct lpfc_dmabuf *) elsiocb->context3;
1796 lpfc_mbuf_free(phba, buf_ptr->virt, buf_ptr->phys);
1797 kfree(buf_ptr);
1798 }
1799 spin_lock_irq(phba->host->host_lock);
James Bottomley604a3e32005-10-29 10:28:33 -05001800 lpfc_sli_release_iocbq(phba, elsiocb);
dea31012005-04-17 16:05:31 -05001801 spin_unlock_irq(phba->host->host_lock);
1802 return 0;
1803}
1804
1805static void
1806lpfc_cmpl_els_logo_acc(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
1807 struct lpfc_iocbq * rspiocb)
1808{
1809 struct lpfc_nodelist *ndlp;
1810
1811 ndlp = (struct lpfc_nodelist *) cmdiocb->context1;
1812
1813 /* ACC to LOGO completes to NPort <nlp_DID> */
1814 lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
1815 "%d:0109 ACC to LOGO completes to NPort x%x "
1816 "Data: x%x x%x x%x\n",
1817 phba->brd_no, ndlp->nlp_DID, ndlp->nlp_flag,
1818 ndlp->nlp_state, ndlp->nlp_rpi);
1819
dea31012005-04-17 16:05:31 -05001820 switch (ndlp->nlp_state) {
1821 case NLP_STE_UNUSED_NODE: /* node is just allocated */
James Smartde0c5b32007-04-25 09:52:27 -04001822 lpfc_drop_node(phba, ndlp);
dea31012005-04-17 16:05:31 -05001823 break;
1824 case NLP_STE_NPR_NODE: /* NPort Recovery mode */
1825 lpfc_unreg_rpi(phba, ndlp);
1826 break;
1827 default:
1828 break;
1829 }
1830 lpfc_els_free_iocb(phba, cmdiocb);
1831 return;
1832}
1833
1834static void
James Smart329f9bc2007-04-25 09:53:01 -04001835lpfc_cmpl_els_acc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
1836 struct lpfc_iocbq *rspiocb)
dea31012005-04-17 16:05:31 -05001837{
James Smart33ccf8d2006-08-17 11:57:58 -04001838 IOCB_t *irsp;
dea31012005-04-17 16:05:31 -05001839 struct lpfc_nodelist *ndlp;
1840 LPFC_MBOXQ_t *mbox = NULL;
James Smart14691152006-12-02 13:34:28 -05001841 struct lpfc_dmabuf *mp;
dea31012005-04-17 16:05:31 -05001842
James Smart33ccf8d2006-08-17 11:57:58 -04001843 irsp = &rspiocb->iocb;
1844
dea31012005-04-17 16:05:31 -05001845 ndlp = (struct lpfc_nodelist *) cmdiocb->context1;
1846 if (cmdiocb->context_un.mbox)
1847 mbox = cmdiocb->context_un.mbox;
1848
1849
1850 /* Check to see if link went down during discovery */
James Smart329f9bc2007-04-25 09:53:01 -04001851 if (lpfc_els_chk_latt(phba) || !ndlp) {
dea31012005-04-17 16:05:31 -05001852 if (mbox) {
James Smart14691152006-12-02 13:34:28 -05001853 mp = (struct lpfc_dmabuf *) mbox->context1;
1854 if (mp) {
1855 lpfc_mbuf_free(phba, mp->virt, mp->phys);
1856 kfree(mp);
1857 }
James Smart329f9bc2007-04-25 09:53:01 -04001858 mempool_free(mbox, phba->mbox_mem_pool);
dea31012005-04-17 16:05:31 -05001859 }
1860 goto out;
1861 }
1862
1863 /* ELS response tag <ulpIoTag> completes */
1864 lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
1865 "%d:0110 ELS response tag x%x completes "
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001866 "Data: x%x x%x x%x x%x x%x x%x x%x\n",
dea31012005-04-17 16:05:31 -05001867 phba->brd_no,
1868 cmdiocb->iocb.ulpIoTag, rspiocb->iocb.ulpStatus,
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001869 rspiocb->iocb.un.ulpWord[4], rspiocb->iocb.ulpTimeout,
1870 ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state,
1871 ndlp->nlp_rpi);
dea31012005-04-17 16:05:31 -05001872
1873 if (mbox) {
1874 if ((rspiocb->iocb.ulpStatus == 0)
1875 && (ndlp->nlp_flag & NLP_ACC_REGLOGIN)) {
dea31012005-04-17 16:05:31 -05001876 lpfc_unreg_rpi(phba, ndlp);
1877 mbox->mbox_cmpl = lpfc_mbx_cmpl_reg_login;
James Smart329f9bc2007-04-25 09:53:01 -04001878 mbox->context2 = lpfc_nlp_get(ndlp);
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05001879 ndlp->nlp_prev_state = ndlp->nlp_state;
James Smartde0c5b32007-04-25 09:52:27 -04001880 lpfc_nlp_set_state(phba, ndlp, NLP_STE_REG_LOGIN_ISSUE);
dea31012005-04-17 16:05:31 -05001881 if (lpfc_sli_issue_mbox(phba, mbox,
1882 (MBX_NOWAIT | MBX_STOP_IOCB))
1883 != MBX_NOT_FINISHED) {
1884 goto out;
1885 }
James Smart329f9bc2007-04-25 09:53:01 -04001886 lpfc_nlp_put(ndlp);
dea31012005-04-17 16:05:31 -05001887 /* NOTE: we should have messages for unsuccessful
1888 reglogin */
dea31012005-04-17 16:05:31 -05001889 } else {
James Smart33ccf8d2006-08-17 11:57:58 -04001890 /* Do not call NO_LIST for lpfc_els_abort'ed ELS cmds */
1891 if (!((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) &&
1892 ((irsp->un.ulpWord[4] == IOERR_SLI_ABORTED) ||
1893 (irsp->un.ulpWord[4] == IOERR_LINK_DOWN) ||
1894 (irsp->un.ulpWord[4] == IOERR_SLI_DOWN)))) {
1895 if (ndlp->nlp_flag & NLP_ACC_REGLOGIN) {
James Smartde0c5b32007-04-25 09:52:27 -04001896 lpfc_drop_node(phba, ndlp);
James Smart33ccf8d2006-08-17 11:57:58 -04001897 ndlp = NULL;
1898 }
dea31012005-04-17 16:05:31 -05001899 }
1900 }
James Smart14691152006-12-02 13:34:28 -05001901 mp = (struct lpfc_dmabuf *) mbox->context1;
1902 if (mp) {
1903 lpfc_mbuf_free(phba, mp->virt, mp->phys);
1904 kfree(mp);
1905 }
1906 mempool_free(mbox, phba->mbox_mem_pool);
dea31012005-04-17 16:05:31 -05001907 }
1908out:
1909 if (ndlp) {
1910 spin_lock_irq(phba->host->host_lock);
1911 ndlp->nlp_flag &= ~NLP_ACC_REGLOGIN;
1912 spin_unlock_irq(phba->host->host_lock);
1913 }
1914 lpfc_els_free_iocb(phba, cmdiocb);
1915 return;
1916}
1917
1918int
1919lpfc_els_rsp_acc(struct lpfc_hba * phba, uint32_t flag,
1920 struct lpfc_iocbq * oldiocb, struct lpfc_nodelist * ndlp,
1921 LPFC_MBOXQ_t * mbox, uint8_t newnode)
1922{
1923 IOCB_t *icmd;
1924 IOCB_t *oldcmd;
1925 struct lpfc_iocbq *elsiocb;
1926 struct lpfc_sli_ring *pring;
1927 struct lpfc_sli *psli;
1928 uint8_t *pcmd;
1929 uint16_t cmdsize;
1930 int rc;
James Smart82d9a2a2006-04-15 11:53:05 -04001931 ELS_PKT *els_pkt_ptr;
dea31012005-04-17 16:05:31 -05001932
1933 psli = &phba->sli;
1934 pring = &psli->ring[LPFC_ELS_RING]; /* ELS ring */
1935 oldcmd = &oldiocb->iocb;
1936
1937 switch (flag) {
1938 case ELS_CMD_ACC:
1939 cmdsize = sizeof (uint32_t);
James Smart488d1462006-03-07 15:02:37 -05001940 elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, oldiocb->retry,
1941 ndlp, ndlp->nlp_DID, ELS_CMD_ACC);
1942 if (!elsiocb) {
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05001943 ndlp->nlp_flag &= ~NLP_LOGO_ACC;
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001944 return 1;
dea31012005-04-17 16:05:31 -05001945 }
1946 icmd = &elsiocb->iocb;
1947 icmd->ulpContext = oldcmd->ulpContext; /* Xri */
1948 pcmd = (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
1949 *((uint32_t *) (pcmd)) = ELS_CMD_ACC;
1950 pcmd += sizeof (uint32_t);
1951 break;
1952 case ELS_CMD_PLOGI:
1953 cmdsize = (sizeof (struct serv_parm) + sizeof (uint32_t));
James Smart488d1462006-03-07 15:02:37 -05001954 elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, oldiocb->retry,
1955 ndlp, ndlp->nlp_DID, ELS_CMD_ACC);
1956 if (!elsiocb)
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001957 return 1;
James Smart488d1462006-03-07 15:02:37 -05001958
dea31012005-04-17 16:05:31 -05001959 icmd = &elsiocb->iocb;
1960 icmd->ulpContext = oldcmd->ulpContext; /* Xri */
1961 pcmd = (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
1962
1963 if (mbox)
1964 elsiocb->context_un.mbox = mbox;
1965
1966 *((uint32_t *) (pcmd)) = ELS_CMD_ACC;
1967 pcmd += sizeof (uint32_t);
1968 memcpy(pcmd, &phba->fc_sparam, sizeof (struct serv_parm));
1969 break;
James Smart82d9a2a2006-04-15 11:53:05 -04001970 case ELS_CMD_PRLO:
1971 cmdsize = sizeof (uint32_t) + sizeof (PRLO);
1972 elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, oldiocb->retry,
1973 ndlp, ndlp->nlp_DID, ELS_CMD_PRLO);
1974 if (!elsiocb)
1975 return 1;
1976
1977 icmd = &elsiocb->iocb;
1978 icmd->ulpContext = oldcmd->ulpContext; /* Xri */
1979 pcmd = (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
1980
1981 memcpy(pcmd, ((struct lpfc_dmabuf *) oldiocb->context2)->virt,
1982 sizeof (uint32_t) + sizeof (PRLO));
1983 *((uint32_t *) (pcmd)) = ELS_CMD_PRLO_ACC;
1984 els_pkt_ptr = (ELS_PKT *) pcmd;
1985 els_pkt_ptr->un.prlo.acceptRspCode = PRLO_REQ_EXECUTED;
1986 break;
dea31012005-04-17 16:05:31 -05001987 default:
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001988 return 1;
dea31012005-04-17 16:05:31 -05001989 }
1990
James Smart329f9bc2007-04-25 09:53:01 -04001991 if (newnode) {
1992 lpfc_nlp_put(ndlp);
dea31012005-04-17 16:05:31 -05001993 elsiocb->context1 = NULL;
James Smart329f9bc2007-04-25 09:53:01 -04001994 }
dea31012005-04-17 16:05:31 -05001995
1996 /* Xmit ELS ACC response tag <ulpIoTag> */
1997 lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
James Smart1dcb58e2007-04-25 09:51:30 -04001998 "%d:0128 Xmit ELS ACC response tag x%x, XRI: x%x, "
1999 "DID: x%x, nlp_flag: x%x nlp_state: x%x RPI: x%x\n",
2000 phba->brd_no, elsiocb->iotag,
dea31012005-04-17 16:05:31 -05002001 elsiocb->iocb.ulpContext, ndlp->nlp_DID,
2002 ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi);
2003
2004 if (ndlp->nlp_flag & NLP_LOGO_ACC) {
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002005 spin_lock_irq(phba->host->host_lock);
2006 ndlp->nlp_flag &= ~NLP_LOGO_ACC;
2007 spin_unlock_irq(phba->host->host_lock);
dea31012005-04-17 16:05:31 -05002008 elsiocb->iocb_cmpl = lpfc_cmpl_els_logo_acc;
2009 } else {
2010 elsiocb->iocb_cmpl = lpfc_cmpl_els_acc;
2011 }
2012
2013 phba->fc_stat.elsXmitACC++;
2014 spin_lock_irq(phba->host->host_lock);
2015 rc = lpfc_sli_issue_iocb(phba, pring, elsiocb, 0);
2016 spin_unlock_irq(phba->host->host_lock);
2017 if (rc == IOCB_ERROR) {
2018 lpfc_els_free_iocb(phba, elsiocb);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002019 return 1;
dea31012005-04-17 16:05:31 -05002020 }
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002021 return 0;
dea31012005-04-17 16:05:31 -05002022}
2023
2024int
2025lpfc_els_rsp_reject(struct lpfc_hba * phba, uint32_t rejectError,
2026 struct lpfc_iocbq * oldiocb, struct lpfc_nodelist * ndlp)
2027{
2028 IOCB_t *icmd;
2029 IOCB_t *oldcmd;
2030 struct lpfc_iocbq *elsiocb;
2031 struct lpfc_sli_ring *pring;
2032 struct lpfc_sli *psli;
2033 uint8_t *pcmd;
2034 uint16_t cmdsize;
2035 int rc;
2036
2037 psli = &phba->sli;
2038 pring = &psli->ring[LPFC_ELS_RING]; /* ELS ring */
2039
2040 cmdsize = 2 * sizeof (uint32_t);
James Smart488d1462006-03-07 15:02:37 -05002041 elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, oldiocb->retry,
2042 ndlp, ndlp->nlp_DID, ELS_CMD_LS_RJT);
2043 if (!elsiocb)
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002044 return 1;
dea31012005-04-17 16:05:31 -05002045
2046 icmd = &elsiocb->iocb;
2047 oldcmd = &oldiocb->iocb;
2048 icmd->ulpContext = oldcmd->ulpContext; /* Xri */
2049 pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
2050
2051 *((uint32_t *) (pcmd)) = ELS_CMD_LS_RJT;
2052 pcmd += sizeof (uint32_t);
2053 *((uint32_t *) (pcmd)) = rejectError;
2054
2055 /* Xmit ELS RJT <err> response tag <ulpIoTag> */
2056 lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
James Smart5b8bd0c2007-04-25 09:52:49 -04002057 "%d:0129 Xmit ELS RJT x%x response tag x%x xri x%x, "
2058 "did x%x, nlp_flag x%x, nlp_state x%x, rpi x%x\n",
2059 phba->brd_no, rejectError, elsiocb->iotag,
dea31012005-04-17 16:05:31 -05002060 elsiocb->iocb.ulpContext, ndlp->nlp_DID,
2061 ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi);
2062
2063 phba->fc_stat.elsXmitLSRJT++;
2064 elsiocb->iocb_cmpl = lpfc_cmpl_els_acc;
2065 spin_lock_irq(phba->host->host_lock);
2066 rc = lpfc_sli_issue_iocb(phba, pring, elsiocb, 0);
2067 spin_unlock_irq(phba->host->host_lock);
2068 if (rc == IOCB_ERROR) {
2069 lpfc_els_free_iocb(phba, elsiocb);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002070 return 1;
dea31012005-04-17 16:05:31 -05002071 }
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002072 return 0;
dea31012005-04-17 16:05:31 -05002073}
2074
2075int
2076lpfc_els_rsp_adisc_acc(struct lpfc_hba * phba,
2077 struct lpfc_iocbq * oldiocb, struct lpfc_nodelist * ndlp)
2078{
2079 ADISC *ap;
2080 IOCB_t *icmd;
2081 IOCB_t *oldcmd;
2082 struct lpfc_iocbq *elsiocb;
2083 struct lpfc_sli_ring *pring;
2084 struct lpfc_sli *psli;
2085 uint8_t *pcmd;
2086 uint16_t cmdsize;
2087 int rc;
2088
2089 psli = &phba->sli;
2090 pring = &psli->ring[LPFC_ELS_RING]; /* ELS ring */
2091
2092 cmdsize = sizeof (uint32_t) + sizeof (ADISC);
James Smart488d1462006-03-07 15:02:37 -05002093 elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, oldiocb->retry,
2094 ndlp, ndlp->nlp_DID, ELS_CMD_ACC);
2095 if (!elsiocb)
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002096 return 1;
dea31012005-04-17 16:05:31 -05002097
dea31012005-04-17 16:05:31 -05002098 icmd = &elsiocb->iocb;
2099 oldcmd = &oldiocb->iocb;
2100 icmd->ulpContext = oldcmd->ulpContext; /* Xri */
James Smart5b8bd0c2007-04-25 09:52:49 -04002101
2102 /* Xmit ADISC ACC response tag <ulpIoTag> */
2103 lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
2104 "%d:0130 Xmit ADISC ACC response iotag x%x xri: "
2105 "x%x, did x%x, nlp_flag x%x, nlp_state x%x rpi x%x\n",
2106 phba->brd_no, elsiocb->iotag,
2107 elsiocb->iocb.ulpContext, ndlp->nlp_DID,
2108 ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi);
2109
dea31012005-04-17 16:05:31 -05002110 pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
2111
2112 *((uint32_t *) (pcmd)) = ELS_CMD_ACC;
2113 pcmd += sizeof (uint32_t);
2114
2115 ap = (ADISC *) (pcmd);
2116 ap->hardAL_PA = phba->fc_pref_ALPA;
2117 memcpy(&ap->portName, &phba->fc_portname, sizeof (struct lpfc_name));
2118 memcpy(&ap->nodeName, &phba->fc_nodename, sizeof (struct lpfc_name));
2119 ap->DID = be32_to_cpu(phba->fc_myDID);
2120
2121 phba->fc_stat.elsXmitACC++;
2122 elsiocb->iocb_cmpl = lpfc_cmpl_els_acc;
2123 spin_lock_irq(phba->host->host_lock);
2124 rc = lpfc_sli_issue_iocb(phba, pring, elsiocb, 0);
2125 spin_unlock_irq(phba->host->host_lock);
2126 if (rc == IOCB_ERROR) {
2127 lpfc_els_free_iocb(phba, elsiocb);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002128 return 1;
dea31012005-04-17 16:05:31 -05002129 }
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002130 return 0;
dea31012005-04-17 16:05:31 -05002131}
2132
2133int
James Smart5b8bd0c2007-04-25 09:52:49 -04002134lpfc_els_rsp_prli_acc(struct lpfc_hba *phba, struct lpfc_iocbq *oldiocb,
2135 struct lpfc_nodelist *ndlp)
dea31012005-04-17 16:05:31 -05002136{
2137 PRLI *npr;
2138 lpfc_vpd_t *vpd;
2139 IOCB_t *icmd;
2140 IOCB_t *oldcmd;
2141 struct lpfc_iocbq *elsiocb;
2142 struct lpfc_sli_ring *pring;
2143 struct lpfc_sli *psli;
2144 uint8_t *pcmd;
2145 uint16_t cmdsize;
2146 int rc;
2147
2148 psli = &phba->sli;
2149 pring = &psli->ring[LPFC_ELS_RING]; /* ELS ring */
2150
2151 cmdsize = sizeof (uint32_t) + sizeof (PRLI);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002152 elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, oldiocb->retry, ndlp,
James Smart488d1462006-03-07 15:02:37 -05002153 ndlp->nlp_DID, (ELS_CMD_ACC | (ELS_CMD_PRLI & ~ELS_RSP_MASK)));
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002154 if (!elsiocb)
2155 return 1;
dea31012005-04-17 16:05:31 -05002156
dea31012005-04-17 16:05:31 -05002157 icmd = &elsiocb->iocb;
2158 oldcmd = &oldiocb->iocb;
2159 icmd->ulpContext = oldcmd->ulpContext; /* Xri */
James Smart5b8bd0c2007-04-25 09:52:49 -04002160
2161 /* Xmit PRLI ACC response tag <ulpIoTag> */
2162 lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
2163 "%d:0131 Xmit PRLI ACC response tag x%x xri x%x, "
2164 "did x%x, nlp_flag x%x, nlp_state x%x, rpi x%x\n",
2165 phba->brd_no, elsiocb->iotag,
2166 elsiocb->iocb.ulpContext, ndlp->nlp_DID,
2167 ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi);
2168
dea31012005-04-17 16:05:31 -05002169 pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
2170
2171 *((uint32_t *) (pcmd)) = (ELS_CMD_ACC | (ELS_CMD_PRLI & ~ELS_RSP_MASK));
2172 pcmd += sizeof (uint32_t);
2173
2174 /* For PRLI, remainder of payload is PRLI parameter page */
2175 memset(pcmd, 0, sizeof (PRLI));
2176
2177 npr = (PRLI *) pcmd;
2178 vpd = &phba->vpd;
2179 /*
2180 * If our firmware version is 3.20 or later,
2181 * set the following bits for FC-TAPE support.
2182 */
2183 if (vpd->rev.feaLevelHigh >= 0x02) {
2184 npr->ConfmComplAllowed = 1;
2185 npr->Retry = 1;
2186 npr->TaskRetryIdReq = 1;
2187 }
2188
2189 npr->acceptRspCode = PRLI_REQ_EXECUTED;
2190 npr->estabImagePair = 1;
2191 npr->readXferRdyDis = 1;
2192 npr->ConfmComplAllowed = 1;
2193
2194 npr->prliType = PRLI_FCP_TYPE;
2195 npr->initiatorFunc = 1;
2196
2197 phba->fc_stat.elsXmitACC++;
2198 elsiocb->iocb_cmpl = lpfc_cmpl_els_acc;
2199
2200 spin_lock_irq(phba->host->host_lock);
2201 rc = lpfc_sli_issue_iocb(phba, pring, elsiocb, 0);
2202 spin_unlock_irq(phba->host->host_lock);
2203 if (rc == IOCB_ERROR) {
2204 lpfc_els_free_iocb(phba, elsiocb);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002205 return 1;
dea31012005-04-17 16:05:31 -05002206 }
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002207 return 0;
dea31012005-04-17 16:05:31 -05002208}
2209
2210static int
James Smart329f9bc2007-04-25 09:53:01 -04002211lpfc_els_rsp_rnid_acc(struct lpfc_hba *phba, uint8_t format,
2212 struct lpfc_iocbq *oldiocb, struct lpfc_nodelist *ndlp)
dea31012005-04-17 16:05:31 -05002213{
2214 RNID *rn;
2215 IOCB_t *icmd;
2216 IOCB_t *oldcmd;
2217 struct lpfc_iocbq *elsiocb;
2218 struct lpfc_sli_ring *pring;
2219 struct lpfc_sli *psli;
2220 uint8_t *pcmd;
2221 uint16_t cmdsize;
2222 int rc;
2223
2224 psli = &phba->sli;
2225 pring = &psli->ring[LPFC_ELS_RING];
2226
2227 cmdsize = sizeof (uint32_t) + sizeof (uint32_t)
2228 + (2 * sizeof (struct lpfc_name));
2229 if (format)
2230 cmdsize += sizeof (RNID_TOP_DISC);
2231
James Smart488d1462006-03-07 15:02:37 -05002232 elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, oldiocb->retry,
2233 ndlp, ndlp->nlp_DID, ELS_CMD_ACC);
2234 if (!elsiocb)
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002235 return 1;
dea31012005-04-17 16:05:31 -05002236
dea31012005-04-17 16:05:31 -05002237 icmd = &elsiocb->iocb;
2238 oldcmd = &oldiocb->iocb;
2239 icmd->ulpContext = oldcmd->ulpContext; /* Xri */
James Smart5b8bd0c2007-04-25 09:52:49 -04002240
2241 /* Xmit RNID ACC response tag <ulpIoTag> */
2242 lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
2243 "%d:0132 Xmit RNID ACC response tag x%x "
2244 "xri x%x\n",
2245 phba->brd_no, elsiocb->iotag,
2246 elsiocb->iocb.ulpContext);
2247
dea31012005-04-17 16:05:31 -05002248 pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
2249
2250 *((uint32_t *) (pcmd)) = ELS_CMD_ACC;
2251 pcmd += sizeof (uint32_t);
2252
2253 memset(pcmd, 0, sizeof (RNID));
2254 rn = (RNID *) (pcmd);
2255 rn->Format = format;
2256 rn->CommonLen = (2 * sizeof (struct lpfc_name));
2257 memcpy(&rn->portName, &phba->fc_portname, sizeof (struct lpfc_name));
2258 memcpy(&rn->nodeName, &phba->fc_nodename, sizeof (struct lpfc_name));
2259 switch (format) {
2260 case 0:
2261 rn->SpecificLen = 0;
2262 break;
2263 case RNID_TOPOLOGY_DISC:
2264 rn->SpecificLen = sizeof (RNID_TOP_DISC);
2265 memcpy(&rn->un.topologyDisc.portName,
2266 &phba->fc_portname, sizeof (struct lpfc_name));
2267 rn->un.topologyDisc.unitType = RNID_HBA;
2268 rn->un.topologyDisc.physPort = 0;
2269 rn->un.topologyDisc.attachedNodes = 0;
2270 break;
2271 default:
2272 rn->CommonLen = 0;
2273 rn->SpecificLen = 0;
2274 break;
2275 }
2276
2277 phba->fc_stat.elsXmitACC++;
2278 elsiocb->iocb_cmpl = lpfc_cmpl_els_acc;
James Smart329f9bc2007-04-25 09:53:01 -04002279 lpfc_nlp_put(ndlp);
dea31012005-04-17 16:05:31 -05002280 elsiocb->context1 = NULL; /* Don't need ndlp for cmpl,
2281 * it could be freed */
2282
2283 spin_lock_irq(phba->host->host_lock);
2284 rc = lpfc_sli_issue_iocb(phba, pring, elsiocb, 0);
2285 spin_unlock_irq(phba->host->host_lock);
2286 if (rc == IOCB_ERROR) {
2287 lpfc_els_free_iocb(phba, elsiocb);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002288 return 1;
dea31012005-04-17 16:05:31 -05002289 }
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002290 return 0;
dea31012005-04-17 16:05:31 -05002291}
2292
2293int
2294lpfc_els_disc_adisc(struct lpfc_hba * phba)
2295{
2296 int sentadisc;
2297 struct lpfc_nodelist *ndlp, *next_ndlp;
2298
2299 sentadisc = 0;
2300 /* go thru NPR list and issue any remaining ELS ADISCs */
2301 list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_npr_list,
2302 nlp_listp) {
2303 if (ndlp->nlp_flag & NLP_NPR_2B_DISC) {
2304 if (ndlp->nlp_flag & NLP_NPR_ADISC) {
2305 ndlp->nlp_flag &= ~NLP_NPR_ADISC;
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05002306 ndlp->nlp_prev_state = ndlp->nlp_state;
James Smartde0c5b32007-04-25 09:52:27 -04002307 lpfc_nlp_set_state(phba, ndlp,
2308 NLP_STE_ADISC_ISSUE);
dea31012005-04-17 16:05:31 -05002309 lpfc_issue_els_adisc(phba, ndlp, 0);
2310 sentadisc++;
2311 phba->num_disc_nodes++;
2312 if (phba->num_disc_nodes >=
2313 phba->cfg_discovery_threads) {
2314 spin_lock_irq(phba->host->host_lock);
2315 phba->fc_flag |= FC_NLP_MORE;
2316 spin_unlock_irq(phba->host->host_lock);
2317 break;
2318 }
2319 }
2320 }
2321 }
2322 if (sentadisc == 0) {
2323 spin_lock_irq(phba->host->host_lock);
2324 phba->fc_flag &= ~FC_NLP_MORE;
2325 spin_unlock_irq(phba->host->host_lock);
2326 }
Jamie Wellnitz2fe165b2006-02-28 19:25:31 -05002327 return sentadisc;
dea31012005-04-17 16:05:31 -05002328}
2329
2330int
2331lpfc_els_disc_plogi(struct lpfc_hba * phba)
2332{
2333 int sentplogi;
2334 struct lpfc_nodelist *ndlp, *next_ndlp;
2335
2336 sentplogi = 0;
2337 /* go thru NPR list and issue any remaining ELS PLOGIs */
2338 list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_npr_list,
2339 nlp_listp) {
2340 if ((ndlp->nlp_flag & NLP_NPR_2B_DISC) &&
2341 (!(ndlp->nlp_flag & NLP_DELAY_TMO))) {
2342 if (!(ndlp->nlp_flag & NLP_NPR_ADISC)) {
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05002343 ndlp->nlp_prev_state = ndlp->nlp_state;
James Smartde0c5b32007-04-25 09:52:27 -04002344 lpfc_nlp_set_state(phba, ndlp,
2345 NLP_STE_PLOGI_ISSUE);
James Smart488d1462006-03-07 15:02:37 -05002346 lpfc_issue_els_plogi(phba, ndlp->nlp_DID, 0);
dea31012005-04-17 16:05:31 -05002347 sentplogi++;
2348 phba->num_disc_nodes++;
2349 if (phba->num_disc_nodes >=
2350 phba->cfg_discovery_threads) {
2351 spin_lock_irq(phba->host->host_lock);
2352 phba->fc_flag |= FC_NLP_MORE;
2353 spin_unlock_irq(phba->host->host_lock);
2354 break;
2355 }
2356 }
2357 }
2358 }
2359 if (sentplogi == 0) {
2360 spin_lock_irq(phba->host->host_lock);
2361 phba->fc_flag &= ~FC_NLP_MORE;
2362 spin_unlock_irq(phba->host->host_lock);
2363 }
Jamie Wellnitz2fe165b2006-02-28 19:25:31 -05002364 return sentplogi;
dea31012005-04-17 16:05:31 -05002365}
2366
2367int
2368lpfc_els_flush_rscn(struct lpfc_hba * phba)
2369{
2370 struct lpfc_dmabuf *mp;
2371 int i;
2372
2373 for (i = 0; i < phba->fc_rscn_id_cnt; i++) {
2374 mp = phba->fc_rscn_id_list[i];
2375 lpfc_mbuf_free(phba, mp->virt, mp->phys);
2376 kfree(mp);
2377 phba->fc_rscn_id_list[i] = NULL;
2378 }
2379 phba->fc_rscn_id_cnt = 0;
2380 spin_lock_irq(phba->host->host_lock);
2381 phba->fc_flag &= ~(FC_RSCN_MODE | FC_RSCN_DISCOVERY);
2382 spin_unlock_irq(phba->host->host_lock);
2383 lpfc_can_disctmo(phba);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002384 return 0;
dea31012005-04-17 16:05:31 -05002385}
2386
2387int
2388lpfc_rscn_payload_check(struct lpfc_hba * phba, uint32_t did)
2389{
2390 D_ID ns_did;
2391 D_ID rscn_did;
2392 struct lpfc_dmabuf *mp;
2393 uint32_t *lp;
2394 uint32_t payload_len, cmd, i, match;
2395
2396 ns_did.un.word = did;
2397 match = 0;
2398
2399 /* Never match fabric nodes for RSCNs */
2400 if ((did & Fabric_DID_MASK) == Fabric_DID_MASK)
2401 return(0);
2402
2403 /* If we are doing a FULL RSCN rediscovery, match everything */
2404 if (phba->fc_flag & FC_RSCN_DISCOVERY) {
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002405 return did;
dea31012005-04-17 16:05:31 -05002406 }
2407
2408 for (i = 0; i < phba->fc_rscn_id_cnt; i++) {
2409 mp = phba->fc_rscn_id_list[i];
2410 lp = (uint32_t *) mp->virt;
2411 cmd = *lp++;
2412 payload_len = be32_to_cpu(cmd) & 0xffff; /* payload length */
2413 payload_len -= sizeof (uint32_t); /* take off word 0 */
2414 while (payload_len) {
2415 rscn_did.un.word = *lp++;
2416 rscn_did.un.word = be32_to_cpu(rscn_did.un.word);
2417 payload_len -= sizeof (uint32_t);
2418 switch (rscn_did.un.b.resv) {
2419 case 0: /* Single N_Port ID effected */
2420 if (ns_did.un.word == rscn_did.un.word) {
2421 match = did;
2422 }
2423 break;
2424 case 1: /* Whole N_Port Area effected */
2425 if ((ns_did.un.b.domain == rscn_did.un.b.domain)
2426 && (ns_did.un.b.area == rscn_did.un.b.area))
2427 {
2428 match = did;
2429 }
2430 break;
2431 case 2: /* Whole N_Port Domain effected */
2432 if (ns_did.un.b.domain == rscn_did.un.b.domain)
2433 {
2434 match = did;
2435 }
2436 break;
2437 case 3: /* Whole Fabric effected */
2438 match = did;
2439 break;
2440 default:
2441 /* Unknown Identifier in RSCN list */
2442 lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
2443 "%d:0217 Unknown Identifier in "
2444 "RSCN payload Data: x%x\n",
2445 phba->brd_no, rscn_did.un.word);
2446 break;
2447 }
2448 if (match) {
2449 break;
2450 }
2451 }
2452 }
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002453 return match;
dea31012005-04-17 16:05:31 -05002454}
2455
2456static int
James Smart329f9bc2007-04-25 09:53:01 -04002457lpfc_rscn_recovery_check(struct lpfc_hba *phba)
dea31012005-04-17 16:05:31 -05002458{
2459 struct lpfc_nodelist *ndlp = NULL, *next_ndlp;
2460 struct list_head *listp;
2461 struct list_head *node_list[7];
2462 int i;
2463
2464 /* Look at all nodes effected by pending RSCNs and move
2465 * them to NPR list.
2466 */
2467 node_list[0] = &phba->fc_npr_list; /* MUST do this list first */
2468 node_list[1] = &phba->fc_nlpmap_list;
2469 node_list[2] = &phba->fc_nlpunmap_list;
2470 node_list[3] = &phba->fc_prli_list;
2471 node_list[4] = &phba->fc_reglogin_list;
2472 node_list[5] = &phba->fc_adisc_list;
2473 node_list[6] = &phba->fc_plogi_list;
2474 for (i = 0; i < 7; i++) {
2475 listp = node_list[i];
2476 if (list_empty(listp))
2477 continue;
2478
2479 list_for_each_entry_safe(ndlp, next_ndlp, listp, nlp_listp) {
2480 if (!(lpfc_rscn_payload_check(phba, ndlp->nlp_DID)))
2481 continue;
2482
2483 lpfc_disc_state_machine(phba, ndlp, NULL,
2484 NLP_EVT_DEVICE_RECOVERY);
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05002485
2486 /* Make sure NLP_DELAY_TMO is NOT running
2487 * after a device recovery event.
2488 */
James Smartfdcebe22006-03-07 15:04:01 -05002489 if (ndlp->nlp_flag & NLP_DELAY_TMO)
2490 lpfc_cancel_retry_delay_tmo(phba, ndlp);
dea31012005-04-17 16:05:31 -05002491 }
2492 }
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002493 return 0;
dea31012005-04-17 16:05:31 -05002494}
2495
2496static int
2497lpfc_els_rcv_rscn(struct lpfc_hba * phba,
2498 struct lpfc_iocbq * cmdiocb,
2499 struct lpfc_nodelist * ndlp, uint8_t newnode)
2500{
2501 struct lpfc_dmabuf *pcmd;
2502 uint32_t *lp;
2503 IOCB_t *icmd;
2504 uint32_t payload_len, cmd;
James Smartd2873e42006-08-18 17:46:43 -04002505 int i;
dea31012005-04-17 16:05:31 -05002506
2507 icmd = &cmdiocb->iocb;
2508 pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
2509 lp = (uint32_t *) pcmd->virt;
2510
2511 cmd = *lp++;
2512 payload_len = be32_to_cpu(cmd) & 0xffff; /* payload length */
2513 payload_len -= sizeof (uint32_t); /* take off word 0 */
2514 cmd &= ELS_CMD_MASK;
2515
2516 /* RSCN received */
2517 lpfc_printf_log(phba,
2518 KERN_INFO,
2519 LOG_DISCOVERY,
2520 "%d:0214 RSCN received Data: x%x x%x x%x x%x\n",
2521 phba->brd_no,
2522 phba->fc_flag, payload_len, *lp, phba->fc_rscn_id_cnt);
2523
James Smartd2873e42006-08-18 17:46:43 -04002524 for (i = 0; i < payload_len/sizeof(uint32_t); i++)
2525 fc_host_post_event(phba->host, fc_get_event_number(),
2526 FCH_EVT_RSCN, lp[i]);
2527
dea31012005-04-17 16:05:31 -05002528 /* If we are about to begin discovery, just ACC the RSCN.
2529 * Discovery processing will satisfy it.
2530 */
James Smart071fbd3d2006-04-15 11:53:20 -04002531 if (phba->hba_state <= LPFC_NS_QRY) {
dea31012005-04-17 16:05:31 -05002532 lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL,
2533 newnode);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002534 return 0;
dea31012005-04-17 16:05:31 -05002535 }
2536
2537 /* If we are already processing an RSCN, save the received
2538 * RSCN payload buffer, cmdiocb->context2 to process later.
2539 */
2540 if (phba->fc_flag & (FC_RSCN_MODE | FC_NDISC_ACTIVE)) {
2541 if ((phba->fc_rscn_id_cnt < FC_MAX_HOLD_RSCN) &&
2542 !(phba->fc_flag & FC_RSCN_DISCOVERY)) {
2543 spin_lock_irq(phba->host->host_lock);
2544 phba->fc_flag |= FC_RSCN_MODE;
2545 spin_unlock_irq(phba->host->host_lock);
2546 phba->fc_rscn_id_list[phba->fc_rscn_id_cnt++] = pcmd;
2547
2548 /* If we zero, cmdiocb->context2, the calling
2549 * routine will not try to free it.
2550 */
2551 cmdiocb->context2 = NULL;
2552
2553 /* Deferred RSCN */
2554 lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
2555 "%d:0235 Deferred RSCN "
2556 "Data: x%x x%x x%x\n",
2557 phba->brd_no, phba->fc_rscn_id_cnt,
2558 phba->fc_flag, phba->hba_state);
2559 } else {
2560 spin_lock_irq(phba->host->host_lock);
2561 phba->fc_flag |= FC_RSCN_DISCOVERY;
2562 spin_unlock_irq(phba->host->host_lock);
2563 /* ReDiscovery RSCN */
2564 lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
2565 "%d:0234 ReDiscovery RSCN "
2566 "Data: x%x x%x x%x\n",
2567 phba->brd_no, phba->fc_rscn_id_cnt,
2568 phba->fc_flag, phba->hba_state);
2569 }
2570 /* Send back ACC */
2571 lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL,
2572 newnode);
2573
2574 /* send RECOVERY event for ALL nodes that match RSCN payload */
2575 lpfc_rscn_recovery_check(phba);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002576 return 0;
dea31012005-04-17 16:05:31 -05002577 }
2578
2579 phba->fc_flag |= FC_RSCN_MODE;
2580 phba->fc_rscn_id_list[phba->fc_rscn_id_cnt++] = pcmd;
2581 /*
2582 * If we zero, cmdiocb->context2, the calling routine will
2583 * not try to free it.
2584 */
2585 cmdiocb->context2 = NULL;
2586
2587 lpfc_set_disctmo(phba);
2588
2589 /* Send back ACC */
2590 lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL, newnode);
2591
2592 /* send RECOVERY event for ALL nodes that match RSCN payload */
2593 lpfc_rscn_recovery_check(phba);
2594
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002595 return lpfc_els_handle_rscn(phba);
dea31012005-04-17 16:05:31 -05002596}
2597
2598int
2599lpfc_els_handle_rscn(struct lpfc_hba * phba)
2600{
2601 struct lpfc_nodelist *ndlp;
2602
2603 /* Start timer for RSCN processing */
2604 lpfc_set_disctmo(phba);
2605
2606 /* RSCN processed */
2607 lpfc_printf_log(phba,
2608 KERN_INFO,
2609 LOG_DISCOVERY,
2610 "%d:0215 RSCN processed Data: x%x x%x x%x x%x\n",
2611 phba->brd_no,
2612 phba->fc_flag, 0, phba->fc_rscn_id_cnt,
2613 phba->hba_state);
2614
2615 /* To process RSCN, first compare RSCN data with NameServer */
2616 phba->fc_ns_retry = 0;
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002617 ndlp = lpfc_findnode_did(phba, NLP_SEARCH_UNMAPPED, NameServer_DID);
2618 if (ndlp) {
dea31012005-04-17 16:05:31 -05002619 /* Good ndlp, issue CT Request to NameServer */
2620 if (lpfc_ns_cmd(phba, ndlp, SLI_CTNS_GID_FT) == 0) {
2621 /* Wait for NameServer query cmpl before we can
2622 continue */
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002623 return 1;
dea31012005-04-17 16:05:31 -05002624 }
2625 } else {
2626 /* If login to NameServer does not exist, issue one */
2627 /* Good status, issue PLOGI to NameServer */
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002628 ndlp = lpfc_findnode_did(phba, NLP_SEARCH_ALL, NameServer_DID);
2629 if (ndlp) {
dea31012005-04-17 16:05:31 -05002630 /* Wait for NameServer login cmpl before we can
2631 continue */
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002632 return 1;
dea31012005-04-17 16:05:31 -05002633 }
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002634 ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL);
2635 if (!ndlp) {
dea31012005-04-17 16:05:31 -05002636 lpfc_els_flush_rscn(phba);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002637 return 0;
dea31012005-04-17 16:05:31 -05002638 } else {
2639 lpfc_nlp_init(phba, ndlp, NameServer_DID);
2640 ndlp->nlp_type |= NLP_FABRIC;
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05002641 ndlp->nlp_prev_state = ndlp->nlp_state;
James Smartde0c5b32007-04-25 09:52:27 -04002642 lpfc_nlp_set_state(phba, ndlp, NLP_STE_PLOGI_ISSUE);
James Smart488d1462006-03-07 15:02:37 -05002643 lpfc_issue_els_plogi(phba, NameServer_DID, 0);
dea31012005-04-17 16:05:31 -05002644 /* Wait for NameServer login cmpl before we can
2645 continue */
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002646 return 1;
dea31012005-04-17 16:05:31 -05002647 }
2648 }
2649
2650 lpfc_els_flush_rscn(phba);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002651 return 0;
dea31012005-04-17 16:05:31 -05002652}
2653
2654static int
2655lpfc_els_rcv_flogi(struct lpfc_hba * phba,
2656 struct lpfc_iocbq * cmdiocb,
2657 struct lpfc_nodelist * ndlp, uint8_t newnode)
2658{
2659 struct lpfc_dmabuf *pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
2660 uint32_t *lp = (uint32_t *) pcmd->virt;
2661 IOCB_t *icmd = &cmdiocb->iocb;
2662 struct serv_parm *sp;
2663 LPFC_MBOXQ_t *mbox;
2664 struct ls_rjt stat;
2665 uint32_t cmd, did;
2666 int rc;
2667
2668 cmd = *lp++;
2669 sp = (struct serv_parm *) lp;
2670
2671 /* FLOGI received */
2672
2673 lpfc_set_disctmo(phba);
2674
2675 if (phba->fc_topology == TOPOLOGY_LOOP) {
2676 /* We should never receive a FLOGI in loop mode, ignore it */
2677 did = icmd->un.elsreq64.remoteID;
2678
2679 /* An FLOGI ELS command <elsCmd> was received from DID <did> in
2680 Loop Mode */
2681 lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
2682 "%d:0113 An FLOGI ELS command x%x was received "
2683 "from DID x%x in Loop Mode\n",
2684 phba->brd_no, cmd, did);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002685 return 1;
dea31012005-04-17 16:05:31 -05002686 }
2687
2688 did = Fabric_DID;
2689
2690 if ((lpfc_check_sparm(phba, ndlp, sp, CLASS3))) {
2691 /* For a FLOGI we accept, then if our portname is greater
2692 * then the remote portname we initiate Nport login.
2693 */
2694
2695 rc = memcmp(&phba->fc_portname, &sp->portName,
2696 sizeof (struct lpfc_name));
2697
2698 if (!rc) {
2699 if ((mbox = mempool_alloc(phba->mbox_mem_pool,
2700 GFP_KERNEL)) == 0) {
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002701 return 1;
dea31012005-04-17 16:05:31 -05002702 }
2703 lpfc_linkdown(phba);
2704 lpfc_init_link(phba, mbox,
2705 phba->cfg_topology,
2706 phba->cfg_link_speed);
2707 mbox->mb.un.varInitLnk.lipsr_AL_PA = 0;
2708 mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
2709 rc = lpfc_sli_issue_mbox
2710 (phba, mbox, (MBX_NOWAIT | MBX_STOP_IOCB));
James Smart5b8bd0c2007-04-25 09:52:49 -04002711 lpfc_set_loopback_flag(phba);
dea31012005-04-17 16:05:31 -05002712 if (rc == MBX_NOT_FINISHED) {
James Smart329f9bc2007-04-25 09:53:01 -04002713 mempool_free(mbox, phba->mbox_mem_pool);
dea31012005-04-17 16:05:31 -05002714 }
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002715 return 1;
Jamie Wellnitz2fe165b2006-02-28 19:25:31 -05002716 } else if (rc > 0) { /* greater than */
dea31012005-04-17 16:05:31 -05002717 spin_lock_irq(phba->host->host_lock);
2718 phba->fc_flag |= FC_PT2PT_PLOGI;
2719 spin_unlock_irq(phba->host->host_lock);
2720 }
2721 phba->fc_flag |= FC_PT2PT;
2722 phba->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP);
2723 } else {
2724 /* Reject this request because invalid parameters */
2725 stat.un.b.lsRjtRsvd0 = 0;
2726 stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
2727 stat.un.b.lsRjtRsnCodeExp = LSEXP_SPARM_OPTIONS;
2728 stat.un.b.vendorUnique = 0;
2729 lpfc_els_rsp_reject(phba, stat.un.lsRjtError, cmdiocb, ndlp);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002730 return 1;
dea31012005-04-17 16:05:31 -05002731 }
2732
2733 /* Send back ACC */
2734 lpfc_els_rsp_acc(phba, ELS_CMD_PLOGI, cmdiocb, ndlp, NULL, newnode);
2735
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002736 return 0;
dea31012005-04-17 16:05:31 -05002737}
2738
2739static int
2740lpfc_els_rcv_rnid(struct lpfc_hba * phba,
2741 struct lpfc_iocbq * cmdiocb, struct lpfc_nodelist * ndlp)
2742{
2743 struct lpfc_dmabuf *pcmd;
2744 uint32_t *lp;
2745 IOCB_t *icmd;
2746 RNID *rn;
2747 struct ls_rjt stat;
2748 uint32_t cmd, did;
2749
2750 icmd = &cmdiocb->iocb;
2751 did = icmd->un.elsreq64.remoteID;
2752 pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
2753 lp = (uint32_t *) pcmd->virt;
2754
2755 cmd = *lp++;
2756 rn = (RNID *) lp;
2757
2758 /* RNID received */
2759
2760 switch (rn->Format) {
2761 case 0:
2762 case RNID_TOPOLOGY_DISC:
2763 /* Send back ACC */
2764 lpfc_els_rsp_rnid_acc(phba, rn->Format, cmdiocb, ndlp);
2765 break;
2766 default:
2767 /* Reject this request because format not supported */
2768 stat.un.b.lsRjtRsvd0 = 0;
2769 stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
2770 stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA;
2771 stat.un.b.vendorUnique = 0;
2772 lpfc_els_rsp_reject(phba, stat.un.lsRjtError, cmdiocb, ndlp);
2773 }
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002774 return 0;
dea31012005-04-17 16:05:31 -05002775}
2776
2777static int
James Smart329f9bc2007-04-25 09:53:01 -04002778lpfc_els_rcv_lirr(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
2779 struct lpfc_nodelist *ndlp)
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05002780{
2781 struct ls_rjt stat;
2782
2783 /* For now, unconditionally reject this command */
2784 stat.un.b.lsRjtRsvd0 = 0;
2785 stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
2786 stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA;
2787 stat.un.b.vendorUnique = 0;
2788 lpfc_els_rsp_reject(phba, stat.un.lsRjtError, cmdiocb, ndlp);
2789 return 0;
2790}
2791
Jamie Wellnitz082c0262006-02-28 19:25:30 -05002792static void
James Smart329f9bc2007-04-25 09:53:01 -04002793lpfc_els_rsp_rps_acc(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05002794{
2795 struct lpfc_sli *psli;
2796 struct lpfc_sli_ring *pring;
2797 MAILBOX_t *mb;
2798 IOCB_t *icmd;
2799 RPS_RSP *rps_rsp;
2800 uint8_t *pcmd;
2801 struct lpfc_iocbq *elsiocb;
2802 struct lpfc_nodelist *ndlp;
2803 uint16_t xri, status;
2804 uint32_t cmdsize;
2805
2806 psli = &phba->sli;
2807 pring = &psli->ring[LPFC_ELS_RING];
2808 mb = &pmb->mb;
2809
2810 ndlp = (struct lpfc_nodelist *) pmb->context2;
2811 xri = (uint16_t) ((unsigned long)(pmb->context1));
Randy Dunlap041976f2006-06-25 01:58:51 -07002812 pmb->context1 = NULL;
2813 pmb->context2 = NULL;
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05002814
2815 if (mb->mbxStatus) {
James Smart329f9bc2007-04-25 09:53:01 -04002816 mempool_free(pmb, phba->mbox_mem_pool);
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05002817 return;
2818 }
2819
2820 cmdsize = sizeof(RPS_RSP) + sizeof(uint32_t);
James Smart329f9bc2007-04-25 09:53:01 -04002821 mempool_free(pmb, phba->mbox_mem_pool);
James Smart488d1462006-03-07 15:02:37 -05002822 elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, lpfc_max_els_tries, ndlp,
2823 ndlp->nlp_DID, ELS_CMD_ACC);
James Smart329f9bc2007-04-25 09:53:01 -04002824 lpfc_nlp_put(ndlp);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002825 if (!elsiocb)
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05002826 return;
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05002827
2828 icmd = &elsiocb->iocb;
2829 icmd->ulpContext = xri;
2830
2831 pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
2832 *((uint32_t *) (pcmd)) = ELS_CMD_ACC;
2833 pcmd += sizeof (uint32_t); /* Skip past command */
2834 rps_rsp = (RPS_RSP *)pcmd;
2835
2836 if (phba->fc_topology != TOPOLOGY_LOOP)
2837 status = 0x10;
2838 else
2839 status = 0x8;
2840 if (phba->fc_flag & FC_FABRIC)
2841 status |= 0x4;
2842
2843 rps_rsp->rsvd1 = 0;
2844 rps_rsp->portStatus = be16_to_cpu(status);
2845 rps_rsp->linkFailureCnt = be32_to_cpu(mb->un.varRdLnk.linkFailureCnt);
2846 rps_rsp->lossSyncCnt = be32_to_cpu(mb->un.varRdLnk.lossSyncCnt);
2847 rps_rsp->lossSignalCnt = be32_to_cpu(mb->un.varRdLnk.lossSignalCnt);
2848 rps_rsp->primSeqErrCnt = be32_to_cpu(mb->un.varRdLnk.primSeqErrCnt);
2849 rps_rsp->invalidXmitWord = be32_to_cpu(mb->un.varRdLnk.invalidXmitWord);
2850 rps_rsp->crcCnt = be32_to_cpu(mb->un.varRdLnk.crcCnt);
2851
2852 /* Xmit ELS RPS ACC response tag <ulpIoTag> */
2853 lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
James Smart5b8bd0c2007-04-25 09:52:49 -04002854 "%d:0118 Xmit ELS RPS ACC response tag x%x xri x%x, "
2855 "did x%x, nlp_flag x%x, nlp_state x%x, rpi x%x\n",
2856 phba->brd_no, elsiocb->iotag,
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05002857 elsiocb->iocb.ulpContext, ndlp->nlp_DID,
2858 ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi);
2859
2860 elsiocb->iocb_cmpl = lpfc_cmpl_els_acc;
2861 phba->fc_stat.elsXmitACC++;
2862 if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) {
2863 lpfc_els_free_iocb(phba, elsiocb);
2864 }
2865 return;
2866}
2867
2868static int
2869lpfc_els_rcv_rps(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
2870 struct lpfc_nodelist * ndlp)
2871{
2872 uint32_t *lp;
2873 uint8_t flag;
2874 LPFC_MBOXQ_t *mbox;
2875 struct lpfc_dmabuf *pcmd;
2876 RPS *rps;
2877 struct ls_rjt stat;
2878
Jamie Wellnitz2fe165b2006-02-28 19:25:31 -05002879 if ((ndlp->nlp_state != NLP_STE_UNMAPPED_NODE) &&
2880 (ndlp->nlp_state != NLP_STE_MAPPED_NODE)) {
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05002881 stat.un.b.lsRjtRsvd0 = 0;
2882 stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
2883 stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA;
2884 stat.un.b.vendorUnique = 0;
2885 lpfc_els_rsp_reject(phba, stat.un.lsRjtError, cmdiocb, ndlp);
2886 }
2887
2888 pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
2889 lp = (uint32_t *) pcmd->virt;
2890 flag = (be32_to_cpu(*lp++) & 0xf);
2891 rps = (RPS *) lp;
2892
2893 if ((flag == 0) ||
2894 ((flag == 1) && (be32_to_cpu(rps->un.portNum) == 0)) ||
2895 ((flag == 2) && (memcmp(&rps->un.portName, &phba->fc_portname,
2896 sizeof (struct lpfc_name)) == 0))) {
2897 if ((mbox = mempool_alloc(phba->mbox_mem_pool, GFP_ATOMIC))) {
2898 lpfc_read_lnk_stat(phba, mbox);
2899 mbox->context1 =
2900 (void *)((unsigned long)cmdiocb->iocb.ulpContext);
James Smart329f9bc2007-04-25 09:53:01 -04002901 mbox->context2 = lpfc_nlp_get(ndlp);
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05002902 mbox->mbox_cmpl = lpfc_els_rsp_rps_acc;
2903 if (lpfc_sli_issue_mbox (phba, mbox,
2904 (MBX_NOWAIT | MBX_STOP_IOCB)) != MBX_NOT_FINISHED) {
2905 /* Mbox completion will send ELS Response */
2906 return 0;
2907 }
James Smart329f9bc2007-04-25 09:53:01 -04002908 lpfc_nlp_put(ndlp);
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05002909 mempool_free(mbox, phba->mbox_mem_pool);
2910 }
2911 }
2912 stat.un.b.lsRjtRsvd0 = 0;
2913 stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
2914 stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA;
2915 stat.un.b.vendorUnique = 0;
2916 lpfc_els_rsp_reject(phba, stat.un.lsRjtError, cmdiocb, ndlp);
2917 return 0;
2918}
2919
Jamie Wellnitz082c0262006-02-28 19:25:30 -05002920static int
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05002921lpfc_els_rsp_rpl_acc(struct lpfc_hba * phba, uint16_t cmdsize,
2922 struct lpfc_iocbq * oldiocb, struct lpfc_nodelist * ndlp)
2923{
2924 IOCB_t *icmd;
2925 IOCB_t *oldcmd;
2926 RPL_RSP rpl_rsp;
2927 struct lpfc_iocbq *elsiocb;
2928 struct lpfc_sli_ring *pring;
2929 struct lpfc_sli *psli;
2930 uint8_t *pcmd;
2931
2932 psli = &phba->sli;
2933 pring = &psli->ring[LPFC_ELS_RING]; /* ELS ring */
2934
James Smart488d1462006-03-07 15:02:37 -05002935 elsiocb = lpfc_prep_els_iocb(phba, 0, cmdsize, oldiocb->retry,
2936 ndlp, ndlp->nlp_DID, ELS_CMD_ACC);
2937 if (!elsiocb)
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05002938 return 1;
James Smart488d1462006-03-07 15:02:37 -05002939
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05002940 icmd = &elsiocb->iocb;
2941 oldcmd = &oldiocb->iocb;
2942 icmd->ulpContext = oldcmd->ulpContext; /* Xri */
2943
2944 pcmd = (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
2945 *((uint32_t *) (pcmd)) = ELS_CMD_ACC;
2946 pcmd += sizeof (uint16_t);
2947 *((uint16_t *)(pcmd)) = be16_to_cpu(cmdsize);
2948 pcmd += sizeof(uint16_t);
2949
2950 /* Setup the RPL ACC payload */
2951 rpl_rsp.listLen = be32_to_cpu(1);
2952 rpl_rsp.index = 0;
2953 rpl_rsp.port_num_blk.portNum = 0;
2954 rpl_rsp.port_num_blk.portID = be32_to_cpu(phba->fc_myDID);
2955 memcpy(&rpl_rsp.port_num_blk.portName, &phba->fc_portname,
2956 sizeof(struct lpfc_name));
2957
2958 memcpy(pcmd, &rpl_rsp, cmdsize - sizeof(uint32_t));
2959
2960
2961 /* Xmit ELS RPL ACC response tag <ulpIoTag> */
2962 lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
James Smart5b8bd0c2007-04-25 09:52:49 -04002963 "%d:0120 Xmit ELS RPL ACC response tag x%x xri x%x, "
2964 "did x%x, nlp_flag x%x, nlp_state x%x, rpi x%x\n",
2965 phba->brd_no, elsiocb->iotag,
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05002966 elsiocb->iocb.ulpContext, ndlp->nlp_DID,
2967 ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi);
2968
2969 elsiocb->iocb_cmpl = lpfc_cmpl_els_acc;
2970
2971 phba->fc_stat.elsXmitACC++;
2972 if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) {
2973 lpfc_els_free_iocb(phba, elsiocb);
2974 return 1;
2975 }
2976 return 0;
2977}
2978
2979static int
2980lpfc_els_rcv_rpl(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
dea31012005-04-17 16:05:31 -05002981 struct lpfc_nodelist * ndlp)
2982{
2983 struct lpfc_dmabuf *pcmd;
2984 uint32_t *lp;
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05002985 uint32_t maxsize;
2986 uint16_t cmdsize;
2987 RPL *rpl;
2988 struct ls_rjt stat;
dea31012005-04-17 16:05:31 -05002989
Jamie Wellnitz2fe165b2006-02-28 19:25:31 -05002990 if ((ndlp->nlp_state != NLP_STE_UNMAPPED_NODE) &&
2991 (ndlp->nlp_state != NLP_STE_MAPPED_NODE)) {
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05002992 stat.un.b.lsRjtRsvd0 = 0;
2993 stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
2994 stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA;
2995 stat.un.b.vendorUnique = 0;
2996 lpfc_els_rsp_reject(phba, stat.un.lsRjtError, cmdiocb, ndlp);
dea31012005-04-17 16:05:31 -05002997 }
2998
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05002999 pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
3000 lp = (uint32_t *) pcmd->virt;
3001 rpl = (RPL *) (lp + 1);
3002
3003 maxsize = be32_to_cpu(rpl->maxsize);
3004
3005 /* We support only one port */
3006 if ((rpl->index == 0) &&
3007 ((maxsize == 0) ||
3008 ((maxsize * sizeof(uint32_t)) >= sizeof(RPL_RSP)))) {
3009 cmdsize = sizeof(uint32_t) + sizeof(RPL_RSP);
Jamie Wellnitz2fe165b2006-02-28 19:25:31 -05003010 } else {
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05003011 cmdsize = sizeof(uint32_t) + maxsize * sizeof(uint32_t);
3012 }
3013 lpfc_els_rsp_rpl_acc(phba, cmdsize, cmdiocb, ndlp);
dea31012005-04-17 16:05:31 -05003014
3015 return 0;
3016}
3017
3018static int
3019lpfc_els_rcv_farp(struct lpfc_hba * phba,
3020 struct lpfc_iocbq * cmdiocb, struct lpfc_nodelist * ndlp)
3021{
3022 struct lpfc_dmabuf *pcmd;
3023 uint32_t *lp;
3024 IOCB_t *icmd;
3025 FARP *fp;
3026 uint32_t cmd, cnt, did;
3027
3028 icmd = &cmdiocb->iocb;
3029 did = icmd->un.elsreq64.remoteID;
3030 pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
3031 lp = (uint32_t *) pcmd->virt;
3032
3033 cmd = *lp++;
3034 fp = (FARP *) lp;
3035
3036 /* FARP-REQ received from DID <did> */
3037 lpfc_printf_log(phba,
3038 KERN_INFO,
James Smarta4bc3372006-12-02 13:34:16 -05003039 LOG_ELS,
dea31012005-04-17 16:05:31 -05003040 "%d:0601 FARP-REQ received from DID x%x\n",
3041 phba->brd_no, did);
3042
3043 /* We will only support match on WWPN or WWNN */
3044 if (fp->Mflags & ~(FARP_MATCH_NODE | FARP_MATCH_PORT)) {
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05003045 return 0;
dea31012005-04-17 16:05:31 -05003046 }
3047
3048 cnt = 0;
3049 /* If this FARP command is searching for my portname */
3050 if (fp->Mflags & FARP_MATCH_PORT) {
3051 if (memcmp(&fp->RportName, &phba->fc_portname,
3052 sizeof (struct lpfc_name)) == 0)
3053 cnt = 1;
3054 }
3055
3056 /* If this FARP command is searching for my nodename */
3057 if (fp->Mflags & FARP_MATCH_NODE) {
3058 if (memcmp(&fp->RnodeName, &phba->fc_nodename,
3059 sizeof (struct lpfc_name)) == 0)
3060 cnt = 1;
3061 }
3062
3063 if (cnt) {
3064 if ((ndlp->nlp_state == NLP_STE_UNMAPPED_NODE) ||
3065 (ndlp->nlp_state == NLP_STE_MAPPED_NODE)) {
3066 /* Log back into the node before sending the FARP. */
3067 if (fp->Rflags & FARP_REQUEST_PLOGI) {
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05003068 ndlp->nlp_prev_state = ndlp->nlp_state;
James Smartde0c5b32007-04-25 09:52:27 -04003069 lpfc_nlp_set_state(phba, ndlp,
3070 NLP_STE_PLOGI_ISSUE);
James Smart488d1462006-03-07 15:02:37 -05003071 lpfc_issue_els_plogi(phba, ndlp->nlp_DID, 0);
dea31012005-04-17 16:05:31 -05003072 }
3073
3074 /* Send a FARP response to that node */
3075 if (fp->Rflags & FARP_REQUEST_FARPR) {
3076 lpfc_issue_els_farpr(phba, did, 0);
3077 }
3078 }
3079 }
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05003080 return 0;
dea31012005-04-17 16:05:31 -05003081}
3082
3083static int
3084lpfc_els_rcv_farpr(struct lpfc_hba * phba,
3085 struct lpfc_iocbq * cmdiocb, struct lpfc_nodelist * ndlp)
3086{
3087 struct lpfc_dmabuf *pcmd;
3088 uint32_t *lp;
3089 IOCB_t *icmd;
3090 uint32_t cmd, did;
3091
3092 icmd = &cmdiocb->iocb;
3093 did = icmd->un.elsreq64.remoteID;
3094 pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
3095 lp = (uint32_t *) pcmd->virt;
3096
3097 cmd = *lp++;
3098 /* FARP-RSP received from DID <did> */
3099 lpfc_printf_log(phba,
3100 KERN_INFO,
James Smarta4bc3372006-12-02 13:34:16 -05003101 LOG_ELS,
dea31012005-04-17 16:05:31 -05003102 "%d:0600 FARP-RSP received from DID x%x\n",
3103 phba->brd_no, did);
3104
3105 /* ACCEPT the Farp resp request */
3106 lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0);
3107
3108 return 0;
3109}
3110
3111static int
3112lpfc_els_rcv_fan(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05003113 struct lpfc_nodelist * fan_ndlp)
dea31012005-04-17 16:05:31 -05003114{
3115 struct lpfc_dmabuf *pcmd;
3116 uint32_t *lp;
3117 IOCB_t *icmd;
dea31012005-04-17 16:05:31 -05003118 uint32_t cmd, did;
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05003119 FAN *fp;
3120 struct lpfc_nodelist *ndlp, *next_ndlp;
3121
3122 /* FAN received */
James Smartdca94792006-08-01 07:34:08 -04003123 lpfc_printf_log(phba, KERN_INFO, LOG_ELS, "%d:0265 FAN received\n",
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05003124 phba->brd_no);
dea31012005-04-17 16:05:31 -05003125
3126 icmd = &cmdiocb->iocb;
3127 did = icmd->un.elsreq64.remoteID;
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05003128 pcmd = (struct lpfc_dmabuf *)cmdiocb->context2;
3129 lp = (uint32_t *)pcmd->virt;
dea31012005-04-17 16:05:31 -05003130
3131 cmd = *lp++;
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05003132 fp = (FAN *)lp;
dea31012005-04-17 16:05:31 -05003133
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05003134 /* FAN received; Fan does not have a reply sequence */
dea31012005-04-17 16:05:31 -05003135
3136 if (phba->hba_state == LPFC_LOCAL_CFG_LINK) {
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05003137 if ((memcmp(&phba->fc_fabparam.nodeName, &fp->FnodeName,
3138 sizeof(struct lpfc_name)) != 0) ||
3139 (memcmp(&phba->fc_fabparam.portName, &fp->FportName,
3140 sizeof(struct lpfc_name)) != 0)) {
3141 /*
3142 * This node has switched fabrics. FLOGI is required
3143 * Clean up the old rpi's
dea31012005-04-17 16:05:31 -05003144 */
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05003145
3146 list_for_each_entry_safe(ndlp, next_ndlp,
3147 &phba->fc_npr_list, nlp_listp) {
3148
3149 if (ndlp->nlp_type & NLP_FABRIC) {
3150 /*
3151 * Clean up old Fabric, Nameserver and
3152 * other NLP_FABRIC logins
3153 */
James Smartde0c5b32007-04-25 09:52:27 -04003154 lpfc_drop_node(phba, ndlp);
Jamie Wellnitz2fe165b2006-02-28 19:25:31 -05003155 } else if (!(ndlp->nlp_flag & NLP_NPR_ADISC)) {
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05003156 /* Fail outstanding I/O now since this
3157 * device is marked for PLOGI
3158 */
3159 lpfc_unreg_rpi(phba, ndlp);
3160 }
3161 }
3162
3163 phba->hba_state = LPFC_FLOGI;
3164 lpfc_set_disctmo(phba);
3165 lpfc_initial_flogi(phba);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05003166 return 0;
dea31012005-04-17 16:05:31 -05003167 }
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05003168 /* Discovery not needed,
3169 * move the nodes to their original state.
3170 */
3171 list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_npr_list,
3172 nlp_listp) {
dea31012005-04-17 16:05:31 -05003173
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05003174 switch (ndlp->nlp_prev_state) {
3175 case NLP_STE_UNMAPPED_NODE:
3176 ndlp->nlp_prev_state = NLP_STE_NPR_NODE;
James Smartde0c5b32007-04-25 09:52:27 -04003177 lpfc_nlp_set_state(phba, ndlp,
3178 NLP_STE_UNMAPPED_NODE);
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05003179 break;
3180
3181 case NLP_STE_MAPPED_NODE:
3182 ndlp->nlp_prev_state = NLP_STE_NPR_NODE;
James Smartde0c5b32007-04-25 09:52:27 -04003183 lpfc_nlp_set_state(phba, ndlp,
3184 NLP_STE_MAPPED_NODE);
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05003185 break;
3186
3187 default:
3188 break;
3189 }
3190 }
3191
3192 /* Start discovery - this should just do CLEAR_LA */
dea31012005-04-17 16:05:31 -05003193 lpfc_disc_start(phba);
3194 }
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05003195 return 0;
dea31012005-04-17 16:05:31 -05003196}
3197
3198void
3199lpfc_els_timeout(unsigned long ptr)
3200{
3201 struct lpfc_hba *phba;
3202 unsigned long iflag;
3203
3204 phba = (struct lpfc_hba *)ptr;
3205 if (phba == 0)
3206 return;
3207 spin_lock_irqsave(phba->host->host_lock, iflag);
3208 if (!(phba->work_hba_events & WORKER_ELS_TMO)) {
3209 phba->work_hba_events |= WORKER_ELS_TMO;
3210 if (phba->work_wait)
3211 wake_up(phba->work_wait);
3212 }
3213 spin_unlock_irqrestore(phba->host->host_lock, iflag);
3214 return;
3215}
3216
3217void
3218lpfc_els_timeout_handler(struct lpfc_hba *phba)
3219{
3220 struct lpfc_sli_ring *pring;
3221 struct lpfc_iocbq *tmp_iocb, *piocb;
3222 IOCB_t *cmd = NULL;
3223 struct lpfc_dmabuf *pcmd;
dea31012005-04-17 16:05:31 -05003224 uint32_t *elscmd;
James Smart7054a602007-04-25 09:52:34 -04003225 uint32_t els_command=0;
dea31012005-04-17 16:05:31 -05003226 uint32_t timeout;
3227 uint32_t remote_ID;
3228
3229 if (phba == 0)
3230 return;
3231 spin_lock_irq(phba->host->host_lock);
3232 /* If the timer is already canceled do nothing */
3233 if (!(phba->work_hba_events & WORKER_ELS_TMO)) {
3234 spin_unlock_irq(phba->host->host_lock);
3235 return;
3236 }
3237 timeout = (uint32_t)(phba->fc_ratov << 1);
3238
3239 pring = &phba->sli.ring[LPFC_ELS_RING];
dea31012005-04-17 16:05:31 -05003240
3241 list_for_each_entry_safe(piocb, tmp_iocb, &pring->txcmplq, list) {
3242 cmd = &piocb->iocb;
3243
James Smart7054a602007-04-25 09:52:34 -04003244 if ((piocb->iocb_flag & LPFC_IO_LIBDFC) ||
3245 (piocb->iocb.ulpCommand == CMD_ABORT_XRI_CN) ||
3246 (piocb->iocb.ulpCommand == CMD_CLOSE_XRI_CN)) {
dea31012005-04-17 16:05:31 -05003247 continue;
3248 }
3249 pcmd = (struct lpfc_dmabuf *) piocb->context2;
James Smart7054a602007-04-25 09:52:34 -04003250 if (pcmd) {
3251 elscmd = (uint32_t *) (pcmd->virt);
3252 els_command = *elscmd;
3253 }
dea31012005-04-17 16:05:31 -05003254
3255 if ((els_command == ELS_CMD_FARP)
3256 || (els_command == ELS_CMD_FARPR)) {
3257 continue;
3258 }
3259
3260 if (piocb->drvrTimeout > 0) {
3261 if (piocb->drvrTimeout >= timeout) {
3262 piocb->drvrTimeout -= timeout;
3263 } else {
3264 piocb->drvrTimeout = 0;
3265 }
3266 continue;
3267 }
3268
dea31012005-04-17 16:05:31 -05003269 if (cmd->ulpCommand == CMD_GEN_REQUEST64_CR) {
3270 struct lpfc_nodelist *ndlp;
James Smart2534ba72007-04-25 09:52:20 -04003271 ndlp = __lpfc_findnode_rpi(phba, cmd->ulpContext);
dea31012005-04-17 16:05:31 -05003272 remote_ID = ndlp->nlp_DID;
dea31012005-04-17 16:05:31 -05003273 } else {
3274 remote_ID = cmd->un.elsreq64.remoteID;
3275 }
3276
3277 lpfc_printf_log(phba,
3278 KERN_ERR,
3279 LOG_ELS,
3280 "%d:0127 ELS timeout Data: x%x x%x x%x x%x\n",
3281 phba->brd_no, els_command,
3282 remote_ID, cmd->ulpCommand, cmd->ulpIoTag);
3283
James Smart07951072007-04-25 09:51:38 -04003284 lpfc_sli_issue_abort_iotag(phba, pring, piocb);
dea31012005-04-17 16:05:31 -05003285 }
James Smart5a0e3262006-07-06 15:49:16 -04003286 if (phba->sli.ring[LPFC_ELS_RING].txcmplq_cnt)
3287 mod_timer(&phba->els_tmofunc, jiffies + HZ * timeout);
3288
dea31012005-04-17 16:05:31 -05003289 spin_unlock_irq(phba->host->host_lock);
3290}
3291
3292void
James Smart329f9bc2007-04-25 09:53:01 -04003293lpfc_els_flush_cmd(struct lpfc_hba *phba)
dea31012005-04-17 16:05:31 -05003294{
James Smart2534ba72007-04-25 09:52:20 -04003295 LIST_HEAD(completions);
James Smart329f9bc2007-04-25 09:53:01 -04003296 struct lpfc_sli_ring *pring = &phba->sli.ring[LPFC_ELS_RING];
dea31012005-04-17 16:05:31 -05003297 struct lpfc_iocbq *tmp_iocb, *piocb;
3298 IOCB_t *cmd = NULL;
dea31012005-04-17 16:05:31 -05003299
dea31012005-04-17 16:05:31 -05003300 spin_lock_irq(phba->host->host_lock);
3301 list_for_each_entry_safe(piocb, tmp_iocb, &pring->txq, list) {
3302 cmd = &piocb->iocb;
3303
3304 if (piocb->iocb_flag & LPFC_IO_LIBDFC) {
3305 continue;
3306 }
3307
3308 /* Do not flush out the QUE_RING and ABORT/CLOSE iocbs */
James Smart329f9bc2007-04-25 09:53:01 -04003309 if (cmd->ulpCommand == CMD_QUE_RING_BUF_CN ||
3310 cmd->ulpCommand == CMD_QUE_RING_BUF64_CN ||
3311 cmd->ulpCommand == CMD_CLOSE_XRI_CN ||
3312 cmd->ulpCommand == CMD_ABORT_XRI_CN)
dea31012005-04-17 16:05:31 -05003313 continue;
dea31012005-04-17 16:05:31 -05003314
James Smart2534ba72007-04-25 09:52:20 -04003315 list_move_tail(&piocb->list, &completions);
James Smart1dcb58e2007-04-25 09:51:30 -04003316 pring->txq_cnt--;
dea31012005-04-17 16:05:31 -05003317
dea31012005-04-17 16:05:31 -05003318 }
3319
3320 list_for_each_entry_safe(piocb, tmp_iocb, &pring->txcmplq, list) {
3321 cmd = &piocb->iocb;
3322
3323 if (piocb->iocb_flag & LPFC_IO_LIBDFC) {
3324 continue;
3325 }
dea31012005-04-17 16:05:31 -05003326
James Smart07951072007-04-25 09:51:38 -04003327 lpfc_sli_issue_abort_iotag(phba, pring, piocb);
dea31012005-04-17 16:05:31 -05003328 }
3329 spin_unlock_irq(phba->host->host_lock);
James Smart2534ba72007-04-25 09:52:20 -04003330
3331 while(!list_empty(&completions)) {
3332 piocb = list_get_first(&completions, struct lpfc_iocbq, list);
3333 cmd = &piocb->iocb;
3334 list_del(&piocb->list);
3335
3336 if (piocb->iocb_cmpl) {
3337 cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
3338 cmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
3339 (piocb->iocb_cmpl) (phba, piocb, piocb);
3340 } else
3341 lpfc_sli_release_iocbq(phba, piocb);
3342 }
3343
dea31012005-04-17 16:05:31 -05003344 return;
3345}
3346
3347void
3348lpfc_els_unsol_event(struct lpfc_hba * phba,
3349 struct lpfc_sli_ring * pring, struct lpfc_iocbq * elsiocb)
3350{
3351 struct lpfc_sli *psli;
3352 struct lpfc_nodelist *ndlp;
3353 struct lpfc_dmabuf *mp;
3354 uint32_t *lp;
3355 IOCB_t *icmd;
3356 struct ls_rjt stat;
3357 uint32_t cmd;
3358 uint32_t did;
3359 uint32_t newnode;
3360 uint32_t drop_cmd = 0; /* by default do NOT drop received cmd */
3361 uint32_t rjt_err = 0;
3362
3363 psli = &phba->sli;
3364 icmd = &elsiocb->iocb;
3365
3366 if ((icmd->ulpStatus == IOSTAT_LOCAL_REJECT) &&
3367 ((icmd->un.ulpWord[4] & 0xff) == IOERR_RCV_BUFFER_WAITING)) {
3368 /* Not enough posted buffers; Try posting more buffers */
3369 phba->fc_stat.NoRcvBuf++;
3370 lpfc_post_buffer(phba, pring, 0, 1);
3371 return;
3372 }
3373
3374 /* If there are no BDEs associated with this IOCB,
3375 * there is nothing to do.
3376 */
3377 if (icmd->ulpBdeCount == 0)
3378 return;
3379
3380 /* type of ELS cmd is first 32bit word in packet */
3381 mp = lpfc_sli_ringpostbuf_get(phba, pring, getPaddr(icmd->un.
3382 cont64[0].
3383 addrHigh,
3384 icmd->un.
3385 cont64[0].addrLow));
3386 if (mp == 0) {
3387 drop_cmd = 1;
3388 goto dropit;
3389 }
3390
3391 newnode = 0;
3392 lp = (uint32_t *) mp->virt;
3393 cmd = *lp++;
3394 lpfc_post_buffer(phba, &psli->ring[LPFC_ELS_RING], 1, 1);
3395
3396 if (icmd->ulpStatus) {
3397 lpfc_mbuf_free(phba, mp->virt, mp->phys);
3398 kfree(mp);
3399 drop_cmd = 1;
3400 goto dropit;
3401 }
3402
3403 /* Check to see if link went down during discovery */
3404 if (lpfc_els_chk_latt(phba)) {
3405 lpfc_mbuf_free(phba, mp->virt, mp->phys);
3406 kfree(mp);
3407 drop_cmd = 1;
3408 goto dropit;
3409 }
3410
3411 did = icmd->un.rcvels.remoteID;
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05003412 ndlp = lpfc_findnode_did(phba, NLP_SEARCH_ALL, did);
3413 if (!ndlp) {
dea31012005-04-17 16:05:31 -05003414 /* Cannot find existing Fabric ndlp, so allocate a new one */
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05003415 ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL);
3416 if (!ndlp) {
dea31012005-04-17 16:05:31 -05003417 lpfc_mbuf_free(phba, mp->virt, mp->phys);
3418 kfree(mp);
3419 drop_cmd = 1;
3420 goto dropit;
3421 }
3422
3423 lpfc_nlp_init(phba, ndlp, did);
3424 newnode = 1;
3425 if ((did & Fabric_DID_MASK) == Fabric_DID_MASK) {
3426 ndlp->nlp_type |= NLP_FABRIC;
3427 }
James Smartde0c5b32007-04-25 09:52:27 -04003428 lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNUSED_NODE);
dea31012005-04-17 16:05:31 -05003429 }
3430
3431 phba->fc_stat.elsRcvFrame++;
James Smart329f9bc2007-04-25 09:53:01 -04003432 if (elsiocb->context1)
3433 lpfc_nlp_put(elsiocb->context1);
3434 elsiocb->context1 = lpfc_nlp_get(ndlp);
dea31012005-04-17 16:05:31 -05003435 elsiocb->context2 = mp;
3436
3437 if ((cmd & ELS_CMD_MASK) == ELS_CMD_RSCN) {
3438 cmd &= ELS_CMD_MASK;
3439 }
3440 /* ELS command <elsCmd> received from NPORT <did> */
3441 lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
3442 "%d:0112 ELS command x%x received from NPORT x%x "
3443 "Data: x%x\n", phba->brd_no, cmd, did, phba->hba_state);
3444
3445 switch (cmd) {
3446 case ELS_CMD_PLOGI:
3447 phba->fc_stat.elsRcvPLOGI++;
3448 if (phba->hba_state < LPFC_DISC_AUTH) {
James.Smart@Emulex.Com1f679ca2005-06-25 10:34:27 -04003449 rjt_err = 1;
dea31012005-04-17 16:05:31 -05003450 break;
3451 }
James Smart92795652006-07-06 15:50:02 -04003452 ndlp = lpfc_plogi_confirm_nport(phba, mp, ndlp);
dea31012005-04-17 16:05:31 -05003453 lpfc_disc_state_machine(phba, ndlp, elsiocb, NLP_EVT_RCV_PLOGI);
3454 break;
3455 case ELS_CMD_FLOGI:
3456 phba->fc_stat.elsRcvFLOGI++;
3457 lpfc_els_rcv_flogi(phba, elsiocb, ndlp, newnode);
James Smartde0c5b32007-04-25 09:52:27 -04003458 if (newnode)
3459 lpfc_drop_node(phba, ndlp);
dea31012005-04-17 16:05:31 -05003460 break;
3461 case ELS_CMD_LOGO:
3462 phba->fc_stat.elsRcvLOGO++;
3463 if (phba->hba_state < LPFC_DISC_AUTH) {
James.Smart@Emulex.Com1f679ca2005-06-25 10:34:27 -04003464 rjt_err = 1;
dea31012005-04-17 16:05:31 -05003465 break;
3466 }
3467 lpfc_disc_state_machine(phba, ndlp, elsiocb, NLP_EVT_RCV_LOGO);
3468 break;
3469 case ELS_CMD_PRLO:
3470 phba->fc_stat.elsRcvPRLO++;
3471 if (phba->hba_state < LPFC_DISC_AUTH) {
James.Smart@Emulex.Com1f679ca2005-06-25 10:34:27 -04003472 rjt_err = 1;
dea31012005-04-17 16:05:31 -05003473 break;
3474 }
3475 lpfc_disc_state_machine(phba, ndlp, elsiocb, NLP_EVT_RCV_PRLO);
3476 break;
3477 case ELS_CMD_RSCN:
3478 phba->fc_stat.elsRcvRSCN++;
3479 lpfc_els_rcv_rscn(phba, elsiocb, ndlp, newnode);
James Smartde0c5b32007-04-25 09:52:27 -04003480 if (newnode)
3481 lpfc_drop_node(phba, ndlp);
dea31012005-04-17 16:05:31 -05003482 break;
3483 case ELS_CMD_ADISC:
3484 phba->fc_stat.elsRcvADISC++;
3485 if (phba->hba_state < LPFC_DISC_AUTH) {
James.Smart@Emulex.Com1f679ca2005-06-25 10:34:27 -04003486 rjt_err = 1;
dea31012005-04-17 16:05:31 -05003487 break;
3488 }
3489 lpfc_disc_state_machine(phba, ndlp, elsiocb, NLP_EVT_RCV_ADISC);
3490 break;
3491 case ELS_CMD_PDISC:
3492 phba->fc_stat.elsRcvPDISC++;
3493 if (phba->hba_state < LPFC_DISC_AUTH) {
James.Smart@Emulex.Com1f679ca2005-06-25 10:34:27 -04003494 rjt_err = 1;
dea31012005-04-17 16:05:31 -05003495 break;
3496 }
3497 lpfc_disc_state_machine(phba, ndlp, elsiocb, NLP_EVT_RCV_PDISC);
3498 break;
3499 case ELS_CMD_FARPR:
3500 phba->fc_stat.elsRcvFARPR++;
3501 lpfc_els_rcv_farpr(phba, elsiocb, ndlp);
3502 break;
3503 case ELS_CMD_FARP:
3504 phba->fc_stat.elsRcvFARP++;
3505 lpfc_els_rcv_farp(phba, elsiocb, ndlp);
3506 break;
3507 case ELS_CMD_FAN:
3508 phba->fc_stat.elsRcvFAN++;
3509 lpfc_els_rcv_fan(phba, elsiocb, ndlp);
3510 break;
dea31012005-04-17 16:05:31 -05003511 case ELS_CMD_PRLI:
3512 phba->fc_stat.elsRcvPRLI++;
3513 if (phba->hba_state < LPFC_DISC_AUTH) {
James.Smart@Emulex.Com1f679ca2005-06-25 10:34:27 -04003514 rjt_err = 1;
dea31012005-04-17 16:05:31 -05003515 break;
3516 }
3517 lpfc_disc_state_machine(phba, ndlp, elsiocb, NLP_EVT_RCV_PRLI);
3518 break;
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05003519 case ELS_CMD_LIRR:
3520 phba->fc_stat.elsRcvLIRR++;
3521 lpfc_els_rcv_lirr(phba, elsiocb, ndlp);
James Smartde0c5b32007-04-25 09:52:27 -04003522 if (newnode)
3523 lpfc_drop_node(phba, ndlp);
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05003524 break;
3525 case ELS_CMD_RPS:
3526 phba->fc_stat.elsRcvRPS++;
3527 lpfc_els_rcv_rps(phba, elsiocb, ndlp);
James Smartde0c5b32007-04-25 09:52:27 -04003528 if (newnode)
3529 lpfc_drop_node(phba, ndlp);
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05003530 break;
3531 case ELS_CMD_RPL:
3532 phba->fc_stat.elsRcvRPL++;
3533 lpfc_els_rcv_rpl(phba, elsiocb, ndlp);
James Smartde0c5b32007-04-25 09:52:27 -04003534 if (newnode)
3535 lpfc_drop_node(phba, ndlp);
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05003536 break;
dea31012005-04-17 16:05:31 -05003537 case ELS_CMD_RNID:
3538 phba->fc_stat.elsRcvRNID++;
3539 lpfc_els_rcv_rnid(phba, elsiocb, ndlp);
James Smartde0c5b32007-04-25 09:52:27 -04003540 if (newnode)
3541 lpfc_drop_node(phba, ndlp);
dea31012005-04-17 16:05:31 -05003542 break;
3543 default:
3544 /* Unsupported ELS command, reject */
James.Smart@Emulex.Com1f679ca2005-06-25 10:34:27 -04003545 rjt_err = 1;
dea31012005-04-17 16:05:31 -05003546
3547 /* Unknown ELS command <elsCmd> received from NPORT <did> */
3548 lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
3549 "%d:0115 Unknown ELS command x%x received from "
3550 "NPORT x%x\n", phba->brd_no, cmd, did);
James Smartde0c5b32007-04-25 09:52:27 -04003551 if (newnode)
3552 lpfc_drop_node(phba, ndlp);
dea31012005-04-17 16:05:31 -05003553 break;
3554 }
3555
3556 /* check if need to LS_RJT received ELS cmd */
3557 if (rjt_err) {
3558 stat.un.b.lsRjtRsvd0 = 0;
3559 stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
James.Smart@Emulex.Com1f679ca2005-06-25 10:34:27 -04003560 stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE;
dea31012005-04-17 16:05:31 -05003561 stat.un.b.vendorUnique = 0;
3562 lpfc_els_rsp_reject(phba, stat.un.lsRjtError, elsiocb, ndlp);
3563 }
3564
James Smart329f9bc2007-04-25 09:53:01 -04003565 lpfc_nlp_put(elsiocb->context1);
3566 elsiocb->context1 = NULL;
dea31012005-04-17 16:05:31 -05003567 if (elsiocb->context2) {
3568 lpfc_mbuf_free(phba, mp->virt, mp->phys);
3569 kfree(mp);
3570 }
3571dropit:
3572 /* check if need to drop received ELS cmd */
3573 if (drop_cmd == 1) {
3574 lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
3575 "%d:0111 Dropping received ELS cmd "
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05003576 "Data: x%x x%x x%x\n", phba->brd_no,
3577 icmd->ulpStatus, icmd->un.ulpWord[4],
3578 icmd->ulpTimeout);
dea31012005-04-17 16:05:31 -05003579 phba->fc_stat.elsRcvDrop++;
3580 }
3581 return;
3582}