blob: 43049b9d64c9ea5d715d8cbc259b462a6eb2b9fa [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. *
James Smarte47c9092008-02-08 18:49:26 -05004 * Copyright (C) 2004-2008 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 *******************************************************************/
James Smart09372822008-01-11 01:52:54 -050021/* See Fibre Channel protocol T11 FC-LS for details */
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"
James Smart92d7f7b2007-06-17 19:56:38 -050038#include "lpfc_vport.h"
James Smart858c9f62007-06-17 19:56:39 -050039#include "lpfc_debugfs.h"
dea31012005-04-17 16:05:31 -050040
41static int lpfc_els_retry(struct lpfc_hba *, struct lpfc_iocbq *,
42 struct lpfc_iocbq *);
James Smart92d7f7b2007-06-17 19:56:38 -050043static void lpfc_cmpl_fabric_iocb(struct lpfc_hba *, struct lpfc_iocbq *,
44 struct lpfc_iocbq *);
Adrian Bunka6ababd2007-11-05 18:07:33 +010045static void lpfc_fabric_abort_vport(struct lpfc_vport *vport);
46static int lpfc_issue_els_fdisc(struct lpfc_vport *vport,
47 struct lpfc_nodelist *ndlp, uint8_t retry);
48static int lpfc_issue_fabric_iocb(struct lpfc_hba *phba,
49 struct lpfc_iocbq *iocb);
50static void lpfc_register_new_vport(struct lpfc_hba *phba,
51 struct lpfc_vport *vport,
52 struct lpfc_nodelist *ndlp);
James Smart92d7f7b2007-06-17 19:56:38 -050053
dea31012005-04-17 16:05:31 -050054static int lpfc_max_els_tries = 3;
55
James Smarte59058c2008-08-24 21:49:00 -040056/**
57 * lpfc_els_chk_latt: Check host link attention event for a vport.
58 * @vport: pointer to a host virtual N_Port data structure.
59 *
60 * This routine checks whether there is an outstanding host link
61 * attention event during the discovery process with the @vport. It is done
62 * by reading the HBA's Host Attention (HA) register. If there is any host
63 * link attention events during this @vport's discovery process, the @vport
64 * shall be marked as FC_ABORT_DISCOVERY, a host link attention clear shall
65 * be issued if the link state is not already in host link cleared state,
66 * and a return code shall indicate whether the host link attention event
67 * had happened.
68 *
69 * Note that, if either the host link is in state LPFC_LINK_DOWN or @vport
70 * state in LPFC_VPORT_READY, the request for checking host link attention
71 * event will be ignored and a return code shall indicate no host link
72 * attention event had happened.
73 *
74 * Return codes
75 * 0 - no host link attention event happened
76 * 1 - host link attention event happened
77 **/
James Smart858c9f62007-06-17 19:56:39 -050078int
James Smart2e0fef82007-06-17 19:56:36 -050079lpfc_els_chk_latt(struct lpfc_vport *vport)
dea31012005-04-17 16:05:31 -050080{
James Smart2e0fef82007-06-17 19:56:36 -050081 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
82 struct lpfc_hba *phba = vport->phba;
dea31012005-04-17 16:05:31 -050083 uint32_t ha_copy;
dea31012005-04-17 16:05:31 -050084
James Smart2e0fef82007-06-17 19:56:36 -050085 if (vport->port_state >= LPFC_VPORT_READY ||
86 phba->link_state == LPFC_LINK_DOWN)
dea31012005-04-17 16:05:31 -050087 return 0;
88
89 /* Read the HBA Host Attention Register */
dea31012005-04-17 16:05:31 -050090 ha_copy = readl(phba->HAregaddr);
dea31012005-04-17 16:05:31 -050091
92 if (!(ha_copy & HA_LATT))
93 return 0;
94
95 /* Pending Link Event during Discovery */
James Smarte8b62012007-08-02 11:10:09 -040096 lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY,
97 "0237 Pending Link Event during "
98 "Discovery: State x%x\n",
99 phba->pport->port_state);
dea31012005-04-17 16:05:31 -0500100
101 /* CLEAR_LA should re-enable link attention events and
102 * we should then imediately take a LATT event. The
103 * LATT processing should call lpfc_linkdown() which
104 * will cleanup any left over in-progress discovery
105 * events.
106 */
James Smart2e0fef82007-06-17 19:56:36 -0500107 spin_lock_irq(shost->host_lock);
108 vport->fc_flag |= FC_ABORT_DISCOVERY;
109 spin_unlock_irq(shost->host_lock);
dea31012005-04-17 16:05:31 -0500110
James Smart92d7f7b2007-06-17 19:56:38 -0500111 if (phba->link_state != LPFC_CLEAR_LA)
James Smarted957682007-06-17 19:56:37 -0500112 lpfc_issue_clear_la(phba, vport);
dea31012005-04-17 16:05:31 -0500113
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500114 return 1;
dea31012005-04-17 16:05:31 -0500115}
116
James Smarte59058c2008-08-24 21:49:00 -0400117/**
118 * lpfc_prep_els_iocb: Allocate and prepare a lpfc iocb data structure.
119 * @vport: pointer to a host virtual N_Port data structure.
120 * @expectRsp: flag indicating whether response is expected.
121 * @cmdSize: size of the ELS command.
122 * @retry: number of retries to the command IOCB when it fails.
123 * @ndlp: pointer to a node-list data structure.
124 * @did: destination identifier.
125 * @elscmd: the ELS command code.
126 *
127 * This routine is used for allocating a lpfc-IOCB data structure from
128 * the driver lpfc-IOCB free-list and prepare the IOCB with the parameters
129 * passed into the routine for discovery state machine to issue an Extended
130 * Link Service (ELS) commands. It is a generic lpfc-IOCB allocation
131 * and preparation routine that is used by all the discovery state machine
132 * routines and the ELS command-specific fields will be later set up by
133 * the individual discovery machine routines after calling this routine
134 * allocating and preparing a generic IOCB data structure. It fills in the
135 * Buffer Descriptor Entries (BDEs), allocates buffers for both command
136 * payload and response payload (if expected). The reference count on the
137 * ndlp is incremented by 1 and the reference to the ndlp is put into
138 * context1 of the IOCB data structure for this IOCB to hold the ndlp
139 * reference for the command's callback function to access later.
140 *
141 * Return code
142 * Pointer to the newly allocated/prepared els iocb data structure
143 * NULL - when els iocb data structure allocation/preparation failed
144 **/
dea31012005-04-17 16:05:31 -0500145static struct lpfc_iocbq *
James Smart2e0fef82007-06-17 19:56:36 -0500146lpfc_prep_els_iocb(struct lpfc_vport *vport, uint8_t expectRsp,
147 uint16_t cmdSize, uint8_t retry,
148 struct lpfc_nodelist *ndlp, uint32_t did,
149 uint32_t elscmd)
dea31012005-04-17 16:05:31 -0500150{
James Smart2e0fef82007-06-17 19:56:36 -0500151 struct lpfc_hba *phba = vport->phba;
James.Smart@Emulex.Com0bd4ca22005-10-28 20:30:02 -0400152 struct lpfc_iocbq *elsiocb;
dea31012005-04-17 16:05:31 -0500153 struct lpfc_dmabuf *pcmd, *prsp, *pbuflist;
154 struct ulp_bde64 *bpl;
155 IOCB_t *icmd;
156
dea31012005-04-17 16:05:31 -0500157
James Smart2e0fef82007-06-17 19:56:36 -0500158 if (!lpfc_is_link_up(phba))
159 return NULL;
dea31012005-04-17 16:05:31 -0500160
dea31012005-04-17 16:05:31 -0500161 /* Allocate buffer for command iocb */
James.Smart@Emulex.Com0bd4ca22005-10-28 20:30:02 -0400162 elsiocb = lpfc_sli_get_iocbq(phba);
dea31012005-04-17 16:05:31 -0500163
164 if (elsiocb == NULL)
165 return NULL;
James Smarte47c9092008-02-08 18:49:26 -0500166
dea31012005-04-17 16:05:31 -0500167 icmd = &elsiocb->iocb;
168
169 /* fill in BDEs for command */
170 /* Allocate buffer for command payload */
James Smart98c9ea52007-10-27 13:37:33 -0400171 pcmd = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL);
172 if (pcmd)
173 pcmd->virt = lpfc_mbuf_alloc(phba, MEM_PRI, &pcmd->phys);
James Smartfa4066b2008-01-11 01:53:27 -0500174 if (!pcmd || !pcmd->virt)
175 goto els_iocb_free_pcmb_exit;
dea31012005-04-17 16:05:31 -0500176
177 INIT_LIST_HEAD(&pcmd->list);
178
179 /* Allocate buffer for response payload */
180 if (expectRsp) {
James Smart92d7f7b2007-06-17 19:56:38 -0500181 prsp = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL);
dea31012005-04-17 16:05:31 -0500182 if (prsp)
183 prsp->virt = lpfc_mbuf_alloc(phba, MEM_PRI,
184 &prsp->phys);
James Smartfa4066b2008-01-11 01:53:27 -0500185 if (!prsp || !prsp->virt)
186 goto els_iocb_free_prsp_exit;
dea31012005-04-17 16:05:31 -0500187 INIT_LIST_HEAD(&prsp->list);
James Smarte47c9092008-02-08 18:49:26 -0500188 } else
dea31012005-04-17 16:05:31 -0500189 prsp = NULL;
dea31012005-04-17 16:05:31 -0500190
191 /* Allocate buffer for Buffer ptr list */
James Smart92d7f7b2007-06-17 19:56:38 -0500192 pbuflist = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL);
dea31012005-04-17 16:05:31 -0500193 if (pbuflist)
James Smarted957682007-06-17 19:56:37 -0500194 pbuflist->virt = lpfc_mbuf_alloc(phba, MEM_PRI,
195 &pbuflist->phys);
James Smartfa4066b2008-01-11 01:53:27 -0500196 if (!pbuflist || !pbuflist->virt)
197 goto els_iocb_free_pbuf_exit;
dea31012005-04-17 16:05:31 -0500198
199 INIT_LIST_HEAD(&pbuflist->list);
200
201 icmd->un.elsreq64.bdl.addrHigh = putPaddrHigh(pbuflist->phys);
202 icmd->un.elsreq64.bdl.addrLow = putPaddrLow(pbuflist->phys);
203 icmd->un.elsreq64.bdl.bdeFlags = BUFF_TYPE_BDL;
James Smart2e0fef82007-06-17 19:56:36 -0500204 icmd->un.elsreq64.remoteID = did; /* DID */
dea31012005-04-17 16:05:31 -0500205 if (expectRsp) {
James Smart92d7f7b2007-06-17 19:56:38 -0500206 icmd->un.elsreq64.bdl.bdeSize = (2 * sizeof(struct ulp_bde64));
dea31012005-04-17 16:05:31 -0500207 icmd->ulpCommand = CMD_ELS_REQUEST64_CR;
James Smart2680eea2007-04-25 09:52:55 -0400208 icmd->ulpTimeout = phba->fc_ratov * 2;
dea31012005-04-17 16:05:31 -0500209 } else {
James Smart92d7f7b2007-06-17 19:56:38 -0500210 icmd->un.elsreq64.bdl.bdeSize = sizeof(struct ulp_bde64);
dea31012005-04-17 16:05:31 -0500211 icmd->ulpCommand = CMD_XMIT_ELS_RSP64_CX;
212 }
dea31012005-04-17 16:05:31 -0500213 icmd->ulpBdeCount = 1;
214 icmd->ulpLe = 1;
215 icmd->ulpClass = CLASS3;
216
James Smart92d7f7b2007-06-17 19:56:38 -0500217 if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) {
218 icmd->un.elsreq64.myID = vport->fc_myDID;
219
220 /* For ELS_REQUEST64_CR, use the VPI by default */
221 icmd->ulpContext = vport->vpi;
222 icmd->ulpCt_h = 0;
223 icmd->ulpCt_l = 1;
224 }
225
dea31012005-04-17 16:05:31 -0500226 bpl = (struct ulp_bde64 *) pbuflist->virt;
227 bpl->addrLow = le32_to_cpu(putPaddrLow(pcmd->phys));
228 bpl->addrHigh = le32_to_cpu(putPaddrHigh(pcmd->phys));
229 bpl->tus.f.bdeSize = cmdSize;
230 bpl->tus.f.bdeFlags = 0;
231 bpl->tus.w = le32_to_cpu(bpl->tus.w);
232
233 if (expectRsp) {
234 bpl++;
235 bpl->addrLow = le32_to_cpu(putPaddrLow(prsp->phys));
236 bpl->addrHigh = le32_to_cpu(putPaddrHigh(prsp->phys));
237 bpl->tus.f.bdeSize = FCELSSIZE;
238 bpl->tus.f.bdeFlags = BUFF_USE_RCV;
239 bpl->tus.w = le32_to_cpu(bpl->tus.w);
240 }
241
James Smartfa4066b2008-01-11 01:53:27 -0500242 /* prevent preparing iocb with NULL ndlp reference */
James Smart51ef4c22007-08-02 11:10:31 -0400243 elsiocb->context1 = lpfc_nlp_get(ndlp);
James Smartfa4066b2008-01-11 01:53:27 -0500244 if (!elsiocb->context1)
245 goto els_iocb_free_pbuf_exit;
James Smart329f9bc2007-04-25 09:53:01 -0400246 elsiocb->context2 = pcmd;
247 elsiocb->context3 = pbuflist;
dea31012005-04-17 16:05:31 -0500248 elsiocb->retry = retry;
James Smart2e0fef82007-06-17 19:56:36 -0500249 elsiocb->vport = vport;
dea31012005-04-17 16:05:31 -0500250 elsiocb->drvrTimeout = (phba->fc_ratov << 1) + LPFC_DRVR_TIMEOUT;
251
252 if (prsp) {
253 list_add(&prsp->list, &pcmd->list);
254 }
dea31012005-04-17 16:05:31 -0500255 if (expectRsp) {
256 /* Xmit ELS command <elsCmd> to remote NPORT <did> */
James Smarte8b62012007-08-02 11:10:09 -0400257 lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
258 "0116 Xmit ELS command x%x to remote "
259 "NPORT x%x I/O tag: x%x, port state: x%x\n",
260 elscmd, did, elsiocb->iotag,
261 vport->port_state);
dea31012005-04-17 16:05:31 -0500262 } else {
263 /* Xmit ELS response <elsCmd> to remote NPORT <did> */
James Smarte8b62012007-08-02 11:10:09 -0400264 lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
265 "0117 Xmit ELS response x%x to remote "
266 "NPORT x%x I/O tag: x%x, size: x%x\n",
267 elscmd, ndlp->nlp_DID, elsiocb->iotag,
268 cmdSize);
dea31012005-04-17 16:05:31 -0500269 }
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500270 return elsiocb;
dea31012005-04-17 16:05:31 -0500271
James Smartfa4066b2008-01-11 01:53:27 -0500272els_iocb_free_pbuf_exit:
273 lpfc_mbuf_free(phba, prsp->virt, prsp->phys);
274 kfree(pbuflist);
275
276els_iocb_free_prsp_exit:
277 lpfc_mbuf_free(phba, pcmd->virt, pcmd->phys);
278 kfree(prsp);
279
280els_iocb_free_pcmb_exit:
281 kfree(pcmd);
282 lpfc_sli_release_iocbq(phba, elsiocb);
283 return NULL;
284}
dea31012005-04-17 16:05:31 -0500285
James Smarte59058c2008-08-24 21:49:00 -0400286/**
287 * lpfc_issue_fabric_reglogin: Issue fabric registration login for a vport.
288 * @vport: pointer to a host virtual N_Port data structure.
289 *
290 * This routine issues a fabric registration login for a @vport. An
291 * active ndlp node with Fabric_DID must already exist for this @vport.
292 * The routine invokes two mailbox commands to carry out fabric registration
293 * login through the HBA firmware: the first mailbox command requests the
294 * HBA to perform link configuration for the @vport; and the second mailbox
295 * command requests the HBA to perform the actual fabric registration login
296 * with the @vport.
297 *
298 * Return code
299 * 0 - successfully issued fabric registration login for @vport
300 * -ENXIO -- failed to issue fabric registration login for @vport
301 **/
dea31012005-04-17 16:05:31 -0500302static int
James Smart92d7f7b2007-06-17 19:56:38 -0500303lpfc_issue_fabric_reglogin(struct lpfc_vport *vport)
304{
305 struct lpfc_hba *phba = vport->phba;
306 LPFC_MBOXQ_t *mbox;
307 struct lpfc_dmabuf *mp;
308 struct lpfc_nodelist *ndlp;
309 struct serv_parm *sp;
310 int rc;
James Smart98c9ea52007-10-27 13:37:33 -0400311 int err = 0;
James Smart92d7f7b2007-06-17 19:56:38 -0500312
313 sp = &phba->fc_fabparam;
314 ndlp = lpfc_findnode_did(vport, Fabric_DID);
James Smarte47c9092008-02-08 18:49:26 -0500315 if (!ndlp || !NLP_CHK_NODE_ACT(ndlp)) {
James Smart98c9ea52007-10-27 13:37:33 -0400316 err = 1;
James Smart92d7f7b2007-06-17 19:56:38 -0500317 goto fail;
James Smart98c9ea52007-10-27 13:37:33 -0400318 }
James Smart92d7f7b2007-06-17 19:56:38 -0500319
320 mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
James Smart98c9ea52007-10-27 13:37:33 -0400321 if (!mbox) {
322 err = 2;
James Smart92d7f7b2007-06-17 19:56:38 -0500323 goto fail;
James Smart98c9ea52007-10-27 13:37:33 -0400324 }
James Smart92d7f7b2007-06-17 19:56:38 -0500325
326 vport->port_state = LPFC_FABRIC_CFG_LINK;
327 lpfc_config_link(phba, mbox);
328 mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
329 mbox->vport = vport;
330
James Smart0b727fe2007-10-27 13:37:25 -0400331 rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT);
James Smart98c9ea52007-10-27 13:37:33 -0400332 if (rc == MBX_NOT_FINISHED) {
333 err = 3;
James Smart92d7f7b2007-06-17 19:56:38 -0500334 goto fail_free_mbox;
James Smart98c9ea52007-10-27 13:37:33 -0400335 }
James Smart92d7f7b2007-06-17 19:56:38 -0500336
337 mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
James Smart98c9ea52007-10-27 13:37:33 -0400338 if (!mbox) {
339 err = 4;
James Smart92d7f7b2007-06-17 19:56:38 -0500340 goto fail;
James Smart98c9ea52007-10-27 13:37:33 -0400341 }
James Smart92d7f7b2007-06-17 19:56:38 -0500342 rc = lpfc_reg_login(phba, vport->vpi, Fabric_DID, (uint8_t *)sp, mbox,
343 0);
James Smart98c9ea52007-10-27 13:37:33 -0400344 if (rc) {
345 err = 5;
James Smart92d7f7b2007-06-17 19:56:38 -0500346 goto fail_free_mbox;
James Smart98c9ea52007-10-27 13:37:33 -0400347 }
James Smart92d7f7b2007-06-17 19:56:38 -0500348
349 mbox->mbox_cmpl = lpfc_mbx_cmpl_fabric_reg_login;
350 mbox->vport = vport;
James Smarte47c9092008-02-08 18:49:26 -0500351 /* increment the reference count on ndlp to hold reference
352 * for the callback routine.
353 */
James Smart92d7f7b2007-06-17 19:56:38 -0500354 mbox->context2 = lpfc_nlp_get(ndlp);
355
James Smart0b727fe2007-10-27 13:37:25 -0400356 rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT);
James Smart98c9ea52007-10-27 13:37:33 -0400357 if (rc == MBX_NOT_FINISHED) {
358 err = 6;
James Smart92d7f7b2007-06-17 19:56:38 -0500359 goto fail_issue_reg_login;
James Smart98c9ea52007-10-27 13:37:33 -0400360 }
James Smart92d7f7b2007-06-17 19:56:38 -0500361
362 return 0;
363
364fail_issue_reg_login:
James Smarte47c9092008-02-08 18:49:26 -0500365 /* decrement the reference count on ndlp just incremented
366 * for the failed mbox command.
367 */
James Smart92d7f7b2007-06-17 19:56:38 -0500368 lpfc_nlp_put(ndlp);
369 mp = (struct lpfc_dmabuf *) mbox->context1;
370 lpfc_mbuf_free(phba, mp->virt, mp->phys);
371 kfree(mp);
372fail_free_mbox:
373 mempool_free(mbox, phba->mbox_mem_pool);
374
375fail:
376 lpfc_vport_set_state(vport, FC_VPORT_FAILED);
James Smarte8b62012007-08-02 11:10:09 -0400377 lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
James Smart98c9ea52007-10-27 13:37:33 -0400378 "0249 Cannot issue Register Fabric login: Err %d\n", err);
James Smart92d7f7b2007-06-17 19:56:38 -0500379 return -ENXIO;
380}
381
James Smarte59058c2008-08-24 21:49:00 -0400382/**
383 * lpfc_cmpl_els_flogi_fabric: Completion function for flogi to a fabric port.
384 * @vport: pointer to a host virtual N_Port data structure.
385 * @ndlp: pointer to a node-list data structure.
386 * @sp: pointer to service parameter data structure.
387 * @irsp: pointer to the IOCB within the lpfc response IOCB.
388 *
389 * This routine is invoked by the lpfc_cmpl_els_flogi() completion callback
390 * function to handle the completion of a Fabric Login (FLOGI) into a fabric
391 * port in a fabric topology. It properly sets up the parameters to the @ndlp
392 * from the IOCB response. It also check the newly assigned N_Port ID to the
393 * @vport against the previously assigned N_Port ID. If it is different from
394 * the previously assigned Destination ID (DID), the lpfc_unreg_rpi() routine
395 * is invoked on all the remaining nodes with the @vport to unregister the
396 * Remote Port Indicators (RPIs). Finally, the lpfc_issue_fabric_reglogin()
397 * is invoked to register login to the fabric.
398 *
399 * Return code
400 * 0 - Success (currently, always return 0)
401 **/
James Smart92d7f7b2007-06-17 19:56:38 -0500402static int
James Smart2e0fef82007-06-17 19:56:36 -0500403lpfc_cmpl_els_flogi_fabric(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
404 struct serv_parm *sp, IOCB_t *irsp)
dea31012005-04-17 16:05:31 -0500405{
James Smart2e0fef82007-06-17 19:56:36 -0500406 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
407 struct lpfc_hba *phba = vport->phba;
James Smart92d7f7b2007-06-17 19:56:38 -0500408 struct lpfc_nodelist *np;
409 struct lpfc_nodelist *next_np;
dea31012005-04-17 16:05:31 -0500410
James Smart2e0fef82007-06-17 19:56:36 -0500411 spin_lock_irq(shost->host_lock);
412 vport->fc_flag |= FC_FABRIC;
413 spin_unlock_irq(shost->host_lock);
dea31012005-04-17 16:05:31 -0500414
415 phba->fc_edtov = be32_to_cpu(sp->cmn.e_d_tov);
416 if (sp->cmn.edtovResolution) /* E_D_TOV ticks are in nanoseconds */
417 phba->fc_edtov = (phba->fc_edtov + 999999) / 1000000;
418
419 phba->fc_ratov = (be32_to_cpu(sp->cmn.w2.r_a_tov) + 999) / 1000;
420
421 if (phba->fc_topology == TOPOLOGY_LOOP) {
James Smart2e0fef82007-06-17 19:56:36 -0500422 spin_lock_irq(shost->host_lock);
423 vport->fc_flag |= FC_PUBLIC_LOOP;
424 spin_unlock_irq(shost->host_lock);
dea31012005-04-17 16:05:31 -0500425 } else {
426 /*
427 * If we are a N-port connected to a Fabric, fixup sparam's so
428 * logins to devices on remote loops work.
429 */
James Smart2e0fef82007-06-17 19:56:36 -0500430 vport->fc_sparam.cmn.altBbCredit = 1;
dea31012005-04-17 16:05:31 -0500431 }
432
James Smart2e0fef82007-06-17 19:56:36 -0500433 vport->fc_myDID = irsp->un.ulpWord[4] & Mask_DID;
dea31012005-04-17 16:05:31 -0500434 memcpy(&ndlp->nlp_portname, &sp->portName, sizeof(struct lpfc_name));
James Smart92d7f7b2007-06-17 19:56:38 -0500435 memcpy(&ndlp->nlp_nodename, &sp->nodeName, sizeof(struct lpfc_name));
dea31012005-04-17 16:05:31 -0500436 ndlp->nlp_class_sup = 0;
437 if (sp->cls1.classValid)
438 ndlp->nlp_class_sup |= FC_COS_CLASS1;
439 if (sp->cls2.classValid)
440 ndlp->nlp_class_sup |= FC_COS_CLASS2;
441 if (sp->cls3.classValid)
442 ndlp->nlp_class_sup |= FC_COS_CLASS3;
443 if (sp->cls4.classValid)
444 ndlp->nlp_class_sup |= FC_COS_CLASS4;
445 ndlp->nlp_maxframe = ((sp->cmn.bbRcvSizeMsb & 0x0F) << 8) |
446 sp->cmn.bbRcvSizeLsb;
447 memcpy(&phba->fc_fabparam, sp, sizeof(struct serv_parm));
448
James Smart92d7f7b2007-06-17 19:56:38 -0500449 if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) {
450 if (sp->cmn.response_multiple_NPort) {
James Smarte8b62012007-08-02 11:10:09 -0400451 lpfc_printf_vlog(vport, KERN_WARNING,
452 LOG_ELS | LOG_VPORT,
453 "1816 FLOGI NPIV supported, "
454 "response data 0x%x\n",
455 sp->cmn.response_multiple_NPort);
James Smart92d7f7b2007-06-17 19:56:38 -0500456 phba->link_flag |= LS_NPIV_FAB_SUPPORTED;
James Smart92d7f7b2007-06-17 19:56:38 -0500457 } else {
458 /* Because we asked f/w for NPIV it still expects us
James Smarte8b62012007-08-02 11:10:09 -0400459 to call reg_vnpid atleast for the physcial host */
460 lpfc_printf_vlog(vport, KERN_WARNING,
461 LOG_ELS | LOG_VPORT,
462 "1817 Fabric does not support NPIV "
463 "- configuring single port mode.\n");
James Smart92d7f7b2007-06-17 19:56:38 -0500464 phba->link_flag &= ~LS_NPIV_FAB_SUPPORTED;
465 }
466 }
467
468 if ((vport->fc_prevDID != vport->fc_myDID) &&
469 !(vport->fc_flag & FC_VPORT_NEEDS_REG_VPI)) {
470
471 /* If our NportID changed, we need to ensure all
472 * remaining NPORTs get unreg_login'ed.
473 */
474 list_for_each_entry_safe(np, next_np,
475 &vport->fc_nodes, nlp_listp) {
James Smarte47c9092008-02-08 18:49:26 -0500476 if (!NLP_CHK_NODE_ACT(ndlp))
477 continue;
James Smart92d7f7b2007-06-17 19:56:38 -0500478 if ((np->nlp_state != NLP_STE_NPR_NODE) ||
479 !(np->nlp_flag & NLP_NPR_ADISC))
480 continue;
481 spin_lock_irq(shost->host_lock);
482 np->nlp_flag &= ~NLP_NPR_ADISC;
483 spin_unlock_irq(shost->host_lock);
484 lpfc_unreg_rpi(vport, np);
485 }
486 if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) {
487 lpfc_mbx_unreg_vpi(vport);
James Smart09372822008-01-11 01:52:54 -0500488 spin_lock_irq(shost->host_lock);
James Smart92d7f7b2007-06-17 19:56:38 -0500489 vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI;
James Smart09372822008-01-11 01:52:54 -0500490 spin_unlock_irq(shost->host_lock);
James Smart92d7f7b2007-06-17 19:56:38 -0500491 }
492 }
493
James Smart92d7f7b2007-06-17 19:56:38 -0500494 lpfc_nlp_set_state(vport, ndlp, NLP_STE_REG_LOGIN_ISSUE);
James Smart2e0fef82007-06-17 19:56:36 -0500495
James Smart92d7f7b2007-06-17 19:56:38 -0500496 if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED &&
497 vport->fc_flag & FC_VPORT_NEEDS_REG_VPI) {
498 lpfc_register_new_vport(phba, vport, ndlp);
499 return 0;
500 }
501 lpfc_issue_fabric_reglogin(vport);
dea31012005-04-17 16:05:31 -0500502 return 0;
dea31012005-04-17 16:05:31 -0500503}
504
James Smarte59058c2008-08-24 21:49:00 -0400505/**
506 * lpfc_cmpl_els_flogi_nport: Completion function for flogi to an N_Port.
507 * @vport: pointer to a host virtual N_Port data structure.
508 * @ndlp: pointer to a node-list data structure.
509 * @sp: pointer to service parameter data structure.
510 *
511 * This routine is invoked by the lpfc_cmpl_els_flogi() completion callback
512 * function to handle the completion of a Fabric Login (FLOGI) into an N_Port
513 * in a point-to-point topology. First, the @vport's N_Port Name is compared
514 * with the received N_Port Name: if the @vport's N_Port Name is greater than
515 * the received N_Port Name lexicographically, this node shall assign local
516 * N_Port ID (PT2PT_LocalID: 1) and remote N_Port ID (PT2PT_RemoteID: 2) and
517 * will send out Port Login (PLOGI) with the N_Port IDs assigned. Otherwise,
518 * this node shall just wait for the remote node to issue PLOGI and assign
519 * N_Port IDs.
520 *
521 * Return code
522 * 0 - Success
523 * -ENXIO - Fail
524 **/
dea31012005-04-17 16:05:31 -0500525static int
James Smart2e0fef82007-06-17 19:56:36 -0500526lpfc_cmpl_els_flogi_nport(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
527 struct serv_parm *sp)
dea31012005-04-17 16:05:31 -0500528{
James Smart2e0fef82007-06-17 19:56:36 -0500529 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
530 struct lpfc_hba *phba = vport->phba;
dea31012005-04-17 16:05:31 -0500531 LPFC_MBOXQ_t *mbox;
532 int rc;
533
James Smart2e0fef82007-06-17 19:56:36 -0500534 spin_lock_irq(shost->host_lock);
535 vport->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP);
536 spin_unlock_irq(shost->host_lock);
dea31012005-04-17 16:05:31 -0500537
538 phba->fc_edtov = FF_DEF_EDTOV;
539 phba->fc_ratov = FF_DEF_RATOV;
James Smart2e0fef82007-06-17 19:56:36 -0500540 rc = memcmp(&vport->fc_portname, &sp->portName,
James Smart92d7f7b2007-06-17 19:56:38 -0500541 sizeof(vport->fc_portname));
dea31012005-04-17 16:05:31 -0500542 if (rc >= 0) {
543 /* This side will initiate the PLOGI */
James Smart2e0fef82007-06-17 19:56:36 -0500544 spin_lock_irq(shost->host_lock);
545 vport->fc_flag |= FC_PT2PT_PLOGI;
546 spin_unlock_irq(shost->host_lock);
dea31012005-04-17 16:05:31 -0500547
548 /*
549 * N_Port ID cannot be 0, set our to LocalID the other
550 * side will be RemoteID.
551 */
552
553 /* not equal */
554 if (rc)
James Smart2e0fef82007-06-17 19:56:36 -0500555 vport->fc_myDID = PT2PT_LocalID;
dea31012005-04-17 16:05:31 -0500556
557 mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
558 if (!mbox)
559 goto fail;
560
561 lpfc_config_link(phba, mbox);
562
563 mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
James Smarted957682007-06-17 19:56:37 -0500564 mbox->vport = vport;
James Smart0b727fe2007-10-27 13:37:25 -0400565 rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT);
dea31012005-04-17 16:05:31 -0500566 if (rc == MBX_NOT_FINISHED) {
567 mempool_free(mbox, phba->mbox_mem_pool);
568 goto fail;
569 }
James Smarte47c9092008-02-08 18:49:26 -0500570 /* Decrement ndlp reference count indicating that ndlp can be
571 * safely released when other references to it are done.
572 */
James Smart329f9bc2007-04-25 09:53:01 -0400573 lpfc_nlp_put(ndlp);
dea31012005-04-17 16:05:31 -0500574
James Smart2e0fef82007-06-17 19:56:36 -0500575 ndlp = lpfc_findnode_did(vport, PT2PT_RemoteID);
dea31012005-04-17 16:05:31 -0500576 if (!ndlp) {
577 /*
578 * Cannot find existing Fabric ndlp, so allocate a
579 * new one
580 */
581 ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL);
582 if (!ndlp)
583 goto fail;
James Smart2e0fef82007-06-17 19:56:36 -0500584 lpfc_nlp_init(vport, ndlp, PT2PT_RemoteID);
James Smarte47c9092008-02-08 18:49:26 -0500585 } else if (!NLP_CHK_NODE_ACT(ndlp)) {
586 ndlp = lpfc_enable_node(vport, ndlp,
587 NLP_STE_UNUSED_NODE);
588 if(!ndlp)
589 goto fail;
dea31012005-04-17 16:05:31 -0500590 }
591
592 memcpy(&ndlp->nlp_portname, &sp->portName,
James Smart2e0fef82007-06-17 19:56:36 -0500593 sizeof(struct lpfc_name));
dea31012005-04-17 16:05:31 -0500594 memcpy(&ndlp->nlp_nodename, &sp->nodeName,
James Smart2e0fef82007-06-17 19:56:36 -0500595 sizeof(struct lpfc_name));
James Smarte47c9092008-02-08 18:49:26 -0500596 /* Set state will put ndlp onto node list if not already done */
James Smart2e0fef82007-06-17 19:56:36 -0500597 lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
598 spin_lock_irq(shost->host_lock);
dea31012005-04-17 16:05:31 -0500599 ndlp->nlp_flag |= NLP_NPR_2B_DISC;
James Smart2e0fef82007-06-17 19:56:36 -0500600 spin_unlock_irq(shost->host_lock);
James Smarte47c9092008-02-08 18:49:26 -0500601 } else
602 /* This side will wait for the PLOGI, decrement ndlp reference
603 * count indicating that ndlp can be released when other
604 * references to it are done.
605 */
James Smart329f9bc2007-04-25 09:53:01 -0400606 lpfc_nlp_put(ndlp);
dea31012005-04-17 16:05:31 -0500607
James Smart09372822008-01-11 01:52:54 -0500608 /* If we are pt2pt with another NPort, force NPIV off! */
609 phba->sli3_options &= ~LPFC_SLI3_NPIV_ENABLED;
610
James Smart2e0fef82007-06-17 19:56:36 -0500611 spin_lock_irq(shost->host_lock);
612 vport->fc_flag |= FC_PT2PT;
613 spin_unlock_irq(shost->host_lock);
dea31012005-04-17 16:05:31 -0500614
615 /* Start discovery - this should just do CLEAR_LA */
James Smart2e0fef82007-06-17 19:56:36 -0500616 lpfc_disc_start(vport);
dea31012005-04-17 16:05:31 -0500617 return 0;
James Smart92d7f7b2007-06-17 19:56:38 -0500618fail:
dea31012005-04-17 16:05:31 -0500619 return -ENXIO;
620}
621
James Smarte59058c2008-08-24 21:49:00 -0400622/**
623 * lpfc_cmpl_els_flogi: Completion callback function for flogi.
624 * @phba: pointer to lpfc hba data structure.
625 * @cmdiocb: pointer to lpfc command iocb data structure.
626 * @rspiocb: pointer to lpfc response iocb data structure.
627 *
628 * This routine is the top-level completion callback function for issuing
629 * a Fabric Login (FLOGI) command. If the response IOCB reported error,
630 * the lpfc_els_retry() routine shall be invoked to retry the FLOGI. If
631 * retry has been made (either immediately or delayed with lpfc_els_retry()
632 * returning 1), the command IOCB will be released and function returned.
633 * If the retry attempt has been given up (possibly reach the maximum
634 * number of retries), one additional decrement of ndlp reference shall be
635 * invoked before going out after releasing the command IOCB. This will
636 * actually release the remote node (Note, lpfc_els_free_iocb() will also
637 * invoke one decrement of ndlp reference count). If no error reported in
638 * the IOCB status, the command Port ID field is used to determine whether
639 * this is a point-to-point topology or a fabric topology: if the Port ID
640 * field is assigned, it is a fabric topology; otherwise, it is a
641 * point-to-point topology. The routine lpfc_cmpl_els_flogi_fabric() or
642 * lpfc_cmpl_els_flogi_nport() shall be invoked accordingly to handle the
643 * specific topology completion conditions.
644 **/
dea31012005-04-17 16:05:31 -0500645static void
James Smart329f9bc2007-04-25 09:53:01 -0400646lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
647 struct lpfc_iocbq *rspiocb)
dea31012005-04-17 16:05:31 -0500648{
James Smart2e0fef82007-06-17 19:56:36 -0500649 struct lpfc_vport *vport = cmdiocb->vport;
650 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
dea31012005-04-17 16:05:31 -0500651 IOCB_t *irsp = &rspiocb->iocb;
652 struct lpfc_nodelist *ndlp = cmdiocb->context1;
653 struct lpfc_dmabuf *pcmd = cmdiocb->context2, *prsp;
654 struct serv_parm *sp;
655 int rc;
656
657 /* Check to see if link went down during discovery */
James Smart2e0fef82007-06-17 19:56:36 -0500658 if (lpfc_els_chk_latt(vport)) {
James Smartfa4066b2008-01-11 01:53:27 -0500659 /* One additional decrement on node reference count to
660 * trigger the release of the node
661 */
James Smart329f9bc2007-04-25 09:53:01 -0400662 lpfc_nlp_put(ndlp);
dea31012005-04-17 16:05:31 -0500663 goto out;
664 }
665
James Smart858c9f62007-06-17 19:56:39 -0500666 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
667 "FLOGI cmpl: status:x%x/x%x state:x%x",
668 irsp->ulpStatus, irsp->un.ulpWord[4],
669 vport->port_state);
670
dea31012005-04-17 16:05:31 -0500671 if (irsp->ulpStatus) {
672 /* Check for retry */
James Smart2e0fef82007-06-17 19:56:36 -0500673 if (lpfc_els_retry(phba, cmdiocb, rspiocb))
dea31012005-04-17 16:05:31 -0500674 goto out;
James Smart2e0fef82007-06-17 19:56:36 -0500675
dea31012005-04-17 16:05:31 -0500676 /* FLOGI failed, so there is no fabric */
James Smart2e0fef82007-06-17 19:56:36 -0500677 spin_lock_irq(shost->host_lock);
678 vport->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP);
679 spin_unlock_irq(shost->host_lock);
dea31012005-04-17 16:05:31 -0500680
James Smart329f9bc2007-04-25 09:53:01 -0400681 /* If private loop, then allow max outstanding els to be
dea31012005-04-17 16:05:31 -0500682 * LPFC_MAX_DISC_THREADS (32). Scanning in the case of no
683 * alpa map would take too long otherwise.
684 */
685 if (phba->alpa_map[0] == 0) {
James Smart3de2a652007-08-02 11:09:59 -0400686 vport->cfg_discovery_threads = LPFC_MAX_DISC_THREADS;
dea31012005-04-17 16:05:31 -0500687 }
688
689 /* FLOGI failure */
James Smarte8b62012007-08-02 11:10:09 -0400690 lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
691 "0100 FLOGI failure Data: x%x x%x "
692 "x%x\n",
693 irsp->ulpStatus, irsp->un.ulpWord[4],
694 irsp->ulpTimeout);
dea31012005-04-17 16:05:31 -0500695 goto flogifail;
696 }
697
698 /*
699 * The FLogI succeeded. Sync the data for the CPU before
700 * accessing it.
701 */
702 prsp = list_get_first(&pcmd->list, struct lpfc_dmabuf, list);
703
704 sp = prsp->virt + sizeof(uint32_t);
705
706 /* FLOGI completes successfully */
James Smarte8b62012007-08-02 11:10:09 -0400707 lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
708 "0101 FLOGI completes sucessfully "
709 "Data: x%x x%x x%x x%x\n",
710 irsp->un.ulpWord[4], sp->cmn.e_d_tov,
711 sp->cmn.w2.r_a_tov, sp->cmn.edtovResolution);
dea31012005-04-17 16:05:31 -0500712
James Smart2e0fef82007-06-17 19:56:36 -0500713 if (vport->port_state == LPFC_FLOGI) {
dea31012005-04-17 16:05:31 -0500714 /*
715 * If Common Service Parameters indicate Nport
716 * we are point to point, if Fport we are Fabric.
717 */
718 if (sp->cmn.fPort)
James Smart2e0fef82007-06-17 19:56:36 -0500719 rc = lpfc_cmpl_els_flogi_fabric(vport, ndlp, sp, irsp);
dea31012005-04-17 16:05:31 -0500720 else
James Smart2e0fef82007-06-17 19:56:36 -0500721 rc = lpfc_cmpl_els_flogi_nport(vport, ndlp, sp);
dea31012005-04-17 16:05:31 -0500722
723 if (!rc)
724 goto out;
725 }
726
727flogifail:
James Smart329f9bc2007-04-25 09:53:01 -0400728 lpfc_nlp_put(ndlp);
dea31012005-04-17 16:05:31 -0500729
James Smart858c9f62007-06-17 19:56:39 -0500730 if (!lpfc_error_lost_link(irsp)) {
dea31012005-04-17 16:05:31 -0500731 /* FLOGI failed, so just use loop map to make discovery list */
James Smart2e0fef82007-06-17 19:56:36 -0500732 lpfc_disc_list_loopmap(vport);
dea31012005-04-17 16:05:31 -0500733
734 /* Start discovery */
James Smart2e0fef82007-06-17 19:56:36 -0500735 lpfc_disc_start(vport);
James Smart87af33f2007-10-27 13:37:43 -0400736 } else if (((irsp->ulpStatus != IOSTAT_LOCAL_REJECT) ||
737 ((irsp->un.ulpWord[4] != IOERR_SLI_ABORTED) &&
738 (irsp->un.ulpWord[4] != IOERR_SLI_DOWN))) &&
739 (phba->link_state != LPFC_CLEAR_LA)) {
740 /* If FLOGI failed enable link interrupt. */
741 lpfc_issue_clear_la(phba, vport);
dea31012005-04-17 16:05:31 -0500742 }
dea31012005-04-17 16:05:31 -0500743out:
744 lpfc_els_free_iocb(phba, cmdiocb);
745}
746
James Smarte59058c2008-08-24 21:49:00 -0400747/**
748 * lpfc_issue_els_flogi: Issue an flogi iocb command for a vport.
749 * @vport: pointer to a host virtual N_Port data structure.
750 * @ndlp: pointer to a node-list data structure.
751 * @retry: number of retries to the command IOCB.
752 *
753 * This routine issues a Fabric Login (FLOGI) Request ELS command
754 * for a @vport. The initiator service parameters are put into the payload
755 * of the FLOGI Request IOCB and the top-level callback function pointer
756 * to lpfc_cmpl_els_flogi() routine is put to the IOCB completion callback
757 * function field. The lpfc_issue_fabric_iocb routine is invoked to send
758 * out FLOGI ELS command with one outstanding fabric IOCB at a time.
759 *
760 * Note that, in lpfc_prep_els_iocb() routine, the reference count of ndlp
761 * will be incremented by 1 for holding the ndlp and the reference to ndlp
762 * will be stored into the context1 field of the IOCB for the completion
763 * callback function to the FLOGI ELS command.
764 *
765 * Return code
766 * 0 - successfully issued flogi iocb for @vport
767 * 1 - failed to issue flogi iocb for @vport
768 **/
dea31012005-04-17 16:05:31 -0500769static int
James Smart2e0fef82007-06-17 19:56:36 -0500770lpfc_issue_els_flogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
dea31012005-04-17 16:05:31 -0500771 uint8_t retry)
772{
James Smart2e0fef82007-06-17 19:56:36 -0500773 struct lpfc_hba *phba = vport->phba;
dea31012005-04-17 16:05:31 -0500774 struct serv_parm *sp;
775 IOCB_t *icmd;
776 struct lpfc_iocbq *elsiocb;
777 struct lpfc_sli_ring *pring;
778 uint8_t *pcmd;
779 uint16_t cmdsize;
780 uint32_t tmo;
781 int rc;
782
783 pring = &phba->sli.ring[LPFC_ELS_RING];
784
James Smart92d7f7b2007-06-17 19:56:38 -0500785 cmdsize = (sizeof(uint32_t) + sizeof(struct serv_parm));
James Smart2e0fef82007-06-17 19:56:36 -0500786 elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp,
787 ndlp->nlp_DID, ELS_CMD_FLOGI);
James Smart92d7f7b2007-06-17 19:56:38 -0500788
James Smart488d1462006-03-07 15:02:37 -0500789 if (!elsiocb)
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500790 return 1;
dea31012005-04-17 16:05:31 -0500791
792 icmd = &elsiocb->iocb;
793 pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
794
795 /* For FLOGI request, remainder of payload is service parameters */
796 *((uint32_t *) (pcmd)) = ELS_CMD_FLOGI;
James Smart92d7f7b2007-06-17 19:56:38 -0500797 pcmd += sizeof(uint32_t);
798 memcpy(pcmd, &vport->fc_sparam, sizeof(struct serv_parm));
dea31012005-04-17 16:05:31 -0500799 sp = (struct serv_parm *) pcmd;
800
801 /* Setup CSPs accordingly for Fabric */
802 sp->cmn.e_d_tov = 0;
803 sp->cmn.w2.r_a_tov = 0;
804 sp->cls1.classValid = 0;
805 sp->cls2.seqDelivery = 1;
806 sp->cls3.seqDelivery = 1;
807 if (sp->cmn.fcphLow < FC_PH3)
808 sp->cmn.fcphLow = FC_PH3;
809 if (sp->cmn.fcphHigh < FC_PH3)
810 sp->cmn.fcphHigh = FC_PH3;
811
James Smart92d7f7b2007-06-17 19:56:38 -0500812 if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) {
813 sp->cmn.request_multiple_Nport = 1;
814
815 /* For FLOGI, Let FLOGI rsp set the NPortID for VPI 0 */
816 icmd->ulpCt_h = 1;
817 icmd->ulpCt_l = 0;
818 }
819
James Smart858c9f62007-06-17 19:56:39 -0500820 if (phba->fc_topology != TOPOLOGY_LOOP) {
821 icmd->un.elsreq64.myID = 0;
822 icmd->un.elsreq64.fl = 1;
823 }
824
dea31012005-04-17 16:05:31 -0500825 tmo = phba->fc_ratov;
826 phba->fc_ratov = LPFC_DISC_FLOGI_TMO;
James Smart2e0fef82007-06-17 19:56:36 -0500827 lpfc_set_disctmo(vport);
dea31012005-04-17 16:05:31 -0500828 phba->fc_ratov = tmo;
829
830 phba->fc_stat.elsXmitFLOGI++;
831 elsiocb->iocb_cmpl = lpfc_cmpl_els_flogi;
James Smart858c9f62007-06-17 19:56:39 -0500832
833 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
834 "Issue FLOGI: opt:x%x",
835 phba->sli3_options, 0, 0);
836
James Smart92d7f7b2007-06-17 19:56:38 -0500837 rc = lpfc_issue_fabric_iocb(phba, elsiocb);
dea31012005-04-17 16:05:31 -0500838 if (rc == IOCB_ERROR) {
839 lpfc_els_free_iocb(phba, elsiocb);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500840 return 1;
dea31012005-04-17 16:05:31 -0500841 }
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500842 return 0;
dea31012005-04-17 16:05:31 -0500843}
844
James Smarte59058c2008-08-24 21:49:00 -0400845/**
846 * lpfc_els_abort_flogi: Abort all outstanding flogi iocbs.
847 * @phba: pointer to lpfc hba data structure.
848 *
849 * This routine aborts all the outstanding Fabric Login (FLOGI) IOCBs
850 * with a @phba. This routine walks all the outstanding IOCBs on the txcmplq
851 * list and issues an abort IOCB commond on each outstanding IOCB that
852 * contains a active Fabric_DID ndlp. Note that this function is to issue
853 * the abort IOCB command on all the outstanding IOCBs, thus when this
854 * function returns, it does not guarantee all the IOCBs are actually aborted.
855 *
856 * Return code
857 * 0 - Sucessfully issued abort iocb on all outstanding flogis (Always 0)
858 **/
dea31012005-04-17 16:05:31 -0500859int
James Smart2e0fef82007-06-17 19:56:36 -0500860lpfc_els_abort_flogi(struct lpfc_hba *phba)
dea31012005-04-17 16:05:31 -0500861{
862 struct lpfc_sli_ring *pring;
863 struct lpfc_iocbq *iocb, *next_iocb;
864 struct lpfc_nodelist *ndlp;
865 IOCB_t *icmd;
866
867 /* Abort outstanding I/O on NPort <nlp_DID> */
868 lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
James Smarte8b62012007-08-02 11:10:09 -0400869 "0201 Abort outstanding I/O on NPort x%x\n",
870 Fabric_DID);
dea31012005-04-17 16:05:31 -0500871
872 pring = &phba->sli.ring[LPFC_ELS_RING];
873
874 /*
875 * Check the txcmplq for an iocb that matches the nport the driver is
876 * searching for.
877 */
James Smart2e0fef82007-06-17 19:56:36 -0500878 spin_lock_irq(&phba->hbalock);
dea31012005-04-17 16:05:31 -0500879 list_for_each_entry_safe(iocb, next_iocb, &pring->txcmplq, list) {
880 icmd = &iocb->iocb;
James Smart2e0fef82007-06-17 19:56:36 -0500881 if (icmd->ulpCommand == CMD_ELS_REQUEST64_CR &&
882 icmd->un.elsreq64.bdl.ulpIoTag32) {
dea31012005-04-17 16:05:31 -0500883 ndlp = (struct lpfc_nodelist *)(iocb->context1);
James Smart58da1ff2008-04-07 10:15:56 -0400884 if (ndlp && NLP_CHK_NODE_ACT(ndlp) &&
885 (ndlp->nlp_DID == Fabric_DID))
James Smart07951072007-04-25 09:51:38 -0400886 lpfc_sli_issue_abort_iotag(phba, pring, iocb);
dea31012005-04-17 16:05:31 -0500887 }
888 }
James Smart2e0fef82007-06-17 19:56:36 -0500889 spin_unlock_irq(&phba->hbalock);
dea31012005-04-17 16:05:31 -0500890
891 return 0;
892}
893
James Smarte59058c2008-08-24 21:49:00 -0400894/**
895 * lpfc_initial_flogi: Issue an initial fabric login for a vport.
896 * @vport: pointer to a host virtual N_Port data structure.
897 *
898 * This routine issues an initial Fabric Login (FLOGI) for the @vport
899 * specified. It first searches the ndlp with the Fabric_DID (0xfffffe) from
900 * the @vport's ndlp list. If no such ndlp found, it will create an ndlp and
901 * put it into the @vport's ndlp list. If an inactive ndlp found on the list,
902 * it will just be enabled and made active. The lpfc_issue_els_flogi() routine
903 * is then invoked with the @vport and the ndlp to perform the FLOGI for the
904 * @vport.
905 *
906 * Return code
907 * 0 - failed to issue initial flogi for @vport
908 * 1 - successfully issued initial flogi for @vport
909 **/
dea31012005-04-17 16:05:31 -0500910int
James Smart2e0fef82007-06-17 19:56:36 -0500911lpfc_initial_flogi(struct lpfc_vport *vport)
dea31012005-04-17 16:05:31 -0500912{
James Smart2e0fef82007-06-17 19:56:36 -0500913 struct lpfc_hba *phba = vport->phba;
dea31012005-04-17 16:05:31 -0500914 struct lpfc_nodelist *ndlp;
915
James Smart98c9ea52007-10-27 13:37:33 -0400916 vport->port_state = LPFC_FLOGI;
917 lpfc_set_disctmo(vport);
918
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500919 /* First look for the Fabric ndlp */
James Smart2e0fef82007-06-17 19:56:36 -0500920 ndlp = lpfc_findnode_did(vport, Fabric_DID);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500921 if (!ndlp) {
dea31012005-04-17 16:05:31 -0500922 /* Cannot find existing Fabric ndlp, so allocate a new one */
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500923 ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL);
924 if (!ndlp)
925 return 0;
James Smart2e0fef82007-06-17 19:56:36 -0500926 lpfc_nlp_init(vport, ndlp, Fabric_DID);
James Smarte47c9092008-02-08 18:49:26 -0500927 /* Put ndlp onto node list */
928 lpfc_enqueue_node(vport, ndlp);
929 } else if (!NLP_CHK_NODE_ACT(ndlp)) {
930 /* re-setup ndlp without removing from node list */
931 ndlp = lpfc_enable_node(vport, ndlp, NLP_STE_UNUSED_NODE);
932 if (!ndlp)
933 return 0;
dea31012005-04-17 16:05:31 -0500934 }
James Smart87af33f2007-10-27 13:37:43 -0400935
James Smarte47c9092008-02-08 18:49:26 -0500936 if (lpfc_issue_els_flogi(vport, ndlp, 0))
James Smartfa4066b2008-01-11 01:53:27 -0500937 /* This decrement of reference count to node shall kick off
938 * the release of the node.
939 */
James Smart329f9bc2007-04-25 09:53:01 -0400940 lpfc_nlp_put(ndlp);
James Smarte47c9092008-02-08 18:49:26 -0500941
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500942 return 1;
dea31012005-04-17 16:05:31 -0500943}
944
James Smarte59058c2008-08-24 21:49:00 -0400945/**
946 * lpfc_initial_fdisc: Issue an initial fabric discovery for a vport.
947 * @vport: pointer to a host virtual N_Port data structure.
948 *
949 * This routine issues an initial Fabric Discover (FDISC) for the @vport
950 * specified. It first searches the ndlp with the Fabric_DID (0xfffffe) from
951 * the @vport's ndlp list. If no such ndlp found, it will create an ndlp and
952 * put it into the @vport's ndlp list. If an inactive ndlp found on the list,
953 * it will just be enabled and made active. The lpfc_issue_els_fdisc() routine
954 * is then invoked with the @vport and the ndlp to perform the FDISC for the
955 * @vport.
956 *
957 * Return code
958 * 0 - failed to issue initial fdisc for @vport
959 * 1 - successfully issued initial fdisc for @vport
960 **/
James Smart92d7f7b2007-06-17 19:56:38 -0500961int
962lpfc_initial_fdisc(struct lpfc_vport *vport)
963{
964 struct lpfc_hba *phba = vport->phba;
965 struct lpfc_nodelist *ndlp;
966
967 /* First look for the Fabric ndlp */
968 ndlp = lpfc_findnode_did(vport, Fabric_DID);
969 if (!ndlp) {
970 /* Cannot find existing Fabric ndlp, so allocate a new one */
971 ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL);
972 if (!ndlp)
973 return 0;
974 lpfc_nlp_init(vport, ndlp, Fabric_DID);
James Smarte47c9092008-02-08 18:49:26 -0500975 /* Put ndlp onto node list */
976 lpfc_enqueue_node(vport, ndlp);
977 } else if (!NLP_CHK_NODE_ACT(ndlp)) {
978 /* re-setup ndlp without removing from node list */
979 ndlp = lpfc_enable_node(vport, ndlp, NLP_STE_UNUSED_NODE);
980 if (!ndlp)
981 return 0;
James Smart92d7f7b2007-06-17 19:56:38 -0500982 }
James Smarte47c9092008-02-08 18:49:26 -0500983
James Smart92d7f7b2007-06-17 19:56:38 -0500984 if (lpfc_issue_els_fdisc(vport, ndlp, 0)) {
James Smartfa4066b2008-01-11 01:53:27 -0500985 /* decrement node reference count to trigger the release of
986 * the node.
987 */
James Smart92d7f7b2007-06-17 19:56:38 -0500988 lpfc_nlp_put(ndlp);
James Smartfa4066b2008-01-11 01:53:27 -0500989 return 0;
James Smart92d7f7b2007-06-17 19:56:38 -0500990 }
991 return 1;
992}
James Smart87af33f2007-10-27 13:37:43 -0400993
James Smarte59058c2008-08-24 21:49:00 -0400994/**
995 * lpfc_more_plogi: Check and issue remaining plogis for a vport.
996 * @vport: pointer to a host virtual N_Port data structure.
997 *
998 * This routine checks whether there are more remaining Port Logins
999 * (PLOGI) to be issued for the @vport. If so, it will invoke the routine
1000 * lpfc_els_disc_plogi() to go through the Node Port Recovery (NPR) nodes
1001 * to issue ELS PLOGIs up to the configured discover threads with the
1002 * @vport (@vport->cfg_discovery_threads). The function also decrement
1003 * the @vport's num_disc_node by 1 if it is not already 0.
1004 **/
James Smart87af33f2007-10-27 13:37:43 -04001005void
James Smart2e0fef82007-06-17 19:56:36 -05001006lpfc_more_plogi(struct lpfc_vport *vport)
dea31012005-04-17 16:05:31 -05001007{
1008 int sentplogi;
1009
James Smart2e0fef82007-06-17 19:56:36 -05001010 if (vport->num_disc_nodes)
1011 vport->num_disc_nodes--;
dea31012005-04-17 16:05:31 -05001012
1013 /* Continue discovery with <num_disc_nodes> PLOGIs to go */
James Smarte8b62012007-08-02 11:10:09 -04001014 lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
1015 "0232 Continue discovery with %d PLOGIs to go "
1016 "Data: x%x x%x x%x\n",
1017 vport->num_disc_nodes, vport->fc_plogi_cnt,
1018 vport->fc_flag, vport->port_state);
dea31012005-04-17 16:05:31 -05001019 /* Check to see if there are more PLOGIs to be sent */
James Smart2e0fef82007-06-17 19:56:36 -05001020 if (vport->fc_flag & FC_NLP_MORE)
1021 /* go thru NPR nodes and issue any remaining ELS PLOGIs */
1022 sentplogi = lpfc_els_disc_plogi(vport);
1023
dea31012005-04-17 16:05:31 -05001024 return;
1025}
1026
James Smarte59058c2008-08-24 21:49:00 -04001027/**
1028 * lpfc_plogi_confirm_nport: Confirm pologi wwpn matches stored ndlp.
1029 * @phba: pointer to lpfc hba data structure.
1030 * @prsp: pointer to response IOCB payload.
1031 * @ndlp: pointer to a node-list data structure.
1032 *
1033 * This routine checks and indicates whether the WWPN of an N_Port, retrieved
1034 * from a PLOGI, matches the WWPN that is stored in the @ndlp for that N_POrt.
1035 * The following cases are considered N_Port confirmed:
1036 * 1) The N_Port is a Fabric ndlp; 2) The @ndlp is on vport list and matches
1037 * the WWPN of the N_Port logged into; 3) The @ndlp is not on vport list but
1038 * it does not have WWPN assigned either. If the WWPN is confirmed, the
1039 * pointer to the @ndlp will be returned. If the WWPN is not confirmed:
1040 * 1) if there is a node on vport list other than the @ndlp with the same
1041 * WWPN of the N_Port PLOGI logged into, the lpfc_unreg_rpi() will be invoked
1042 * on that node to release the RPI associated with the node; 2) if there is
1043 * no node found on vport list with the same WWPN of the N_Port PLOGI logged
1044 * into, a new node shall be allocated (or activated). In either case, the
1045 * parameters of the @ndlp shall be copied to the new_ndlp, the @ndlp shall
1046 * be released and the new_ndlp shall be put on to the vport node list and
1047 * its pointer returned as the confirmed node.
1048 *
1049 * Note that before the @ndlp got "released", the keepDID from not-matching
1050 * or inactive "new_ndlp" on the vport node list is assigned to the nlp_DID
1051 * of the @ndlp. This is because the release of @ndlp is actually to put it
1052 * into an inactive state on the vport node list and the vport node list
1053 * management algorithm does not allow two node with a same DID.
1054 *
1055 * Return code
1056 * pointer to the PLOGI N_Port @ndlp
1057 **/
James Smart488d1462006-03-07 15:02:37 -05001058static struct lpfc_nodelist *
James Smart92d7f7b2007-06-17 19:56:38 -05001059lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t *prsp,
James Smart488d1462006-03-07 15:02:37 -05001060 struct lpfc_nodelist *ndlp)
1061{
James Smart2e0fef82007-06-17 19:56:36 -05001062 struct lpfc_vport *vport = ndlp->vport;
James Smart488d1462006-03-07 15:02:37 -05001063 struct lpfc_nodelist *new_ndlp;
James Smart0ff10d42008-01-11 01:52:36 -05001064 struct lpfc_rport_data *rdata;
1065 struct fc_rport *rport;
James Smart488d1462006-03-07 15:02:37 -05001066 struct serv_parm *sp;
James Smart92d7f7b2007-06-17 19:56:38 -05001067 uint8_t name[sizeof(struct lpfc_name)];
James Smart58da1ff2008-04-07 10:15:56 -04001068 uint32_t rc, keepDID = 0;
James Smart488d1462006-03-07 15:02:37 -05001069
James Smart2fb9bd82006-12-02 13:33:57 -05001070 /* Fabric nodes can have the same WWPN so we don't bother searching
1071 * by WWPN. Just return the ndlp that was given to us.
1072 */
1073 if (ndlp->nlp_type & NLP_FABRIC)
1074 return ndlp;
1075
James Smart92d7f7b2007-06-17 19:56:38 -05001076 sp = (struct serv_parm *) ((uint8_t *) prsp + sizeof(uint32_t));
James Smart685f0bf2007-04-25 09:53:08 -04001077 memset(name, 0, sizeof(struct lpfc_name));
James Smart488d1462006-03-07 15:02:37 -05001078
James Smart685f0bf2007-04-25 09:53:08 -04001079 /* Now we find out if the NPort we are logging into, matches the WWPN
James Smart488d1462006-03-07 15:02:37 -05001080 * we have for that ndlp. If not, we have some work to do.
1081 */
James Smart2e0fef82007-06-17 19:56:36 -05001082 new_ndlp = lpfc_findnode_wwpn(vport, &sp->portName);
James Smart488d1462006-03-07 15:02:37 -05001083
James Smarte47c9092008-02-08 18:49:26 -05001084 if (new_ndlp == ndlp && NLP_CHK_NODE_ACT(new_ndlp))
James Smart488d1462006-03-07 15:02:37 -05001085 return ndlp;
James Smart488d1462006-03-07 15:02:37 -05001086
1087 if (!new_ndlp) {
James Smart2e0fef82007-06-17 19:56:36 -05001088 rc = memcmp(&ndlp->nlp_portname, name,
1089 sizeof(struct lpfc_name));
James Smart92795652006-07-06 15:50:02 -04001090 if (!rc)
1091 return ndlp;
James Smart488d1462006-03-07 15:02:37 -05001092 new_ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_ATOMIC);
1093 if (!new_ndlp)
1094 return ndlp;
James Smart2e0fef82007-06-17 19:56:36 -05001095 lpfc_nlp_init(vport, new_ndlp, ndlp->nlp_DID);
James Smarte47c9092008-02-08 18:49:26 -05001096 } else if (!NLP_CHK_NODE_ACT(new_ndlp)) {
James Smart58da1ff2008-04-07 10:15:56 -04001097 rc = memcmp(&ndlp->nlp_portname, name,
1098 sizeof(struct lpfc_name));
1099 if (!rc)
1100 return ndlp;
James Smarte47c9092008-02-08 18:49:26 -05001101 new_ndlp = lpfc_enable_node(vport, new_ndlp,
1102 NLP_STE_UNUSED_NODE);
1103 if (!new_ndlp)
1104 return ndlp;
James Smart58da1ff2008-04-07 10:15:56 -04001105 keepDID = new_ndlp->nlp_DID;
1106 } else
1107 keepDID = new_ndlp->nlp_DID;
James Smart488d1462006-03-07 15:02:37 -05001108
James Smart2e0fef82007-06-17 19:56:36 -05001109 lpfc_unreg_rpi(vport, new_ndlp);
James Smart488d1462006-03-07 15:02:37 -05001110 new_ndlp->nlp_DID = ndlp->nlp_DID;
James Smart92795652006-07-06 15:50:02 -04001111 new_ndlp->nlp_prev_state = ndlp->nlp_prev_state;
James Smart0ff10d42008-01-11 01:52:36 -05001112
1113 if (ndlp->nlp_flag & NLP_NPR_2B_DISC)
1114 new_ndlp->nlp_flag |= NLP_NPR_2B_DISC;
1115 ndlp->nlp_flag &= ~NLP_NPR_2B_DISC;
1116
James Smarte47c9092008-02-08 18:49:26 -05001117 /* Set state will put new_ndlp on to node list if not already done */
James Smart2e0fef82007-06-17 19:56:36 -05001118 lpfc_nlp_set_state(vport, new_ndlp, ndlp->nlp_state);
James Smart488d1462006-03-07 15:02:37 -05001119
James Smart2e0fef82007-06-17 19:56:36 -05001120 /* Move this back to NPR state */
James Smart87af33f2007-10-27 13:37:43 -04001121 if (memcmp(&ndlp->nlp_portname, name, sizeof(struct lpfc_name)) == 0) {
1122 /* The new_ndlp is replacing ndlp totally, so we need
1123 * to put ndlp on UNUSED list and try to free it.
1124 */
James Smart0ff10d42008-01-11 01:52:36 -05001125
1126 /* Fix up the rport accordingly */
1127 rport = ndlp->rport;
1128 if (rport) {
1129 rdata = rport->dd_data;
1130 if (rdata->pnode == ndlp) {
1131 lpfc_nlp_put(ndlp);
1132 ndlp->rport = NULL;
1133 rdata->pnode = lpfc_nlp_get(new_ndlp);
1134 new_ndlp->rport = rport;
1135 }
1136 new_ndlp->nlp_type = ndlp->nlp_type;
1137 }
James Smart58da1ff2008-04-07 10:15:56 -04001138 /* We shall actually free the ndlp with both nlp_DID and
1139 * nlp_portname fields equals 0 to avoid any ndlp on the
1140 * nodelist never to be used.
1141 */
1142 if (ndlp->nlp_DID == 0) {
1143 spin_lock_irq(&phba->ndlp_lock);
1144 NLP_SET_FREE_REQ(ndlp);
1145 spin_unlock_irq(&phba->ndlp_lock);
1146 }
James Smart0ff10d42008-01-11 01:52:36 -05001147
James Smart58da1ff2008-04-07 10:15:56 -04001148 /* Two ndlps cannot have the same did on the nodelist */
1149 ndlp->nlp_DID = keepDID;
James Smart2e0fef82007-06-17 19:56:36 -05001150 lpfc_drop_node(vport, ndlp);
James Smart87af33f2007-10-27 13:37:43 -04001151 }
James Smart92795652006-07-06 15:50:02 -04001152 else {
James Smart2e0fef82007-06-17 19:56:36 -05001153 lpfc_unreg_rpi(vport, ndlp);
James Smart58da1ff2008-04-07 10:15:56 -04001154 /* Two ndlps cannot have the same did */
1155 ndlp->nlp_DID = keepDID;
James Smart2e0fef82007-06-17 19:56:36 -05001156 lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
James Smart92795652006-07-06 15:50:02 -04001157 }
James Smart488d1462006-03-07 15:02:37 -05001158 return new_ndlp;
1159}
1160
James Smarte59058c2008-08-24 21:49:00 -04001161/**
1162 * lpfc_end_rscn: Check and handle more rscn for a vport.
1163 * @vport: pointer to a host virtual N_Port data structure.
1164 *
1165 * This routine checks whether more Registration State Change
1166 * Notifications (RSCNs) came in while the discovery state machine was in
1167 * the FC_RSCN_MODE. If so, the lpfc_els_handle_rscn() routine will be
1168 * invoked to handle the additional RSCNs for the @vport. Otherwise, the
1169 * FC_RSCN_MODE bit will be cleared with the @vport to mark as the end of
1170 * handling the RSCNs.
1171 **/
James Smart87af33f2007-10-27 13:37:43 -04001172void
1173lpfc_end_rscn(struct lpfc_vport *vport)
1174{
1175 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
1176
1177 if (vport->fc_flag & FC_RSCN_MODE) {
1178 /*
1179 * Check to see if more RSCNs came in while we were
1180 * processing this one.
1181 */
1182 if (vport->fc_rscn_id_cnt ||
1183 (vport->fc_flag & FC_RSCN_DISCOVERY) != 0)
1184 lpfc_els_handle_rscn(vport);
1185 else {
1186 spin_lock_irq(shost->host_lock);
1187 vport->fc_flag &= ~FC_RSCN_MODE;
1188 spin_unlock_irq(shost->host_lock);
1189 }
1190 }
1191}
1192
James Smarte59058c2008-08-24 21:49:00 -04001193/**
1194 * lpfc_cmpl_els_plogi: Completion callback function for plogi.
1195 * @phba: pointer to lpfc hba data structure.
1196 * @cmdiocb: pointer to lpfc command iocb data structure.
1197 * @rspiocb: pointer to lpfc response iocb data structure.
1198 *
1199 * This routine is the completion callback function for issuing the Port
1200 * Login (PLOGI) command. For PLOGI completion, there must be an active
1201 * ndlp on the vport node list that matches the remote node ID from the
1202 * PLOGI reponse IOCB. If such ndlp does not exist, the PLOGI is simply
1203 * ignored and command IOCB released. The PLOGI response IOCB status is
1204 * checked for error conditons. If there is error status reported, PLOGI
1205 * retry shall be attempted by invoking the lpfc_els_retry() routine.
1206 * Otherwise, the lpfc_plogi_confirm_nport() routine shall be invoked on
1207 * the ndlp and the NLP_EVT_CMPL_PLOGI state to the Discover State Machine
1208 * (DSM) is set for this PLOGI completion. Finally, it checks whether
1209 * there are additional N_Port nodes with the vport that need to perform
1210 * PLOGI. If so, the lpfc_more_plogi() routine is invoked to issue addition
1211 * PLOGIs.
1212 **/
dea31012005-04-17 16:05:31 -05001213static void
James Smart2e0fef82007-06-17 19:56:36 -05001214lpfc_cmpl_els_plogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
1215 struct lpfc_iocbq *rspiocb)
dea31012005-04-17 16:05:31 -05001216{
James Smart2e0fef82007-06-17 19:56:36 -05001217 struct lpfc_vport *vport = cmdiocb->vport;
1218 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
dea31012005-04-17 16:05:31 -05001219 IOCB_t *irsp;
dea31012005-04-17 16:05:31 -05001220 struct lpfc_nodelist *ndlp;
James Smart92795652006-07-06 15:50:02 -04001221 struct lpfc_dmabuf *prsp;
dea31012005-04-17 16:05:31 -05001222 int disc, rc, did, type;
1223
dea31012005-04-17 16:05:31 -05001224 /* we pass cmdiocb to state machine which needs rspiocb as well */
1225 cmdiocb->context_un.rsp_iocb = rspiocb;
1226
1227 irsp = &rspiocb->iocb;
James Smart858c9f62007-06-17 19:56:39 -05001228 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
1229 "PLOGI cmpl: status:x%x/x%x did:x%x",
1230 irsp->ulpStatus, irsp->un.ulpWord[4],
1231 irsp->un.elsreq64.remoteID);
1232
James Smart2e0fef82007-06-17 19:56:36 -05001233 ndlp = lpfc_findnode_did(vport, irsp->un.elsreq64.remoteID);
James Smarte47c9092008-02-08 18:49:26 -05001234 if (!ndlp || !NLP_CHK_NODE_ACT(ndlp)) {
James Smarte8b62012007-08-02 11:10:09 -04001235 lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
1236 "0136 PLOGI completes to NPort x%x "
1237 "with no ndlp. Data: x%x x%x x%x\n",
1238 irsp->un.elsreq64.remoteID,
1239 irsp->ulpStatus, irsp->un.ulpWord[4],
1240 irsp->ulpIoTag);
James Smart488d1462006-03-07 15:02:37 -05001241 goto out;
James Smarted957682007-06-17 19:56:37 -05001242 }
dea31012005-04-17 16:05:31 -05001243
1244 /* Since ndlp can be freed in the disc state machine, note if this node
1245 * is being used during discovery.
1246 */
James Smart2e0fef82007-06-17 19:56:36 -05001247 spin_lock_irq(shost->host_lock);
dea31012005-04-17 16:05:31 -05001248 disc = (ndlp->nlp_flag & NLP_NPR_2B_DISC);
James Smart488d1462006-03-07 15:02:37 -05001249 ndlp->nlp_flag &= ~NLP_NPR_2B_DISC;
James Smart2e0fef82007-06-17 19:56:36 -05001250 spin_unlock_irq(shost->host_lock);
dea31012005-04-17 16:05:31 -05001251 rc = 0;
1252
1253 /* PLOGI completes to NPort <nlp_DID> */
James Smarte8b62012007-08-02 11:10:09 -04001254 lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
1255 "0102 PLOGI completes to NPort x%x "
1256 "Data: x%x x%x x%x x%x x%x\n",
1257 ndlp->nlp_DID, irsp->ulpStatus, irsp->un.ulpWord[4],
1258 irsp->ulpTimeout, disc, vport->num_disc_nodes);
dea31012005-04-17 16:05:31 -05001259 /* Check to see if link went down during discovery */
James Smart2e0fef82007-06-17 19:56:36 -05001260 if (lpfc_els_chk_latt(vport)) {
1261 spin_lock_irq(shost->host_lock);
dea31012005-04-17 16:05:31 -05001262 ndlp->nlp_flag |= NLP_NPR_2B_DISC;
James Smart2e0fef82007-06-17 19:56:36 -05001263 spin_unlock_irq(shost->host_lock);
dea31012005-04-17 16:05:31 -05001264 goto out;
1265 }
1266
1267 /* ndlp could be freed in DSM, save these values now */
1268 type = ndlp->nlp_type;
1269 did = ndlp->nlp_DID;
1270
1271 if (irsp->ulpStatus) {
1272 /* Check for retry */
1273 if (lpfc_els_retry(phba, cmdiocb, rspiocb)) {
1274 /* ELS command is being retried */
1275 if (disc) {
James Smart2e0fef82007-06-17 19:56:36 -05001276 spin_lock_irq(shost->host_lock);
dea31012005-04-17 16:05:31 -05001277 ndlp->nlp_flag |= NLP_NPR_2B_DISC;
James Smart2e0fef82007-06-17 19:56:36 -05001278 spin_unlock_irq(shost->host_lock);
dea31012005-04-17 16:05:31 -05001279 }
1280 goto out;
1281 }
dea31012005-04-17 16:05:31 -05001282 /* PLOGI failed */
1283 /* Do not call DSM for lpfc_els_abort'ed ELS cmds */
James Smarte47c9092008-02-08 18:49:26 -05001284 if (lpfc_error_lost_link(irsp))
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001285 rc = NLP_STE_FREED_NODE;
James Smarte47c9092008-02-08 18:49:26 -05001286 else
James Smart2e0fef82007-06-17 19:56:36 -05001287 rc = lpfc_disc_state_machine(vport, ndlp, cmdiocb,
James Smart92d7f7b2007-06-17 19:56:38 -05001288 NLP_EVT_CMPL_PLOGI);
dea31012005-04-17 16:05:31 -05001289 } else {
1290 /* Good status, call state machine */
James Smart92795652006-07-06 15:50:02 -04001291 prsp = list_entry(((struct lpfc_dmabuf *)
James Smart92d7f7b2007-06-17 19:56:38 -05001292 cmdiocb->context2)->list.next,
1293 struct lpfc_dmabuf, list);
1294 ndlp = lpfc_plogi_confirm_nport(phba, prsp->virt, ndlp);
James Smart2e0fef82007-06-17 19:56:36 -05001295 rc = lpfc_disc_state_machine(vport, ndlp, cmdiocb,
James Smart92d7f7b2007-06-17 19:56:38 -05001296 NLP_EVT_CMPL_PLOGI);
dea31012005-04-17 16:05:31 -05001297 }
1298
James Smart2e0fef82007-06-17 19:56:36 -05001299 if (disc && vport->num_disc_nodes) {
dea31012005-04-17 16:05:31 -05001300 /* Check to see if there are more PLOGIs to be sent */
James Smart2e0fef82007-06-17 19:56:36 -05001301 lpfc_more_plogi(vport);
dea31012005-04-17 16:05:31 -05001302
James Smart2e0fef82007-06-17 19:56:36 -05001303 if (vport->num_disc_nodes == 0) {
1304 spin_lock_irq(shost->host_lock);
1305 vport->fc_flag &= ~FC_NDISC_ACTIVE;
1306 spin_unlock_irq(shost->host_lock);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001307
James Smart2e0fef82007-06-17 19:56:36 -05001308 lpfc_can_disctmo(vport);
James Smart87af33f2007-10-27 13:37:43 -04001309 lpfc_end_rscn(vport);
dea31012005-04-17 16:05:31 -05001310 }
1311 }
1312
1313out:
1314 lpfc_els_free_iocb(phba, cmdiocb);
1315 return;
1316}
1317
James Smarte59058c2008-08-24 21:49:00 -04001318/**
1319 * lpfc_issue_els_plogi: Issue an plogi iocb command for a vport.
1320 * @vport: pointer to a host virtual N_Port data structure.
1321 * @did: destination port identifier.
1322 * @retry: number of retries to the command IOCB.
1323 *
1324 * This routine issues a Port Login (PLOGI) command to a remote N_Port
1325 * (with the @did) for a @vport. Before issuing a PLOGI to a remote N_Port,
1326 * the ndlp with the remote N_Port DID must exist on the @vport's ndlp list.
1327 * This routine constructs the proper feilds of the PLOGI IOCB and invokes
1328 * the lpfc_sli_issue_iocb() routine to send out PLOGI ELS command.
1329 *
1330 * Note that, in lpfc_prep_els_iocb() routine, the reference count of ndlp
1331 * will be incremented by 1 for holding the ndlp and the reference to ndlp
1332 * will be stored into the context1 field of the IOCB for the completion
1333 * callback function to the PLOGI ELS command.
1334 *
1335 * Return code
1336 * 0 - Successfully issued a plogi for @vport
1337 * 1 - failed to issue a plogi for @vport
1338 **/
dea31012005-04-17 16:05:31 -05001339int
James Smart2e0fef82007-06-17 19:56:36 -05001340lpfc_issue_els_plogi(struct lpfc_vport *vport, uint32_t did, uint8_t retry)
dea31012005-04-17 16:05:31 -05001341{
James Smart2e0fef82007-06-17 19:56:36 -05001342 struct lpfc_hba *phba = vport->phba;
dea31012005-04-17 16:05:31 -05001343 struct serv_parm *sp;
1344 IOCB_t *icmd;
James Smart98c9ea52007-10-27 13:37:33 -04001345 struct lpfc_nodelist *ndlp;
dea31012005-04-17 16:05:31 -05001346 struct lpfc_iocbq *elsiocb;
1347 struct lpfc_sli_ring *pring;
1348 struct lpfc_sli *psli;
1349 uint8_t *pcmd;
1350 uint16_t cmdsize;
James Smart92d7f7b2007-06-17 19:56:38 -05001351 int ret;
dea31012005-04-17 16:05:31 -05001352
1353 psli = &phba->sli;
1354 pring = &psli->ring[LPFC_ELS_RING]; /* ELS ring */
1355
James Smart98c9ea52007-10-27 13:37:33 -04001356 ndlp = lpfc_findnode_did(vport, did);
James Smarte47c9092008-02-08 18:49:26 -05001357 if (ndlp && !NLP_CHK_NODE_ACT(ndlp))
1358 ndlp = NULL;
James Smart98c9ea52007-10-27 13:37:33 -04001359
James Smarte47c9092008-02-08 18:49:26 -05001360 /* If ndlp is not NULL, we will bump the reference count on it */
James Smart92d7f7b2007-06-17 19:56:38 -05001361 cmdsize = (sizeof(uint32_t) + sizeof(struct serv_parm));
James Smart98c9ea52007-10-27 13:37:33 -04001362 elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp, did,
James Smart2e0fef82007-06-17 19:56:36 -05001363 ELS_CMD_PLOGI);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001364 if (!elsiocb)
1365 return 1;
dea31012005-04-17 16:05:31 -05001366
1367 icmd = &elsiocb->iocb;
1368 pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
1369
1370 /* For PLOGI request, remainder of payload is service parameters */
1371 *((uint32_t *) (pcmd)) = ELS_CMD_PLOGI;
James Smart92d7f7b2007-06-17 19:56:38 -05001372 pcmd += sizeof(uint32_t);
1373 memcpy(pcmd, &vport->fc_sparam, sizeof(struct serv_parm));
dea31012005-04-17 16:05:31 -05001374 sp = (struct serv_parm *) pcmd;
1375
1376 if (sp->cmn.fcphLow < FC_PH_4_3)
1377 sp->cmn.fcphLow = FC_PH_4_3;
1378
1379 if (sp->cmn.fcphHigh < FC_PH3)
1380 sp->cmn.fcphHigh = FC_PH3;
1381
James Smart858c9f62007-06-17 19:56:39 -05001382 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
1383 "Issue PLOGI: did:x%x",
1384 did, 0, 0);
1385
dea31012005-04-17 16:05:31 -05001386 phba->fc_stat.elsXmitPLOGI++;
1387 elsiocb->iocb_cmpl = lpfc_cmpl_els_plogi;
James Smart92d7f7b2007-06-17 19:56:38 -05001388 ret = lpfc_sli_issue_iocb(phba, pring, elsiocb, 0);
1389
1390 if (ret == IOCB_ERROR) {
dea31012005-04-17 16:05:31 -05001391 lpfc_els_free_iocb(phba, elsiocb);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001392 return 1;
dea31012005-04-17 16:05:31 -05001393 }
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001394 return 0;
dea31012005-04-17 16:05:31 -05001395}
1396
James Smarte59058c2008-08-24 21:49:00 -04001397/**
1398 * lpfc_cmpl_els_prli: Completion callback function for prli.
1399 * @phba: pointer to lpfc hba data structure.
1400 * @cmdiocb: pointer to lpfc command iocb data structure.
1401 * @rspiocb: pointer to lpfc response iocb data structure.
1402 *
1403 * This routine is the completion callback function for a Process Login
1404 * (PRLI) ELS command. The PRLI response IOCB status is checked for error
1405 * status. If there is error status reported, PRLI retry shall be attempted
1406 * by invoking the lpfc_els_retry() routine. Otherwise, the state
1407 * NLP_EVT_CMPL_PRLI is sent to the Discover State Machine (DSM) for this
1408 * ndlp to mark the PRLI completion.
1409 **/
dea31012005-04-17 16:05:31 -05001410static void
James Smart2e0fef82007-06-17 19:56:36 -05001411lpfc_cmpl_els_prli(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
1412 struct lpfc_iocbq *rspiocb)
dea31012005-04-17 16:05:31 -05001413{
James Smart2e0fef82007-06-17 19:56:36 -05001414 struct lpfc_vport *vport = cmdiocb->vport;
1415 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
dea31012005-04-17 16:05:31 -05001416 IOCB_t *irsp;
1417 struct lpfc_sli *psli;
1418 struct lpfc_nodelist *ndlp;
1419
1420 psli = &phba->sli;
1421 /* we pass cmdiocb to state machine which needs rspiocb as well */
1422 cmdiocb->context_un.rsp_iocb = rspiocb;
1423
1424 irsp = &(rspiocb->iocb);
1425 ndlp = (struct lpfc_nodelist *) cmdiocb->context1;
James Smart2e0fef82007-06-17 19:56:36 -05001426 spin_lock_irq(shost->host_lock);
dea31012005-04-17 16:05:31 -05001427 ndlp->nlp_flag &= ~NLP_PRLI_SND;
James Smart2e0fef82007-06-17 19:56:36 -05001428 spin_unlock_irq(shost->host_lock);
dea31012005-04-17 16:05:31 -05001429
James Smart858c9f62007-06-17 19:56:39 -05001430 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
1431 "PRLI cmpl: status:x%x/x%x did:x%x",
1432 irsp->ulpStatus, irsp->un.ulpWord[4],
1433 ndlp->nlp_DID);
dea31012005-04-17 16:05:31 -05001434 /* PRLI completes to NPort <nlp_DID> */
James Smarte8b62012007-08-02 11:10:09 -04001435 lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
1436 "0103 PRLI completes to NPort x%x "
1437 "Data: x%x x%x x%x x%x\n",
1438 ndlp->nlp_DID, irsp->ulpStatus, irsp->un.ulpWord[4],
1439 irsp->ulpTimeout, vport->num_disc_nodes);
dea31012005-04-17 16:05:31 -05001440
James Smart2e0fef82007-06-17 19:56:36 -05001441 vport->fc_prli_sent--;
dea31012005-04-17 16:05:31 -05001442 /* Check to see if link went down during discovery */
James Smart2e0fef82007-06-17 19:56:36 -05001443 if (lpfc_els_chk_latt(vport))
dea31012005-04-17 16:05:31 -05001444 goto out;
1445
1446 if (irsp->ulpStatus) {
1447 /* Check for retry */
1448 if (lpfc_els_retry(phba, cmdiocb, rspiocb)) {
1449 /* ELS command is being retried */
1450 goto out;
1451 }
1452 /* PRLI failed */
1453 /* Do not call DSM for lpfc_els_abort'ed ELS cmds */
James Smarte47c9092008-02-08 18:49:26 -05001454 if (lpfc_error_lost_link(irsp))
dea31012005-04-17 16:05:31 -05001455 goto out;
James Smarte47c9092008-02-08 18:49:26 -05001456 else
James Smart2e0fef82007-06-17 19:56:36 -05001457 lpfc_disc_state_machine(vport, ndlp, cmdiocb,
James Smart92d7f7b2007-06-17 19:56:38 -05001458 NLP_EVT_CMPL_PRLI);
James Smarte47c9092008-02-08 18:49:26 -05001459 } else
dea31012005-04-17 16:05:31 -05001460 /* Good status, call state machine */
James Smart2e0fef82007-06-17 19:56:36 -05001461 lpfc_disc_state_machine(vport, ndlp, cmdiocb,
James Smart92d7f7b2007-06-17 19:56:38 -05001462 NLP_EVT_CMPL_PRLI);
dea31012005-04-17 16:05:31 -05001463out:
1464 lpfc_els_free_iocb(phba, cmdiocb);
1465 return;
1466}
1467
James Smarte59058c2008-08-24 21:49:00 -04001468/**
1469 * lpfc_issue_els_prli: Issue a prli iocb command for a vport.
1470 * @vport: pointer to a host virtual N_Port data structure.
1471 * @ndlp: pointer to a node-list data structure.
1472 * @retry: number of retries to the command IOCB.
1473 *
1474 * This routine issues a Process Login (PRLI) ELS command for the
1475 * @vport. The PRLI service parameters are set up in the payload of the
1476 * PRLI Request command and the pointer to lpfc_cmpl_els_prli() routine
1477 * is put to the IOCB completion callback func field before invoking the
1478 * routine lpfc_sli_issue_iocb() to send out PRLI command.
1479 *
1480 * Note that, in lpfc_prep_els_iocb() routine, the reference count of ndlp
1481 * will be incremented by 1 for holding the ndlp and the reference to ndlp
1482 * will be stored into the context1 field of the IOCB for the completion
1483 * callback function to the PRLI ELS command.
1484 *
1485 * Return code
1486 * 0 - successfully issued prli iocb command for @vport
1487 * 1 - failed to issue prli iocb command for @vport
1488 **/
dea31012005-04-17 16:05:31 -05001489int
James Smart2e0fef82007-06-17 19:56:36 -05001490lpfc_issue_els_prli(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
dea31012005-04-17 16:05:31 -05001491 uint8_t retry)
1492{
James Smart2e0fef82007-06-17 19:56:36 -05001493 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
1494 struct lpfc_hba *phba = vport->phba;
dea31012005-04-17 16:05:31 -05001495 PRLI *npr;
1496 IOCB_t *icmd;
1497 struct lpfc_iocbq *elsiocb;
1498 struct lpfc_sli_ring *pring;
1499 struct lpfc_sli *psli;
1500 uint8_t *pcmd;
1501 uint16_t cmdsize;
1502
1503 psli = &phba->sli;
1504 pring = &psli->ring[LPFC_ELS_RING]; /* ELS ring */
1505
James Smart92d7f7b2007-06-17 19:56:38 -05001506 cmdsize = (sizeof(uint32_t) + sizeof(PRLI));
James Smart2e0fef82007-06-17 19:56:36 -05001507 elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp,
1508 ndlp->nlp_DID, ELS_CMD_PRLI);
James Smart488d1462006-03-07 15:02:37 -05001509 if (!elsiocb)
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001510 return 1;
dea31012005-04-17 16:05:31 -05001511
1512 icmd = &elsiocb->iocb;
1513 pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
1514
1515 /* For PRLI request, remainder of payload is service parameters */
James Smart92d7f7b2007-06-17 19:56:38 -05001516 memset(pcmd, 0, (sizeof(PRLI) + sizeof(uint32_t)));
dea31012005-04-17 16:05:31 -05001517 *((uint32_t *) (pcmd)) = ELS_CMD_PRLI;
James Smart92d7f7b2007-06-17 19:56:38 -05001518 pcmd += sizeof(uint32_t);
dea31012005-04-17 16:05:31 -05001519
1520 /* For PRLI, remainder of payload is PRLI parameter page */
1521 npr = (PRLI *) pcmd;
1522 /*
1523 * If our firmware version is 3.20 or later,
1524 * set the following bits for FC-TAPE support.
1525 */
1526 if (phba->vpd.rev.feaLevelHigh >= 0x02) {
1527 npr->ConfmComplAllowed = 1;
1528 npr->Retry = 1;
1529 npr->TaskRetryIdReq = 1;
1530 }
1531 npr->estabImagePair = 1;
1532 npr->readXferRdyDis = 1;
1533
1534 /* For FCP support */
1535 npr->prliType = PRLI_FCP_TYPE;
1536 npr->initiatorFunc = 1;
1537
James Smart858c9f62007-06-17 19:56:39 -05001538 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
1539 "Issue PRLI: did:x%x",
1540 ndlp->nlp_DID, 0, 0);
1541
dea31012005-04-17 16:05:31 -05001542 phba->fc_stat.elsXmitPRLI++;
1543 elsiocb->iocb_cmpl = lpfc_cmpl_els_prli;
James Smart2e0fef82007-06-17 19:56:36 -05001544 spin_lock_irq(shost->host_lock);
dea31012005-04-17 16:05:31 -05001545 ndlp->nlp_flag |= NLP_PRLI_SND;
James Smart2e0fef82007-06-17 19:56:36 -05001546 spin_unlock_irq(shost->host_lock);
dea31012005-04-17 16:05:31 -05001547 if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) {
James Smart2e0fef82007-06-17 19:56:36 -05001548 spin_lock_irq(shost->host_lock);
dea31012005-04-17 16:05:31 -05001549 ndlp->nlp_flag &= ~NLP_PRLI_SND;
James Smart2e0fef82007-06-17 19:56:36 -05001550 spin_unlock_irq(shost->host_lock);
dea31012005-04-17 16:05:31 -05001551 lpfc_els_free_iocb(phba, elsiocb);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001552 return 1;
dea31012005-04-17 16:05:31 -05001553 }
James Smart2e0fef82007-06-17 19:56:36 -05001554 vport->fc_prli_sent++;
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001555 return 0;
dea31012005-04-17 16:05:31 -05001556}
1557
James Smarte59058c2008-08-24 21:49:00 -04001558/**
1559 * lpfc_more_adisc: Issue more adisc as needed.
1560 * @vport: pointer to a host virtual N_Port data structure.
1561 *
1562 * This routine determines whether there are more ndlps on a @vport
1563 * node list need to have Address Discover (ADISC) issued. If so, it will
1564 * invoke the lpfc_els_disc_adisc() routine to issue ADISC on the @vport's
1565 * remaining nodes which need to have ADISC sent.
1566 **/
James Smart0ff10d42008-01-11 01:52:36 -05001567void
James Smart2e0fef82007-06-17 19:56:36 -05001568lpfc_more_adisc(struct lpfc_vport *vport)
dea31012005-04-17 16:05:31 -05001569{
1570 int sentadisc;
1571
James Smart2e0fef82007-06-17 19:56:36 -05001572 if (vport->num_disc_nodes)
1573 vport->num_disc_nodes--;
dea31012005-04-17 16:05:31 -05001574 /* Continue discovery with <num_disc_nodes> ADISCs to go */
James Smarte8b62012007-08-02 11:10:09 -04001575 lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
1576 "0210 Continue discovery with %d ADISCs to go "
1577 "Data: x%x x%x x%x\n",
1578 vport->num_disc_nodes, vport->fc_adisc_cnt,
1579 vport->fc_flag, vport->port_state);
dea31012005-04-17 16:05:31 -05001580 /* Check to see if there are more ADISCs to be sent */
James Smart2e0fef82007-06-17 19:56:36 -05001581 if (vport->fc_flag & FC_NLP_MORE) {
1582 lpfc_set_disctmo(vport);
1583 /* go thru NPR nodes and issue any remaining ELS ADISCs */
1584 sentadisc = lpfc_els_disc_adisc(vport);
dea31012005-04-17 16:05:31 -05001585 }
1586 return;
1587}
1588
James Smarte59058c2008-08-24 21:49:00 -04001589/**
1590 * lpfc_rscn_disc: Perform rscn discovery for a vport.
1591 * @vport: pointer to a host virtual N_Port data structure.
1592 *
1593 * This routine performs Registration State Change Notification (RSCN)
1594 * discovery for a @vport. If the @vport's node port recovery count is not
1595 * zero, it will invoke the lpfc_els_disc_plogi() to perform PLOGI for all
1596 * the nodes that need recovery. If none of the PLOGI were needed through
1597 * the lpfc_els_disc_plogi() routine, the lpfc_end_rscn() routine shall be
1598 * invoked to check and handle possible more RSCN came in during the period
1599 * of processing the current ones.
1600 **/
dea31012005-04-17 16:05:31 -05001601static void
James Smart2e0fef82007-06-17 19:56:36 -05001602lpfc_rscn_disc(struct lpfc_vport *vport)
dea31012005-04-17 16:05:31 -05001603{
James Smart858c9f62007-06-17 19:56:39 -05001604 lpfc_can_disctmo(vport);
1605
dea31012005-04-17 16:05:31 -05001606 /* RSCN discovery */
James Smart2e0fef82007-06-17 19:56:36 -05001607 /* go thru NPR nodes and issue ELS PLOGIs */
1608 if (vport->fc_npr_cnt)
1609 if (lpfc_els_disc_plogi(vport))
dea31012005-04-17 16:05:31 -05001610 return;
James Smart2e0fef82007-06-17 19:56:36 -05001611
James Smart87af33f2007-10-27 13:37:43 -04001612 lpfc_end_rscn(vport);
dea31012005-04-17 16:05:31 -05001613}
1614
James Smarte59058c2008-08-24 21:49:00 -04001615/**
1616 * lpfc_cmpl_els_adisc: Completion callback function for adisc.
1617 * @phba: pointer to lpfc hba data structure.
1618 * @cmdiocb: pointer to lpfc command iocb data structure.
1619 * @rspiocb: pointer to lpfc response iocb data structure.
1620 *
1621 * This routine is the completion function for issuing the Address Discover
1622 * (ADISC) command. It first checks to see whether link went down during
1623 * the discovery process. If so, the node will be marked as node port
1624 * recovery for issuing discover IOCB by the link attention handler and
1625 * exit. Otherwise, the response status is checked. If error was reported
1626 * in the response status, the ADISC command shall be retried by invoking
1627 * the lpfc_els_retry() routine. Otherwise, if no error was reported in
1628 * the response status, the state machine is invoked to set transition
1629 * with respect to NLP_EVT_CMPL_ADISC event.
1630 **/
dea31012005-04-17 16:05:31 -05001631static void
James Smart2e0fef82007-06-17 19:56:36 -05001632lpfc_cmpl_els_adisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
1633 struct lpfc_iocbq *rspiocb)
dea31012005-04-17 16:05:31 -05001634{
James Smart2e0fef82007-06-17 19:56:36 -05001635 struct lpfc_vport *vport = cmdiocb->vport;
1636 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
dea31012005-04-17 16:05:31 -05001637 IOCB_t *irsp;
dea31012005-04-17 16:05:31 -05001638 struct lpfc_nodelist *ndlp;
James Smart2e0fef82007-06-17 19:56:36 -05001639 int disc;
dea31012005-04-17 16:05:31 -05001640
1641 /* we pass cmdiocb to state machine which needs rspiocb as well */
1642 cmdiocb->context_un.rsp_iocb = rspiocb;
1643
1644 irsp = &(rspiocb->iocb);
1645 ndlp = (struct lpfc_nodelist *) cmdiocb->context1;
dea31012005-04-17 16:05:31 -05001646
James Smart858c9f62007-06-17 19:56:39 -05001647 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
1648 "ADISC cmpl: status:x%x/x%x did:x%x",
1649 irsp->ulpStatus, irsp->un.ulpWord[4],
1650 ndlp->nlp_DID);
1651
dea31012005-04-17 16:05:31 -05001652 /* Since ndlp can be freed in the disc state machine, note if this node
1653 * is being used during discovery.
1654 */
James Smart2e0fef82007-06-17 19:56:36 -05001655 spin_lock_irq(shost->host_lock);
dea31012005-04-17 16:05:31 -05001656 disc = (ndlp->nlp_flag & NLP_NPR_2B_DISC);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001657 ndlp->nlp_flag &= ~(NLP_ADISC_SND | NLP_NPR_2B_DISC);
James Smart2e0fef82007-06-17 19:56:36 -05001658 spin_unlock_irq(shost->host_lock);
dea31012005-04-17 16:05:31 -05001659 /* ADISC completes to NPort <nlp_DID> */
James Smarte8b62012007-08-02 11:10:09 -04001660 lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
1661 "0104 ADISC completes to NPort x%x "
1662 "Data: x%x x%x x%x x%x x%x\n",
1663 ndlp->nlp_DID, irsp->ulpStatus, irsp->un.ulpWord[4],
1664 irsp->ulpTimeout, disc, vport->num_disc_nodes);
dea31012005-04-17 16:05:31 -05001665 /* Check to see if link went down during discovery */
James Smart2e0fef82007-06-17 19:56:36 -05001666 if (lpfc_els_chk_latt(vport)) {
1667 spin_lock_irq(shost->host_lock);
dea31012005-04-17 16:05:31 -05001668 ndlp->nlp_flag |= NLP_NPR_2B_DISC;
James Smart2e0fef82007-06-17 19:56:36 -05001669 spin_unlock_irq(shost->host_lock);
dea31012005-04-17 16:05:31 -05001670 goto out;
1671 }
1672
1673 if (irsp->ulpStatus) {
1674 /* Check for retry */
1675 if (lpfc_els_retry(phba, cmdiocb, rspiocb)) {
1676 /* ELS command is being retried */
1677 if (disc) {
James Smart2e0fef82007-06-17 19:56:36 -05001678 spin_lock_irq(shost->host_lock);
dea31012005-04-17 16:05:31 -05001679 ndlp->nlp_flag |= NLP_NPR_2B_DISC;
James Smart2e0fef82007-06-17 19:56:36 -05001680 spin_unlock_irq(shost->host_lock);
1681 lpfc_set_disctmo(vport);
dea31012005-04-17 16:05:31 -05001682 }
1683 goto out;
1684 }
1685 /* ADISC failed */
1686 /* Do not call DSM for lpfc_els_abort'ed ELS cmds */
James Smarte47c9092008-02-08 18:49:26 -05001687 if (!lpfc_error_lost_link(irsp))
James Smart2e0fef82007-06-17 19:56:36 -05001688 lpfc_disc_state_machine(vport, ndlp, cmdiocb,
James Smart858c9f62007-06-17 19:56:39 -05001689 NLP_EVT_CMPL_ADISC);
James Smarte47c9092008-02-08 18:49:26 -05001690 } else
dea31012005-04-17 16:05:31 -05001691 /* Good status, call state machine */
James Smart2e0fef82007-06-17 19:56:36 -05001692 lpfc_disc_state_machine(vport, ndlp, cmdiocb,
dea31012005-04-17 16:05:31 -05001693 NLP_EVT_CMPL_ADISC);
dea31012005-04-17 16:05:31 -05001694
James Smart2e0fef82007-06-17 19:56:36 -05001695 if (disc && vport->num_disc_nodes) {
dea31012005-04-17 16:05:31 -05001696 /* Check to see if there are more ADISCs to be sent */
James Smart2e0fef82007-06-17 19:56:36 -05001697 lpfc_more_adisc(vport);
dea31012005-04-17 16:05:31 -05001698
1699 /* Check to see if we are done with ADISC authentication */
James Smart2e0fef82007-06-17 19:56:36 -05001700 if (vport->num_disc_nodes == 0) {
James Smart92d7f7b2007-06-17 19:56:38 -05001701 /* If we get here, there is nothing left to ADISC */
1702 /*
1703 * For NPIV, cmpl_reg_vpi will set port_state to READY,
1704 * and continue discovery.
1705 */
1706 if ((phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) &&
1707 !(vport->fc_flag & FC_RSCN_MODE)) {
1708 lpfc_issue_reg_vpi(phba, vport);
1709 goto out;
1710 }
1711 /*
1712 * For SLI2, we need to set port_state to READY
1713 * and continue discovery.
1714 */
1715 if (vport->port_state < LPFC_VPORT_READY) {
1716 /* If we get here, there is nothing to ADISC */
James Smarted957682007-06-17 19:56:37 -05001717 if (vport->port_type == LPFC_PHYSICAL_PORT)
James Smart2e0fef82007-06-17 19:56:36 -05001718 lpfc_issue_clear_la(phba, vport);
James Smart92d7f7b2007-06-17 19:56:38 -05001719
1720 if (!(vport->fc_flag & FC_ABORT_DISCOVERY)) {
1721 vport->num_disc_nodes = 0;
1722 /* go thru NPR list, issue ELS PLOGIs */
1723 if (vport->fc_npr_cnt)
1724 lpfc_els_disc_plogi(vport);
1725
1726 if (!vport->num_disc_nodes) {
1727 spin_lock_irq(shost->host_lock);
1728 vport->fc_flag &=
1729 ~FC_NDISC_ACTIVE;
1730 spin_unlock_irq(
1731 shost->host_lock);
1732 lpfc_can_disctmo(vport);
1733 }
1734 }
1735 vport->port_state = LPFC_VPORT_READY;
dea31012005-04-17 16:05:31 -05001736 } else {
James Smart2e0fef82007-06-17 19:56:36 -05001737 lpfc_rscn_disc(vport);
dea31012005-04-17 16:05:31 -05001738 }
1739 }
1740 }
dea31012005-04-17 16:05:31 -05001741out:
1742 lpfc_els_free_iocb(phba, cmdiocb);
1743 return;
1744}
1745
James Smarte59058c2008-08-24 21:49:00 -04001746/**
1747 * lpfc_issue_els_adisc: Issue an address discover iocb to an node on a vport.
1748 * @vport: pointer to a virtual N_Port data structure.
1749 * @ndlp: pointer to a node-list data structure.
1750 * @retry: number of retries to the command IOCB.
1751 *
1752 * This routine issues an Address Discover (ADISC) for an @ndlp on a
1753 * @vport. It prepares the payload of the ADISC ELS command, updates the
1754 * and states of the ndlp, and invokes the lpfc_sli_issue_iocb() routine
1755 * to issue the ADISC ELS command.
1756 *
1757 * Note that, in lpfc_prep_els_iocb() routine, the reference count of ndlp
1758 * will be incremented by 1 for holding the ndlp and the reference to ndlp
1759 * will be stored into the context1 field of the IOCB for the completion
1760 * callback function to the ADISC ELS command.
1761 *
1762 * Return code
1763 * 0 - successfully issued adisc
1764 * 1 - failed to issue adisc
1765 **/
dea31012005-04-17 16:05:31 -05001766int
James Smart2e0fef82007-06-17 19:56:36 -05001767lpfc_issue_els_adisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
dea31012005-04-17 16:05:31 -05001768 uint8_t retry)
1769{
James Smart2e0fef82007-06-17 19:56:36 -05001770 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
1771 struct lpfc_hba *phba = vport->phba;
dea31012005-04-17 16:05:31 -05001772 ADISC *ap;
1773 IOCB_t *icmd;
1774 struct lpfc_iocbq *elsiocb;
James Smart2e0fef82007-06-17 19:56:36 -05001775 struct lpfc_sli *psli = &phba->sli;
1776 struct lpfc_sli_ring *pring = &psli->ring[LPFC_ELS_RING];
dea31012005-04-17 16:05:31 -05001777 uint8_t *pcmd;
1778 uint16_t cmdsize;
1779
James Smart92d7f7b2007-06-17 19:56:38 -05001780 cmdsize = (sizeof(uint32_t) + sizeof(ADISC));
James Smart2e0fef82007-06-17 19:56:36 -05001781 elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp,
1782 ndlp->nlp_DID, ELS_CMD_ADISC);
James Smart488d1462006-03-07 15:02:37 -05001783 if (!elsiocb)
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001784 return 1;
dea31012005-04-17 16:05:31 -05001785
1786 icmd = &elsiocb->iocb;
1787 pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
1788
1789 /* For ADISC request, remainder of payload is service parameters */
1790 *((uint32_t *) (pcmd)) = ELS_CMD_ADISC;
James Smart92d7f7b2007-06-17 19:56:38 -05001791 pcmd += sizeof(uint32_t);
dea31012005-04-17 16:05:31 -05001792
1793 /* Fill in ADISC payload */
1794 ap = (ADISC *) pcmd;
1795 ap->hardAL_PA = phba->fc_pref_ALPA;
James Smart92d7f7b2007-06-17 19:56:38 -05001796 memcpy(&ap->portName, &vport->fc_portname, sizeof(struct lpfc_name));
1797 memcpy(&ap->nodeName, &vport->fc_nodename, sizeof(struct lpfc_name));
James Smart2e0fef82007-06-17 19:56:36 -05001798 ap->DID = be32_to_cpu(vport->fc_myDID);
dea31012005-04-17 16:05:31 -05001799
James Smart858c9f62007-06-17 19:56:39 -05001800 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
1801 "Issue ADISC: did:x%x",
1802 ndlp->nlp_DID, 0, 0);
1803
dea31012005-04-17 16:05:31 -05001804 phba->fc_stat.elsXmitADISC++;
1805 elsiocb->iocb_cmpl = lpfc_cmpl_els_adisc;
James Smart2e0fef82007-06-17 19:56:36 -05001806 spin_lock_irq(shost->host_lock);
dea31012005-04-17 16:05:31 -05001807 ndlp->nlp_flag |= NLP_ADISC_SND;
James Smart2e0fef82007-06-17 19:56:36 -05001808 spin_unlock_irq(shost->host_lock);
dea31012005-04-17 16:05:31 -05001809 if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) {
James Smart2e0fef82007-06-17 19:56:36 -05001810 spin_lock_irq(shost->host_lock);
dea31012005-04-17 16:05:31 -05001811 ndlp->nlp_flag &= ~NLP_ADISC_SND;
James Smart2e0fef82007-06-17 19:56:36 -05001812 spin_unlock_irq(shost->host_lock);
dea31012005-04-17 16:05:31 -05001813 lpfc_els_free_iocb(phba, elsiocb);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001814 return 1;
dea31012005-04-17 16:05:31 -05001815 }
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001816 return 0;
dea31012005-04-17 16:05:31 -05001817}
1818
James Smarte59058c2008-08-24 21:49:00 -04001819/**
1820 * lpfc_cmpl_els_logo: Completion callback function for logo.
1821 * @phba: pointer to lpfc hba data structure.
1822 * @cmdiocb: pointer to lpfc command iocb data structure.
1823 * @rspiocb: pointer to lpfc response iocb data structure.
1824 *
1825 * This routine is the completion function for issuing the ELS Logout (LOGO)
1826 * command. If no error status was reported from the LOGO response, the
1827 * state machine of the associated ndlp shall be invoked for transition with
1828 * respect to NLP_EVT_CMPL_LOGO event. Otherwise, if error status was reported,
1829 * the lpfc_els_retry() routine will be invoked to retry the LOGO command.
1830 **/
dea31012005-04-17 16:05:31 -05001831static void
James Smart2e0fef82007-06-17 19:56:36 -05001832lpfc_cmpl_els_logo(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
1833 struct lpfc_iocbq *rspiocb)
dea31012005-04-17 16:05:31 -05001834{
James Smart2e0fef82007-06-17 19:56:36 -05001835 struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) cmdiocb->context1;
1836 struct lpfc_vport *vport = ndlp->vport;
1837 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
dea31012005-04-17 16:05:31 -05001838 IOCB_t *irsp;
1839 struct lpfc_sli *psli;
dea31012005-04-17 16:05:31 -05001840
1841 psli = &phba->sli;
1842 /* we pass cmdiocb to state machine which needs rspiocb as well */
1843 cmdiocb->context_un.rsp_iocb = rspiocb;
1844
1845 irsp = &(rspiocb->iocb);
James Smart2e0fef82007-06-17 19:56:36 -05001846 spin_lock_irq(shost->host_lock);
dea31012005-04-17 16:05:31 -05001847 ndlp->nlp_flag &= ~NLP_LOGO_SND;
James Smart2e0fef82007-06-17 19:56:36 -05001848 spin_unlock_irq(shost->host_lock);
dea31012005-04-17 16:05:31 -05001849
James Smart858c9f62007-06-17 19:56:39 -05001850 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
1851 "LOGO cmpl: status:x%x/x%x did:x%x",
1852 irsp->ulpStatus, irsp->un.ulpWord[4],
1853 ndlp->nlp_DID);
dea31012005-04-17 16:05:31 -05001854 /* LOGO completes to NPort <nlp_DID> */
James Smarte8b62012007-08-02 11:10:09 -04001855 lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
1856 "0105 LOGO completes to NPort x%x "
1857 "Data: x%x x%x x%x x%x\n",
1858 ndlp->nlp_DID, irsp->ulpStatus, irsp->un.ulpWord[4],
1859 irsp->ulpTimeout, vport->num_disc_nodes);
dea31012005-04-17 16:05:31 -05001860 /* Check to see if link went down during discovery */
James Smart2e0fef82007-06-17 19:56:36 -05001861 if (lpfc_els_chk_latt(vport))
dea31012005-04-17 16:05:31 -05001862 goto out;
1863
James Smart92d7f7b2007-06-17 19:56:38 -05001864 if (ndlp->nlp_flag & NLP_TARGET_REMOVE) {
1865 /* NLP_EVT_DEVICE_RM should unregister the RPI
1866 * which should abort all outstanding IOs.
1867 */
1868 lpfc_disc_state_machine(vport, ndlp, cmdiocb,
1869 NLP_EVT_DEVICE_RM);
1870 goto out;
1871 }
1872
dea31012005-04-17 16:05:31 -05001873 if (irsp->ulpStatus) {
1874 /* Check for retry */
James Smart2e0fef82007-06-17 19:56:36 -05001875 if (lpfc_els_retry(phba, cmdiocb, rspiocb))
dea31012005-04-17 16:05:31 -05001876 /* ELS command is being retried */
1877 goto out;
dea31012005-04-17 16:05:31 -05001878 /* LOGO failed */
1879 /* Do not call DSM for lpfc_els_abort'ed ELS cmds */
James Smart858c9f62007-06-17 19:56:39 -05001880 if (lpfc_error_lost_link(irsp))
dea31012005-04-17 16:05:31 -05001881 goto out;
James Smart858c9f62007-06-17 19:56:39 -05001882 else
James Smart2e0fef82007-06-17 19:56:36 -05001883 lpfc_disc_state_machine(vport, ndlp, cmdiocb,
James Smart92d7f7b2007-06-17 19:56:38 -05001884 NLP_EVT_CMPL_LOGO);
James Smarte47c9092008-02-08 18:49:26 -05001885 } else
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05001886 /* Good status, call state machine.
1887 * This will unregister the rpi if needed.
1888 */
James Smart2e0fef82007-06-17 19:56:36 -05001889 lpfc_disc_state_machine(vport, ndlp, cmdiocb,
James Smart92d7f7b2007-06-17 19:56:38 -05001890 NLP_EVT_CMPL_LOGO);
dea31012005-04-17 16:05:31 -05001891out:
1892 lpfc_els_free_iocb(phba, cmdiocb);
1893 return;
1894}
1895
James Smarte59058c2008-08-24 21:49:00 -04001896/**
1897 * lpfc_issue_els_logo: Issue a logo to an node on a vport.
1898 * @vport: pointer to a virtual N_Port data structure.
1899 * @ndlp: pointer to a node-list data structure.
1900 * @retry: number of retries to the command IOCB.
1901 *
1902 * This routine constructs and issues an ELS Logout (LOGO) iocb command
1903 * to a remote node, referred by an @ndlp on a @vport. It constructs the
1904 * payload of the IOCB, properly sets up the @ndlp state, and invokes the
1905 * lpfc_sli_issue_iocb() routine to send out the LOGO ELS command.
1906 *
1907 * Note that, in lpfc_prep_els_iocb() routine, the reference count of ndlp
1908 * will be incremented by 1 for holding the ndlp and the reference to ndlp
1909 * will be stored into the context1 field of the IOCB for the completion
1910 * callback function to the LOGO ELS command.
1911 *
1912 * Return code
1913 * 0 - successfully issued logo
1914 * 1 - failed to issue logo
1915 **/
dea31012005-04-17 16:05:31 -05001916int
James Smart2e0fef82007-06-17 19:56:36 -05001917lpfc_issue_els_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
dea31012005-04-17 16:05:31 -05001918 uint8_t retry)
1919{
James Smart2e0fef82007-06-17 19:56:36 -05001920 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
1921 struct lpfc_hba *phba = vport->phba;
dea31012005-04-17 16:05:31 -05001922 IOCB_t *icmd;
1923 struct lpfc_iocbq *elsiocb;
1924 struct lpfc_sli_ring *pring;
1925 struct lpfc_sli *psli;
1926 uint8_t *pcmd;
1927 uint16_t cmdsize;
James Smart92d7f7b2007-06-17 19:56:38 -05001928 int rc;
dea31012005-04-17 16:05:31 -05001929
1930 psli = &phba->sli;
1931 pring = &psli->ring[LPFC_ELS_RING];
1932
James Smart98c9ea52007-10-27 13:37:33 -04001933 spin_lock_irq(shost->host_lock);
1934 if (ndlp->nlp_flag & NLP_LOGO_SND) {
1935 spin_unlock_irq(shost->host_lock);
1936 return 0;
1937 }
1938 spin_unlock_irq(shost->host_lock);
1939
James Smart92d7f7b2007-06-17 19:56:38 -05001940 cmdsize = (2 * sizeof(uint32_t)) + sizeof(struct lpfc_name);
James Smart2e0fef82007-06-17 19:56:36 -05001941 elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp,
1942 ndlp->nlp_DID, ELS_CMD_LOGO);
James Smart488d1462006-03-07 15:02:37 -05001943 if (!elsiocb)
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001944 return 1;
dea31012005-04-17 16:05:31 -05001945
1946 icmd = &elsiocb->iocb;
1947 pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
1948 *((uint32_t *) (pcmd)) = ELS_CMD_LOGO;
James Smart92d7f7b2007-06-17 19:56:38 -05001949 pcmd += sizeof(uint32_t);
dea31012005-04-17 16:05:31 -05001950
1951 /* Fill in LOGO payload */
James Smart2e0fef82007-06-17 19:56:36 -05001952 *((uint32_t *) (pcmd)) = be32_to_cpu(vport->fc_myDID);
James Smart92d7f7b2007-06-17 19:56:38 -05001953 pcmd += sizeof(uint32_t);
1954 memcpy(pcmd, &vport->fc_portname, sizeof(struct lpfc_name));
dea31012005-04-17 16:05:31 -05001955
James Smart858c9f62007-06-17 19:56:39 -05001956 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
1957 "Issue LOGO: did:x%x",
1958 ndlp->nlp_DID, 0, 0);
1959
dea31012005-04-17 16:05:31 -05001960 phba->fc_stat.elsXmitLOGO++;
1961 elsiocb->iocb_cmpl = lpfc_cmpl_els_logo;
James Smart2e0fef82007-06-17 19:56:36 -05001962 spin_lock_irq(shost->host_lock);
dea31012005-04-17 16:05:31 -05001963 ndlp->nlp_flag |= NLP_LOGO_SND;
James Smart2e0fef82007-06-17 19:56:36 -05001964 spin_unlock_irq(shost->host_lock);
James Smart92d7f7b2007-06-17 19:56:38 -05001965 rc = lpfc_sli_issue_iocb(phba, pring, elsiocb, 0);
1966
1967 if (rc == IOCB_ERROR) {
James Smart2e0fef82007-06-17 19:56:36 -05001968 spin_lock_irq(shost->host_lock);
dea31012005-04-17 16:05:31 -05001969 ndlp->nlp_flag &= ~NLP_LOGO_SND;
James Smart2e0fef82007-06-17 19:56:36 -05001970 spin_unlock_irq(shost->host_lock);
dea31012005-04-17 16:05:31 -05001971 lpfc_els_free_iocb(phba, elsiocb);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001972 return 1;
dea31012005-04-17 16:05:31 -05001973 }
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001974 return 0;
dea31012005-04-17 16:05:31 -05001975}
1976
James Smarte59058c2008-08-24 21:49:00 -04001977/**
1978 * lpfc_cmpl_els_cmd: Completion callback function for generic els command.
1979 * @phba: pointer to lpfc hba data structure.
1980 * @cmdiocb: pointer to lpfc command iocb data structure.
1981 * @rspiocb: pointer to lpfc response iocb data structure.
1982 *
1983 * This routine is a generic completion callback function for ELS commands.
1984 * Specifically, it is the callback function which does not need to perform
1985 * any command specific operations. It is currently used by the ELS command
1986 * issuing routines for the ELS State Change Request (SCR),
1987 * lpfc_issue_els_scr(), and the ELS Fibre Channel Address Resolution
1988 * Protocol Response (FARPR) routine, lpfc_issue_els_farpr(). Other than
1989 * certain debug loggings, this callback function simply invokes the
1990 * lpfc_els_chk_latt() routine to check whether link went down during the
1991 * discovery process.
1992 **/
dea31012005-04-17 16:05:31 -05001993static void
James Smart2e0fef82007-06-17 19:56:36 -05001994lpfc_cmpl_els_cmd(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
1995 struct lpfc_iocbq *rspiocb)
dea31012005-04-17 16:05:31 -05001996{
James Smart2e0fef82007-06-17 19:56:36 -05001997 struct lpfc_vport *vport = cmdiocb->vport;
dea31012005-04-17 16:05:31 -05001998 IOCB_t *irsp;
1999
2000 irsp = &rspiocb->iocb;
2001
James Smart858c9f62007-06-17 19:56:39 -05002002 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
2003 "ELS cmd cmpl: status:x%x/x%x did:x%x",
2004 irsp->ulpStatus, irsp->un.ulpWord[4],
2005 irsp->un.elsreq64.remoteID);
dea31012005-04-17 16:05:31 -05002006 /* ELS cmd tag <ulpIoTag> completes */
James Smarte8b62012007-08-02 11:10:09 -04002007 lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
2008 "0106 ELS cmd tag x%x completes Data: x%x x%x x%x\n",
2009 irsp->ulpIoTag, irsp->ulpStatus,
2010 irsp->un.ulpWord[4], irsp->ulpTimeout);
dea31012005-04-17 16:05:31 -05002011 /* Check to see if link went down during discovery */
James Smart2e0fef82007-06-17 19:56:36 -05002012 lpfc_els_chk_latt(vport);
dea31012005-04-17 16:05:31 -05002013 lpfc_els_free_iocb(phba, cmdiocb);
2014 return;
2015}
2016
James Smarte59058c2008-08-24 21:49:00 -04002017/**
2018 * lpfc_issue_els_scr: Issue a scr to an node on a vport.
2019 * @vport: pointer to a host virtual N_Port data structure.
2020 * @nportid: N_Port identifier to the remote node.
2021 * @retry: number of retries to the command IOCB.
2022 *
2023 * This routine issues a State Change Request (SCR) to a fabric node
2024 * on a @vport. The remote node @nportid is passed into the function. It
2025 * first search the @vport node list to find the matching ndlp. If no such
2026 * ndlp is found, a new ndlp shall be created for this (SCR) purpose. An
2027 * IOCB is allocated, payload prepared, and the lpfc_sli_issue_iocb()
2028 * routine is invoked to send the SCR IOCB.
2029 *
2030 * Note that, in lpfc_prep_els_iocb() routine, the reference count of ndlp
2031 * will be incremented by 1 for holding the ndlp and the reference to ndlp
2032 * will be stored into the context1 field of the IOCB for the completion
2033 * callback function to the SCR ELS command.
2034 *
2035 * Return code
2036 * 0 - Successfully issued scr command
2037 * 1 - Failed to issue scr command
2038 **/
dea31012005-04-17 16:05:31 -05002039int
James Smart2e0fef82007-06-17 19:56:36 -05002040lpfc_issue_els_scr(struct lpfc_vport *vport, uint32_t nportid, uint8_t retry)
dea31012005-04-17 16:05:31 -05002041{
James Smart2e0fef82007-06-17 19:56:36 -05002042 struct lpfc_hba *phba = vport->phba;
dea31012005-04-17 16:05:31 -05002043 IOCB_t *icmd;
2044 struct lpfc_iocbq *elsiocb;
2045 struct lpfc_sli_ring *pring;
2046 struct lpfc_sli *psli;
2047 uint8_t *pcmd;
2048 uint16_t cmdsize;
2049 struct lpfc_nodelist *ndlp;
2050
2051 psli = &phba->sli;
2052 pring = &psli->ring[LPFC_ELS_RING]; /* ELS ring */
James Smart92d7f7b2007-06-17 19:56:38 -05002053 cmdsize = (sizeof(uint32_t) + sizeof(SCR));
dea31012005-04-17 16:05:31 -05002054
James Smarte47c9092008-02-08 18:49:26 -05002055 ndlp = lpfc_findnode_did(vport, nportid);
2056 if (!ndlp) {
2057 ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL);
2058 if (!ndlp)
2059 return 1;
2060 lpfc_nlp_init(vport, ndlp, nportid);
2061 lpfc_enqueue_node(vport, ndlp);
2062 } else if (!NLP_CHK_NODE_ACT(ndlp)) {
2063 ndlp = lpfc_enable_node(vport, ndlp, NLP_STE_UNUSED_NODE);
2064 if (!ndlp)
2065 return 1;
2066 }
dea31012005-04-17 16:05:31 -05002067
James Smart2e0fef82007-06-17 19:56:36 -05002068 elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp,
2069 ndlp->nlp_DID, ELS_CMD_SCR);
2070
James Smart488d1462006-03-07 15:02:37 -05002071 if (!elsiocb) {
James Smartfa4066b2008-01-11 01:53:27 -05002072 /* This will trigger the release of the node just
2073 * allocated
2074 */
James Smart329f9bc2007-04-25 09:53:01 -04002075 lpfc_nlp_put(ndlp);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002076 return 1;
dea31012005-04-17 16:05:31 -05002077 }
2078
2079 icmd = &elsiocb->iocb;
2080 pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
2081
2082 *((uint32_t *) (pcmd)) = ELS_CMD_SCR;
James Smart92d7f7b2007-06-17 19:56:38 -05002083 pcmd += sizeof(uint32_t);
dea31012005-04-17 16:05:31 -05002084
2085 /* For SCR, remainder of payload is SCR parameter page */
James Smart92d7f7b2007-06-17 19:56:38 -05002086 memset(pcmd, 0, sizeof(SCR));
dea31012005-04-17 16:05:31 -05002087 ((SCR *) pcmd)->Function = SCR_FUNC_FULL;
2088
James Smart858c9f62007-06-17 19:56:39 -05002089 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
2090 "Issue SCR: did:x%x",
2091 ndlp->nlp_DID, 0, 0);
2092
dea31012005-04-17 16:05:31 -05002093 phba->fc_stat.elsXmitSCR++;
2094 elsiocb->iocb_cmpl = lpfc_cmpl_els_cmd;
dea31012005-04-17 16:05:31 -05002095 if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) {
James Smartfa4066b2008-01-11 01:53:27 -05002096 /* The additional lpfc_nlp_put will cause the following
2097 * lpfc_els_free_iocb routine to trigger the rlease of
2098 * the node.
2099 */
James Smart329f9bc2007-04-25 09:53:01 -04002100 lpfc_nlp_put(ndlp);
dea31012005-04-17 16:05:31 -05002101 lpfc_els_free_iocb(phba, elsiocb);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002102 return 1;
dea31012005-04-17 16:05:31 -05002103 }
James Smartfa4066b2008-01-11 01:53:27 -05002104 /* This will cause the callback-function lpfc_cmpl_els_cmd to
2105 * trigger the release of node.
2106 */
James Smart329f9bc2007-04-25 09:53:01 -04002107 lpfc_nlp_put(ndlp);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002108 return 0;
dea31012005-04-17 16:05:31 -05002109}
2110
James Smarte59058c2008-08-24 21:49:00 -04002111/**
2112 * lpfc_issue_els_farpr: Issue a farp to an node on a vport.
2113 * @vport: pointer to a host virtual N_Port data structure.
2114 * @nportid: N_Port identifier to the remote node.
2115 * @retry: number of retries to the command IOCB.
2116 *
2117 * This routine issues a Fibre Channel Address Resolution Response
2118 * (FARPR) to a node on a vport. The remote node N_Port identifier (@nportid)
2119 * is passed into the function. It first search the @vport node list to find
2120 * the matching ndlp. If no such ndlp is found, a new ndlp shall be created
2121 * for this (FARPR) purpose. An IOCB is allocated, payload prepared, and the
2122 * lpfc_sli_issue_iocb() routine is invoked to send the FARPR ELS command.
2123 *
2124 * Note that, in lpfc_prep_els_iocb() routine, the reference count of ndlp
2125 * will be incremented by 1 for holding the ndlp and the reference to ndlp
2126 * will be stored into the context1 field of the IOCB for the completion
2127 * callback function to the PARPR ELS command.
2128 *
2129 * Return code
2130 * 0 - Successfully issued farpr command
2131 * 1 - Failed to issue farpr command
2132 **/
dea31012005-04-17 16:05:31 -05002133static int
James Smart2e0fef82007-06-17 19:56:36 -05002134lpfc_issue_els_farpr(struct lpfc_vport *vport, uint32_t nportid, uint8_t retry)
dea31012005-04-17 16:05:31 -05002135{
James Smart2e0fef82007-06-17 19:56:36 -05002136 struct lpfc_hba *phba = vport->phba;
dea31012005-04-17 16:05:31 -05002137 IOCB_t *icmd;
2138 struct lpfc_iocbq *elsiocb;
2139 struct lpfc_sli_ring *pring;
2140 struct lpfc_sli *psli;
2141 FARP *fp;
2142 uint8_t *pcmd;
2143 uint32_t *lp;
2144 uint16_t cmdsize;
2145 struct lpfc_nodelist *ondlp;
2146 struct lpfc_nodelist *ndlp;
2147
2148 psli = &phba->sli;
2149 pring = &psli->ring[LPFC_ELS_RING]; /* ELS ring */
James Smart92d7f7b2007-06-17 19:56:38 -05002150 cmdsize = (sizeof(uint32_t) + sizeof(FARP));
dea31012005-04-17 16:05:31 -05002151
James Smarte47c9092008-02-08 18:49:26 -05002152 ndlp = lpfc_findnode_did(vport, nportid);
2153 if (!ndlp) {
2154 ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL);
2155 if (!ndlp)
2156 return 1;
2157 lpfc_nlp_init(vport, ndlp, nportid);
2158 lpfc_enqueue_node(vport, ndlp);
2159 } else if (!NLP_CHK_NODE_ACT(ndlp)) {
2160 ndlp = lpfc_enable_node(vport, ndlp, NLP_STE_UNUSED_NODE);
2161 if (!ndlp)
2162 return 1;
2163 }
James Smart2e0fef82007-06-17 19:56:36 -05002164
2165 elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp,
2166 ndlp->nlp_DID, ELS_CMD_RNID);
James Smart488d1462006-03-07 15:02:37 -05002167 if (!elsiocb) {
James Smartfa4066b2008-01-11 01:53:27 -05002168 /* This will trigger the release of the node just
2169 * allocated
2170 */
James Smart329f9bc2007-04-25 09:53:01 -04002171 lpfc_nlp_put(ndlp);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002172 return 1;
dea31012005-04-17 16:05:31 -05002173 }
2174
2175 icmd = &elsiocb->iocb;
2176 pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
2177
2178 *((uint32_t *) (pcmd)) = ELS_CMD_FARPR;
James Smart92d7f7b2007-06-17 19:56:38 -05002179 pcmd += sizeof(uint32_t);
dea31012005-04-17 16:05:31 -05002180
2181 /* Fill in FARPR payload */
2182 fp = (FARP *) (pcmd);
James Smart92d7f7b2007-06-17 19:56:38 -05002183 memset(fp, 0, sizeof(FARP));
dea31012005-04-17 16:05:31 -05002184 lp = (uint32_t *) pcmd;
2185 *lp++ = be32_to_cpu(nportid);
James Smart2e0fef82007-06-17 19:56:36 -05002186 *lp++ = be32_to_cpu(vport->fc_myDID);
dea31012005-04-17 16:05:31 -05002187 fp->Rflags = 0;
2188 fp->Mflags = (FARP_MATCH_PORT | FARP_MATCH_NODE);
2189
James Smart92d7f7b2007-06-17 19:56:38 -05002190 memcpy(&fp->RportName, &vport->fc_portname, sizeof(struct lpfc_name));
2191 memcpy(&fp->RnodeName, &vport->fc_nodename, sizeof(struct lpfc_name));
James Smart2e0fef82007-06-17 19:56:36 -05002192 ondlp = lpfc_findnode_did(vport, nportid);
James Smarte47c9092008-02-08 18:49:26 -05002193 if (ondlp && NLP_CHK_NODE_ACT(ondlp)) {
dea31012005-04-17 16:05:31 -05002194 memcpy(&fp->OportName, &ondlp->nlp_portname,
James Smart92d7f7b2007-06-17 19:56:38 -05002195 sizeof(struct lpfc_name));
dea31012005-04-17 16:05:31 -05002196 memcpy(&fp->OnodeName, &ondlp->nlp_nodename,
James Smart92d7f7b2007-06-17 19:56:38 -05002197 sizeof(struct lpfc_name));
dea31012005-04-17 16:05:31 -05002198 }
2199
James Smart858c9f62007-06-17 19:56:39 -05002200 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
2201 "Issue FARPR: did:x%x",
2202 ndlp->nlp_DID, 0, 0);
2203
dea31012005-04-17 16:05:31 -05002204 phba->fc_stat.elsXmitFARPR++;
2205 elsiocb->iocb_cmpl = lpfc_cmpl_els_cmd;
dea31012005-04-17 16:05:31 -05002206 if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) {
James Smartfa4066b2008-01-11 01:53:27 -05002207 /* The additional lpfc_nlp_put will cause the following
2208 * lpfc_els_free_iocb routine to trigger the release of
2209 * the node.
2210 */
James Smart329f9bc2007-04-25 09:53:01 -04002211 lpfc_nlp_put(ndlp);
dea31012005-04-17 16:05:31 -05002212 lpfc_els_free_iocb(phba, elsiocb);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002213 return 1;
dea31012005-04-17 16:05:31 -05002214 }
James Smartfa4066b2008-01-11 01:53:27 -05002215 /* This will cause the callback-function lpfc_cmpl_els_cmd to
2216 * trigger the release of the node.
2217 */
James Smart329f9bc2007-04-25 09:53:01 -04002218 lpfc_nlp_put(ndlp);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002219 return 0;
dea31012005-04-17 16:05:31 -05002220}
2221
James Smarte59058c2008-08-24 21:49:00 -04002222/**
2223 * lpfc_cancel_retry_delay_tmo: Cancel the timer with delayed iocb-cmd retry.
2224 * @vport: pointer to a host virtual N_Port data structure.
2225 * @nlp: pointer to a node-list data structure.
2226 *
2227 * This routine cancels the timer with a delayed IOCB-command retry for
2228 * a @vport's @ndlp. It stops the timer for the delayed function retrial and
2229 * removes the ELS retry event if it presents. In addition, if the
2230 * NLP_NPR_2B_DISC bit is set in the @nlp's nlp_flag bitmap, ADISC IOCB
2231 * commands are sent for the @vport's nodes that require issuing discovery
2232 * ADISC.
2233 **/
dea31012005-04-17 16:05:31 -05002234void
James Smart2e0fef82007-06-17 19:56:36 -05002235lpfc_cancel_retry_delay_tmo(struct lpfc_vport *vport, struct lpfc_nodelist *nlp)
James Smartfdcebe22006-03-07 15:04:01 -05002236{
James Smart2e0fef82007-06-17 19:56:36 -05002237 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
James Smarte47c9092008-02-08 18:49:26 -05002238 struct lpfc_work_evt *evtp;
James Smart2e0fef82007-06-17 19:56:36 -05002239
James Smart0d2b6b82008-06-14 22:52:47 -04002240 if (!(nlp->nlp_flag & NLP_DELAY_TMO))
2241 return;
James Smart2e0fef82007-06-17 19:56:36 -05002242 spin_lock_irq(shost->host_lock);
James Smartfdcebe22006-03-07 15:04:01 -05002243 nlp->nlp_flag &= ~NLP_DELAY_TMO;
James Smart2e0fef82007-06-17 19:56:36 -05002244 spin_unlock_irq(shost->host_lock);
James Smartfdcebe22006-03-07 15:04:01 -05002245 del_timer_sync(&nlp->nlp_delayfunc);
2246 nlp->nlp_last_elscmd = 0;
James Smarte47c9092008-02-08 18:49:26 -05002247 if (!list_empty(&nlp->els_retry_evt.evt_listp)) {
James Smartfdcebe22006-03-07 15:04:01 -05002248 list_del_init(&nlp->els_retry_evt.evt_listp);
James Smarte47c9092008-02-08 18:49:26 -05002249 /* Decrement nlp reference count held for the delayed retry */
2250 evtp = &nlp->els_retry_evt;
2251 lpfc_nlp_put((struct lpfc_nodelist *)evtp->evt_arg1);
2252 }
James Smartfdcebe22006-03-07 15:04:01 -05002253 if (nlp->nlp_flag & NLP_NPR_2B_DISC) {
James Smart2e0fef82007-06-17 19:56:36 -05002254 spin_lock_irq(shost->host_lock);
James Smartfdcebe22006-03-07 15:04:01 -05002255 nlp->nlp_flag &= ~NLP_NPR_2B_DISC;
James Smart2e0fef82007-06-17 19:56:36 -05002256 spin_unlock_irq(shost->host_lock);
2257 if (vport->num_disc_nodes) {
James Smart0d2b6b82008-06-14 22:52:47 -04002258 if (vport->port_state < LPFC_VPORT_READY) {
2259 /* Check if there are more ADISCs to be sent */
2260 lpfc_more_adisc(vport);
2261 if ((vport->num_disc_nodes == 0) &&
2262 (vport->fc_npr_cnt))
2263 lpfc_els_disc_plogi(vport);
2264 } else {
2265 /* Check if there are more PLOGIs to be sent */
2266 lpfc_more_plogi(vport);
2267 }
James Smart2e0fef82007-06-17 19:56:36 -05002268 if (vport->num_disc_nodes == 0) {
2269 spin_lock_irq(shost->host_lock);
2270 vport->fc_flag &= ~FC_NDISC_ACTIVE;
2271 spin_unlock_irq(shost->host_lock);
2272 lpfc_can_disctmo(vport);
James Smarted957682007-06-17 19:56:37 -05002273 lpfc_end_rscn(vport);
James Smartfdcebe22006-03-07 15:04:01 -05002274 }
2275 }
2276 }
2277 return;
2278}
2279
James Smarte59058c2008-08-24 21:49:00 -04002280/**
2281 * lpfc_els_retry_delay: Timer function with a ndlp delayed function timer.
2282 * @ptr: holder for the pointer to the timer function associated data (ndlp).
2283 *
2284 * This routine is invoked by the ndlp delayed-function timer to check
2285 * whether there is any pending ELS retry event(s) with the node. If not, it
2286 * simply returns. Otherwise, if there is at least one ELS delayed event, it
2287 * adds the delayed events to the HBA work list and invokes the
2288 * lpfc_worker_wake_up() routine to wake up worker thread to process the
2289 * event. Note that lpfc_nlp_get() is called before posting the event to
2290 * the work list to hold reference count of ndlp so that it guarantees the
2291 * reference to ndlp will still be available when the worker thread gets
2292 * to the event associated with the ndlp.
2293 **/
James Smartfdcebe22006-03-07 15:04:01 -05002294void
dea31012005-04-17 16:05:31 -05002295lpfc_els_retry_delay(unsigned long ptr)
2296{
James Smart2e0fef82007-06-17 19:56:36 -05002297 struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) ptr;
2298 struct lpfc_vport *vport = ndlp->vport;
James Smart2e0fef82007-06-17 19:56:36 -05002299 struct lpfc_hba *phba = vport->phba;
James Smart92d7f7b2007-06-17 19:56:38 -05002300 unsigned long flags;
James Smart2e0fef82007-06-17 19:56:36 -05002301 struct lpfc_work_evt *evtp = &ndlp->els_retry_evt;
dea31012005-04-17 16:05:31 -05002302
James Smart92d7f7b2007-06-17 19:56:38 -05002303 spin_lock_irqsave(&phba->hbalock, flags);
dea31012005-04-17 16:05:31 -05002304 if (!list_empty(&evtp->evt_listp)) {
James Smart92d7f7b2007-06-17 19:56:38 -05002305 spin_unlock_irqrestore(&phba->hbalock, flags);
dea31012005-04-17 16:05:31 -05002306 return;
2307 }
2308
James Smartfa4066b2008-01-11 01:53:27 -05002309 /* We need to hold the node by incrementing the reference
2310 * count until the queued work is done
2311 */
2312 evtp->evt_arg1 = lpfc_nlp_get(ndlp);
James Smart5e9d9b82008-06-14 22:52:53 -04002313 if (evtp->evt_arg1) {
2314 evtp->evt = LPFC_EVT_ELS_RETRY;
2315 list_add_tail(&evtp->evt_listp, &phba->work_list);
James Smart92d7f7b2007-06-17 19:56:38 -05002316 lpfc_worker_wake_up(phba);
James Smart5e9d9b82008-06-14 22:52:53 -04002317 }
James Smart92d7f7b2007-06-17 19:56:38 -05002318 spin_unlock_irqrestore(&phba->hbalock, flags);
dea31012005-04-17 16:05:31 -05002319 return;
2320}
2321
James Smarte59058c2008-08-24 21:49:00 -04002322/**
2323 * lpfc_els_retry_delay_handler: Work thread handler for ndlp delayed function.
2324 * @ndlp: pointer to a node-list data structure.
2325 *
2326 * This routine is the worker-thread handler for processing the @ndlp delayed
2327 * event(s), posted by the lpfc_els_retry_delay() routine. It simply retrieves
2328 * the last ELS command from the associated ndlp and invokes the proper ELS
2329 * function according to the delayed ELS command to retry the command.
2330 **/
dea31012005-04-17 16:05:31 -05002331void
2332lpfc_els_retry_delay_handler(struct lpfc_nodelist *ndlp)
2333{
James Smart2e0fef82007-06-17 19:56:36 -05002334 struct lpfc_vport *vport = ndlp->vport;
2335 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
2336 uint32_t cmd, did, retry;
dea31012005-04-17 16:05:31 -05002337
James Smart2e0fef82007-06-17 19:56:36 -05002338 spin_lock_irq(shost->host_lock);
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05002339 did = ndlp->nlp_DID;
2340 cmd = ndlp->nlp_last_elscmd;
2341 ndlp->nlp_last_elscmd = 0;
dea31012005-04-17 16:05:31 -05002342
2343 if (!(ndlp->nlp_flag & NLP_DELAY_TMO)) {
James Smart2e0fef82007-06-17 19:56:36 -05002344 spin_unlock_irq(shost->host_lock);
dea31012005-04-17 16:05:31 -05002345 return;
2346 }
2347
2348 ndlp->nlp_flag &= ~NLP_DELAY_TMO;
James Smart2e0fef82007-06-17 19:56:36 -05002349 spin_unlock_irq(shost->host_lock);
James Smart1a169682006-03-07 15:04:06 -05002350 /*
2351 * If a discovery event readded nlp_delayfunc after timer
2352 * firing and before processing the timer, cancel the
2353 * nlp_delayfunc.
2354 */
2355 del_timer_sync(&ndlp->nlp_delayfunc);
dea31012005-04-17 16:05:31 -05002356 retry = ndlp->nlp_retry;
2357
2358 switch (cmd) {
2359 case ELS_CMD_FLOGI:
James Smart2e0fef82007-06-17 19:56:36 -05002360 lpfc_issue_els_flogi(vport, ndlp, retry);
dea31012005-04-17 16:05:31 -05002361 break;
2362 case ELS_CMD_PLOGI:
James Smart2e0fef82007-06-17 19:56:36 -05002363 if (!lpfc_issue_els_plogi(vport, ndlp->nlp_DID, retry)) {
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05002364 ndlp->nlp_prev_state = ndlp->nlp_state;
James Smart2e0fef82007-06-17 19:56:36 -05002365 lpfc_nlp_set_state(vport, ndlp, NLP_STE_PLOGI_ISSUE);
Jamie Wellnitz6ad42532006-02-28 19:25:16 -05002366 }
dea31012005-04-17 16:05:31 -05002367 break;
2368 case ELS_CMD_ADISC:
James Smart2e0fef82007-06-17 19:56:36 -05002369 if (!lpfc_issue_els_adisc(vport, ndlp, retry)) {
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05002370 ndlp->nlp_prev_state = ndlp->nlp_state;
James Smart2e0fef82007-06-17 19:56:36 -05002371 lpfc_nlp_set_state(vport, ndlp, NLP_STE_ADISC_ISSUE);
Jamie Wellnitz6ad42532006-02-28 19:25:16 -05002372 }
dea31012005-04-17 16:05:31 -05002373 break;
2374 case ELS_CMD_PRLI:
James Smart2e0fef82007-06-17 19:56:36 -05002375 if (!lpfc_issue_els_prli(vport, ndlp, retry)) {
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05002376 ndlp->nlp_prev_state = ndlp->nlp_state;
James Smart2e0fef82007-06-17 19:56:36 -05002377 lpfc_nlp_set_state(vport, ndlp, NLP_STE_PRLI_ISSUE);
Jamie Wellnitz6ad42532006-02-28 19:25:16 -05002378 }
dea31012005-04-17 16:05:31 -05002379 break;
2380 case ELS_CMD_LOGO:
James Smart2e0fef82007-06-17 19:56:36 -05002381 if (!lpfc_issue_els_logo(vport, ndlp, retry)) {
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05002382 ndlp->nlp_prev_state = ndlp->nlp_state;
James Smart2e0fef82007-06-17 19:56:36 -05002383 lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
Jamie Wellnitz6ad42532006-02-28 19:25:16 -05002384 }
dea31012005-04-17 16:05:31 -05002385 break;
James Smart92d7f7b2007-06-17 19:56:38 -05002386 case ELS_CMD_FDISC:
2387 lpfc_issue_els_fdisc(vport, ndlp, retry);
2388 break;
dea31012005-04-17 16:05:31 -05002389 }
2390 return;
2391}
2392
James Smarte59058c2008-08-24 21:49:00 -04002393/**
2394 * lpfc_els_retry: Make retry decision on an els command iocb.
2395 * @phba: pointer to lpfc hba data structure.
2396 * @cmdiocb: pointer to lpfc command iocb data structure.
2397 * @rspiocb: pointer to lpfc response iocb data structure.
2398 *
2399 * This routine makes a retry decision on an ELS command IOCB, which has
2400 * failed. The following ELS IOCBs use this function for retrying the command
2401 * when previously issued command responsed with error status: FLOGI, PLOGI,
2402 * PRLI, ADISC, LOGO, and FDISC. Based on the ELS command type and the
2403 * returned error status, it makes the decision whether a retry shall be
2404 * issued for the command, and whether a retry shall be made immediately or
2405 * delayed. In the former case, the corresponding ELS command issuing-function
2406 * is called to retry the command. In the later case, the ELS command shall
2407 * be posted to the ndlp delayed event and delayed function timer set to the
2408 * ndlp for the delayed command issusing.
2409 *
2410 * Return code
2411 * 0 - No retry of els command is made
2412 * 1 - Immediate or delayed retry of els command is made
2413 **/
dea31012005-04-17 16:05:31 -05002414static int
James Smart2e0fef82007-06-17 19:56:36 -05002415lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
2416 struct lpfc_iocbq *rspiocb)
dea31012005-04-17 16:05:31 -05002417{
James Smart2e0fef82007-06-17 19:56:36 -05002418 struct lpfc_vport *vport = cmdiocb->vport;
2419 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
2420 IOCB_t *irsp = &rspiocb->iocb;
2421 struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) cmdiocb->context1;
2422 struct lpfc_dmabuf *pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
dea31012005-04-17 16:05:31 -05002423 uint32_t *elscmd;
2424 struct ls_rjt stat;
James Smart2e0fef82007-06-17 19:56:36 -05002425 int retry = 0, maxretry = lpfc_max_els_tries, delay = 0;
James Smart98c9ea52007-10-27 13:37:33 -04002426 int logerr = 0;
James Smart2e0fef82007-06-17 19:56:36 -05002427 uint32_t cmd = 0;
James Smart488d1462006-03-07 15:02:37 -05002428 uint32_t did;
dea31012005-04-17 16:05:31 -05002429
James Smart488d1462006-03-07 15:02:37 -05002430
dea31012005-04-17 16:05:31 -05002431 /* Note: context2 may be 0 for internal driver abort
2432 * of delays ELS command.
2433 */
2434
2435 if (pcmd && pcmd->virt) {
2436 elscmd = (uint32_t *) (pcmd->virt);
2437 cmd = *elscmd++;
2438 }
2439
James Smarte47c9092008-02-08 18:49:26 -05002440 if (ndlp && NLP_CHK_NODE_ACT(ndlp))
James Smart488d1462006-03-07 15:02:37 -05002441 did = ndlp->nlp_DID;
2442 else {
2443 /* We should only hit this case for retrying PLOGI */
2444 did = irsp->un.elsreq64.remoteID;
James Smart2e0fef82007-06-17 19:56:36 -05002445 ndlp = lpfc_findnode_did(vport, did);
James Smarte47c9092008-02-08 18:49:26 -05002446 if ((!ndlp || !NLP_CHK_NODE_ACT(ndlp))
2447 && (cmd != ELS_CMD_PLOGI))
James Smart488d1462006-03-07 15:02:37 -05002448 return 1;
2449 }
2450
James Smart858c9f62007-06-17 19:56:39 -05002451 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
2452 "Retry ELS: wd7:x%x wd4:x%x did:x%x",
2453 *(((uint32_t *) irsp) + 7), irsp->un.ulpWord[4], ndlp->nlp_DID);
2454
dea31012005-04-17 16:05:31 -05002455 switch (irsp->ulpStatus) {
2456 case IOSTAT_FCP_RSP_ERROR:
2457 case IOSTAT_REMOTE_STOP:
2458 break;
2459
2460 case IOSTAT_LOCAL_REJECT:
2461 switch ((irsp->un.ulpWord[4] & 0xff)) {
2462 case IOERR_LOOP_OPEN_FAILURE:
James Smart2e0fef82007-06-17 19:56:36 -05002463 if (cmd == ELS_CMD_PLOGI && cmdiocb->retry == 0)
James Smart92d7f7b2007-06-17 19:56:38 -05002464 delay = 1000;
dea31012005-04-17 16:05:31 -05002465 retry = 1;
2466 break;
2467
James Smart92d7f7b2007-06-17 19:56:38 -05002468 case IOERR_ILLEGAL_COMMAND:
James Smart7f5f3d02008-02-08 18:50:14 -05002469 lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
2470 "0124 Retry illegal cmd x%x "
2471 "retry:x%x delay:x%x\n",
2472 cmd, cmdiocb->retry, delay);
2473 retry = 1;
2474 /* All command's retry policy */
2475 maxretry = 8;
2476 if (cmdiocb->retry > 2)
2477 delay = 1000;
James Smart92d7f7b2007-06-17 19:56:38 -05002478 break;
2479
dea31012005-04-17 16:05:31 -05002480 case IOERR_NO_RESOURCES:
James Smart98c9ea52007-10-27 13:37:33 -04002481 logerr = 1; /* HBA out of resources */
James Smart858c9f62007-06-17 19:56:39 -05002482 retry = 1;
2483 if (cmdiocb->retry > 100)
2484 delay = 100;
2485 maxretry = 250;
2486 break;
2487
2488 case IOERR_ILLEGAL_FRAME:
James Smart92d7f7b2007-06-17 19:56:38 -05002489 delay = 100;
dea31012005-04-17 16:05:31 -05002490 retry = 1;
2491 break;
2492
James Smart858c9f62007-06-17 19:56:39 -05002493 case IOERR_SEQUENCE_TIMEOUT:
dea31012005-04-17 16:05:31 -05002494 case IOERR_INVALID_RPI:
2495 retry = 1;
2496 break;
2497 }
2498 break;
2499
2500 case IOSTAT_NPORT_RJT:
2501 case IOSTAT_FABRIC_RJT:
2502 if (irsp->un.ulpWord[4] & RJT_UNAVAIL_TEMP) {
2503 retry = 1;
2504 break;
2505 }
2506 break;
2507
2508 case IOSTAT_NPORT_BSY:
2509 case IOSTAT_FABRIC_BSY:
James Smart98c9ea52007-10-27 13:37:33 -04002510 logerr = 1; /* Fabric / Remote NPort out of resources */
dea31012005-04-17 16:05:31 -05002511 retry = 1;
2512 break;
2513
2514 case IOSTAT_LS_RJT:
2515 stat.un.lsRjtError = be32_to_cpu(irsp->un.ulpWord[4]);
2516 /* Added for Vendor specifc support
2517 * Just keep retrying for these Rsn / Exp codes
2518 */
2519 switch (stat.un.b.lsRjtRsnCode) {
2520 case LSRJT_UNABLE_TPC:
2521 if (stat.un.b.lsRjtRsnCodeExp ==
2522 LSEXP_CMD_IN_PROGRESS) {
2523 if (cmd == ELS_CMD_PLOGI) {
James Smart92d7f7b2007-06-17 19:56:38 -05002524 delay = 1000;
dea31012005-04-17 16:05:31 -05002525 maxretry = 48;
2526 }
2527 retry = 1;
2528 break;
2529 }
2530 if (cmd == ELS_CMD_PLOGI) {
James Smart92d7f7b2007-06-17 19:56:38 -05002531 delay = 1000;
dea31012005-04-17 16:05:31 -05002532 maxretry = lpfc_max_els_tries + 1;
2533 retry = 1;
2534 break;
2535 }
James Smart92d7f7b2007-06-17 19:56:38 -05002536 if ((phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) &&
2537 (cmd == ELS_CMD_FDISC) &&
2538 (stat.un.b.lsRjtRsnCodeExp == LSEXP_OUT_OF_RESOURCE)){
James Smarte8b62012007-08-02 11:10:09 -04002539 lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
2540 "0125 FDISC Failed (x%x). "
2541 "Fabric out of resources\n",
2542 stat.un.lsRjtError);
James Smart92d7f7b2007-06-17 19:56:38 -05002543 lpfc_vport_set_state(vport,
2544 FC_VPORT_NO_FABRIC_RSCS);
2545 }
dea31012005-04-17 16:05:31 -05002546 break;
2547
2548 case LSRJT_LOGICAL_BSY:
James Smart858c9f62007-06-17 19:56:39 -05002549 if ((cmd == ELS_CMD_PLOGI) ||
2550 (cmd == ELS_CMD_PRLI)) {
James Smart92d7f7b2007-06-17 19:56:38 -05002551 delay = 1000;
dea31012005-04-17 16:05:31 -05002552 maxretry = 48;
James Smart92d7f7b2007-06-17 19:56:38 -05002553 } else if (cmd == ELS_CMD_FDISC) {
James Smart51ef4c22007-08-02 11:10:31 -04002554 /* FDISC retry policy */
2555 maxretry = 48;
2556 if (cmdiocb->retry >= 32)
2557 delay = 1000;
dea31012005-04-17 16:05:31 -05002558 }
2559 retry = 1;
2560 break;
James Smart92d7f7b2007-06-17 19:56:38 -05002561
2562 case LSRJT_LOGICAL_ERR:
James Smart7f5f3d02008-02-08 18:50:14 -05002563 /* There are some cases where switches return this
2564 * error when they are not ready and should be returning
2565 * Logical Busy. We should delay every time.
2566 */
2567 if (cmd == ELS_CMD_FDISC &&
2568 stat.un.b.lsRjtRsnCodeExp == LSEXP_PORT_LOGIN_REQ) {
2569 maxretry = 3;
2570 delay = 1000;
2571 retry = 1;
2572 break;
2573 }
James Smart92d7f7b2007-06-17 19:56:38 -05002574 case LSRJT_PROTOCOL_ERR:
2575 if ((phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) &&
2576 (cmd == ELS_CMD_FDISC) &&
2577 ((stat.un.b.lsRjtRsnCodeExp == LSEXP_INVALID_PNAME) ||
2578 (stat.un.b.lsRjtRsnCodeExp == LSEXP_INVALID_NPORT_ID))
2579 ) {
James Smarte8b62012007-08-02 11:10:09 -04002580 lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
2581 "0123 FDISC Failed (x%x). "
2582 "Fabric Detected Bad WWN\n",
2583 stat.un.lsRjtError);
James Smart92d7f7b2007-06-17 19:56:38 -05002584 lpfc_vport_set_state(vport,
2585 FC_VPORT_FABRIC_REJ_WWN);
2586 }
2587 break;
dea31012005-04-17 16:05:31 -05002588 }
2589 break;
2590
2591 case IOSTAT_INTERMED_RSP:
2592 case IOSTAT_BA_RJT:
2593 break;
2594
2595 default:
2596 break;
2597 }
2598
James Smart488d1462006-03-07 15:02:37 -05002599 if (did == FDMI_DID)
dea31012005-04-17 16:05:31 -05002600 retry = 1;
dea31012005-04-17 16:05:31 -05002601
James Smart98c9ea52007-10-27 13:37:33 -04002602 if ((cmd == ELS_CMD_FLOGI) &&
James Smart1b32f6a2008-02-08 18:49:39 -05002603 (phba->fc_topology != TOPOLOGY_LOOP) &&
2604 !lpfc_error_lost_link(irsp)) {
James Smart98c9ea52007-10-27 13:37:33 -04002605 /* FLOGI retry policy */
2606 retry = 1;
2607 maxretry = 48;
2608 if (cmdiocb->retry >= 32)
2609 delay = 1000;
2610 }
2611
dea31012005-04-17 16:05:31 -05002612 if ((++cmdiocb->retry) >= maxretry) {
2613 phba->fc_stat.elsRetryExceeded++;
2614 retry = 0;
2615 }
2616
James Smarted957682007-06-17 19:56:37 -05002617 if ((vport->load_flag & FC_UNLOADING) != 0)
2618 retry = 0;
2619
dea31012005-04-17 16:05:31 -05002620 if (retry) {
2621
2622 /* Retry ELS command <elsCmd> to remote NPORT <did> */
James Smarte8b62012007-08-02 11:10:09 -04002623 lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
2624 "0107 Retry ELS command x%x to remote "
2625 "NPORT x%x Data: x%x x%x\n",
2626 cmd, did, cmdiocb->retry, delay);
dea31012005-04-17 16:05:31 -05002627
James Smart858c9f62007-06-17 19:56:39 -05002628 if (((cmd == ELS_CMD_PLOGI) || (cmd == ELS_CMD_ADISC)) &&
2629 ((irsp->ulpStatus != IOSTAT_LOCAL_REJECT) ||
2630 ((irsp->un.ulpWord[4] & 0xff) != IOERR_NO_RESOURCES))) {
2631 /* Don't reset timer for no resources */
2632
dea31012005-04-17 16:05:31 -05002633 /* If discovery / RSCN timer is running, reset it */
James Smart2e0fef82007-06-17 19:56:36 -05002634 if (timer_pending(&vport->fc_disctmo) ||
James Smart92d7f7b2007-06-17 19:56:38 -05002635 (vport->fc_flag & FC_RSCN_MODE))
James Smart2e0fef82007-06-17 19:56:36 -05002636 lpfc_set_disctmo(vport);
dea31012005-04-17 16:05:31 -05002637 }
2638
2639 phba->fc_stat.elsXmitRetry++;
James Smart58da1ff2008-04-07 10:15:56 -04002640 if (ndlp && NLP_CHK_NODE_ACT(ndlp) && delay) {
dea31012005-04-17 16:05:31 -05002641 phba->fc_stat.elsDelayRetry++;
2642 ndlp->nlp_retry = cmdiocb->retry;
2643
James Smart92d7f7b2007-06-17 19:56:38 -05002644 /* delay is specified in milliseconds */
2645 mod_timer(&ndlp->nlp_delayfunc,
2646 jiffies + msecs_to_jiffies(delay));
James Smart2e0fef82007-06-17 19:56:36 -05002647 spin_lock_irq(shost->host_lock);
dea31012005-04-17 16:05:31 -05002648 ndlp->nlp_flag |= NLP_DELAY_TMO;
James Smart2e0fef82007-06-17 19:56:36 -05002649 spin_unlock_irq(shost->host_lock);
dea31012005-04-17 16:05:31 -05002650
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05002651 ndlp->nlp_prev_state = ndlp->nlp_state;
James Smart858c9f62007-06-17 19:56:39 -05002652 if (cmd == ELS_CMD_PRLI)
2653 lpfc_nlp_set_state(vport, ndlp,
2654 NLP_STE_REG_LOGIN_ISSUE);
2655 else
2656 lpfc_nlp_set_state(vport, ndlp,
2657 NLP_STE_NPR_NODE);
dea31012005-04-17 16:05:31 -05002658 ndlp->nlp_last_elscmd = cmd;
2659
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002660 return 1;
dea31012005-04-17 16:05:31 -05002661 }
2662 switch (cmd) {
2663 case ELS_CMD_FLOGI:
James Smart2e0fef82007-06-17 19:56:36 -05002664 lpfc_issue_els_flogi(vport, ndlp, cmdiocb->retry);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002665 return 1;
James Smart92d7f7b2007-06-17 19:56:38 -05002666 case ELS_CMD_FDISC:
2667 lpfc_issue_els_fdisc(vport, ndlp, cmdiocb->retry);
2668 return 1;
dea31012005-04-17 16:05:31 -05002669 case ELS_CMD_PLOGI:
James Smart58da1ff2008-04-07 10:15:56 -04002670 if (ndlp && NLP_CHK_NODE_ACT(ndlp)) {
James Smart488d1462006-03-07 15:02:37 -05002671 ndlp->nlp_prev_state = ndlp->nlp_state;
James Smart2e0fef82007-06-17 19:56:36 -05002672 lpfc_nlp_set_state(vport, ndlp,
James Smartde0c5b32007-04-25 09:52:27 -04002673 NLP_STE_PLOGI_ISSUE);
James Smart488d1462006-03-07 15:02:37 -05002674 }
James Smart2e0fef82007-06-17 19:56:36 -05002675 lpfc_issue_els_plogi(vport, did, cmdiocb->retry);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002676 return 1;
dea31012005-04-17 16:05:31 -05002677 case ELS_CMD_ADISC:
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05002678 ndlp->nlp_prev_state = ndlp->nlp_state;
James Smart2e0fef82007-06-17 19:56:36 -05002679 lpfc_nlp_set_state(vport, ndlp, NLP_STE_ADISC_ISSUE);
2680 lpfc_issue_els_adisc(vport, ndlp, cmdiocb->retry);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002681 return 1;
dea31012005-04-17 16:05:31 -05002682 case ELS_CMD_PRLI:
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05002683 ndlp->nlp_prev_state = ndlp->nlp_state;
James Smart2e0fef82007-06-17 19:56:36 -05002684 lpfc_nlp_set_state(vport, ndlp, NLP_STE_PRLI_ISSUE);
2685 lpfc_issue_els_prli(vport, ndlp, cmdiocb->retry);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002686 return 1;
dea31012005-04-17 16:05:31 -05002687 case ELS_CMD_LOGO:
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05002688 ndlp->nlp_prev_state = ndlp->nlp_state;
James Smart2e0fef82007-06-17 19:56:36 -05002689 lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
2690 lpfc_issue_els_logo(vport, ndlp, cmdiocb->retry);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002691 return 1;
dea31012005-04-17 16:05:31 -05002692 }
2693 }
dea31012005-04-17 16:05:31 -05002694 /* No retry ELS command <elsCmd> to remote NPORT <did> */
James Smart98c9ea52007-10-27 13:37:33 -04002695 if (logerr) {
2696 lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
2697 "0137 No retry ELS command x%x to remote "
2698 "NPORT x%x: Out of Resources: Error:x%x/%x\n",
2699 cmd, did, irsp->ulpStatus,
2700 irsp->un.ulpWord[4]);
2701 }
2702 else {
2703 lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
James Smarta58cbd52007-08-02 11:09:43 -04002704 "0108 No retry ELS command x%x to remote "
2705 "NPORT x%x Retried:%d Error:x%x/%x\n",
2706 cmd, did, cmdiocb->retry, irsp->ulpStatus,
2707 irsp->un.ulpWord[4]);
James Smart98c9ea52007-10-27 13:37:33 -04002708 }
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002709 return 0;
dea31012005-04-17 16:05:31 -05002710}
2711
James Smarte59058c2008-08-24 21:49:00 -04002712/**
2713 * lpfc_els_free_data: Free lpfc dma buffer and data structure with an iocb.
2714 * @phba: pointer to lpfc hba data structure.
2715 * @buf_ptr1: pointer to the lpfc DMA buffer data structure.
2716 *
2717 * This routine releases the lpfc DMA (Direct Memory Access) buffer(s)
2718 * associated with a command IOCB back to the lpfc DMA buffer pool. It first
2719 * checks to see whether there is a lpfc DMA buffer associated with the
2720 * response of the command IOCB. If so, it will be released before releasing
2721 * the lpfc DMA buffer associated with the IOCB itself.
2722 *
2723 * Return code
2724 * 0 - Successfully released lpfc DMA buffer (currently, always return 0)
2725 **/
James Smart09372822008-01-11 01:52:54 -05002726static int
James Smart87af33f2007-10-27 13:37:43 -04002727lpfc_els_free_data(struct lpfc_hba *phba, struct lpfc_dmabuf *buf_ptr1)
2728{
2729 struct lpfc_dmabuf *buf_ptr;
2730
James Smarte59058c2008-08-24 21:49:00 -04002731 /* Free the response before processing the command. */
James Smart87af33f2007-10-27 13:37:43 -04002732 if (!list_empty(&buf_ptr1->list)) {
2733 list_remove_head(&buf_ptr1->list, buf_ptr,
2734 struct lpfc_dmabuf,
2735 list);
2736 lpfc_mbuf_free(phba, buf_ptr->virt, buf_ptr->phys);
2737 kfree(buf_ptr);
2738 }
2739 lpfc_mbuf_free(phba, buf_ptr1->virt, buf_ptr1->phys);
2740 kfree(buf_ptr1);
2741 return 0;
2742}
2743
James Smarte59058c2008-08-24 21:49:00 -04002744/**
2745 * lpfc_els_free_bpl: Free lpfc dma buffer and data structure with bpl.
2746 * @phba: pointer to lpfc hba data structure.
2747 * @buf_ptr: pointer to the lpfc dma buffer data structure.
2748 *
2749 * This routine releases the lpfc Direct Memory Access (DMA) buffer
2750 * associated with a Buffer Pointer List (BPL) back to the lpfc DMA buffer
2751 * pool.
2752 *
2753 * Return code
2754 * 0 - Successfully released lpfc DMA buffer (currently, always return 0)
2755 **/
James Smart09372822008-01-11 01:52:54 -05002756static int
James Smart87af33f2007-10-27 13:37:43 -04002757lpfc_els_free_bpl(struct lpfc_hba *phba, struct lpfc_dmabuf *buf_ptr)
2758{
2759 lpfc_mbuf_free(phba, buf_ptr->virt, buf_ptr->phys);
2760 kfree(buf_ptr);
2761 return 0;
2762}
2763
James Smarte59058c2008-08-24 21:49:00 -04002764/**
2765 * lpfc_els_free_iocb: Free a command iocb and its associated resources.
2766 * @phba: pointer to lpfc hba data structure.
2767 * @elsiocb: pointer to lpfc els command iocb data structure.
2768 *
2769 * This routine frees a command IOCB and its associated resources. The
2770 * command IOCB data structure contains the reference to various associated
2771 * resources, these fields must be set to NULL if the associated reference
2772 * not present:
2773 * context1 - reference to ndlp
2774 * context2 - reference to cmd
2775 * context2->next - reference to rsp
2776 * context3 - reference to bpl
2777 *
2778 * It first properly decrements the reference count held on ndlp for the
2779 * IOCB completion callback function. If LPFC_DELAY_MEM_FREE flag is not
2780 * set, it invokes the lpfc_els_free_data() routine to release the Direct
2781 * Memory Access (DMA) buffers associated with the IOCB. Otherwise, it
2782 * adds the DMA buffer the @phba data structure for the delayed release.
2783 * If reference to the Buffer Pointer List (BPL) is present, the
2784 * lpfc_els_free_bpl() routine is invoked to release the DMA memory
2785 * associated with BPL. Finally, the lpfc_sli_release_iocbq() routine is
2786 * invoked to release the IOCB data structure back to @phba IOCBQ list.
2787 *
2788 * Return code
2789 * 0 - Success (currently, always return 0)
2790 **/
James Smart87af33f2007-10-27 13:37:43 -04002791int
James Smart329f9bc2007-04-25 09:53:01 -04002792lpfc_els_free_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *elsiocb)
dea31012005-04-17 16:05:31 -05002793{
2794 struct lpfc_dmabuf *buf_ptr, *buf_ptr1;
James Smarta8adb832007-10-27 13:37:53 -04002795 struct lpfc_nodelist *ndlp;
dea31012005-04-17 16:05:31 -05002796
James Smarta8adb832007-10-27 13:37:53 -04002797 ndlp = (struct lpfc_nodelist *)elsiocb->context1;
2798 if (ndlp) {
2799 if (ndlp->nlp_flag & NLP_DEFER_RM) {
2800 lpfc_nlp_put(ndlp);
2801
2802 /* If the ndlp is not being used by another discovery
2803 * thread, free it.
2804 */
2805 if (!lpfc_nlp_not_used(ndlp)) {
2806 /* If ndlp is being used by another discovery
2807 * thread, just clear NLP_DEFER_RM
2808 */
2809 ndlp->nlp_flag &= ~NLP_DEFER_RM;
2810 }
2811 }
2812 else
2813 lpfc_nlp_put(ndlp);
James Smart329f9bc2007-04-25 09:53:01 -04002814 elsiocb->context1 = NULL;
2815 }
dea31012005-04-17 16:05:31 -05002816 /* context2 = cmd, context2->next = rsp, context3 = bpl */
2817 if (elsiocb->context2) {
James Smart0ff10d42008-01-11 01:52:36 -05002818 if (elsiocb->iocb_flag & LPFC_DELAY_MEM_FREE) {
2819 /* Firmware could still be in progress of DMAing
2820 * payload, so don't free data buffer till after
2821 * a hbeat.
2822 */
2823 elsiocb->iocb_flag &= ~LPFC_DELAY_MEM_FREE;
2824 buf_ptr = elsiocb->context2;
2825 elsiocb->context2 = NULL;
2826 if (buf_ptr) {
2827 buf_ptr1 = NULL;
2828 spin_lock_irq(&phba->hbalock);
2829 if (!list_empty(&buf_ptr->list)) {
2830 list_remove_head(&buf_ptr->list,
2831 buf_ptr1, struct lpfc_dmabuf,
2832 list);
2833 INIT_LIST_HEAD(&buf_ptr1->list);
2834 list_add_tail(&buf_ptr1->list,
2835 &phba->elsbuf);
2836 phba->elsbuf_cnt++;
2837 }
2838 INIT_LIST_HEAD(&buf_ptr->list);
2839 list_add_tail(&buf_ptr->list, &phba->elsbuf);
2840 phba->elsbuf_cnt++;
2841 spin_unlock_irq(&phba->hbalock);
2842 }
2843 } else {
2844 buf_ptr1 = (struct lpfc_dmabuf *) elsiocb->context2;
2845 lpfc_els_free_data(phba, buf_ptr1);
2846 }
dea31012005-04-17 16:05:31 -05002847 }
2848
2849 if (elsiocb->context3) {
2850 buf_ptr = (struct lpfc_dmabuf *) elsiocb->context3;
James Smart87af33f2007-10-27 13:37:43 -04002851 lpfc_els_free_bpl(phba, buf_ptr);
dea31012005-04-17 16:05:31 -05002852 }
James Bottomley604a3e32005-10-29 10:28:33 -05002853 lpfc_sli_release_iocbq(phba, elsiocb);
dea31012005-04-17 16:05:31 -05002854 return 0;
2855}
2856
James Smarte59058c2008-08-24 21:49:00 -04002857/**
2858 * lpfc_cmpl_els_logo_acc: Completion callback function to logo acc response.
2859 * @phba: pointer to lpfc hba data structure.
2860 * @cmdiocb: pointer to lpfc command iocb data structure.
2861 * @rspiocb: pointer to lpfc response iocb data structure.
2862 *
2863 * This routine is the completion callback function to the Logout (LOGO)
2864 * Accept (ACC) Response ELS command. This routine is invoked to indicate
2865 * the completion of the LOGO process. It invokes the lpfc_nlp_not_used() to
2866 * release the ndlp if it has the last reference remaining (reference count
2867 * is 1). If succeeded (meaning ndlp released), it sets the IOCB context1
2868 * field to NULL to inform the following lpfc_els_free_iocb() routine no
2869 * ndlp reference count needs to be decremented. Otherwise, the ndlp
2870 * reference use-count shall be decremented by the lpfc_els_free_iocb()
2871 * routine. Finally, the lpfc_els_free_iocb() is invoked to release the
2872 * IOCB data structure.
2873 **/
dea31012005-04-17 16:05:31 -05002874static void
James Smart2e0fef82007-06-17 19:56:36 -05002875lpfc_cmpl_els_logo_acc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
2876 struct lpfc_iocbq *rspiocb)
dea31012005-04-17 16:05:31 -05002877{
James Smart2e0fef82007-06-17 19:56:36 -05002878 struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) cmdiocb->context1;
2879 struct lpfc_vport *vport = cmdiocb->vport;
James Smart858c9f62007-06-17 19:56:39 -05002880 IOCB_t *irsp;
2881
2882 irsp = &rspiocb->iocb;
2883 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP,
2884 "ACC LOGO cmpl: status:x%x/x%x did:x%x",
2885 irsp->ulpStatus, irsp->un.ulpWord[4], ndlp->nlp_DID);
dea31012005-04-17 16:05:31 -05002886 /* ACC to LOGO completes to NPort <nlp_DID> */
James Smarte8b62012007-08-02 11:10:09 -04002887 lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
2888 "0109 ACC to LOGO completes to NPort x%x "
2889 "Data: x%x x%x x%x\n",
2890 ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state,
2891 ndlp->nlp_rpi);
James Smart87af33f2007-10-27 13:37:43 -04002892
2893 if (ndlp->nlp_state == NLP_STE_NPR_NODE) {
2894 /* NPort Recovery mode or node is just allocated */
2895 if (!lpfc_nlp_not_used(ndlp)) {
2896 /* If the ndlp is being used by another discovery
2897 * thread, just unregister the RPI.
2898 */
2899 lpfc_unreg_rpi(vport, ndlp);
James Smartfa4066b2008-01-11 01:53:27 -05002900 } else {
2901 /* Indicate the node has already released, should
2902 * not reference to it from within lpfc_els_free_iocb.
2903 */
2904 cmdiocb->context1 = NULL;
James Smart87af33f2007-10-27 13:37:43 -04002905 }
dea31012005-04-17 16:05:31 -05002906 }
2907 lpfc_els_free_iocb(phba, cmdiocb);
2908 return;
2909}
2910
James Smarte59058c2008-08-24 21:49:00 -04002911/**
2912 * lpfc_mbx_cmpl_dflt_rpi: Completion callbk func for unreg dflt rpi mbox cmd.
2913 * @phba: pointer to lpfc hba data structure.
2914 * @pmb: pointer to the driver internal queue element for mailbox command.
2915 *
2916 * This routine is the completion callback function for unregister default
2917 * RPI (Remote Port Index) mailbox command to the @phba. It simply releases
2918 * the associated lpfc Direct Memory Access (DMA) buffer back to the pool and
2919 * decrements the ndlp reference count held for this completion callback
2920 * function. After that, it invokes the lpfc_nlp_not_used() to check
2921 * whether there is only one reference left on the ndlp. If so, it will
2922 * perform one more decrement and trigger the release of the ndlp.
2923 **/
James Smart858c9f62007-06-17 19:56:39 -05002924void
2925lpfc_mbx_cmpl_dflt_rpi(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
2926{
2927 struct lpfc_dmabuf *mp = (struct lpfc_dmabuf *) (pmb->context1);
2928 struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) pmb->context2;
2929
2930 pmb->context1 = NULL;
2931 lpfc_mbuf_free(phba, mp->virt, mp->phys);
2932 kfree(mp);
2933 mempool_free(pmb, phba->mbox_mem_pool);
James Smart58da1ff2008-04-07 10:15:56 -04002934 if (ndlp && NLP_CHK_NODE_ACT(ndlp)) {
James Smarta8adb832007-10-27 13:37:53 -04002935 lpfc_nlp_put(ndlp);
James Smarta8adb832007-10-27 13:37:53 -04002936 /* This is the end of the default RPI cleanup logic for this
2937 * ndlp. If no other discovery threads are using this ndlp.
2938 * we should free all resources associated with it.
2939 */
2940 lpfc_nlp_not_used(ndlp);
2941 }
James Smart858c9f62007-06-17 19:56:39 -05002942 return;
2943}
2944
James Smarte59058c2008-08-24 21:49:00 -04002945/**
2946 * lpfc_cmpl_els_rsp: Completion callback function for els response iocb cmd.
2947 * @phba: pointer to lpfc hba data structure.
2948 * @cmdiocb: pointer to lpfc command iocb data structure.
2949 * @rspiocb: pointer to lpfc response iocb data structure.
2950 *
2951 * This routine is the completion callback function for ELS Response IOCB
2952 * command. In normal case, this callback function just properly sets the
2953 * nlp_flag bitmap in the ndlp data structure, if the mbox command reference
2954 * field in the command IOCB is not NULL, the referred mailbox command will
2955 * be send out, and then invokes the lpfc_els_free_iocb() routine to release
2956 * the IOCB. Under error conditions, such as when a LS_RJT is returned or a
2957 * link down event occurred during the discovery, the lpfc_nlp_not_used()
2958 * routine shall be invoked trying to release the ndlp if no other threads
2959 * are currently referring it.
2960 **/
dea31012005-04-17 16:05:31 -05002961static void
James Smart858c9f62007-06-17 19:56:39 -05002962lpfc_cmpl_els_rsp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
James Smart329f9bc2007-04-25 09:53:01 -04002963 struct lpfc_iocbq *rspiocb)
dea31012005-04-17 16:05:31 -05002964{
James Smart2e0fef82007-06-17 19:56:36 -05002965 struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) cmdiocb->context1;
2966 struct lpfc_vport *vport = ndlp ? ndlp->vport : NULL;
2967 struct Scsi_Host *shost = vport ? lpfc_shost_from_vport(vport) : NULL;
James Smart87af33f2007-10-27 13:37:43 -04002968 IOCB_t *irsp;
2969 uint8_t *pcmd;
dea31012005-04-17 16:05:31 -05002970 LPFC_MBOXQ_t *mbox = NULL;
James Smart2e0fef82007-06-17 19:56:36 -05002971 struct lpfc_dmabuf *mp = NULL;
James Smart87af33f2007-10-27 13:37:43 -04002972 uint32_t ls_rjt = 0;
dea31012005-04-17 16:05:31 -05002973
James Smart33ccf8d2006-08-17 11:57:58 -04002974 irsp = &rspiocb->iocb;
2975
dea31012005-04-17 16:05:31 -05002976 if (cmdiocb->context_un.mbox)
2977 mbox = cmdiocb->context_un.mbox;
2978
James Smartfa4066b2008-01-11 01:53:27 -05002979 /* First determine if this is a LS_RJT cmpl. Note, this callback
2980 * function can have cmdiocb->contest1 (ndlp) field set to NULL.
2981 */
James Smart87af33f2007-10-27 13:37:43 -04002982 pcmd = (uint8_t *) (((struct lpfc_dmabuf *) cmdiocb->context2)->virt);
James Smart58da1ff2008-04-07 10:15:56 -04002983 if (ndlp && NLP_CHK_NODE_ACT(ndlp) &&
2984 (*((uint32_t *) (pcmd)) == ELS_CMD_LS_RJT)) {
James Smartfa4066b2008-01-11 01:53:27 -05002985 /* A LS_RJT associated with Default RPI cleanup has its own
2986 * seperate code path.
James Smart87af33f2007-10-27 13:37:43 -04002987 */
2988 if (!(ndlp->nlp_flag & NLP_RM_DFLT_RPI))
2989 ls_rjt = 1;
2990 }
2991
dea31012005-04-17 16:05:31 -05002992 /* Check to see if link went down during discovery */
James Smart58da1ff2008-04-07 10:15:56 -04002993 if (!ndlp || !NLP_CHK_NODE_ACT(ndlp) || lpfc_els_chk_latt(vport)) {
dea31012005-04-17 16:05:31 -05002994 if (mbox) {
James Smart14691152006-12-02 13:34:28 -05002995 mp = (struct lpfc_dmabuf *) mbox->context1;
2996 if (mp) {
2997 lpfc_mbuf_free(phba, mp->virt, mp->phys);
2998 kfree(mp);
2999 }
James Smart329f9bc2007-04-25 09:53:01 -04003000 mempool_free(mbox, phba->mbox_mem_pool);
dea31012005-04-17 16:05:31 -05003001 }
James Smart58da1ff2008-04-07 10:15:56 -04003002 if (ndlp && NLP_CHK_NODE_ACT(ndlp) &&
3003 (ndlp->nlp_flag & NLP_RM_DFLT_RPI))
James Smartfa4066b2008-01-11 01:53:27 -05003004 if (lpfc_nlp_not_used(ndlp)) {
James Smart98c9ea52007-10-27 13:37:33 -04003005 ndlp = NULL;
James Smartfa4066b2008-01-11 01:53:27 -05003006 /* Indicate the node has already released,
3007 * should not reference to it from within
3008 * the routine lpfc_els_free_iocb.
3009 */
3010 cmdiocb->context1 = NULL;
3011 }
dea31012005-04-17 16:05:31 -05003012 goto out;
3013 }
3014
James Smart858c9f62007-06-17 19:56:39 -05003015 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP,
James Smart51ef4c22007-08-02 11:10:31 -04003016 "ELS rsp cmpl: status:x%x/x%x did:x%x",
James Smart858c9f62007-06-17 19:56:39 -05003017 irsp->ulpStatus, irsp->un.ulpWord[4],
James Smart51ef4c22007-08-02 11:10:31 -04003018 cmdiocb->iocb.un.elsreq64.remoteID);
dea31012005-04-17 16:05:31 -05003019 /* ELS response tag <ulpIoTag> completes */
James Smarte8b62012007-08-02 11:10:09 -04003020 lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
3021 "0110 ELS response tag x%x completes "
3022 "Data: x%x x%x x%x x%x x%x x%x x%x\n",
3023 cmdiocb->iocb.ulpIoTag, rspiocb->iocb.ulpStatus,
3024 rspiocb->iocb.un.ulpWord[4], rspiocb->iocb.ulpTimeout,
3025 ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state,
3026 ndlp->nlp_rpi);
dea31012005-04-17 16:05:31 -05003027 if (mbox) {
3028 if ((rspiocb->iocb.ulpStatus == 0)
3029 && (ndlp->nlp_flag & NLP_ACC_REGLOGIN)) {
James Smart2e0fef82007-06-17 19:56:36 -05003030 lpfc_unreg_rpi(vport, ndlp);
James Smarte47c9092008-02-08 18:49:26 -05003031 /* Increment reference count to ndlp to hold the
3032 * reference to ndlp for the callback function.
3033 */
James Smart329f9bc2007-04-25 09:53:01 -04003034 mbox->context2 = lpfc_nlp_get(ndlp);
James Smart2e0fef82007-06-17 19:56:36 -05003035 mbox->vport = vport;
James Smart858c9f62007-06-17 19:56:39 -05003036 if (ndlp->nlp_flag & NLP_RM_DFLT_RPI) {
3037 mbox->mbox_flag |= LPFC_MBX_IMED_UNREG;
3038 mbox->mbox_cmpl = lpfc_mbx_cmpl_dflt_rpi;
3039 }
3040 else {
3041 mbox->mbox_cmpl = lpfc_mbx_cmpl_reg_login;
3042 ndlp->nlp_prev_state = ndlp->nlp_state;
3043 lpfc_nlp_set_state(vport, ndlp,
James Smart2e0fef82007-06-17 19:56:36 -05003044 NLP_STE_REG_LOGIN_ISSUE);
James Smart858c9f62007-06-17 19:56:39 -05003045 }
James Smart0b727fe2007-10-27 13:37:25 -04003046 if (lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT)
James Smarte47c9092008-02-08 18:49:26 -05003047 != MBX_NOT_FINISHED)
dea31012005-04-17 16:05:31 -05003048 goto out;
James Smarte47c9092008-02-08 18:49:26 -05003049 else
3050 /* Decrement the ndlp reference count we
3051 * set for this failed mailbox command.
3052 */
3053 lpfc_nlp_put(ndlp);
James Smart98c9ea52007-10-27 13:37:33 -04003054
3055 /* ELS rsp: Cannot issue reg_login for <NPortid> */
3056 lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
3057 "0138 ELS rsp: Cannot issue reg_login for x%x "
3058 "Data: x%x x%x x%x\n",
3059 ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state,
3060 ndlp->nlp_rpi);
3061
James Smartfa4066b2008-01-11 01:53:27 -05003062 if (lpfc_nlp_not_used(ndlp)) {
James Smart98c9ea52007-10-27 13:37:33 -04003063 ndlp = NULL;
James Smartfa4066b2008-01-11 01:53:27 -05003064 /* Indicate node has already been released,
3065 * should not reference to it from within
3066 * the routine lpfc_els_free_iocb.
3067 */
3068 cmdiocb->context1 = NULL;
3069 }
dea31012005-04-17 16:05:31 -05003070 } else {
James Smart858c9f62007-06-17 19:56:39 -05003071 /* Do not drop node for lpfc_els_abort'ed ELS cmds */
3072 if (!lpfc_error_lost_link(irsp) &&
3073 ndlp->nlp_flag & NLP_ACC_REGLOGIN) {
James Smartfa4066b2008-01-11 01:53:27 -05003074 if (lpfc_nlp_not_used(ndlp)) {
James Smart98c9ea52007-10-27 13:37:33 -04003075 ndlp = NULL;
James Smartfa4066b2008-01-11 01:53:27 -05003076 /* Indicate node has already been
3077 * released, should not reference
3078 * to it from within the routine
3079 * lpfc_els_free_iocb.
3080 */
3081 cmdiocb->context1 = NULL;
3082 }
dea31012005-04-17 16:05:31 -05003083 }
3084 }
James Smart14691152006-12-02 13:34:28 -05003085 mp = (struct lpfc_dmabuf *) mbox->context1;
3086 if (mp) {
3087 lpfc_mbuf_free(phba, mp->virt, mp->phys);
3088 kfree(mp);
3089 }
3090 mempool_free(mbox, phba->mbox_mem_pool);
dea31012005-04-17 16:05:31 -05003091 }
3092out:
James Smart58da1ff2008-04-07 10:15:56 -04003093 if (ndlp && NLP_CHK_NODE_ACT(ndlp)) {
James Smart2e0fef82007-06-17 19:56:36 -05003094 spin_lock_irq(shost->host_lock);
James Smart858c9f62007-06-17 19:56:39 -05003095 ndlp->nlp_flag &= ~(NLP_ACC_REGLOGIN | NLP_RM_DFLT_RPI);
James Smart2e0fef82007-06-17 19:56:36 -05003096 spin_unlock_irq(shost->host_lock);
James Smart87af33f2007-10-27 13:37:43 -04003097
3098 /* If the node is not being used by another discovery thread,
3099 * and we are sending a reject, we are done with it.
3100 * Release driver reference count here and free associated
3101 * resources.
3102 */
3103 if (ls_rjt)
James Smartfa4066b2008-01-11 01:53:27 -05003104 if (lpfc_nlp_not_used(ndlp))
3105 /* Indicate node has already been released,
3106 * should not reference to it from within
3107 * the routine lpfc_els_free_iocb.
3108 */
3109 cmdiocb->context1 = NULL;
dea31012005-04-17 16:05:31 -05003110 }
James Smart87af33f2007-10-27 13:37:43 -04003111
dea31012005-04-17 16:05:31 -05003112 lpfc_els_free_iocb(phba, cmdiocb);
3113 return;
3114}
3115
James Smarte59058c2008-08-24 21:49:00 -04003116/**
3117 * lpfc_els_rsp_acc: Prepare and issue an acc response iocb command.
3118 * @vport: pointer to a host virtual N_Port data structure.
3119 * @flag: the els command code to be accepted.
3120 * @oldiocb: pointer to the original lpfc command iocb data structure.
3121 * @ndlp: pointer to a node-list data structure.
3122 * @mbox: pointer to the driver internal queue element for mailbox command.
3123 *
3124 * This routine prepares and issues an Accept (ACC) response IOCB
3125 * command. It uses the @flag to properly set up the IOCB field for the
3126 * specific ACC response command to be issued and invokes the
3127 * lpfc_sli_issue_iocb() routine to send out ACC response IOCB. If a
3128 * @mbox pointer is passed in, it will be put into the context_un.mbox
3129 * field of the IOCB for the completion callback function to issue the
3130 * mailbox command to the HBA later when callback is invoked.
3131 *
3132 * Note that, in lpfc_prep_els_iocb() routine, the reference count of ndlp
3133 * will be incremented by 1 for holding the ndlp and the reference to ndlp
3134 * will be stored into the context1 field of the IOCB for the completion
3135 * callback function to the corresponding response ELS IOCB command.
3136 *
3137 * Return code
3138 * 0 - Successfully issued acc response
3139 * 1 - Failed to issue acc response
3140 **/
dea31012005-04-17 16:05:31 -05003141int
James Smart2e0fef82007-06-17 19:56:36 -05003142lpfc_els_rsp_acc(struct lpfc_vport *vport, uint32_t flag,
3143 struct lpfc_iocbq *oldiocb, struct lpfc_nodelist *ndlp,
James Smart51ef4c22007-08-02 11:10:31 -04003144 LPFC_MBOXQ_t *mbox)
dea31012005-04-17 16:05:31 -05003145{
James Smart2e0fef82007-06-17 19:56:36 -05003146 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
3147 struct lpfc_hba *phba = vport->phba;
dea31012005-04-17 16:05:31 -05003148 IOCB_t *icmd;
3149 IOCB_t *oldcmd;
3150 struct lpfc_iocbq *elsiocb;
3151 struct lpfc_sli_ring *pring;
3152 struct lpfc_sli *psli;
3153 uint8_t *pcmd;
3154 uint16_t cmdsize;
3155 int rc;
James Smart82d9a2a2006-04-15 11:53:05 -04003156 ELS_PKT *els_pkt_ptr;
dea31012005-04-17 16:05:31 -05003157
3158 psli = &phba->sli;
3159 pring = &psli->ring[LPFC_ELS_RING]; /* ELS ring */
3160 oldcmd = &oldiocb->iocb;
3161
3162 switch (flag) {
3163 case ELS_CMD_ACC:
James Smart92d7f7b2007-06-17 19:56:38 -05003164 cmdsize = sizeof(uint32_t);
James Smart2e0fef82007-06-17 19:56:36 -05003165 elsiocb = lpfc_prep_els_iocb(vport, 0, cmdsize, oldiocb->retry,
3166 ndlp, ndlp->nlp_DID, ELS_CMD_ACC);
James Smart488d1462006-03-07 15:02:37 -05003167 if (!elsiocb) {
James Smart2e0fef82007-06-17 19:56:36 -05003168 spin_lock_irq(shost->host_lock);
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05003169 ndlp->nlp_flag &= ~NLP_LOGO_ACC;
James Smart2e0fef82007-06-17 19:56:36 -05003170 spin_unlock_irq(shost->host_lock);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05003171 return 1;
dea31012005-04-17 16:05:31 -05003172 }
James Smart2e0fef82007-06-17 19:56:36 -05003173
dea31012005-04-17 16:05:31 -05003174 icmd = &elsiocb->iocb;
3175 icmd->ulpContext = oldcmd->ulpContext; /* Xri */
3176 pcmd = (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
3177 *((uint32_t *) (pcmd)) = ELS_CMD_ACC;
James Smart92d7f7b2007-06-17 19:56:38 -05003178 pcmd += sizeof(uint32_t);
James Smart858c9f62007-06-17 19:56:39 -05003179
3180 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP,
3181 "Issue ACC: did:x%x flg:x%x",
3182 ndlp->nlp_DID, ndlp->nlp_flag, 0);
dea31012005-04-17 16:05:31 -05003183 break;
3184 case ELS_CMD_PLOGI:
James Smart92d7f7b2007-06-17 19:56:38 -05003185 cmdsize = (sizeof(struct serv_parm) + sizeof(uint32_t));
James Smart2e0fef82007-06-17 19:56:36 -05003186 elsiocb = lpfc_prep_els_iocb(vport, 0, cmdsize, oldiocb->retry,
3187 ndlp, ndlp->nlp_DID, ELS_CMD_ACC);
James Smart488d1462006-03-07 15:02:37 -05003188 if (!elsiocb)
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05003189 return 1;
James Smart488d1462006-03-07 15:02:37 -05003190
dea31012005-04-17 16:05:31 -05003191 icmd = &elsiocb->iocb;
3192 icmd->ulpContext = oldcmd->ulpContext; /* Xri */
3193 pcmd = (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
3194
3195 if (mbox)
3196 elsiocb->context_un.mbox = mbox;
3197
3198 *((uint32_t *) (pcmd)) = ELS_CMD_ACC;
James Smart92d7f7b2007-06-17 19:56:38 -05003199 pcmd += sizeof(uint32_t);
3200 memcpy(pcmd, &vport->fc_sparam, sizeof(struct serv_parm));
James Smart858c9f62007-06-17 19:56:39 -05003201
3202 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP,
3203 "Issue ACC PLOGI: did:x%x flg:x%x",
3204 ndlp->nlp_DID, ndlp->nlp_flag, 0);
dea31012005-04-17 16:05:31 -05003205 break;
James Smart82d9a2a2006-04-15 11:53:05 -04003206 case ELS_CMD_PRLO:
James Smart92d7f7b2007-06-17 19:56:38 -05003207 cmdsize = sizeof(uint32_t) + sizeof(PRLO);
James Smart2e0fef82007-06-17 19:56:36 -05003208 elsiocb = lpfc_prep_els_iocb(vport, 0, cmdsize, oldiocb->retry,
James Smart82d9a2a2006-04-15 11:53:05 -04003209 ndlp, ndlp->nlp_DID, ELS_CMD_PRLO);
3210 if (!elsiocb)
3211 return 1;
3212
3213 icmd = &elsiocb->iocb;
3214 icmd->ulpContext = oldcmd->ulpContext; /* Xri */
3215 pcmd = (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
3216
3217 memcpy(pcmd, ((struct lpfc_dmabuf *) oldiocb->context2)->virt,
James Smart92d7f7b2007-06-17 19:56:38 -05003218 sizeof(uint32_t) + sizeof(PRLO));
James Smart82d9a2a2006-04-15 11:53:05 -04003219 *((uint32_t *) (pcmd)) = ELS_CMD_PRLO_ACC;
3220 els_pkt_ptr = (ELS_PKT *) pcmd;
3221 els_pkt_ptr->un.prlo.acceptRspCode = PRLO_REQ_EXECUTED;
James Smart858c9f62007-06-17 19:56:39 -05003222
3223 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP,
3224 "Issue ACC PRLO: did:x%x flg:x%x",
3225 ndlp->nlp_DID, ndlp->nlp_flag, 0);
James Smart82d9a2a2006-04-15 11:53:05 -04003226 break;
dea31012005-04-17 16:05:31 -05003227 default:
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05003228 return 1;
dea31012005-04-17 16:05:31 -05003229 }
dea31012005-04-17 16:05:31 -05003230 /* Xmit ELS ACC response tag <ulpIoTag> */
James Smarte8b62012007-08-02 11:10:09 -04003231 lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
3232 "0128 Xmit ELS ACC response tag x%x, XRI: x%x, "
3233 "DID: x%x, nlp_flag: x%x nlp_state: x%x RPI: x%x\n",
3234 elsiocb->iotag, elsiocb->iocb.ulpContext,
3235 ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state,
3236 ndlp->nlp_rpi);
dea31012005-04-17 16:05:31 -05003237 if (ndlp->nlp_flag & NLP_LOGO_ACC) {
James Smart2e0fef82007-06-17 19:56:36 -05003238 spin_lock_irq(shost->host_lock);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05003239 ndlp->nlp_flag &= ~NLP_LOGO_ACC;
James Smart2e0fef82007-06-17 19:56:36 -05003240 spin_unlock_irq(shost->host_lock);
dea31012005-04-17 16:05:31 -05003241 elsiocb->iocb_cmpl = lpfc_cmpl_els_logo_acc;
3242 } else {
James Smart858c9f62007-06-17 19:56:39 -05003243 elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp;
dea31012005-04-17 16:05:31 -05003244 }
3245
3246 phba->fc_stat.elsXmitACC++;
dea31012005-04-17 16:05:31 -05003247 rc = lpfc_sli_issue_iocb(phba, pring, elsiocb, 0);
dea31012005-04-17 16:05:31 -05003248 if (rc == IOCB_ERROR) {
3249 lpfc_els_free_iocb(phba, elsiocb);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05003250 return 1;
dea31012005-04-17 16:05:31 -05003251 }
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05003252 return 0;
dea31012005-04-17 16:05:31 -05003253}
3254
James Smarte59058c2008-08-24 21:49:00 -04003255/**
3256 * lpfc_els_rsp_reject: Propare and issue a rjt response iocb command.
3257 * @vport: pointer to a virtual N_Port data structure.
3258 * @rejectError:
3259 * @oldiocb: pointer to the original lpfc command iocb data structure.
3260 * @ndlp: pointer to a node-list data structure.
3261 * @mbox: pointer to the driver internal queue element for mailbox command.
3262 *
3263 * This routine prepares and issue an Reject (RJT) response IOCB
3264 * command. If a @mbox pointer is passed in, it will be put into the
3265 * context_un.mbox field of the IOCB for the completion callback function
3266 * to issue to the HBA later.
3267 *
3268 * Note that, in lpfc_prep_els_iocb() routine, the reference count of ndlp
3269 * will be incremented by 1 for holding the ndlp and the reference to ndlp
3270 * will be stored into the context1 field of the IOCB for the completion
3271 * callback function to the reject response ELS IOCB command.
3272 *
3273 * Return code
3274 * 0 - Successfully issued reject response
3275 * 1 - Failed to issue reject response
3276 **/
dea31012005-04-17 16:05:31 -05003277int
James Smart2e0fef82007-06-17 19:56:36 -05003278lpfc_els_rsp_reject(struct lpfc_vport *vport, uint32_t rejectError,
James Smart858c9f62007-06-17 19:56:39 -05003279 struct lpfc_iocbq *oldiocb, struct lpfc_nodelist *ndlp,
3280 LPFC_MBOXQ_t *mbox)
dea31012005-04-17 16:05:31 -05003281{
James Smart2e0fef82007-06-17 19:56:36 -05003282 struct lpfc_hba *phba = vport->phba;
dea31012005-04-17 16:05:31 -05003283 IOCB_t *icmd;
3284 IOCB_t *oldcmd;
3285 struct lpfc_iocbq *elsiocb;
3286 struct lpfc_sli_ring *pring;
3287 struct lpfc_sli *psli;
3288 uint8_t *pcmd;
3289 uint16_t cmdsize;
3290 int rc;
3291
3292 psli = &phba->sli;
3293 pring = &psli->ring[LPFC_ELS_RING]; /* ELS ring */
3294
James Smart92d7f7b2007-06-17 19:56:38 -05003295 cmdsize = 2 * sizeof(uint32_t);
James Smart2e0fef82007-06-17 19:56:36 -05003296 elsiocb = lpfc_prep_els_iocb(vport, 0, cmdsize, oldiocb->retry, ndlp,
3297 ndlp->nlp_DID, ELS_CMD_LS_RJT);
James Smart488d1462006-03-07 15:02:37 -05003298 if (!elsiocb)
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05003299 return 1;
dea31012005-04-17 16:05:31 -05003300
3301 icmd = &elsiocb->iocb;
3302 oldcmd = &oldiocb->iocb;
3303 icmd->ulpContext = oldcmd->ulpContext; /* Xri */
3304 pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
3305
3306 *((uint32_t *) (pcmd)) = ELS_CMD_LS_RJT;
James Smart92d7f7b2007-06-17 19:56:38 -05003307 pcmd += sizeof(uint32_t);
dea31012005-04-17 16:05:31 -05003308 *((uint32_t *) (pcmd)) = rejectError;
3309
James Smart51ef4c22007-08-02 11:10:31 -04003310 if (mbox)
James Smart858c9f62007-06-17 19:56:39 -05003311 elsiocb->context_un.mbox = mbox;
James Smart858c9f62007-06-17 19:56:39 -05003312
dea31012005-04-17 16:05:31 -05003313 /* Xmit ELS RJT <err> response tag <ulpIoTag> */
James Smarte8b62012007-08-02 11:10:09 -04003314 lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
3315 "0129 Xmit ELS RJT x%x response tag x%x "
3316 "xri x%x, did x%x, nlp_flag x%x, nlp_state x%x, "
3317 "rpi x%x\n",
3318 rejectError, elsiocb->iotag,
3319 elsiocb->iocb.ulpContext, ndlp->nlp_DID,
3320 ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi);
James Smart858c9f62007-06-17 19:56:39 -05003321 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP,
3322 "Issue LS_RJT: did:x%x flg:x%x err:x%x",
3323 ndlp->nlp_DID, ndlp->nlp_flag, rejectError);
3324
dea31012005-04-17 16:05:31 -05003325 phba->fc_stat.elsXmitLSRJT++;
James Smart858c9f62007-06-17 19:56:39 -05003326 elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp;
dea31012005-04-17 16:05:31 -05003327 rc = lpfc_sli_issue_iocb(phba, pring, elsiocb, 0);
James Smart51ef4c22007-08-02 11:10:31 -04003328
dea31012005-04-17 16:05:31 -05003329 if (rc == IOCB_ERROR) {
3330 lpfc_els_free_iocb(phba, elsiocb);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05003331 return 1;
dea31012005-04-17 16:05:31 -05003332 }
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05003333 return 0;
dea31012005-04-17 16:05:31 -05003334}
3335
James Smarte59058c2008-08-24 21:49:00 -04003336/**
3337 * lpfc_els_rsp_adisc_acc: Prepare and issue acc response to adisc iocb cmd.
3338 * @vport: pointer to a virtual N_Port data structure.
3339 * @oldiocb: pointer to the original lpfc command iocb data structure.
3340 * @ndlp: pointer to a node-list data structure.
3341 *
3342 * This routine prepares and issues an Accept (ACC) response to Address
3343 * Discover (ADISC) ELS command. It simply prepares the payload of the IOCB
3344 * and invokes the lpfc_sli_issue_iocb() routine to send out the command.
3345 *
3346 * Note that, in lpfc_prep_els_iocb() routine, the reference count of ndlp
3347 * will be incremented by 1 for holding the ndlp and the reference to ndlp
3348 * will be stored into the context1 field of the IOCB for the completion
3349 * callback function to the ADISC Accept response ELS IOCB command.
3350 *
3351 * Return code
3352 * 0 - Successfully issued acc adisc response
3353 * 1 - Failed to issue adisc acc response
3354 **/
dea31012005-04-17 16:05:31 -05003355int
James Smart2e0fef82007-06-17 19:56:36 -05003356lpfc_els_rsp_adisc_acc(struct lpfc_vport *vport, struct lpfc_iocbq *oldiocb,
3357 struct lpfc_nodelist *ndlp)
dea31012005-04-17 16:05:31 -05003358{
James Smart2e0fef82007-06-17 19:56:36 -05003359 struct lpfc_hba *phba = vport->phba;
3360 struct lpfc_sli *psli = &phba->sli;
3361 struct lpfc_sli_ring *pring = &psli->ring[LPFC_ELS_RING];
dea31012005-04-17 16:05:31 -05003362 ADISC *ap;
James Smart2e0fef82007-06-17 19:56:36 -05003363 IOCB_t *icmd, *oldcmd;
dea31012005-04-17 16:05:31 -05003364 struct lpfc_iocbq *elsiocb;
dea31012005-04-17 16:05:31 -05003365 uint8_t *pcmd;
3366 uint16_t cmdsize;
3367 int rc;
3368
James Smart92d7f7b2007-06-17 19:56:38 -05003369 cmdsize = sizeof(uint32_t) + sizeof(ADISC);
James Smart2e0fef82007-06-17 19:56:36 -05003370 elsiocb = lpfc_prep_els_iocb(vport, 0, cmdsize, oldiocb->retry, ndlp,
3371 ndlp->nlp_DID, ELS_CMD_ACC);
James Smart488d1462006-03-07 15:02:37 -05003372 if (!elsiocb)
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05003373 return 1;
dea31012005-04-17 16:05:31 -05003374
dea31012005-04-17 16:05:31 -05003375 icmd = &elsiocb->iocb;
3376 oldcmd = &oldiocb->iocb;
3377 icmd->ulpContext = oldcmd->ulpContext; /* Xri */
James Smart5b8bd0c2007-04-25 09:52:49 -04003378
3379 /* Xmit ADISC ACC response tag <ulpIoTag> */
James Smarte8b62012007-08-02 11:10:09 -04003380 lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
3381 "0130 Xmit ADISC ACC response iotag x%x xri: "
3382 "x%x, did x%x, nlp_flag x%x, nlp_state x%x rpi x%x\n",
3383 elsiocb->iotag, elsiocb->iocb.ulpContext,
3384 ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state,
3385 ndlp->nlp_rpi);
dea31012005-04-17 16:05:31 -05003386 pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
3387
3388 *((uint32_t *) (pcmd)) = ELS_CMD_ACC;
James Smart92d7f7b2007-06-17 19:56:38 -05003389 pcmd += sizeof(uint32_t);
dea31012005-04-17 16:05:31 -05003390
3391 ap = (ADISC *) (pcmd);
3392 ap->hardAL_PA = phba->fc_pref_ALPA;
James Smart92d7f7b2007-06-17 19:56:38 -05003393 memcpy(&ap->portName, &vport->fc_portname, sizeof(struct lpfc_name));
3394 memcpy(&ap->nodeName, &vport->fc_nodename, sizeof(struct lpfc_name));
James Smart2e0fef82007-06-17 19:56:36 -05003395 ap->DID = be32_to_cpu(vport->fc_myDID);
dea31012005-04-17 16:05:31 -05003396
James Smart858c9f62007-06-17 19:56:39 -05003397 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP,
3398 "Issue ACC ADISC: did:x%x flg:x%x",
3399 ndlp->nlp_DID, ndlp->nlp_flag, 0);
3400
dea31012005-04-17 16:05:31 -05003401 phba->fc_stat.elsXmitACC++;
James Smart858c9f62007-06-17 19:56:39 -05003402 elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp;
dea31012005-04-17 16:05:31 -05003403 rc = lpfc_sli_issue_iocb(phba, pring, elsiocb, 0);
dea31012005-04-17 16:05:31 -05003404 if (rc == IOCB_ERROR) {
3405 lpfc_els_free_iocb(phba, elsiocb);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05003406 return 1;
dea31012005-04-17 16:05:31 -05003407 }
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05003408 return 0;
dea31012005-04-17 16:05:31 -05003409}
3410
James Smarte59058c2008-08-24 21:49:00 -04003411/**
3412 * lpfc_els_rsp_prli_acc: Prepare and issue acc response to prli iocb cmd.
3413 * @vport: pointer to a virtual N_Port data structure.
3414 * @oldiocb: pointer to the original lpfc command iocb data structure.
3415 * @ndlp: pointer to a node-list data structure.
3416 *
3417 * This routine prepares and issues an Accept (ACC) response to Process
3418 * Login (PRLI) ELS command. It simply prepares the payload of the IOCB
3419 * and invokes the lpfc_sli_issue_iocb() routine to send out the command.
3420 *
3421 * Note that, in lpfc_prep_els_iocb() routine, the reference count of ndlp
3422 * will be incremented by 1 for holding the ndlp and the reference to ndlp
3423 * will be stored into the context1 field of the IOCB for the completion
3424 * callback function to the PRLI Accept response ELS IOCB command.
3425 *
3426 * Return code
3427 * 0 - Successfully issued acc prli response
3428 * 1 - Failed to issue acc prli response
3429 **/
dea31012005-04-17 16:05:31 -05003430int
James Smart2e0fef82007-06-17 19:56:36 -05003431lpfc_els_rsp_prli_acc(struct lpfc_vport *vport, struct lpfc_iocbq *oldiocb,
James Smart5b8bd0c2007-04-25 09:52:49 -04003432 struct lpfc_nodelist *ndlp)
dea31012005-04-17 16:05:31 -05003433{
James Smart2e0fef82007-06-17 19:56:36 -05003434 struct lpfc_hba *phba = vport->phba;
dea31012005-04-17 16:05:31 -05003435 PRLI *npr;
3436 lpfc_vpd_t *vpd;
3437 IOCB_t *icmd;
3438 IOCB_t *oldcmd;
3439 struct lpfc_iocbq *elsiocb;
3440 struct lpfc_sli_ring *pring;
3441 struct lpfc_sli *psli;
3442 uint8_t *pcmd;
3443 uint16_t cmdsize;
3444 int rc;
3445
3446 psli = &phba->sli;
3447 pring = &psli->ring[LPFC_ELS_RING]; /* ELS ring */
3448
James Smart92d7f7b2007-06-17 19:56:38 -05003449 cmdsize = sizeof(uint32_t) + sizeof(PRLI);
James Smart2e0fef82007-06-17 19:56:36 -05003450 elsiocb = lpfc_prep_els_iocb(vport, 0, cmdsize, oldiocb->retry, ndlp,
James Smart92d7f7b2007-06-17 19:56:38 -05003451 ndlp->nlp_DID, (ELS_CMD_ACC | (ELS_CMD_PRLI & ~ELS_RSP_MASK)));
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05003452 if (!elsiocb)
3453 return 1;
dea31012005-04-17 16:05:31 -05003454
dea31012005-04-17 16:05:31 -05003455 icmd = &elsiocb->iocb;
3456 oldcmd = &oldiocb->iocb;
3457 icmd->ulpContext = oldcmd->ulpContext; /* Xri */
James Smart5b8bd0c2007-04-25 09:52:49 -04003458 /* Xmit PRLI ACC response tag <ulpIoTag> */
James Smarte8b62012007-08-02 11:10:09 -04003459 lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
3460 "0131 Xmit PRLI ACC response tag x%x xri x%x, "
3461 "did x%x, nlp_flag x%x, nlp_state x%x, rpi x%x\n",
3462 elsiocb->iotag, elsiocb->iocb.ulpContext,
3463 ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state,
3464 ndlp->nlp_rpi);
dea31012005-04-17 16:05:31 -05003465 pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
3466
3467 *((uint32_t *) (pcmd)) = (ELS_CMD_ACC | (ELS_CMD_PRLI & ~ELS_RSP_MASK));
James Smart92d7f7b2007-06-17 19:56:38 -05003468 pcmd += sizeof(uint32_t);
dea31012005-04-17 16:05:31 -05003469
3470 /* For PRLI, remainder of payload is PRLI parameter page */
James Smart92d7f7b2007-06-17 19:56:38 -05003471 memset(pcmd, 0, sizeof(PRLI));
dea31012005-04-17 16:05:31 -05003472
3473 npr = (PRLI *) pcmd;
3474 vpd = &phba->vpd;
3475 /*
James Smart0d2b6b82008-06-14 22:52:47 -04003476 * If the remote port is a target and our firmware version is 3.20 or
3477 * later, set the following bits for FC-TAPE support.
dea31012005-04-17 16:05:31 -05003478 */
James Smart0d2b6b82008-06-14 22:52:47 -04003479 if ((ndlp->nlp_type & NLP_FCP_TARGET) &&
3480 (vpd->rev.feaLevelHigh >= 0x02)) {
dea31012005-04-17 16:05:31 -05003481 npr->ConfmComplAllowed = 1;
3482 npr->Retry = 1;
3483 npr->TaskRetryIdReq = 1;
3484 }
3485
3486 npr->acceptRspCode = PRLI_REQ_EXECUTED;
3487 npr->estabImagePair = 1;
3488 npr->readXferRdyDis = 1;
3489 npr->ConfmComplAllowed = 1;
3490
3491 npr->prliType = PRLI_FCP_TYPE;
3492 npr->initiatorFunc = 1;
3493
James Smart858c9f62007-06-17 19:56:39 -05003494 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP,
3495 "Issue ACC PRLI: did:x%x flg:x%x",
3496 ndlp->nlp_DID, ndlp->nlp_flag, 0);
3497
dea31012005-04-17 16:05:31 -05003498 phba->fc_stat.elsXmitACC++;
James Smart858c9f62007-06-17 19:56:39 -05003499 elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp;
dea31012005-04-17 16:05:31 -05003500
dea31012005-04-17 16:05:31 -05003501 rc = lpfc_sli_issue_iocb(phba, pring, elsiocb, 0);
dea31012005-04-17 16:05:31 -05003502 if (rc == IOCB_ERROR) {
3503 lpfc_els_free_iocb(phba, elsiocb);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05003504 return 1;
dea31012005-04-17 16:05:31 -05003505 }
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05003506 return 0;
dea31012005-04-17 16:05:31 -05003507}
3508
James Smarte59058c2008-08-24 21:49:00 -04003509/**
3510 * lpfc_els_rsp_rnid_acc: Issue rnid acc response iocb command.
3511 * @vport: pointer to a virtual N_Port data structure.
3512 * @format: rnid command format.
3513 * @oldiocb: pointer to the original lpfc command iocb data structure.
3514 * @ndlp: pointer to a node-list data structure.
3515 *
3516 * This routine issues a Request Node Identification Data (RNID) Accept
3517 * (ACC) response. It constructs the RNID ACC response command according to
3518 * the proper @format and then calls the lpfc_sli_issue_iocb() routine to
3519 * issue the response. Note that this command does not need to hold the ndlp
3520 * reference count for the callback. So, the ndlp reference count taken by
3521 * the lpfc_prep_els_iocb() routine is put back and the context1 field of
3522 * IOCB is set to NULL to indicate to the lpfc_els_free_iocb() routine that
3523 * there is no ndlp reference available.
3524 *
3525 * Note that, in lpfc_prep_els_iocb() routine, the reference count of ndlp
3526 * will be incremented by 1 for holding the ndlp and the reference to ndlp
3527 * will be stored into the context1 field of the IOCB for the completion
3528 * callback function. However, for the RNID Accept Response ELS command,
3529 * this is undone later by this routine after the IOCB is allocated.
3530 *
3531 * Return code
3532 * 0 - Successfully issued acc rnid response
3533 * 1 - Failed to issue acc rnid response
3534 **/
dea31012005-04-17 16:05:31 -05003535static int
James Smart2e0fef82007-06-17 19:56:36 -05003536lpfc_els_rsp_rnid_acc(struct lpfc_vport *vport, uint8_t format,
James Smart329f9bc2007-04-25 09:53:01 -04003537 struct lpfc_iocbq *oldiocb, struct lpfc_nodelist *ndlp)
dea31012005-04-17 16:05:31 -05003538{
James Smart2e0fef82007-06-17 19:56:36 -05003539 struct lpfc_hba *phba = vport->phba;
dea31012005-04-17 16:05:31 -05003540 RNID *rn;
James Smart2e0fef82007-06-17 19:56:36 -05003541 IOCB_t *icmd, *oldcmd;
dea31012005-04-17 16:05:31 -05003542 struct lpfc_iocbq *elsiocb;
3543 struct lpfc_sli_ring *pring;
3544 struct lpfc_sli *psli;
3545 uint8_t *pcmd;
3546 uint16_t cmdsize;
3547 int rc;
3548
3549 psli = &phba->sli;
3550 pring = &psli->ring[LPFC_ELS_RING];
3551
James Smart92d7f7b2007-06-17 19:56:38 -05003552 cmdsize = sizeof(uint32_t) + sizeof(uint32_t)
3553 + (2 * sizeof(struct lpfc_name));
dea31012005-04-17 16:05:31 -05003554 if (format)
James Smart92d7f7b2007-06-17 19:56:38 -05003555 cmdsize += sizeof(RNID_TOP_DISC);
dea31012005-04-17 16:05:31 -05003556
James Smart2e0fef82007-06-17 19:56:36 -05003557 elsiocb = lpfc_prep_els_iocb(vport, 0, cmdsize, oldiocb->retry, ndlp,
3558 ndlp->nlp_DID, ELS_CMD_ACC);
James Smart488d1462006-03-07 15:02:37 -05003559 if (!elsiocb)
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05003560 return 1;
dea31012005-04-17 16:05:31 -05003561
dea31012005-04-17 16:05:31 -05003562 icmd = &elsiocb->iocb;
3563 oldcmd = &oldiocb->iocb;
3564 icmd->ulpContext = oldcmd->ulpContext; /* Xri */
James Smart5b8bd0c2007-04-25 09:52:49 -04003565 /* Xmit RNID ACC response tag <ulpIoTag> */
James Smarte8b62012007-08-02 11:10:09 -04003566 lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
3567 "0132 Xmit RNID ACC response tag x%x xri x%x\n",
3568 elsiocb->iotag, elsiocb->iocb.ulpContext);
dea31012005-04-17 16:05:31 -05003569 pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
dea31012005-04-17 16:05:31 -05003570 *((uint32_t *) (pcmd)) = ELS_CMD_ACC;
James Smart92d7f7b2007-06-17 19:56:38 -05003571 pcmd += sizeof(uint32_t);
dea31012005-04-17 16:05:31 -05003572
James Smart92d7f7b2007-06-17 19:56:38 -05003573 memset(pcmd, 0, sizeof(RNID));
dea31012005-04-17 16:05:31 -05003574 rn = (RNID *) (pcmd);
3575 rn->Format = format;
James Smart92d7f7b2007-06-17 19:56:38 -05003576 rn->CommonLen = (2 * sizeof(struct lpfc_name));
3577 memcpy(&rn->portName, &vport->fc_portname, sizeof(struct lpfc_name));
3578 memcpy(&rn->nodeName, &vport->fc_nodename, sizeof(struct lpfc_name));
dea31012005-04-17 16:05:31 -05003579 switch (format) {
3580 case 0:
3581 rn->SpecificLen = 0;
3582 break;
3583 case RNID_TOPOLOGY_DISC:
James Smart92d7f7b2007-06-17 19:56:38 -05003584 rn->SpecificLen = sizeof(RNID_TOP_DISC);
dea31012005-04-17 16:05:31 -05003585 memcpy(&rn->un.topologyDisc.portName,
James Smart92d7f7b2007-06-17 19:56:38 -05003586 &vport->fc_portname, sizeof(struct lpfc_name));
dea31012005-04-17 16:05:31 -05003587 rn->un.topologyDisc.unitType = RNID_HBA;
3588 rn->un.topologyDisc.physPort = 0;
3589 rn->un.topologyDisc.attachedNodes = 0;
3590 break;
3591 default:
3592 rn->CommonLen = 0;
3593 rn->SpecificLen = 0;
3594 break;
3595 }
3596
James Smart858c9f62007-06-17 19:56:39 -05003597 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP,
3598 "Issue ACC RNID: did:x%x flg:x%x",
3599 ndlp->nlp_DID, ndlp->nlp_flag, 0);
3600
dea31012005-04-17 16:05:31 -05003601 phba->fc_stat.elsXmitACC++;
James Smart858c9f62007-06-17 19:56:39 -05003602 elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp;
James Smart329f9bc2007-04-25 09:53:01 -04003603 lpfc_nlp_put(ndlp);
dea31012005-04-17 16:05:31 -05003604 elsiocb->context1 = NULL; /* Don't need ndlp for cmpl,
3605 * it could be freed */
3606
dea31012005-04-17 16:05:31 -05003607 rc = lpfc_sli_issue_iocb(phba, pring, elsiocb, 0);
dea31012005-04-17 16:05:31 -05003608 if (rc == IOCB_ERROR) {
3609 lpfc_els_free_iocb(phba, elsiocb);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05003610 return 1;
dea31012005-04-17 16:05:31 -05003611 }
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05003612 return 0;
dea31012005-04-17 16:05:31 -05003613}
3614
James Smarte59058c2008-08-24 21:49:00 -04003615/**
3616 * lpfc_els_disc_adisc: Issue remaining adisc iocbs to npr nodes of a vport.
3617 * @vport: pointer to a host virtual N_Port data structure.
3618 *
3619 * This routine issues Address Discover (ADISC) ELS commands to those
3620 * N_Ports which are in node port recovery state and ADISC has not been issued
3621 * for the @vport. Each time an ELS ADISC IOCB is issued by invoking the
3622 * lpfc_issue_els_adisc() routine, the per @vport number of discover count
3623 * (num_disc_nodes) shall be incremented. If the num_disc_nodes reaches a
3624 * pre-configured threshold (cfg_discovery_threads), the @vport fc_flag will
3625 * be marked with FC_NLP_MORE bit and the process of issuing remaining ADISC
3626 * IOCBs quit for later pick up. On the other hand, after walking through
3627 * all the ndlps with the @vport and there is none ADISC IOCB issued, the
3628 * @vport fc_flag shall be cleared with FC_NLP_MORE bit indicating there is
3629 * no more ADISC need to be sent.
3630 *
3631 * Return code
3632 * The number of N_Ports with adisc issued.
3633 **/
dea31012005-04-17 16:05:31 -05003634int
James Smart2e0fef82007-06-17 19:56:36 -05003635lpfc_els_disc_adisc(struct lpfc_vport *vport)
dea31012005-04-17 16:05:31 -05003636{
James Smart2e0fef82007-06-17 19:56:36 -05003637 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
dea31012005-04-17 16:05:31 -05003638 struct lpfc_nodelist *ndlp, *next_ndlp;
James Smart2e0fef82007-06-17 19:56:36 -05003639 int sentadisc = 0;
dea31012005-04-17 16:05:31 -05003640
James Smart685f0bf2007-04-25 09:53:08 -04003641 /* go thru NPR nodes and issue any remaining ELS ADISCs */
James Smart2e0fef82007-06-17 19:56:36 -05003642 list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) {
James Smarte47c9092008-02-08 18:49:26 -05003643 if (!NLP_CHK_NODE_ACT(ndlp))
3644 continue;
James Smart685f0bf2007-04-25 09:53:08 -04003645 if (ndlp->nlp_state == NLP_STE_NPR_NODE &&
3646 (ndlp->nlp_flag & NLP_NPR_2B_DISC) != 0 &&
3647 (ndlp->nlp_flag & NLP_NPR_ADISC) != 0) {
James Smart2e0fef82007-06-17 19:56:36 -05003648 spin_lock_irq(shost->host_lock);
James Smart685f0bf2007-04-25 09:53:08 -04003649 ndlp->nlp_flag &= ~NLP_NPR_ADISC;
James Smart2e0fef82007-06-17 19:56:36 -05003650 spin_unlock_irq(shost->host_lock);
James Smart685f0bf2007-04-25 09:53:08 -04003651 ndlp->nlp_prev_state = ndlp->nlp_state;
James Smart2e0fef82007-06-17 19:56:36 -05003652 lpfc_nlp_set_state(vport, ndlp, NLP_STE_ADISC_ISSUE);
3653 lpfc_issue_els_adisc(vport, ndlp, 0);
James Smart685f0bf2007-04-25 09:53:08 -04003654 sentadisc++;
James Smart2e0fef82007-06-17 19:56:36 -05003655 vport->num_disc_nodes++;
3656 if (vport->num_disc_nodes >=
James Smart3de2a652007-08-02 11:09:59 -04003657 vport->cfg_discovery_threads) {
James Smart2e0fef82007-06-17 19:56:36 -05003658 spin_lock_irq(shost->host_lock);
3659 vport->fc_flag |= FC_NLP_MORE;
3660 spin_unlock_irq(shost->host_lock);
James Smart685f0bf2007-04-25 09:53:08 -04003661 break;
dea31012005-04-17 16:05:31 -05003662 }
3663 }
3664 }
3665 if (sentadisc == 0) {
James Smart2e0fef82007-06-17 19:56:36 -05003666 spin_lock_irq(shost->host_lock);
3667 vport->fc_flag &= ~FC_NLP_MORE;
3668 spin_unlock_irq(shost->host_lock);
dea31012005-04-17 16:05:31 -05003669 }
Jamie Wellnitz2fe165b2006-02-28 19:25:31 -05003670 return sentadisc;
dea31012005-04-17 16:05:31 -05003671}
3672
James Smarte59058c2008-08-24 21:49:00 -04003673/**
3674 * lpfc_els_disc_plogi: Issue plogi for all npr nodes of a vport before adisc.
3675 * @vport: pointer to a host virtual N_Port data structure.
3676 *
3677 * This routine issues Port Login (PLOGI) ELS commands to all the N_Ports
3678 * which are in node port recovery state, with a @vport. Each time an ELS
3679 * ADISC PLOGI IOCB is issued by invoking the lpfc_issue_els_plogi() routine,
3680 * the per @vport number of discover count (num_disc_nodes) shall be
3681 * incremented. If the num_disc_nodes reaches a pre-configured threshold
3682 * (cfg_discovery_threads), the @vport fc_flag will be marked with FC_NLP_MORE
3683 * bit set and quit the process of issuing remaining ADISC PLOGIN IOCBs for
3684 * later pick up. On the other hand, after walking through all the ndlps with
3685 * the @vport and there is none ADISC PLOGI IOCB issued, the @vport fc_flag
3686 * shall be cleared with the FC_NLP_MORE bit indicating there is no more ADISC
3687 * PLOGI need to be sent.
3688 *
3689 * Return code
3690 * The number of N_Ports with plogi issued.
3691 **/
dea31012005-04-17 16:05:31 -05003692int
James Smart2e0fef82007-06-17 19:56:36 -05003693lpfc_els_disc_plogi(struct lpfc_vport *vport)
dea31012005-04-17 16:05:31 -05003694{
James Smart2e0fef82007-06-17 19:56:36 -05003695 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
dea31012005-04-17 16:05:31 -05003696 struct lpfc_nodelist *ndlp, *next_ndlp;
James Smart2e0fef82007-06-17 19:56:36 -05003697 int sentplogi = 0;
dea31012005-04-17 16:05:31 -05003698
James Smart2e0fef82007-06-17 19:56:36 -05003699 /* go thru NPR nodes and issue any remaining ELS PLOGIs */
3700 list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) {
James Smarte47c9092008-02-08 18:49:26 -05003701 if (!NLP_CHK_NODE_ACT(ndlp))
3702 continue;
James Smart685f0bf2007-04-25 09:53:08 -04003703 if (ndlp->nlp_state == NLP_STE_NPR_NODE &&
3704 (ndlp->nlp_flag & NLP_NPR_2B_DISC) != 0 &&
3705 (ndlp->nlp_flag & NLP_DELAY_TMO) == 0 &&
3706 (ndlp->nlp_flag & NLP_NPR_ADISC) == 0) {
3707 ndlp->nlp_prev_state = ndlp->nlp_state;
James Smart2e0fef82007-06-17 19:56:36 -05003708 lpfc_nlp_set_state(vport, ndlp, NLP_STE_PLOGI_ISSUE);
3709 lpfc_issue_els_plogi(vport, ndlp->nlp_DID, 0);
James Smart685f0bf2007-04-25 09:53:08 -04003710 sentplogi++;
James Smart2e0fef82007-06-17 19:56:36 -05003711 vport->num_disc_nodes++;
3712 if (vport->num_disc_nodes >=
James Smart3de2a652007-08-02 11:09:59 -04003713 vport->cfg_discovery_threads) {
James Smart2e0fef82007-06-17 19:56:36 -05003714 spin_lock_irq(shost->host_lock);
3715 vport->fc_flag |= FC_NLP_MORE;
3716 spin_unlock_irq(shost->host_lock);
James Smart685f0bf2007-04-25 09:53:08 -04003717 break;
dea31012005-04-17 16:05:31 -05003718 }
3719 }
3720 }
James Smart87af33f2007-10-27 13:37:43 -04003721 if (sentplogi) {
3722 lpfc_set_disctmo(vport);
3723 }
3724 else {
James Smart2e0fef82007-06-17 19:56:36 -05003725 spin_lock_irq(shost->host_lock);
3726 vport->fc_flag &= ~FC_NLP_MORE;
3727 spin_unlock_irq(shost->host_lock);
dea31012005-04-17 16:05:31 -05003728 }
Jamie Wellnitz2fe165b2006-02-28 19:25:31 -05003729 return sentplogi;
dea31012005-04-17 16:05:31 -05003730}
3731
James Smarte59058c2008-08-24 21:49:00 -04003732/**
3733 * lpfc_els_flush_rscn: Clean up any rscn activities with a vport.
3734 * @vport: pointer to a host virtual N_Port data structure.
3735 *
3736 * This routine cleans up any Registration State Change Notification
3737 * (RSCN) activity with a @vport. Note that the fc_rscn_flush flag of the
3738 * @vport together with the host_lock is used to prevent multiple thread
3739 * trying to access the RSCN array on a same @vport at the same time.
3740 **/
James Smart92d7f7b2007-06-17 19:56:38 -05003741void
James Smart2e0fef82007-06-17 19:56:36 -05003742lpfc_els_flush_rscn(struct lpfc_vport *vport)
dea31012005-04-17 16:05:31 -05003743{
James Smart2e0fef82007-06-17 19:56:36 -05003744 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
3745 struct lpfc_hba *phba = vport->phba;
dea31012005-04-17 16:05:31 -05003746 int i;
3747
James Smart7f5f3d02008-02-08 18:50:14 -05003748 spin_lock_irq(shost->host_lock);
3749 if (vport->fc_rscn_flush) {
3750 /* Another thread is walking fc_rscn_id_list on this vport */
3751 spin_unlock_irq(shost->host_lock);
3752 return;
3753 }
3754 /* Indicate we are walking lpfc_els_flush_rscn on this vport */
3755 vport->fc_rscn_flush = 1;
3756 spin_unlock_irq(shost->host_lock);
3757
James Smart2e0fef82007-06-17 19:56:36 -05003758 for (i = 0; i < vport->fc_rscn_id_cnt; i++) {
James Smart92d7f7b2007-06-17 19:56:38 -05003759 lpfc_in_buf_free(phba, vport->fc_rscn_id_list[i]);
James Smart2e0fef82007-06-17 19:56:36 -05003760 vport->fc_rscn_id_list[i] = NULL;
dea31012005-04-17 16:05:31 -05003761 }
James Smart2e0fef82007-06-17 19:56:36 -05003762 spin_lock_irq(shost->host_lock);
3763 vport->fc_rscn_id_cnt = 0;
3764 vport->fc_flag &= ~(FC_RSCN_MODE | FC_RSCN_DISCOVERY);
3765 spin_unlock_irq(shost->host_lock);
3766 lpfc_can_disctmo(vport);
James Smart7f5f3d02008-02-08 18:50:14 -05003767 /* Indicate we are done walking this fc_rscn_id_list */
3768 vport->fc_rscn_flush = 0;
dea31012005-04-17 16:05:31 -05003769}
3770
James Smarte59058c2008-08-24 21:49:00 -04003771/**
3772 * lpfc_rscn_payload_check: Check whether there is a pending rscn to a did.
3773 * @vport: pointer to a host virtual N_Port data structure.
3774 * @did: remote destination port identifier.
3775 *
3776 * This routine checks whether there is any pending Registration State
3777 * Configuration Notification (RSCN) to a @did on @vport.
3778 *
3779 * Return code
3780 * None zero - The @did matched with a pending rscn
3781 * 0 - not able to match @did with a pending rscn
3782 **/
dea31012005-04-17 16:05:31 -05003783int
James Smart2e0fef82007-06-17 19:56:36 -05003784lpfc_rscn_payload_check(struct lpfc_vport *vport, uint32_t did)
dea31012005-04-17 16:05:31 -05003785{
3786 D_ID ns_did;
3787 D_ID rscn_did;
dea31012005-04-17 16:05:31 -05003788 uint32_t *lp;
James Smart92d7f7b2007-06-17 19:56:38 -05003789 uint32_t payload_len, i;
James Smart7f5f3d02008-02-08 18:50:14 -05003790 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
dea31012005-04-17 16:05:31 -05003791
3792 ns_did.un.word = did;
dea31012005-04-17 16:05:31 -05003793
3794 /* Never match fabric nodes for RSCNs */
3795 if ((did & Fabric_DID_MASK) == Fabric_DID_MASK)
James Smart2e0fef82007-06-17 19:56:36 -05003796 return 0;
dea31012005-04-17 16:05:31 -05003797
3798 /* If we are doing a FULL RSCN rediscovery, match everything */
James Smart2e0fef82007-06-17 19:56:36 -05003799 if (vport->fc_flag & FC_RSCN_DISCOVERY)
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05003800 return did;
dea31012005-04-17 16:05:31 -05003801
James Smart7f5f3d02008-02-08 18:50:14 -05003802 spin_lock_irq(shost->host_lock);
3803 if (vport->fc_rscn_flush) {
3804 /* Another thread is walking fc_rscn_id_list on this vport */
3805 spin_unlock_irq(shost->host_lock);
3806 return 0;
3807 }
3808 /* Indicate we are walking fc_rscn_id_list on this vport */
3809 vport->fc_rscn_flush = 1;
3810 spin_unlock_irq(shost->host_lock);
James Smart2e0fef82007-06-17 19:56:36 -05003811 for (i = 0; i < vport->fc_rscn_id_cnt; i++) {
James Smart92d7f7b2007-06-17 19:56:38 -05003812 lp = vport->fc_rscn_id_list[i]->virt;
3813 payload_len = be32_to_cpu(*lp++ & ~ELS_CMD_MASK);
3814 payload_len -= sizeof(uint32_t); /* take off word 0 */
dea31012005-04-17 16:05:31 -05003815 while (payload_len) {
James Smart92d7f7b2007-06-17 19:56:38 -05003816 rscn_did.un.word = be32_to_cpu(*lp++);
3817 payload_len -= sizeof(uint32_t);
dea31012005-04-17 16:05:31 -05003818 switch (rscn_did.un.b.resv) {
3819 case 0: /* Single N_Port ID effected */
James Smart2e0fef82007-06-17 19:56:36 -05003820 if (ns_did.un.word == rscn_did.un.word)
James Smart7f5f3d02008-02-08 18:50:14 -05003821 goto return_did_out;
dea31012005-04-17 16:05:31 -05003822 break;
3823 case 1: /* Whole N_Port Area effected */
3824 if ((ns_did.un.b.domain == rscn_did.un.b.domain)
3825 && (ns_did.un.b.area == rscn_did.un.b.area))
James Smart7f5f3d02008-02-08 18:50:14 -05003826 goto return_did_out;
dea31012005-04-17 16:05:31 -05003827 break;
3828 case 2: /* Whole N_Port Domain effected */
3829 if (ns_did.un.b.domain == rscn_did.un.b.domain)
James Smart7f5f3d02008-02-08 18:50:14 -05003830 goto return_did_out;
dea31012005-04-17 16:05:31 -05003831 break;
3832 default:
James Smart2e0fef82007-06-17 19:56:36 -05003833 /* Unknown Identifier in RSCN node */
James Smarte8b62012007-08-02 11:10:09 -04003834 lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY,
3835 "0217 Unknown Identifier in "
3836 "RSCN payload Data: x%x\n",
3837 rscn_did.un.word);
James Smart92d7f7b2007-06-17 19:56:38 -05003838 case 3: /* Whole Fabric effected */
James Smart7f5f3d02008-02-08 18:50:14 -05003839 goto return_did_out;
dea31012005-04-17 16:05:31 -05003840 }
3841 }
James Smart92d7f7b2007-06-17 19:56:38 -05003842 }
James Smart7f5f3d02008-02-08 18:50:14 -05003843 /* Indicate we are done with walking fc_rscn_id_list on this vport */
3844 vport->fc_rscn_flush = 0;
James Smart92d7f7b2007-06-17 19:56:38 -05003845 return 0;
James Smart7f5f3d02008-02-08 18:50:14 -05003846return_did_out:
3847 /* Indicate we are done with walking fc_rscn_id_list on this vport */
3848 vport->fc_rscn_flush = 0;
3849 return did;
dea31012005-04-17 16:05:31 -05003850}
3851
James Smarte59058c2008-08-24 21:49:00 -04003852/**
3853 * lpfc_rscn_recovery_check: Send recovery event to vport nodes matching rscn
3854 * @vport: pointer to a host virtual N_Port data structure.
3855 *
3856 * This routine sends recovery (NLP_EVT_DEVICE_RECOVERY) event to the
3857 * state machine for a @vport's nodes that are with pending RSCN (Registration
3858 * State Change Notification).
3859 *
3860 * Return code
3861 * 0 - Successful (currently alway return 0)
3862 **/
dea31012005-04-17 16:05:31 -05003863static int
James Smart2e0fef82007-06-17 19:56:36 -05003864lpfc_rscn_recovery_check(struct lpfc_vport *vport)
dea31012005-04-17 16:05:31 -05003865{
James Smart685f0bf2007-04-25 09:53:08 -04003866 struct lpfc_nodelist *ndlp = NULL;
dea31012005-04-17 16:05:31 -05003867
James Smart0d2b6b82008-06-14 22:52:47 -04003868 /* Move all affected nodes by pending RSCNs to NPR state. */
James Smart2e0fef82007-06-17 19:56:36 -05003869 list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) {
James Smarte47c9092008-02-08 18:49:26 -05003870 if (!NLP_CHK_NODE_ACT(ndlp) ||
James Smart0d2b6b82008-06-14 22:52:47 -04003871 (ndlp->nlp_state == NLP_STE_UNUSED_NODE) ||
3872 !lpfc_rscn_payload_check(vport, ndlp->nlp_DID))
dea31012005-04-17 16:05:31 -05003873 continue;
James Smart2e0fef82007-06-17 19:56:36 -05003874 lpfc_disc_state_machine(vport, ndlp, NULL,
James Smart0d2b6b82008-06-14 22:52:47 -04003875 NLP_EVT_DEVICE_RECOVERY);
3876 lpfc_cancel_retry_delay_tmo(vport, ndlp);
dea31012005-04-17 16:05:31 -05003877 }
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05003878 return 0;
dea31012005-04-17 16:05:31 -05003879}
3880
James Smarte59058c2008-08-24 21:49:00 -04003881/**
3882 * lpfc_els_rcv_rscn: Process an unsolicited rscn iocb.
3883 * @vport: pointer to a host virtual N_Port data structure.
3884 * @cmdiocb: pointer to lpfc command iocb data structure.
3885 * @ndlp: pointer to a node-list data structure.
3886 *
3887 * This routine processes an unsolicited RSCN (Registration State Change
3888 * Notification) IOCB. First, the payload of the unsolicited RSCN is walked
3889 * to invoke fc_host_post_event() routine to the FC transport layer. If the
3890 * discover state machine is about to begin discovery, it just accepts the
3891 * RSCN and the discovery process will satisfy the RSCN. If this RSCN only
3892 * contains N_Port IDs for other vports on this HBA, it just accepts the
3893 * RSCN and ignore processing it. If the state machine is in the recovery
3894 * state, the fc_rscn_id_list of this @vport is walked and the
3895 * lpfc_rscn_recovery_check() routine is invoked to send recovery event for
3896 * all nodes that match RSCN payload. Otherwise, the lpfc_els_handle_rscn()
3897 * routine is invoked to handle the RSCN event.
3898 *
3899 * Return code
3900 * 0 - Just sent the acc response
3901 * 1 - Sent the acc response and waited for name server completion
3902 **/
dea31012005-04-17 16:05:31 -05003903static int
James Smart2e0fef82007-06-17 19:56:36 -05003904lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
James Smart51ef4c22007-08-02 11:10:31 -04003905 struct lpfc_nodelist *ndlp)
dea31012005-04-17 16:05:31 -05003906{
James Smart2e0fef82007-06-17 19:56:36 -05003907 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
3908 struct lpfc_hba *phba = vport->phba;
dea31012005-04-17 16:05:31 -05003909 struct lpfc_dmabuf *pcmd;
James Smart92d7f7b2007-06-17 19:56:38 -05003910 uint32_t *lp, *datap;
dea31012005-04-17 16:05:31 -05003911 IOCB_t *icmd;
James Smart92d7f7b2007-06-17 19:56:38 -05003912 uint32_t payload_len, length, nportid, *cmd;
James Smart7f5f3d02008-02-08 18:50:14 -05003913 int rscn_cnt;
James Smart92d7f7b2007-06-17 19:56:38 -05003914 int rscn_id = 0, hba_id = 0;
James Smartd2873e42006-08-18 17:46:43 -04003915 int i;
dea31012005-04-17 16:05:31 -05003916
3917 icmd = &cmdiocb->iocb;
3918 pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
3919 lp = (uint32_t *) pcmd->virt;
3920
James Smart92d7f7b2007-06-17 19:56:38 -05003921 payload_len = be32_to_cpu(*lp++ & ~ELS_CMD_MASK);
3922 payload_len -= sizeof(uint32_t); /* take off word 0 */
dea31012005-04-17 16:05:31 -05003923 /* RSCN received */
James Smarte8b62012007-08-02 11:10:09 -04003924 lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
3925 "0214 RSCN received Data: x%x x%x x%x x%x\n",
James Smart7f5f3d02008-02-08 18:50:14 -05003926 vport->fc_flag, payload_len, *lp,
3927 vport->fc_rscn_id_cnt);
James Smartd2873e42006-08-18 17:46:43 -04003928 for (i = 0; i < payload_len/sizeof(uint32_t); i++)
James Smart2e0fef82007-06-17 19:56:36 -05003929 fc_host_post_event(shost, fc_get_event_number(),
James Smartd2873e42006-08-18 17:46:43 -04003930 FCH_EVT_RSCN, lp[i]);
3931
dea31012005-04-17 16:05:31 -05003932 /* If we are about to begin discovery, just ACC the RSCN.
3933 * Discovery processing will satisfy it.
3934 */
James Smart2e0fef82007-06-17 19:56:36 -05003935 if (vport->port_state <= LPFC_NS_QRY) {
James Smart858c9f62007-06-17 19:56:39 -05003936 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
3937 "RCV RSCN ignore: did:x%x/ste:x%x flg:x%x",
3938 ndlp->nlp_DID, vport->port_state, ndlp->nlp_flag);
3939
James Smart51ef4c22007-08-02 11:10:31 -04003940 lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05003941 return 0;
dea31012005-04-17 16:05:31 -05003942 }
3943
James Smart92d7f7b2007-06-17 19:56:38 -05003944 /* If this RSCN just contains NPortIDs for other vports on this HBA,
3945 * just ACC and ignore it.
3946 */
3947 if ((phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) &&
James Smart3de2a652007-08-02 11:09:59 -04003948 !(vport->cfg_peer_port_login)) {
James Smart92d7f7b2007-06-17 19:56:38 -05003949 i = payload_len;
3950 datap = lp;
3951 while (i > 0) {
3952 nportid = *datap++;
3953 nportid = ((be32_to_cpu(nportid)) & Mask_DID);
3954 i -= sizeof(uint32_t);
3955 rscn_id++;
James Smart549e55c2007-08-02 11:09:51 -04003956 if (lpfc_find_vport_by_did(phba, nportid))
3957 hba_id++;
James Smart92d7f7b2007-06-17 19:56:38 -05003958 }
3959 if (rscn_id == hba_id) {
3960 /* ALL NPortIDs in RSCN are on HBA */
James Smarte8b62012007-08-02 11:10:09 -04003961 lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
3962 "0214 Ignore RSCN "
3963 "Data: x%x x%x x%x x%x\n",
3964 vport->fc_flag, payload_len,
James Smart7f5f3d02008-02-08 18:50:14 -05003965 *lp, vport->fc_rscn_id_cnt);
James Smart858c9f62007-06-17 19:56:39 -05003966 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
3967 "RCV RSCN vport: did:x%x/ste:x%x flg:x%x",
3968 ndlp->nlp_DID, vport->port_state,
3969 ndlp->nlp_flag);
3970
James Smart92d7f7b2007-06-17 19:56:38 -05003971 lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb,
James Smart51ef4c22007-08-02 11:10:31 -04003972 ndlp, NULL);
James Smart92d7f7b2007-06-17 19:56:38 -05003973 return 0;
3974 }
3975 }
3976
James Smart7f5f3d02008-02-08 18:50:14 -05003977 spin_lock_irq(shost->host_lock);
3978 if (vport->fc_rscn_flush) {
3979 /* Another thread is walking fc_rscn_id_list on this vport */
3980 spin_unlock_irq(shost->host_lock);
3981 vport->fc_flag |= FC_RSCN_DISCOVERY;
James Smart58da1ff2008-04-07 10:15:56 -04003982 /* Send back ACC */
3983 lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL);
James Smart7f5f3d02008-02-08 18:50:14 -05003984 return 0;
3985 }
3986 /* Indicate we are walking fc_rscn_id_list on this vport */
3987 vport->fc_rscn_flush = 1;
3988 spin_unlock_irq(shost->host_lock);
3989 /* Get the array count after sucessfully have the token */
3990 rscn_cnt = vport->fc_rscn_id_cnt;
dea31012005-04-17 16:05:31 -05003991 /* If we are already processing an RSCN, save the received
3992 * RSCN payload buffer, cmdiocb->context2 to process later.
3993 */
James Smart2e0fef82007-06-17 19:56:36 -05003994 if (vport->fc_flag & (FC_RSCN_MODE | FC_NDISC_ACTIVE)) {
James Smart858c9f62007-06-17 19:56:39 -05003995 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
3996 "RCV RSCN defer: did:x%x/ste:x%x flg:x%x",
3997 ndlp->nlp_DID, vport->port_state, ndlp->nlp_flag);
3998
James Smart09372822008-01-11 01:52:54 -05003999 spin_lock_irq(shost->host_lock);
James Smart92d7f7b2007-06-17 19:56:38 -05004000 vport->fc_flag |= FC_RSCN_DEFERRED;
4001 if ((rscn_cnt < FC_MAX_HOLD_RSCN) &&
James Smart2e0fef82007-06-17 19:56:36 -05004002 !(vport->fc_flag & FC_RSCN_DISCOVERY)) {
James Smart2e0fef82007-06-17 19:56:36 -05004003 vport->fc_flag |= FC_RSCN_MODE;
4004 spin_unlock_irq(shost->host_lock);
James Smart92d7f7b2007-06-17 19:56:38 -05004005 if (rscn_cnt) {
4006 cmd = vport->fc_rscn_id_list[rscn_cnt-1]->virt;
4007 length = be32_to_cpu(*cmd & ~ELS_CMD_MASK);
4008 }
4009 if ((rscn_cnt) &&
4010 (payload_len + length <= LPFC_BPL_SIZE)) {
4011 *cmd &= ELS_CMD_MASK;
James Smart7f5f3d02008-02-08 18:50:14 -05004012 *cmd |= cpu_to_be32(payload_len + length);
James Smart92d7f7b2007-06-17 19:56:38 -05004013 memcpy(((uint8_t *)cmd) + length, lp,
4014 payload_len);
4015 } else {
4016 vport->fc_rscn_id_list[rscn_cnt] = pcmd;
4017 vport->fc_rscn_id_cnt++;
4018 /* If we zero, cmdiocb->context2, the calling
4019 * routine will not try to free it.
4020 */
4021 cmdiocb->context2 = NULL;
4022 }
dea31012005-04-17 16:05:31 -05004023 /* Deferred RSCN */
James Smarte8b62012007-08-02 11:10:09 -04004024 lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
4025 "0235 Deferred RSCN "
4026 "Data: x%x x%x x%x\n",
4027 vport->fc_rscn_id_cnt, vport->fc_flag,
4028 vport->port_state);
dea31012005-04-17 16:05:31 -05004029 } else {
James Smart2e0fef82007-06-17 19:56:36 -05004030 vport->fc_flag |= FC_RSCN_DISCOVERY;
4031 spin_unlock_irq(shost->host_lock);
dea31012005-04-17 16:05:31 -05004032 /* ReDiscovery RSCN */
James Smarte8b62012007-08-02 11:10:09 -04004033 lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
4034 "0234 ReDiscovery RSCN "
4035 "Data: x%x x%x x%x\n",
4036 vport->fc_rscn_id_cnt, vport->fc_flag,
4037 vport->port_state);
dea31012005-04-17 16:05:31 -05004038 }
James Smart7f5f3d02008-02-08 18:50:14 -05004039 /* Indicate we are done walking fc_rscn_id_list on this vport */
4040 vport->fc_rscn_flush = 0;
dea31012005-04-17 16:05:31 -05004041 /* Send back ACC */
James Smart51ef4c22007-08-02 11:10:31 -04004042 lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL);
dea31012005-04-17 16:05:31 -05004043 /* send RECOVERY event for ALL nodes that match RSCN payload */
James Smart2e0fef82007-06-17 19:56:36 -05004044 lpfc_rscn_recovery_check(vport);
James Smart09372822008-01-11 01:52:54 -05004045 spin_lock_irq(shost->host_lock);
James Smart92d7f7b2007-06-17 19:56:38 -05004046 vport->fc_flag &= ~FC_RSCN_DEFERRED;
James Smart09372822008-01-11 01:52:54 -05004047 spin_unlock_irq(shost->host_lock);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05004048 return 0;
dea31012005-04-17 16:05:31 -05004049 }
James Smart858c9f62007-06-17 19:56:39 -05004050 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
4051 "RCV RSCN: did:x%x/ste:x%x flg:x%x",
4052 ndlp->nlp_DID, vport->port_state, ndlp->nlp_flag);
4053
James Smart2e0fef82007-06-17 19:56:36 -05004054 spin_lock_irq(shost->host_lock);
4055 vport->fc_flag |= FC_RSCN_MODE;
4056 spin_unlock_irq(shost->host_lock);
4057 vport->fc_rscn_id_list[vport->fc_rscn_id_cnt++] = pcmd;
James Smart7f5f3d02008-02-08 18:50:14 -05004058 /* Indicate we are done walking fc_rscn_id_list on this vport */
4059 vport->fc_rscn_flush = 0;
dea31012005-04-17 16:05:31 -05004060 /*
4061 * If we zero, cmdiocb->context2, the calling routine will
4062 * not try to free it.
4063 */
4064 cmdiocb->context2 = NULL;
James Smart2e0fef82007-06-17 19:56:36 -05004065 lpfc_set_disctmo(vport);
dea31012005-04-17 16:05:31 -05004066 /* Send back ACC */
James Smart51ef4c22007-08-02 11:10:31 -04004067 lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL);
dea31012005-04-17 16:05:31 -05004068 /* send RECOVERY event for ALL nodes that match RSCN payload */
James Smart2e0fef82007-06-17 19:56:36 -05004069 lpfc_rscn_recovery_check(vport);
James Smart2e0fef82007-06-17 19:56:36 -05004070 return lpfc_els_handle_rscn(vport);
dea31012005-04-17 16:05:31 -05004071}
4072
James Smarte59058c2008-08-24 21:49:00 -04004073/**
4074 * lpfc_els_handle_rscn: Handle rscn for a vport.
4075 * @vport: pointer to a host virtual N_Port data structure.
4076 *
4077 * This routine handles the Registration State Configuration Notification
4078 * (RSCN) for a @vport. If login to NameServer does not exist, a new ndlp shall
4079 * be created and a Port Login (PLOGI) to the NameServer is issued. Otherwise,
4080 * if the ndlp to NameServer exists, a Common Transport (CT) command to the
4081 * NameServer shall be issued. If CT command to the NameServer fails to be
4082 * issued, the lpfc_els_flush_rscn() routine shall be invoked to clean up any
4083 * RSCN activities with the @vport.
4084 *
4085 * Return code
4086 * 0 - Cleaned up rscn on the @vport
4087 * 1 - Wait for plogi to name server before proceed
4088 **/
dea31012005-04-17 16:05:31 -05004089int
James Smart2e0fef82007-06-17 19:56:36 -05004090lpfc_els_handle_rscn(struct lpfc_vport *vport)
dea31012005-04-17 16:05:31 -05004091{
4092 struct lpfc_nodelist *ndlp;
James Smart2e0fef82007-06-17 19:56:36 -05004093 struct lpfc_hba *phba = vport->phba;
dea31012005-04-17 16:05:31 -05004094
James Smart92d7f7b2007-06-17 19:56:38 -05004095 /* Ignore RSCN if the port is being torn down. */
4096 if (vport->load_flag & FC_UNLOADING) {
4097 lpfc_els_flush_rscn(vport);
4098 return 0;
4099 }
4100
dea31012005-04-17 16:05:31 -05004101 /* Start timer for RSCN processing */
James Smart2e0fef82007-06-17 19:56:36 -05004102 lpfc_set_disctmo(vport);
dea31012005-04-17 16:05:31 -05004103
4104 /* RSCN processed */
James Smarte8b62012007-08-02 11:10:09 -04004105 lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
4106 "0215 RSCN processed Data: x%x x%x x%x x%x\n",
4107 vport->fc_flag, 0, vport->fc_rscn_id_cnt,
4108 vport->port_state);
dea31012005-04-17 16:05:31 -05004109
4110 /* To process RSCN, first compare RSCN data with NameServer */
James Smart2e0fef82007-06-17 19:56:36 -05004111 vport->fc_ns_retry = 0;
James Smart0ff10d42008-01-11 01:52:36 -05004112 vport->num_disc_nodes = 0;
4113
James Smart2e0fef82007-06-17 19:56:36 -05004114 ndlp = lpfc_findnode_did(vport, NameServer_DID);
James Smarte47c9092008-02-08 18:49:26 -05004115 if (ndlp && NLP_CHK_NODE_ACT(ndlp)
4116 && ndlp->nlp_state == NLP_STE_UNMAPPED_NODE) {
dea31012005-04-17 16:05:31 -05004117 /* Good ndlp, issue CT Request to NameServer */
James Smart92d7f7b2007-06-17 19:56:38 -05004118 if (lpfc_ns_cmd(vport, SLI_CTNS_GID_FT, 0, 0) == 0)
dea31012005-04-17 16:05:31 -05004119 /* Wait for NameServer query cmpl before we can
4120 continue */
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05004121 return 1;
dea31012005-04-17 16:05:31 -05004122 } else {
4123 /* If login to NameServer does not exist, issue one */
4124 /* Good status, issue PLOGI to NameServer */
James Smart2e0fef82007-06-17 19:56:36 -05004125 ndlp = lpfc_findnode_did(vport, NameServer_DID);
James Smarte47c9092008-02-08 18:49:26 -05004126 if (ndlp && NLP_CHK_NODE_ACT(ndlp))
dea31012005-04-17 16:05:31 -05004127 /* Wait for NameServer login cmpl before we can
4128 continue */
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05004129 return 1;
James Smart2e0fef82007-06-17 19:56:36 -05004130
James Smarte47c9092008-02-08 18:49:26 -05004131 if (ndlp) {
4132 ndlp = lpfc_enable_node(vport, ndlp,
4133 NLP_STE_PLOGI_ISSUE);
4134 if (!ndlp) {
4135 lpfc_els_flush_rscn(vport);
4136 return 0;
4137 }
4138 ndlp->nlp_prev_state = NLP_STE_UNUSED_NODE;
dea31012005-04-17 16:05:31 -05004139 } else {
James Smarte47c9092008-02-08 18:49:26 -05004140 ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL);
4141 if (!ndlp) {
4142 lpfc_els_flush_rscn(vport);
4143 return 0;
4144 }
James Smart2e0fef82007-06-17 19:56:36 -05004145 lpfc_nlp_init(vport, ndlp, NameServer_DID);
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05004146 ndlp->nlp_prev_state = ndlp->nlp_state;
James Smart2e0fef82007-06-17 19:56:36 -05004147 lpfc_nlp_set_state(vport, ndlp, NLP_STE_PLOGI_ISSUE);
dea31012005-04-17 16:05:31 -05004148 }
James Smarte47c9092008-02-08 18:49:26 -05004149 ndlp->nlp_type |= NLP_FABRIC;
4150 lpfc_issue_els_plogi(vport, NameServer_DID, 0);
4151 /* Wait for NameServer login cmpl before we can
4152 * continue
4153 */
4154 return 1;
dea31012005-04-17 16:05:31 -05004155 }
4156
James Smart2e0fef82007-06-17 19:56:36 -05004157 lpfc_els_flush_rscn(vport);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05004158 return 0;
dea31012005-04-17 16:05:31 -05004159}
4160
James Smarte59058c2008-08-24 21:49:00 -04004161/**
4162 * lpfc_els_rcv_flogi: Process an unsolicited flogi iocb.
4163 * @vport: pointer to a host virtual N_Port data structure.
4164 * @cmdiocb: pointer to lpfc command iocb data structure.
4165 * @ndlp: pointer to a node-list data structure.
4166 *
4167 * This routine processes Fabric Login (FLOGI) IOCB received as an ELS
4168 * unsolicited event. An unsolicited FLOGI can be received in a point-to-
4169 * point topology. As an unsolicited FLOGI should not be received in a loop
4170 * mode, any unsolicited FLOGI received in loop mode shall be ignored. The
4171 * lpfc_check_sparm() routine is invoked to check the parameters in the
4172 * unsolicited FLOGI. If parameters validation failed, the routine
4173 * lpfc_els_rsp_reject() shall be called with reject reason code set to
4174 * LSEXP_SPARM_OPTIONS to reject the FLOGI. Otherwise, the Port WWN in the
4175 * FLOGI shall be compared with the Port WWN of the @vport to determine who
4176 * will initiate PLOGI. The higher lexicographical value party shall has
4177 * higher priority (as the winning port) and will initiate PLOGI and
4178 * communicate Port_IDs (Addresses) for both nodes in PLOGI. The result
4179 * of this will be marked in the @vport fc_flag field with FC_PT2PT_PLOGI
4180 * and then the lpfc_els_rsp_acc() routine is invoked to accept the FLOGI.
4181 *
4182 * Return code
4183 * 0 - Successfully processed the unsolicited flogi
4184 * 1 - Failed to process the unsolicited flogi
4185 **/
dea31012005-04-17 16:05:31 -05004186static int
James Smart2e0fef82007-06-17 19:56:36 -05004187lpfc_els_rcv_flogi(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
James Smart51ef4c22007-08-02 11:10:31 -04004188 struct lpfc_nodelist *ndlp)
dea31012005-04-17 16:05:31 -05004189{
James Smart2e0fef82007-06-17 19:56:36 -05004190 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
4191 struct lpfc_hba *phba = vport->phba;
dea31012005-04-17 16:05:31 -05004192 struct lpfc_dmabuf *pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
4193 uint32_t *lp = (uint32_t *) pcmd->virt;
4194 IOCB_t *icmd = &cmdiocb->iocb;
4195 struct serv_parm *sp;
4196 LPFC_MBOXQ_t *mbox;
4197 struct ls_rjt stat;
4198 uint32_t cmd, did;
4199 int rc;
4200
4201 cmd = *lp++;
4202 sp = (struct serv_parm *) lp;
4203
4204 /* FLOGI received */
4205
James Smart2e0fef82007-06-17 19:56:36 -05004206 lpfc_set_disctmo(vport);
dea31012005-04-17 16:05:31 -05004207
4208 if (phba->fc_topology == TOPOLOGY_LOOP) {
4209 /* We should never receive a FLOGI in loop mode, ignore it */
4210 did = icmd->un.elsreq64.remoteID;
4211
4212 /* An FLOGI ELS command <elsCmd> was received from DID <did> in
4213 Loop Mode */
James Smarte8b62012007-08-02 11:10:09 -04004214 lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
4215 "0113 An FLOGI ELS command x%x was "
4216 "received from DID x%x in Loop Mode\n",
4217 cmd, did);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05004218 return 1;
dea31012005-04-17 16:05:31 -05004219 }
4220
4221 did = Fabric_DID;
4222
James Smart2e0fef82007-06-17 19:56:36 -05004223 if ((lpfc_check_sparm(vport, ndlp, sp, CLASS3))) {
dea31012005-04-17 16:05:31 -05004224 /* For a FLOGI we accept, then if our portname is greater
4225 * then the remote portname we initiate Nport login.
4226 */
4227
James Smart2e0fef82007-06-17 19:56:36 -05004228 rc = memcmp(&vport->fc_portname, &sp->portName,
James Smart92d7f7b2007-06-17 19:56:38 -05004229 sizeof(struct lpfc_name));
dea31012005-04-17 16:05:31 -05004230
4231 if (!rc) {
James Smart2e0fef82007-06-17 19:56:36 -05004232 mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
4233 if (!mbox)
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05004234 return 1;
James Smart2e0fef82007-06-17 19:56:36 -05004235
dea31012005-04-17 16:05:31 -05004236 lpfc_linkdown(phba);
4237 lpfc_init_link(phba, mbox,
4238 phba->cfg_topology,
4239 phba->cfg_link_speed);
4240 mbox->mb.un.varInitLnk.lipsr_AL_PA = 0;
4241 mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
James Smarted957682007-06-17 19:56:37 -05004242 mbox->vport = vport;
James Smart0b727fe2007-10-27 13:37:25 -04004243 rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT);
James Smart5b8bd0c2007-04-25 09:52:49 -04004244 lpfc_set_loopback_flag(phba);
dea31012005-04-17 16:05:31 -05004245 if (rc == MBX_NOT_FINISHED) {
James Smart329f9bc2007-04-25 09:53:01 -04004246 mempool_free(mbox, phba->mbox_mem_pool);
dea31012005-04-17 16:05:31 -05004247 }
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05004248 return 1;
Jamie Wellnitz2fe165b2006-02-28 19:25:31 -05004249 } else if (rc > 0) { /* greater than */
James Smart2e0fef82007-06-17 19:56:36 -05004250 spin_lock_irq(shost->host_lock);
4251 vport->fc_flag |= FC_PT2PT_PLOGI;
4252 spin_unlock_irq(shost->host_lock);
dea31012005-04-17 16:05:31 -05004253 }
James Smart2e0fef82007-06-17 19:56:36 -05004254 spin_lock_irq(shost->host_lock);
4255 vport->fc_flag |= FC_PT2PT;
4256 vport->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP);
4257 spin_unlock_irq(shost->host_lock);
dea31012005-04-17 16:05:31 -05004258 } else {
4259 /* Reject this request because invalid parameters */
4260 stat.un.b.lsRjtRsvd0 = 0;
4261 stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
4262 stat.un.b.lsRjtRsnCodeExp = LSEXP_SPARM_OPTIONS;
4263 stat.un.b.vendorUnique = 0;
James Smart858c9f62007-06-17 19:56:39 -05004264 lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp,
4265 NULL);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05004266 return 1;
dea31012005-04-17 16:05:31 -05004267 }
4268
4269 /* Send back ACC */
James Smart51ef4c22007-08-02 11:10:31 -04004270 lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb, ndlp, NULL);
dea31012005-04-17 16:05:31 -05004271
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05004272 return 0;
dea31012005-04-17 16:05:31 -05004273}
4274
James Smarte59058c2008-08-24 21:49:00 -04004275/**
4276 * lpfc_els_rcv_rnid: Process an unsolicited rnid iocb.
4277 * @vport: pointer to a host virtual N_Port data structure.
4278 * @cmdiocb: pointer to lpfc command iocb data structure.
4279 * @ndlp: pointer to a node-list data structure.
4280 *
4281 * This routine processes Request Node Identification Data (RNID) IOCB
4282 * received as an ELS unsolicited event. Only when the RNID specified format
4283 * 0x0 or 0xDF (Topology Discovery Specific Node Identification Data)
4284 * present, this routine will invoke the lpfc_els_rsp_rnid_acc() routine to
4285 * Accept (ACC) the RNID ELS command. All the other RNID formats are
4286 * rejected by invoking the lpfc_els_rsp_reject() routine.
4287 *
4288 * Return code
4289 * 0 - Successfully processed rnid iocb (currently always return 0)
4290 **/
dea31012005-04-17 16:05:31 -05004291static int
James Smart2e0fef82007-06-17 19:56:36 -05004292lpfc_els_rcv_rnid(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
4293 struct lpfc_nodelist *ndlp)
dea31012005-04-17 16:05:31 -05004294{
4295 struct lpfc_dmabuf *pcmd;
4296 uint32_t *lp;
4297 IOCB_t *icmd;
4298 RNID *rn;
4299 struct ls_rjt stat;
4300 uint32_t cmd, did;
4301
4302 icmd = &cmdiocb->iocb;
4303 did = icmd->un.elsreq64.remoteID;
4304 pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
4305 lp = (uint32_t *) pcmd->virt;
4306
4307 cmd = *lp++;
4308 rn = (RNID *) lp;
4309
4310 /* RNID received */
4311
4312 switch (rn->Format) {
4313 case 0:
4314 case RNID_TOPOLOGY_DISC:
4315 /* Send back ACC */
James Smart2e0fef82007-06-17 19:56:36 -05004316 lpfc_els_rsp_rnid_acc(vport, rn->Format, cmdiocb, ndlp);
dea31012005-04-17 16:05:31 -05004317 break;
4318 default:
4319 /* Reject this request because format not supported */
4320 stat.un.b.lsRjtRsvd0 = 0;
4321 stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
4322 stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA;
4323 stat.un.b.vendorUnique = 0;
James Smart858c9f62007-06-17 19:56:39 -05004324 lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp,
4325 NULL);
dea31012005-04-17 16:05:31 -05004326 }
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05004327 return 0;
dea31012005-04-17 16:05:31 -05004328}
4329
James Smarte59058c2008-08-24 21:49:00 -04004330/**
4331 * lpfc_els_rcv_lirr: Process an unsolicited lirr iocb.
4332 * @vport: pointer to a host virtual N_Port data structure.
4333 * @cmdiocb: pointer to lpfc command iocb data structure.
4334 * @ndlp: pointer to a node-list data structure.
4335 *
4336 * This routine processes a Link Incident Report Registration(LIRR) IOCB
4337 * received as an ELS unsolicited event. Currently, this function just invokes
4338 * the lpfc_els_rsp_reject() routine to reject the LIRR IOCB unconditionally.
4339 *
4340 * Return code
4341 * 0 - Successfully processed lirr iocb (currently always return 0)
4342 **/
dea31012005-04-17 16:05:31 -05004343static int
James Smart2e0fef82007-06-17 19:56:36 -05004344lpfc_els_rcv_lirr(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
4345 struct lpfc_nodelist *ndlp)
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05004346{
4347 struct ls_rjt stat;
4348
4349 /* For now, unconditionally reject this command */
4350 stat.un.b.lsRjtRsvd0 = 0;
4351 stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
4352 stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA;
4353 stat.un.b.vendorUnique = 0;
James Smart858c9f62007-06-17 19:56:39 -05004354 lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, NULL);
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05004355 return 0;
4356}
4357
James Smarte59058c2008-08-24 21:49:00 -04004358/**
4359 * lpfc_els_rsp_rps_acc: Completion callbk func for MBX_READ_LNK_STAT mbox cmd.
4360 * @phba: pointer to lpfc hba data structure.
4361 * @pmb: pointer to the driver internal queue element for mailbox command.
4362 *
4363 * This routine is the completion callback function for the MBX_READ_LNK_STAT
4364 * mailbox command. This callback function is to actually send the Accept
4365 * (ACC) response to a Read Port Status (RPS) unsolicited IOCB event. It
4366 * collects the link statistics from the completion of the MBX_READ_LNK_STAT
4367 * mailbox command, constructs the RPS response with the link statistics
4368 * collected, and then invokes the lpfc_sli_issue_iocb() routine to send ACC
4369 * response to the RPS.
4370 *
4371 * Note that, in lpfc_prep_els_iocb() routine, the reference count of ndlp
4372 * will be incremented by 1 for holding the ndlp and the reference to ndlp
4373 * will be stored into the context1 field of the IOCB for the completion
4374 * callback function to the RPS Accept Response ELS IOCB command.
4375 *
4376 **/
Jamie Wellnitz082c0262006-02-28 19:25:30 -05004377static void
James Smart329f9bc2007-04-25 09:53:01 -04004378lpfc_els_rsp_rps_acc(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05004379{
James Smart2e0fef82007-06-17 19:56:36 -05004380 struct lpfc_sli *psli = &phba->sli;
4381 struct lpfc_sli_ring *pring = &psli->ring[LPFC_ELS_RING];
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05004382 MAILBOX_t *mb;
4383 IOCB_t *icmd;
4384 RPS_RSP *rps_rsp;
4385 uint8_t *pcmd;
4386 struct lpfc_iocbq *elsiocb;
4387 struct lpfc_nodelist *ndlp;
4388 uint16_t xri, status;
4389 uint32_t cmdsize;
4390
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05004391 mb = &pmb->mb;
4392
4393 ndlp = (struct lpfc_nodelist *) pmb->context2;
4394 xri = (uint16_t) ((unsigned long)(pmb->context1));
Randy Dunlap041976f2006-06-25 01:58:51 -07004395 pmb->context1 = NULL;
4396 pmb->context2 = NULL;
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05004397
4398 if (mb->mbxStatus) {
James Smart329f9bc2007-04-25 09:53:01 -04004399 mempool_free(pmb, phba->mbox_mem_pool);
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05004400 return;
4401 }
4402
4403 cmdsize = sizeof(RPS_RSP) + sizeof(uint32_t);
James Smart329f9bc2007-04-25 09:53:01 -04004404 mempool_free(pmb, phba->mbox_mem_pool);
James Smart2e0fef82007-06-17 19:56:36 -05004405 elsiocb = lpfc_prep_els_iocb(phba->pport, 0, cmdsize,
4406 lpfc_max_els_tries, ndlp,
4407 ndlp->nlp_DID, ELS_CMD_ACC);
James Smartfa4066b2008-01-11 01:53:27 -05004408
4409 /* Decrement the ndlp reference count from previous mbox command */
James Smart329f9bc2007-04-25 09:53:01 -04004410 lpfc_nlp_put(ndlp);
James Smartfa4066b2008-01-11 01:53:27 -05004411
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05004412 if (!elsiocb)
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05004413 return;
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05004414
4415 icmd = &elsiocb->iocb;
4416 icmd->ulpContext = xri;
4417
4418 pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
4419 *((uint32_t *) (pcmd)) = ELS_CMD_ACC;
James Smart92d7f7b2007-06-17 19:56:38 -05004420 pcmd += sizeof(uint32_t); /* Skip past command */
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05004421 rps_rsp = (RPS_RSP *)pcmd;
4422
4423 if (phba->fc_topology != TOPOLOGY_LOOP)
4424 status = 0x10;
4425 else
4426 status = 0x8;
James Smart2e0fef82007-06-17 19:56:36 -05004427 if (phba->pport->fc_flag & FC_FABRIC)
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05004428 status |= 0x4;
4429
4430 rps_rsp->rsvd1 = 0;
James Smart09372822008-01-11 01:52:54 -05004431 rps_rsp->portStatus = cpu_to_be16(status);
4432 rps_rsp->linkFailureCnt = cpu_to_be32(mb->un.varRdLnk.linkFailureCnt);
4433 rps_rsp->lossSyncCnt = cpu_to_be32(mb->un.varRdLnk.lossSyncCnt);
4434 rps_rsp->lossSignalCnt = cpu_to_be32(mb->un.varRdLnk.lossSignalCnt);
4435 rps_rsp->primSeqErrCnt = cpu_to_be32(mb->un.varRdLnk.primSeqErrCnt);
4436 rps_rsp->invalidXmitWord = cpu_to_be32(mb->un.varRdLnk.invalidXmitWord);
4437 rps_rsp->crcCnt = cpu_to_be32(mb->un.varRdLnk.crcCnt);
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05004438 /* Xmit ELS RPS ACC response tag <ulpIoTag> */
James Smarte8b62012007-08-02 11:10:09 -04004439 lpfc_printf_vlog(ndlp->vport, KERN_INFO, LOG_ELS,
4440 "0118 Xmit ELS RPS ACC response tag x%x xri x%x, "
4441 "did x%x, nlp_flag x%x, nlp_state x%x, rpi x%x\n",
4442 elsiocb->iotag, elsiocb->iocb.ulpContext,
4443 ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state,
4444 ndlp->nlp_rpi);
James Smart858c9f62007-06-17 19:56:39 -05004445 elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp;
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05004446 phba->fc_stat.elsXmitACC++;
James Smarted957682007-06-17 19:56:37 -05004447 if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR)
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05004448 lpfc_els_free_iocb(phba, elsiocb);
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05004449 return;
4450}
4451
James Smarte59058c2008-08-24 21:49:00 -04004452/**
4453 * lpfc_els_rcv_rps: Process an unsolicited rps iocb.
4454 * @vport: pointer to a host virtual N_Port data structure.
4455 * @cmdiocb: pointer to lpfc command iocb data structure.
4456 * @ndlp: pointer to a node-list data structure.
4457 *
4458 * This routine processes Read Port Status (RPS) IOCB received as an
4459 * ELS unsolicited event. It first checks the remote port state. If the
4460 * remote port is not in NLP_STE_UNMAPPED_NODE state or NLP_STE_MAPPED_NODE
4461 * state, it invokes the lpfc_els_rsp_reject() routine to send the reject
4462 * response. Otherwise, it issue the MBX_READ_LNK_STAT mailbox command
4463 * for reading the HBA link statistics. It is for the callback function,
4464 * lpfc_els_rsp_rps_acc(), set to the MBX_READ_LNK_STAT mailbox command
4465 * to actually sending out RPS Accept (ACC) response.
4466 *
4467 * Return codes
4468 * 0 - Successfully processed rps iocb (currently always return 0)
4469 **/
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05004470static int
James Smart2e0fef82007-06-17 19:56:36 -05004471lpfc_els_rcv_rps(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
4472 struct lpfc_nodelist *ndlp)
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05004473{
James Smart2e0fef82007-06-17 19:56:36 -05004474 struct lpfc_hba *phba = vport->phba;
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05004475 uint32_t *lp;
4476 uint8_t flag;
4477 LPFC_MBOXQ_t *mbox;
4478 struct lpfc_dmabuf *pcmd;
4479 RPS *rps;
4480 struct ls_rjt stat;
4481
Jamie Wellnitz2fe165b2006-02-28 19:25:31 -05004482 if ((ndlp->nlp_state != NLP_STE_UNMAPPED_NODE) &&
4483 (ndlp->nlp_state != NLP_STE_MAPPED_NODE)) {
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05004484 stat.un.b.lsRjtRsvd0 = 0;
4485 stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
4486 stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA;
4487 stat.un.b.vendorUnique = 0;
James Smart858c9f62007-06-17 19:56:39 -05004488 lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp,
4489 NULL);
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05004490 }
4491
4492 pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
4493 lp = (uint32_t *) pcmd->virt;
4494 flag = (be32_to_cpu(*lp++) & 0xf);
4495 rps = (RPS *) lp;
4496
4497 if ((flag == 0) ||
4498 ((flag == 1) && (be32_to_cpu(rps->un.portNum) == 0)) ||
James Smart2e0fef82007-06-17 19:56:36 -05004499 ((flag == 2) && (memcmp(&rps->un.portName, &vport->fc_portname,
James Smart92d7f7b2007-06-17 19:56:38 -05004500 sizeof(struct lpfc_name)) == 0))) {
James Smart2e0fef82007-06-17 19:56:36 -05004501
James Smart92d7f7b2007-06-17 19:56:38 -05004502 printk("Fix me....\n");
4503 dump_stack();
James Smart2e0fef82007-06-17 19:56:36 -05004504 mbox = mempool_alloc(phba->mbox_mem_pool, GFP_ATOMIC);
4505 if (mbox) {
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05004506 lpfc_read_lnk_stat(phba, mbox);
4507 mbox->context1 =
James Smart92d7f7b2007-06-17 19:56:38 -05004508 (void *)((unsigned long) cmdiocb->iocb.ulpContext);
James Smart329f9bc2007-04-25 09:53:01 -04004509 mbox->context2 = lpfc_nlp_get(ndlp);
James Smart92d7f7b2007-06-17 19:56:38 -05004510 mbox->vport = vport;
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05004511 mbox->mbox_cmpl = lpfc_els_rsp_rps_acc;
James Smartfa4066b2008-01-11 01:53:27 -05004512 if (lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT)
James Smart0b727fe2007-10-27 13:37:25 -04004513 != MBX_NOT_FINISHED)
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05004514 /* Mbox completion will send ELS Response */
4515 return 0;
James Smartfa4066b2008-01-11 01:53:27 -05004516 /* Decrement reference count used for the failed mbox
4517 * command.
4518 */
James Smart329f9bc2007-04-25 09:53:01 -04004519 lpfc_nlp_put(ndlp);
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05004520 mempool_free(mbox, phba->mbox_mem_pool);
4521 }
4522 }
4523 stat.un.b.lsRjtRsvd0 = 0;
4524 stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
4525 stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA;
4526 stat.un.b.vendorUnique = 0;
James Smart858c9f62007-06-17 19:56:39 -05004527 lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, NULL);
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05004528 return 0;
4529}
4530
James Smarte59058c2008-08-24 21:49:00 -04004531/**
4532 * lpfc_els_rsp_rpl_acc: Issue an accept rpl els command.
4533 * @vport: pointer to a host virtual N_Port data structure.
4534 * @cmdsize: size of the ELS command.
4535 * @oldiocb: pointer to the original lpfc command iocb data structure.
4536 * @ndlp: pointer to a node-list data structure.
4537 *
4538 * This routine issuees an Accept (ACC) Read Port List (RPL) ELS command.
4539 * It is to be called by the lpfc_els_rcv_rpl() routine to accept the RPL.
4540 *
4541 * Note that, in lpfc_prep_els_iocb() routine, the reference count of ndlp
4542 * will be incremented by 1 for holding the ndlp and the reference to ndlp
4543 * will be stored into the context1 field of the IOCB for the completion
4544 * callback function to the RPL Accept Response ELS command.
4545 *
4546 * Return code
4547 * 0 - Successfully issued ACC RPL ELS command
4548 * 1 - Failed to issue ACC RPL ELS command
4549 **/
Jamie Wellnitz082c0262006-02-28 19:25:30 -05004550static int
James Smart2e0fef82007-06-17 19:56:36 -05004551lpfc_els_rsp_rpl_acc(struct lpfc_vport *vport, uint16_t cmdsize,
4552 struct lpfc_iocbq *oldiocb, struct lpfc_nodelist *ndlp)
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05004553{
James Smart2e0fef82007-06-17 19:56:36 -05004554 struct lpfc_hba *phba = vport->phba;
4555 IOCB_t *icmd, *oldcmd;
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05004556 RPL_RSP rpl_rsp;
4557 struct lpfc_iocbq *elsiocb;
James Smart2e0fef82007-06-17 19:56:36 -05004558 struct lpfc_sli *psli = &phba->sli;
4559 struct lpfc_sli_ring *pring = &psli->ring[LPFC_ELS_RING];
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05004560 uint8_t *pcmd;
4561
James Smart2e0fef82007-06-17 19:56:36 -05004562 elsiocb = lpfc_prep_els_iocb(vport, 0, cmdsize, oldiocb->retry, ndlp,
4563 ndlp->nlp_DID, ELS_CMD_ACC);
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05004564
James Smart488d1462006-03-07 15:02:37 -05004565 if (!elsiocb)
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05004566 return 1;
James Smart488d1462006-03-07 15:02:37 -05004567
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05004568 icmd = &elsiocb->iocb;
4569 oldcmd = &oldiocb->iocb;
4570 icmd->ulpContext = oldcmd->ulpContext; /* Xri */
4571
4572 pcmd = (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
4573 *((uint32_t *) (pcmd)) = ELS_CMD_ACC;
James Smart92d7f7b2007-06-17 19:56:38 -05004574 pcmd += sizeof(uint16_t);
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05004575 *((uint16_t *)(pcmd)) = be16_to_cpu(cmdsize);
4576 pcmd += sizeof(uint16_t);
4577
4578 /* Setup the RPL ACC payload */
4579 rpl_rsp.listLen = be32_to_cpu(1);
4580 rpl_rsp.index = 0;
4581 rpl_rsp.port_num_blk.portNum = 0;
James Smart2e0fef82007-06-17 19:56:36 -05004582 rpl_rsp.port_num_blk.portID = be32_to_cpu(vport->fc_myDID);
4583 memcpy(&rpl_rsp.port_num_blk.portName, &vport->fc_portname,
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05004584 sizeof(struct lpfc_name));
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05004585 memcpy(pcmd, &rpl_rsp, cmdsize - sizeof(uint32_t));
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05004586 /* Xmit ELS RPL ACC response tag <ulpIoTag> */
James Smarte8b62012007-08-02 11:10:09 -04004587 lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
4588 "0120 Xmit ELS RPL ACC response tag x%x "
4589 "xri x%x, did x%x, nlp_flag x%x, nlp_state x%x, "
4590 "rpi x%x\n",
4591 elsiocb->iotag, elsiocb->iocb.ulpContext,
4592 ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state,
4593 ndlp->nlp_rpi);
James Smart858c9f62007-06-17 19:56:39 -05004594 elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp;
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05004595 phba->fc_stat.elsXmitACC++;
4596 if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) {
4597 lpfc_els_free_iocb(phba, elsiocb);
4598 return 1;
4599 }
4600 return 0;
4601}
4602
James Smarte59058c2008-08-24 21:49:00 -04004603/**
4604 * lpfc_els_rcv_rpl: Process an unsolicited rpl iocb.
4605 * @vport: pointer to a host virtual N_Port data structure.
4606 * @cmdiocb: pointer to lpfc command iocb data structure.
4607 * @ndlp: pointer to a node-list data structure.
4608 *
4609 * This routine processes Read Port List (RPL) IOCB received as an ELS
4610 * unsolicited event. It first checks the remote port state. If the remote
4611 * port is not in NLP_STE_UNMAPPED_NODE and NLP_STE_MAPPED_NODE states, it
4612 * invokes the lpfc_els_rsp_reject() routine to send reject response.
4613 * Otherwise, this routine then invokes the lpfc_els_rsp_rpl_acc() routine
4614 * to accept the RPL.
4615 *
4616 * Return code
4617 * 0 - Successfully processed rpl iocb (currently always return 0)
4618 **/
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05004619static int
James Smart2e0fef82007-06-17 19:56:36 -05004620lpfc_els_rcv_rpl(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
4621 struct lpfc_nodelist *ndlp)
dea31012005-04-17 16:05:31 -05004622{
4623 struct lpfc_dmabuf *pcmd;
4624 uint32_t *lp;
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05004625 uint32_t maxsize;
4626 uint16_t cmdsize;
4627 RPL *rpl;
4628 struct ls_rjt stat;
dea31012005-04-17 16:05:31 -05004629
Jamie Wellnitz2fe165b2006-02-28 19:25:31 -05004630 if ((ndlp->nlp_state != NLP_STE_UNMAPPED_NODE) &&
4631 (ndlp->nlp_state != NLP_STE_MAPPED_NODE)) {
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05004632 stat.un.b.lsRjtRsvd0 = 0;
4633 stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
4634 stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA;
4635 stat.un.b.vendorUnique = 0;
James Smart858c9f62007-06-17 19:56:39 -05004636 lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp,
4637 NULL);
dea31012005-04-17 16:05:31 -05004638 }
4639
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05004640 pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
4641 lp = (uint32_t *) pcmd->virt;
4642 rpl = (RPL *) (lp + 1);
4643
4644 maxsize = be32_to_cpu(rpl->maxsize);
4645
4646 /* We support only one port */
4647 if ((rpl->index == 0) &&
4648 ((maxsize == 0) ||
4649 ((maxsize * sizeof(uint32_t)) >= sizeof(RPL_RSP)))) {
4650 cmdsize = sizeof(uint32_t) + sizeof(RPL_RSP);
Jamie Wellnitz2fe165b2006-02-28 19:25:31 -05004651 } else {
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05004652 cmdsize = sizeof(uint32_t) + maxsize * sizeof(uint32_t);
4653 }
James Smart2e0fef82007-06-17 19:56:36 -05004654 lpfc_els_rsp_rpl_acc(vport, cmdsize, cmdiocb, ndlp);
dea31012005-04-17 16:05:31 -05004655
4656 return 0;
4657}
4658
James Smarte59058c2008-08-24 21:49:00 -04004659/**
4660 * lpfc_els_rcv_farp: Process an unsolicited farp request els command.
4661 * @vport: pointer to a virtual N_Port data structure.
4662 * @cmdiocb: pointer to lpfc command iocb data structure.
4663 * @ndlp: pointer to a node-list data structure.
4664 *
4665 * This routine processes Fibre Channel Address Resolution Protocol
4666 * (FARP) Request IOCB received as an ELS unsolicited event. Currently,
4667 * the lpfc driver only supports matching on WWPN or WWNN for FARP. As such,
4668 * FARP_MATCH_PORT flag and FARP_MATCH_NODE flag are checked against the
4669 * Match Flag in the FARP request IOCB: if FARP_MATCH_PORT flag is set, the
4670 * remote PortName is compared against the FC PortName stored in the @vport
4671 * data structure; if FARP_MATCH_NODE flag is set, the remote NodeName is
4672 * compared against the FC NodeName stored in the @vport data structure.
4673 * If any of these matches and the FARP_REQUEST_FARPR flag is set in the
4674 * FARP request IOCB Response Flag, the lpfc_issue_els_farpr() routine is
4675 * invoked to send out FARP Response to the remote node. Before sending the
4676 * FARP Response, however, the FARP_REQUEST_PLOGI flag is check in the FARP
4677 * request IOCB Response Flag and, if it is set, the lpfc_issue_els_plogi()
4678 * routine is invoked to log into the remote port first.
4679 *
4680 * Return code
4681 * 0 - Either the FARP Match Mode not supported or successfully processed
4682 **/
dea31012005-04-17 16:05:31 -05004683static int
James Smart2e0fef82007-06-17 19:56:36 -05004684lpfc_els_rcv_farp(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
4685 struct lpfc_nodelist *ndlp)
dea31012005-04-17 16:05:31 -05004686{
4687 struct lpfc_dmabuf *pcmd;
4688 uint32_t *lp;
4689 IOCB_t *icmd;
4690 FARP *fp;
4691 uint32_t cmd, cnt, did;
4692
4693 icmd = &cmdiocb->iocb;
4694 did = icmd->un.elsreq64.remoteID;
4695 pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
4696 lp = (uint32_t *) pcmd->virt;
4697
4698 cmd = *lp++;
4699 fp = (FARP *) lp;
dea31012005-04-17 16:05:31 -05004700 /* FARP-REQ received from DID <did> */
James Smarte8b62012007-08-02 11:10:09 -04004701 lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
4702 "0601 FARP-REQ received from DID x%x\n", did);
dea31012005-04-17 16:05:31 -05004703 /* We will only support match on WWPN or WWNN */
4704 if (fp->Mflags & ~(FARP_MATCH_NODE | FARP_MATCH_PORT)) {
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05004705 return 0;
dea31012005-04-17 16:05:31 -05004706 }
4707
4708 cnt = 0;
4709 /* If this FARP command is searching for my portname */
4710 if (fp->Mflags & FARP_MATCH_PORT) {
James Smart2e0fef82007-06-17 19:56:36 -05004711 if (memcmp(&fp->RportName, &vport->fc_portname,
James Smart92d7f7b2007-06-17 19:56:38 -05004712 sizeof(struct lpfc_name)) == 0)
dea31012005-04-17 16:05:31 -05004713 cnt = 1;
4714 }
4715
4716 /* If this FARP command is searching for my nodename */
4717 if (fp->Mflags & FARP_MATCH_NODE) {
James Smart2e0fef82007-06-17 19:56:36 -05004718 if (memcmp(&fp->RnodeName, &vport->fc_nodename,
James Smart92d7f7b2007-06-17 19:56:38 -05004719 sizeof(struct lpfc_name)) == 0)
dea31012005-04-17 16:05:31 -05004720 cnt = 1;
4721 }
4722
4723 if (cnt) {
4724 if ((ndlp->nlp_state == NLP_STE_UNMAPPED_NODE) ||
4725 (ndlp->nlp_state == NLP_STE_MAPPED_NODE)) {
4726 /* Log back into the node before sending the FARP. */
4727 if (fp->Rflags & FARP_REQUEST_PLOGI) {
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05004728 ndlp->nlp_prev_state = ndlp->nlp_state;
James Smart2e0fef82007-06-17 19:56:36 -05004729 lpfc_nlp_set_state(vport, ndlp,
James Smartde0c5b32007-04-25 09:52:27 -04004730 NLP_STE_PLOGI_ISSUE);
James Smart2e0fef82007-06-17 19:56:36 -05004731 lpfc_issue_els_plogi(vport, ndlp->nlp_DID, 0);
dea31012005-04-17 16:05:31 -05004732 }
4733
4734 /* Send a FARP response to that node */
James Smart2e0fef82007-06-17 19:56:36 -05004735 if (fp->Rflags & FARP_REQUEST_FARPR)
4736 lpfc_issue_els_farpr(vport, did, 0);
dea31012005-04-17 16:05:31 -05004737 }
4738 }
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05004739 return 0;
dea31012005-04-17 16:05:31 -05004740}
4741
James Smarte59058c2008-08-24 21:49:00 -04004742/**
4743 * lpfc_els_rcv_farpr: Process an unsolicited farp response iocb.
4744 * @vport: pointer to a host virtual N_Port data structure.
4745 * @cmdiocb: pointer to lpfc command iocb data structure.
4746 * @ndlp: pointer to a node-list data structure.
4747 *
4748 * This routine processes Fibre Channel Address Resolution Protocol
4749 * Response (FARPR) IOCB received as an ELS unsolicited event. It simply
4750 * invokes the lpfc_els_rsp_acc() routine to the remote node to accept
4751 * the FARP response request.
4752 *
4753 * Return code
4754 * 0 - Successfully processed FARPR IOCB (currently always return 0)
4755 **/
dea31012005-04-17 16:05:31 -05004756static int
James Smart2e0fef82007-06-17 19:56:36 -05004757lpfc_els_rcv_farpr(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
4758 struct lpfc_nodelist *ndlp)
dea31012005-04-17 16:05:31 -05004759{
4760 struct lpfc_dmabuf *pcmd;
4761 uint32_t *lp;
4762 IOCB_t *icmd;
4763 uint32_t cmd, did;
4764
4765 icmd = &cmdiocb->iocb;
4766 did = icmd->un.elsreq64.remoteID;
4767 pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
4768 lp = (uint32_t *) pcmd->virt;
4769
4770 cmd = *lp++;
4771 /* FARP-RSP received from DID <did> */
James Smarte8b62012007-08-02 11:10:09 -04004772 lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
4773 "0600 FARP-RSP received from DID x%x\n", did);
dea31012005-04-17 16:05:31 -05004774 /* ACCEPT the Farp resp request */
James Smart51ef4c22007-08-02 11:10:31 -04004775 lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL);
dea31012005-04-17 16:05:31 -05004776
4777 return 0;
4778}
4779
James Smarte59058c2008-08-24 21:49:00 -04004780/**
4781 * lpfc_els_rcv_fan: Process an unsolicited fan iocb command.
4782 * @vport: pointer to a host virtual N_Port data structure.
4783 * @cmdiocb: pointer to lpfc command iocb data structure.
4784 * @fan_ndlp: pointer to a node-list data structure.
4785 *
4786 * This routine processes a Fabric Address Notification (FAN) IOCB
4787 * command received as an ELS unsolicited event. The FAN ELS command will
4788 * only be processed on a physical port (i.e., the @vport represents the
4789 * physical port). The fabric NodeName and PortName from the FAN IOCB are
4790 * compared against those in the phba data structure. If any of those is
4791 * different, the lpfc_initial_flogi() routine is invoked to initialize
4792 * Fabric Login (FLOGI) to the fabric to start the discover over. Otherwise,
4793 * if both of those are identical, the lpfc_issue_fabric_reglogin() routine
4794 * is invoked to register login to the fabric.
4795 *
4796 * Return code
4797 * 0 - Successfully processed fan iocb (currently always return 0).
4798 **/
dea31012005-04-17 16:05:31 -05004799static int
James Smart2e0fef82007-06-17 19:56:36 -05004800lpfc_els_rcv_fan(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
4801 struct lpfc_nodelist *fan_ndlp)
dea31012005-04-17 16:05:31 -05004802{
James Smart2e0fef82007-06-17 19:56:36 -05004803 struct lpfc_hba *phba = vport->phba;
James Smart0d2b6b82008-06-14 22:52:47 -04004804 uint32_t *lp;
4805 FAN *fp;
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05004806
James Smart0d2b6b82008-06-14 22:52:47 -04004807 lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, "0265 FAN received\n");
4808 lp = (uint32_t *)((struct lpfc_dmabuf *)cmdiocb->context2)->virt;
4809 fp = (FAN *) ++lp;
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05004810 /* FAN received; Fan does not have a reply sequence */
James Smart0d2b6b82008-06-14 22:52:47 -04004811 if ((vport == phba->pport) &&
4812 (vport->port_state == LPFC_LOCAL_CFG_LINK)) {
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05004813 if ((memcmp(&phba->fc_fabparam.nodeName, &fp->FnodeName,
James Smart0d2b6b82008-06-14 22:52:47 -04004814 sizeof(struct lpfc_name))) ||
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05004815 (memcmp(&phba->fc_fabparam.portName, &fp->FportName,
James Smart0d2b6b82008-06-14 22:52:47 -04004816 sizeof(struct lpfc_name)))) {
4817 /* This port has switched fabrics. FLOGI is required */
James Smart2e0fef82007-06-17 19:56:36 -05004818 lpfc_initial_flogi(vport);
James Smart0d2b6b82008-06-14 22:52:47 -04004819 } else {
4820 /* FAN verified - skip FLOGI */
4821 vport->fc_myDID = vport->fc_prevDID;
4822 lpfc_issue_fabric_reglogin(vport);
dea31012005-04-17 16:05:31 -05004823 }
dea31012005-04-17 16:05:31 -05004824 }
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05004825 return 0;
dea31012005-04-17 16:05:31 -05004826}
4827
James Smarte59058c2008-08-24 21:49:00 -04004828/**
4829 * lpfc_els_timeout: Handler funciton to the els timer.
4830 * @ptr: holder for the timer function associated data.
4831 *
4832 * This routine is invoked by the ELS timer after timeout. It posts the ELS
4833 * timer timeout event by setting the WORKER_ELS_TMO bit to the work port
4834 * event bitmap and then invokes the lpfc_worker_wake_up() routine to wake
4835 * up the worker thread. It is for the worker thread to invoke the routine
4836 * lpfc_els_timeout_handler() to work on the posted event WORKER_ELS_TMO.
4837 **/
dea31012005-04-17 16:05:31 -05004838void
4839lpfc_els_timeout(unsigned long ptr)
4840{
James Smart2e0fef82007-06-17 19:56:36 -05004841 struct lpfc_vport *vport = (struct lpfc_vport *) ptr;
4842 struct lpfc_hba *phba = vport->phba;
James Smart5e9d9b82008-06-14 22:52:53 -04004843 uint32_t tmo_posted;
dea31012005-04-17 16:05:31 -05004844 unsigned long iflag;
4845
James Smart2e0fef82007-06-17 19:56:36 -05004846 spin_lock_irqsave(&vport->work_port_lock, iflag);
James Smart5e9d9b82008-06-14 22:52:53 -04004847 tmo_posted = vport->work_port_events & WORKER_ELS_TMO;
4848 if (!tmo_posted)
James Smart2e0fef82007-06-17 19:56:36 -05004849 vport->work_port_events |= WORKER_ELS_TMO;
James Smart5e9d9b82008-06-14 22:52:53 -04004850 spin_unlock_irqrestore(&vport->work_port_lock, iflag);
James Smart92d7f7b2007-06-17 19:56:38 -05004851
James Smart5e9d9b82008-06-14 22:52:53 -04004852 if (!tmo_posted)
4853 lpfc_worker_wake_up(phba);
dea31012005-04-17 16:05:31 -05004854 return;
4855}
4856
James Smarte59058c2008-08-24 21:49:00 -04004857/**
4858 * lpfc_els_timeout_handler: Process an els timeout event.
4859 * @vport: pointer to a virtual N_Port data structure.
4860 *
4861 * This routine is the actual handler function that processes an ELS timeout
4862 * event. It walks the ELS ring to get and abort all the IOCBs (except the
4863 * ABORT/CLOSE/FARP/FARPR/FDISC), which are associated with the @vport by
4864 * invoking the lpfc_sli_issue_abort_iotag() routine.
4865 **/
dea31012005-04-17 16:05:31 -05004866void
James Smart2e0fef82007-06-17 19:56:36 -05004867lpfc_els_timeout_handler(struct lpfc_vport *vport)
dea31012005-04-17 16:05:31 -05004868{
James Smart2e0fef82007-06-17 19:56:36 -05004869 struct lpfc_hba *phba = vport->phba;
dea31012005-04-17 16:05:31 -05004870 struct lpfc_sli_ring *pring;
4871 struct lpfc_iocbq *tmp_iocb, *piocb;
4872 IOCB_t *cmd = NULL;
4873 struct lpfc_dmabuf *pcmd;
James Smart2e0fef82007-06-17 19:56:36 -05004874 uint32_t els_command = 0;
dea31012005-04-17 16:05:31 -05004875 uint32_t timeout;
James Smart2e0fef82007-06-17 19:56:36 -05004876 uint32_t remote_ID = 0xffffffff;
dea31012005-04-17 16:05:31 -05004877
dea31012005-04-17 16:05:31 -05004878 /* If the timer is already canceled do nothing */
James Smart2e0fef82007-06-17 19:56:36 -05004879 if ((vport->work_port_events & WORKER_ELS_TMO) == 0) {
dea31012005-04-17 16:05:31 -05004880 return;
4881 }
James Smart2e0fef82007-06-17 19:56:36 -05004882 spin_lock_irq(&phba->hbalock);
dea31012005-04-17 16:05:31 -05004883 timeout = (uint32_t)(phba->fc_ratov << 1);
4884
4885 pring = &phba->sli.ring[LPFC_ELS_RING];
dea31012005-04-17 16:05:31 -05004886
4887 list_for_each_entry_safe(piocb, tmp_iocb, &pring->txcmplq, list) {
4888 cmd = &piocb->iocb;
4889
James Smart2e0fef82007-06-17 19:56:36 -05004890 if ((piocb->iocb_flag & LPFC_IO_LIBDFC) != 0 ||
4891 piocb->iocb.ulpCommand == CMD_ABORT_XRI_CN ||
4892 piocb->iocb.ulpCommand == CMD_CLOSE_XRI_CN)
dea31012005-04-17 16:05:31 -05004893 continue;
James Smart2e0fef82007-06-17 19:56:36 -05004894
4895 if (piocb->vport != vport)
4896 continue;
4897
dea31012005-04-17 16:05:31 -05004898 pcmd = (struct lpfc_dmabuf *) piocb->context2;
James Smart2e0fef82007-06-17 19:56:36 -05004899 if (pcmd)
4900 els_command = *(uint32_t *) (pcmd->virt);
dea31012005-04-17 16:05:31 -05004901
James Smart92d7f7b2007-06-17 19:56:38 -05004902 if (els_command == ELS_CMD_FARP ||
4903 els_command == ELS_CMD_FARPR ||
4904 els_command == ELS_CMD_FDISC)
dea31012005-04-17 16:05:31 -05004905 continue;
James Smart92d7f7b2007-06-17 19:56:38 -05004906
dea31012005-04-17 16:05:31 -05004907 if (piocb->drvrTimeout > 0) {
James Smart92d7f7b2007-06-17 19:56:38 -05004908 if (piocb->drvrTimeout >= timeout)
dea31012005-04-17 16:05:31 -05004909 piocb->drvrTimeout -= timeout;
James Smart92d7f7b2007-06-17 19:56:38 -05004910 else
dea31012005-04-17 16:05:31 -05004911 piocb->drvrTimeout = 0;
dea31012005-04-17 16:05:31 -05004912 continue;
4913 }
4914
James Smart2e0fef82007-06-17 19:56:36 -05004915 remote_ID = 0xffffffff;
4916 if (cmd->ulpCommand != CMD_GEN_REQUEST64_CR)
dea31012005-04-17 16:05:31 -05004917 remote_ID = cmd->un.elsreq64.remoteID;
James Smart2e0fef82007-06-17 19:56:36 -05004918 else {
4919 struct lpfc_nodelist *ndlp;
4920 ndlp = __lpfc_findnode_rpi(vport, cmd->ulpContext);
James Smart58da1ff2008-04-07 10:15:56 -04004921 if (ndlp && NLP_CHK_NODE_ACT(ndlp))
James Smart2e0fef82007-06-17 19:56:36 -05004922 remote_ID = ndlp->nlp_DID;
dea31012005-04-17 16:05:31 -05004923 }
James Smarte8b62012007-08-02 11:10:09 -04004924 lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
4925 "0127 ELS timeout Data: x%x x%x x%x "
4926 "x%x\n", els_command,
4927 remote_ID, cmd->ulpCommand, cmd->ulpIoTag);
James Smart07951072007-04-25 09:51:38 -04004928 lpfc_sli_issue_abort_iotag(phba, pring, piocb);
dea31012005-04-17 16:05:31 -05004929 }
James Smart2e0fef82007-06-17 19:56:36 -05004930 spin_unlock_irq(&phba->hbalock);
James Smart5a0e3262006-07-06 15:49:16 -04004931
James Smart2e0fef82007-06-17 19:56:36 -05004932 if (phba->sli.ring[LPFC_ELS_RING].txcmplq_cnt)
4933 mod_timer(&vport->els_tmofunc, jiffies + HZ * timeout);
dea31012005-04-17 16:05:31 -05004934}
4935
James Smarte59058c2008-08-24 21:49:00 -04004936/**
4937 * lpfc_els_flush_cmd: Clean up the outstanding els commands to a vport.
4938 * @vport: pointer to a host virtual N_Port data structure.
4939 *
4940 * This routine is used to clean up all the outstanding ELS commands on a
4941 * @vport. It first aborts the @vport by invoking lpfc_fabric_abort_vport()
4942 * routine. After that, it walks the ELS transmit queue to remove all the
4943 * IOCBs with the @vport other than the QUE_RING and ABORT/CLOSE IOCBs. For
4944 * the IOCBs with a non-NULL completion callback function, the callback
4945 * function will be invoked with the status set to IOSTAT_LOCAL_REJECT and
4946 * un.ulpWord[4] set to IOERR_SLI_ABORTED. For IOCBs with a NULL completion
4947 * callback function, the IOCB will simply be released. Finally, it walks
4948 * the ELS transmit completion queue to issue an abort IOCB to any transmit
4949 * completion queue IOCB that is associated with the @vport and is not
4950 * an IOCB from libdfc (i.e., the management plane IOCBs that are not
4951 * part of the discovery state machine) out to HBA by invoking the
4952 * lpfc_sli_issue_abort_iotag() routine. Note that this function issues the
4953 * abort IOCB to any transmit completion queueed IOCB, it does not guarantee
4954 * the IOCBs are aborted when this function returns.
4955 **/
dea31012005-04-17 16:05:31 -05004956void
James Smart2e0fef82007-06-17 19:56:36 -05004957lpfc_els_flush_cmd(struct lpfc_vport *vport)
dea31012005-04-17 16:05:31 -05004958{
James Smart2534ba72007-04-25 09:52:20 -04004959 LIST_HEAD(completions);
James Smart2e0fef82007-06-17 19:56:36 -05004960 struct lpfc_hba *phba = vport->phba;
James Smart329f9bc2007-04-25 09:53:01 -04004961 struct lpfc_sli_ring *pring = &phba->sli.ring[LPFC_ELS_RING];
dea31012005-04-17 16:05:31 -05004962 struct lpfc_iocbq *tmp_iocb, *piocb;
4963 IOCB_t *cmd = NULL;
James Smart92d7f7b2007-06-17 19:56:38 -05004964
4965 lpfc_fabric_abort_vport(vport);
dea31012005-04-17 16:05:31 -05004966
James Smart2e0fef82007-06-17 19:56:36 -05004967 spin_lock_irq(&phba->hbalock);
dea31012005-04-17 16:05:31 -05004968 list_for_each_entry_safe(piocb, tmp_iocb, &pring->txq, list) {
4969 cmd = &piocb->iocb;
4970
4971 if (piocb->iocb_flag & LPFC_IO_LIBDFC) {
4972 continue;
4973 }
4974
4975 /* Do not flush out the QUE_RING and ABORT/CLOSE iocbs */
James Smart329f9bc2007-04-25 09:53:01 -04004976 if (cmd->ulpCommand == CMD_QUE_RING_BUF_CN ||
4977 cmd->ulpCommand == CMD_QUE_RING_BUF64_CN ||
4978 cmd->ulpCommand == CMD_CLOSE_XRI_CN ||
4979 cmd->ulpCommand == CMD_ABORT_XRI_CN)
dea31012005-04-17 16:05:31 -05004980 continue;
dea31012005-04-17 16:05:31 -05004981
James Smart2e0fef82007-06-17 19:56:36 -05004982 if (piocb->vport != vport)
4983 continue;
4984
James Smart2534ba72007-04-25 09:52:20 -04004985 list_move_tail(&piocb->list, &completions);
James Smart1dcb58e2007-04-25 09:51:30 -04004986 pring->txq_cnt--;
dea31012005-04-17 16:05:31 -05004987 }
4988
4989 list_for_each_entry_safe(piocb, tmp_iocb, &pring->txcmplq, list) {
dea31012005-04-17 16:05:31 -05004990 if (piocb->iocb_flag & LPFC_IO_LIBDFC) {
4991 continue;
4992 }
dea31012005-04-17 16:05:31 -05004993
James Smart2e0fef82007-06-17 19:56:36 -05004994 if (piocb->vport != vport)
4995 continue;
4996
James Smart07951072007-04-25 09:51:38 -04004997 lpfc_sli_issue_abort_iotag(phba, pring, piocb);
dea31012005-04-17 16:05:31 -05004998 }
James Smart2e0fef82007-06-17 19:56:36 -05004999 spin_unlock_irq(&phba->hbalock);
James Smart2534ba72007-04-25 09:52:20 -04005000
James Smart2e0fef82007-06-17 19:56:36 -05005001 while (!list_empty(&completions)) {
James Smart2534ba72007-04-25 09:52:20 -04005002 piocb = list_get_first(&completions, struct lpfc_iocbq, list);
5003 cmd = &piocb->iocb;
James Smart92d7f7b2007-06-17 19:56:38 -05005004 list_del_init(&piocb->list);
James Smart2534ba72007-04-25 09:52:20 -04005005
James Smart2e0fef82007-06-17 19:56:36 -05005006 if (!piocb->iocb_cmpl)
5007 lpfc_sli_release_iocbq(phba, piocb);
5008 else {
James Smart2534ba72007-04-25 09:52:20 -04005009 cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
5010 cmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
5011 (piocb->iocb_cmpl) (phba, piocb, piocb);
James Smart2e0fef82007-06-17 19:56:36 -05005012 }
James Smart2534ba72007-04-25 09:52:20 -04005013 }
5014
dea31012005-04-17 16:05:31 -05005015 return;
5016}
5017
James Smarte59058c2008-08-24 21:49:00 -04005018/**
5019 * lpfc_els_flush_all_cmd: Clean up all the outstanding els commands to a HBA.
5020 * @phba: pointer to lpfc hba data structure.
5021 *
5022 * This routine is used to clean up all the outstanding ELS commands on a
5023 * @phba. It first aborts the @phba by invoking the lpfc_fabric_abort_hba()
5024 * routine. After that, it walks the ELS transmit queue to remove all the
5025 * IOCBs to the @phba other than the QUE_RING and ABORT/CLOSE IOCBs. For
5026 * the IOCBs with the completion callback function associated, the callback
5027 * function will be invoked with the status set to IOSTAT_LOCAL_REJECT and
5028 * un.ulpWord[4] set to IOERR_SLI_ABORTED. For IOCBs without the completion
5029 * callback function associated, the IOCB will simply be released. Finally,
5030 * it walks the ELS transmit completion queue to issue an abort IOCB to any
5031 * transmit completion queue IOCB that is not an IOCB from libdfc (i.e., the
5032 * management plane IOCBs that are not part of the discovery state machine)
5033 * out to HBA by invoking the lpfc_sli_issue_abort_iotag() routine.
5034 **/
James Smart549e55c2007-08-02 11:09:51 -04005035void
5036lpfc_els_flush_all_cmd(struct lpfc_hba *phba)
5037{
5038 LIST_HEAD(completions);
5039 struct lpfc_sli_ring *pring = &phba->sli.ring[LPFC_ELS_RING];
5040 struct lpfc_iocbq *tmp_iocb, *piocb;
5041 IOCB_t *cmd = NULL;
5042
5043 lpfc_fabric_abort_hba(phba);
5044 spin_lock_irq(&phba->hbalock);
5045 list_for_each_entry_safe(piocb, tmp_iocb, &pring->txq, list) {
5046 cmd = &piocb->iocb;
5047 if (piocb->iocb_flag & LPFC_IO_LIBDFC)
5048 continue;
5049 /* Do not flush out the QUE_RING and ABORT/CLOSE iocbs */
5050 if (cmd->ulpCommand == CMD_QUE_RING_BUF_CN ||
5051 cmd->ulpCommand == CMD_QUE_RING_BUF64_CN ||
5052 cmd->ulpCommand == CMD_CLOSE_XRI_CN ||
5053 cmd->ulpCommand == CMD_ABORT_XRI_CN)
5054 continue;
5055 list_move_tail(&piocb->list, &completions);
5056 pring->txq_cnt--;
5057 }
5058 list_for_each_entry_safe(piocb, tmp_iocb, &pring->txcmplq, list) {
5059 if (piocb->iocb_flag & LPFC_IO_LIBDFC)
5060 continue;
5061 lpfc_sli_issue_abort_iotag(phba, pring, piocb);
5062 }
5063 spin_unlock_irq(&phba->hbalock);
5064 while (!list_empty(&completions)) {
5065 piocb = list_get_first(&completions, struct lpfc_iocbq, list);
5066 cmd = &piocb->iocb;
5067 list_del_init(&piocb->list);
5068 if (!piocb->iocb_cmpl)
5069 lpfc_sli_release_iocbq(phba, piocb);
5070 else {
5071 cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
5072 cmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
5073 (piocb->iocb_cmpl) (phba, piocb, piocb);
5074 }
5075 }
5076 return;
5077}
5078
James Smarte59058c2008-08-24 21:49:00 -04005079/**
5080 * lpfc_els_unsol_buffer: Process an unsolicited event data buffer.
5081 * @phba: pointer to lpfc hba data structure.
5082 * @pring: pointer to a SLI ring.
5083 * @vport: pointer to a host virtual N_Port data structure.
5084 * @elsiocb: pointer to lpfc els command iocb data structure.
5085 *
5086 * This routine is used for processing the IOCB associated with a unsolicited
5087 * event. It first determines whether there is an existing ndlp that matches
5088 * the DID from the unsolicited IOCB. If not, it will create a new one with
5089 * the DID from the unsolicited IOCB. The ELS command from the unsolicited
5090 * IOCB is then used to invoke the proper routine and to set up proper state
5091 * of the discovery state machine.
5092 **/
James Smarted957682007-06-17 19:56:37 -05005093static void
5094lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
James Smart92d7f7b2007-06-17 19:56:38 -05005095 struct lpfc_vport *vport, struct lpfc_iocbq *elsiocb)
dea31012005-04-17 16:05:31 -05005096{
James Smart87af33f2007-10-27 13:37:43 -04005097 struct Scsi_Host *shost;
dea31012005-04-17 16:05:31 -05005098 struct lpfc_nodelist *ndlp;
dea31012005-04-17 16:05:31 -05005099 struct ls_rjt stat;
James Smart92d7f7b2007-06-17 19:56:38 -05005100 uint32_t *payload;
James Smart2e0fef82007-06-17 19:56:36 -05005101 uint32_t cmd, did, newnode, rjt_err = 0;
James Smarted957682007-06-17 19:56:37 -05005102 IOCB_t *icmd = &elsiocb->iocb;
dea31012005-04-17 16:05:31 -05005103
James Smarte47c9092008-02-08 18:49:26 -05005104 if (!vport || !(elsiocb->context2))
dea31012005-04-17 16:05:31 -05005105 goto dropit;
James Smart2e0fef82007-06-17 19:56:36 -05005106
dea31012005-04-17 16:05:31 -05005107 newnode = 0;
James Smart92d7f7b2007-06-17 19:56:38 -05005108 payload = ((struct lpfc_dmabuf *)elsiocb->context2)->virt;
5109 cmd = *payload;
James Smarted957682007-06-17 19:56:37 -05005110 if ((phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) == 0)
James Smart495a7142008-06-14 22:52:59 -04005111 lpfc_post_buffer(phba, pring, 1);
dea31012005-04-17 16:05:31 -05005112
James Smart858c9f62007-06-17 19:56:39 -05005113 did = icmd->un.rcvels.remoteID;
5114 if (icmd->ulpStatus) {
5115 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
5116 "RCV Unsol ELS: status:x%x/x%x did:x%x",
5117 icmd->ulpStatus, icmd->un.ulpWord[4], did);
dea31012005-04-17 16:05:31 -05005118 goto dropit;
James Smart858c9f62007-06-17 19:56:39 -05005119 }
dea31012005-04-17 16:05:31 -05005120
5121 /* Check to see if link went down during discovery */
James Smarted957682007-06-17 19:56:37 -05005122 if (lpfc_els_chk_latt(vport))
dea31012005-04-17 16:05:31 -05005123 goto dropit;
dea31012005-04-17 16:05:31 -05005124
James Smart92d7f7b2007-06-17 19:56:38 -05005125 /* Ignore traffic recevied during vport shutdown. */
5126 if (vport->load_flag & FC_UNLOADING)
5127 goto dropit;
5128
James Smart2e0fef82007-06-17 19:56:36 -05005129 ndlp = lpfc_findnode_did(vport, did);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05005130 if (!ndlp) {
dea31012005-04-17 16:05:31 -05005131 /* Cannot find existing Fabric ndlp, so allocate a new one */
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05005132 ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL);
James Smarted957682007-06-17 19:56:37 -05005133 if (!ndlp)
dea31012005-04-17 16:05:31 -05005134 goto dropit;
dea31012005-04-17 16:05:31 -05005135
James Smart2e0fef82007-06-17 19:56:36 -05005136 lpfc_nlp_init(vport, ndlp, did);
James Smart98c9ea52007-10-27 13:37:33 -04005137 lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
dea31012005-04-17 16:05:31 -05005138 newnode = 1;
James Smarte47c9092008-02-08 18:49:26 -05005139 if ((did & Fabric_DID_MASK) == Fabric_DID_MASK)
dea31012005-04-17 16:05:31 -05005140 ndlp->nlp_type |= NLP_FABRIC;
James Smart58da1ff2008-04-07 10:15:56 -04005141 } else if (!NLP_CHK_NODE_ACT(ndlp)) {
5142 ndlp = lpfc_enable_node(vport, ndlp,
5143 NLP_STE_UNUSED_NODE);
5144 if (!ndlp)
5145 goto dropit;
5146 lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
5147 newnode = 1;
5148 if ((did & Fabric_DID_MASK) == Fabric_DID_MASK)
5149 ndlp->nlp_type |= NLP_FABRIC;
5150 } else if (ndlp->nlp_state == NLP_STE_UNUSED_NODE) {
5151 /* This is similar to the new node path */
5152 ndlp = lpfc_nlp_get(ndlp);
5153 if (!ndlp)
5154 goto dropit;
5155 lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
5156 newnode = 1;
James Smart87af33f2007-10-27 13:37:43 -04005157 }
dea31012005-04-17 16:05:31 -05005158
5159 phba->fc_stat.elsRcvFrame++;
James Smart329f9bc2007-04-25 09:53:01 -04005160 if (elsiocb->context1)
5161 lpfc_nlp_put(elsiocb->context1);
James Smarte47c9092008-02-08 18:49:26 -05005162
James Smart329f9bc2007-04-25 09:53:01 -04005163 elsiocb->context1 = lpfc_nlp_get(ndlp);
James Smart2e0fef82007-06-17 19:56:36 -05005164 elsiocb->vport = vport;
dea31012005-04-17 16:05:31 -05005165
5166 if ((cmd & ELS_CMD_MASK) == ELS_CMD_RSCN) {
5167 cmd &= ELS_CMD_MASK;
5168 }
5169 /* ELS command <elsCmd> received from NPORT <did> */
James Smarte8b62012007-08-02 11:10:09 -04005170 lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
5171 "0112 ELS command x%x received from NPORT x%x "
5172 "Data: x%x\n", cmd, did, vport->port_state);
dea31012005-04-17 16:05:31 -05005173 switch (cmd) {
5174 case ELS_CMD_PLOGI:
James Smart858c9f62007-06-17 19:56:39 -05005175 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
5176 "RCV PLOGI: did:x%x/ste:x%x flg:x%x",
5177 did, vport->port_state, ndlp->nlp_flag);
5178
dea31012005-04-17 16:05:31 -05005179 phba->fc_stat.elsRcvPLOGI++;
James Smart858c9f62007-06-17 19:56:39 -05005180 ndlp = lpfc_plogi_confirm_nport(phba, payload, ndlp);
5181
5182 if (vport->port_state < LPFC_DISC_AUTH) {
James Smart1b32f6a2008-02-08 18:49:39 -05005183 if (!(phba->pport->fc_flag & FC_PT2PT) ||
5184 (phba->pport->fc_flag & FC_PT2PT_PLOGI)) {
5185 rjt_err = LSRJT_UNABLE_TPC;
5186 break;
5187 }
5188 /* We get here, and drop thru, if we are PT2PT with
5189 * another NPort and the other side has initiated
5190 * the PLOGI before responding to our FLOGI.
5191 */
dea31012005-04-17 16:05:31 -05005192 }
James Smart87af33f2007-10-27 13:37:43 -04005193
5194 shost = lpfc_shost_from_vport(vport);
5195 spin_lock_irq(shost->host_lock);
5196 ndlp->nlp_flag &= ~NLP_TARGET_REMOVE;
5197 spin_unlock_irq(shost->host_lock);
5198
James Smart2e0fef82007-06-17 19:56:36 -05005199 lpfc_disc_state_machine(vport, ndlp, elsiocb,
5200 NLP_EVT_RCV_PLOGI);
James Smart858c9f62007-06-17 19:56:39 -05005201
dea31012005-04-17 16:05:31 -05005202 break;
5203 case ELS_CMD_FLOGI:
James Smart858c9f62007-06-17 19:56:39 -05005204 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
5205 "RCV FLOGI: did:x%x/ste:x%x flg:x%x",
5206 did, vport->port_state, ndlp->nlp_flag);
5207
dea31012005-04-17 16:05:31 -05005208 phba->fc_stat.elsRcvFLOGI++;
James Smart51ef4c22007-08-02 11:10:31 -04005209 lpfc_els_rcv_flogi(vport, elsiocb, ndlp);
James Smart87af33f2007-10-27 13:37:43 -04005210 if (newnode)
James Smart98c9ea52007-10-27 13:37:33 -04005211 lpfc_nlp_put(ndlp);
dea31012005-04-17 16:05:31 -05005212 break;
5213 case ELS_CMD_LOGO:
James Smart858c9f62007-06-17 19:56:39 -05005214 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
5215 "RCV LOGO: did:x%x/ste:x%x flg:x%x",
5216 did, vport->port_state, ndlp->nlp_flag);
5217
dea31012005-04-17 16:05:31 -05005218 phba->fc_stat.elsRcvLOGO++;
James Smart2e0fef82007-06-17 19:56:36 -05005219 if (vport->port_state < LPFC_DISC_AUTH) {
James Smart858c9f62007-06-17 19:56:39 -05005220 rjt_err = LSRJT_UNABLE_TPC;
dea31012005-04-17 16:05:31 -05005221 break;
5222 }
James Smart2e0fef82007-06-17 19:56:36 -05005223 lpfc_disc_state_machine(vport, ndlp, elsiocb, NLP_EVT_RCV_LOGO);
dea31012005-04-17 16:05:31 -05005224 break;
5225 case ELS_CMD_PRLO:
James Smart858c9f62007-06-17 19:56:39 -05005226 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
5227 "RCV PRLO: did:x%x/ste:x%x flg:x%x",
5228 did, vport->port_state, ndlp->nlp_flag);
5229
dea31012005-04-17 16:05:31 -05005230 phba->fc_stat.elsRcvPRLO++;
James Smart2e0fef82007-06-17 19:56:36 -05005231 if (vport->port_state < LPFC_DISC_AUTH) {
James Smart858c9f62007-06-17 19:56:39 -05005232 rjt_err = LSRJT_UNABLE_TPC;
dea31012005-04-17 16:05:31 -05005233 break;
5234 }
James Smart2e0fef82007-06-17 19:56:36 -05005235 lpfc_disc_state_machine(vport, ndlp, elsiocb, NLP_EVT_RCV_PRLO);
dea31012005-04-17 16:05:31 -05005236 break;
5237 case ELS_CMD_RSCN:
5238 phba->fc_stat.elsRcvRSCN++;
James Smart51ef4c22007-08-02 11:10:31 -04005239 lpfc_els_rcv_rscn(vport, elsiocb, ndlp);
James Smart87af33f2007-10-27 13:37:43 -04005240 if (newnode)
James Smart98c9ea52007-10-27 13:37:33 -04005241 lpfc_nlp_put(ndlp);
dea31012005-04-17 16:05:31 -05005242 break;
5243 case ELS_CMD_ADISC:
James Smart858c9f62007-06-17 19:56:39 -05005244 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
5245 "RCV ADISC: did:x%x/ste:x%x flg:x%x",
5246 did, vport->port_state, ndlp->nlp_flag);
5247
dea31012005-04-17 16:05:31 -05005248 phba->fc_stat.elsRcvADISC++;
James Smart2e0fef82007-06-17 19:56:36 -05005249 if (vport->port_state < LPFC_DISC_AUTH) {
James Smart858c9f62007-06-17 19:56:39 -05005250 rjt_err = LSRJT_UNABLE_TPC;
dea31012005-04-17 16:05:31 -05005251 break;
5252 }
James Smart2e0fef82007-06-17 19:56:36 -05005253 lpfc_disc_state_machine(vport, ndlp, elsiocb,
5254 NLP_EVT_RCV_ADISC);
dea31012005-04-17 16:05:31 -05005255 break;
5256 case ELS_CMD_PDISC:
James Smart858c9f62007-06-17 19:56:39 -05005257 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
5258 "RCV PDISC: did:x%x/ste:x%x flg:x%x",
5259 did, vport->port_state, ndlp->nlp_flag);
5260
dea31012005-04-17 16:05:31 -05005261 phba->fc_stat.elsRcvPDISC++;
James Smart2e0fef82007-06-17 19:56:36 -05005262 if (vport->port_state < LPFC_DISC_AUTH) {
James Smart858c9f62007-06-17 19:56:39 -05005263 rjt_err = LSRJT_UNABLE_TPC;
dea31012005-04-17 16:05:31 -05005264 break;
5265 }
James Smart2e0fef82007-06-17 19:56:36 -05005266 lpfc_disc_state_machine(vport, ndlp, elsiocb,
5267 NLP_EVT_RCV_PDISC);
dea31012005-04-17 16:05:31 -05005268 break;
5269 case ELS_CMD_FARPR:
James Smart858c9f62007-06-17 19:56:39 -05005270 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
5271 "RCV FARPR: did:x%x/ste:x%x flg:x%x",
5272 did, vport->port_state, ndlp->nlp_flag);
5273
dea31012005-04-17 16:05:31 -05005274 phba->fc_stat.elsRcvFARPR++;
James Smart2e0fef82007-06-17 19:56:36 -05005275 lpfc_els_rcv_farpr(vport, elsiocb, ndlp);
dea31012005-04-17 16:05:31 -05005276 break;
5277 case ELS_CMD_FARP:
James Smart858c9f62007-06-17 19:56:39 -05005278 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
5279 "RCV FARP: did:x%x/ste:x%x flg:x%x",
5280 did, vport->port_state, ndlp->nlp_flag);
5281
dea31012005-04-17 16:05:31 -05005282 phba->fc_stat.elsRcvFARP++;
James Smart2e0fef82007-06-17 19:56:36 -05005283 lpfc_els_rcv_farp(vport, elsiocb, ndlp);
dea31012005-04-17 16:05:31 -05005284 break;
5285 case ELS_CMD_FAN:
James Smart858c9f62007-06-17 19:56:39 -05005286 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
5287 "RCV FAN: did:x%x/ste:x%x flg:x%x",
5288 did, vport->port_state, ndlp->nlp_flag);
5289
dea31012005-04-17 16:05:31 -05005290 phba->fc_stat.elsRcvFAN++;
James Smart2e0fef82007-06-17 19:56:36 -05005291 lpfc_els_rcv_fan(vport, elsiocb, ndlp);
dea31012005-04-17 16:05:31 -05005292 break;
dea31012005-04-17 16:05:31 -05005293 case ELS_CMD_PRLI:
James Smart858c9f62007-06-17 19:56:39 -05005294 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
5295 "RCV PRLI: did:x%x/ste:x%x flg:x%x",
5296 did, vport->port_state, ndlp->nlp_flag);
5297
dea31012005-04-17 16:05:31 -05005298 phba->fc_stat.elsRcvPRLI++;
James Smart2e0fef82007-06-17 19:56:36 -05005299 if (vport->port_state < LPFC_DISC_AUTH) {
James Smart858c9f62007-06-17 19:56:39 -05005300 rjt_err = LSRJT_UNABLE_TPC;
dea31012005-04-17 16:05:31 -05005301 break;
5302 }
James Smart2e0fef82007-06-17 19:56:36 -05005303 lpfc_disc_state_machine(vport, ndlp, elsiocb, NLP_EVT_RCV_PRLI);
dea31012005-04-17 16:05:31 -05005304 break;
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05005305 case ELS_CMD_LIRR:
James Smart858c9f62007-06-17 19:56:39 -05005306 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
5307 "RCV LIRR: did:x%x/ste:x%x flg:x%x",
5308 did, vport->port_state, ndlp->nlp_flag);
5309
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05005310 phba->fc_stat.elsRcvLIRR++;
James Smart2e0fef82007-06-17 19:56:36 -05005311 lpfc_els_rcv_lirr(vport, elsiocb, ndlp);
James Smart87af33f2007-10-27 13:37:43 -04005312 if (newnode)
James Smart98c9ea52007-10-27 13:37:33 -04005313 lpfc_nlp_put(ndlp);
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05005314 break;
5315 case ELS_CMD_RPS:
James Smart858c9f62007-06-17 19:56:39 -05005316 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
5317 "RCV RPS: did:x%x/ste:x%x flg:x%x",
5318 did, vport->port_state, ndlp->nlp_flag);
5319
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05005320 phba->fc_stat.elsRcvRPS++;
James Smart2e0fef82007-06-17 19:56:36 -05005321 lpfc_els_rcv_rps(vport, elsiocb, ndlp);
James Smart87af33f2007-10-27 13:37:43 -04005322 if (newnode)
James Smart98c9ea52007-10-27 13:37:33 -04005323 lpfc_nlp_put(ndlp);
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05005324 break;
5325 case ELS_CMD_RPL:
James Smart858c9f62007-06-17 19:56:39 -05005326 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
5327 "RCV RPL: did:x%x/ste:x%x flg:x%x",
5328 did, vport->port_state, ndlp->nlp_flag);
5329
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05005330 phba->fc_stat.elsRcvRPL++;
James Smart2e0fef82007-06-17 19:56:36 -05005331 lpfc_els_rcv_rpl(vport, elsiocb, ndlp);
James Smart87af33f2007-10-27 13:37:43 -04005332 if (newnode)
James Smart98c9ea52007-10-27 13:37:33 -04005333 lpfc_nlp_put(ndlp);
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05005334 break;
dea31012005-04-17 16:05:31 -05005335 case ELS_CMD_RNID:
James Smart858c9f62007-06-17 19:56:39 -05005336 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
5337 "RCV RNID: did:x%x/ste:x%x flg:x%x",
5338 did, vport->port_state, ndlp->nlp_flag);
5339
dea31012005-04-17 16:05:31 -05005340 phba->fc_stat.elsRcvRNID++;
James Smart2e0fef82007-06-17 19:56:36 -05005341 lpfc_els_rcv_rnid(vport, elsiocb, ndlp);
James Smart87af33f2007-10-27 13:37:43 -04005342 if (newnode)
James Smart98c9ea52007-10-27 13:37:33 -04005343 lpfc_nlp_put(ndlp);
dea31012005-04-17 16:05:31 -05005344 break;
5345 default:
James Smart858c9f62007-06-17 19:56:39 -05005346 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
5347 "RCV ELS cmd: cmd:x%x did:x%x/ste:x%x",
5348 cmd, did, vport->port_state);
5349
dea31012005-04-17 16:05:31 -05005350 /* Unsupported ELS command, reject */
James Smart858c9f62007-06-17 19:56:39 -05005351 rjt_err = LSRJT_INVALID_CMD;
dea31012005-04-17 16:05:31 -05005352
5353 /* Unknown ELS command <elsCmd> received from NPORT <did> */
James Smarte8b62012007-08-02 11:10:09 -04005354 lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
5355 "0115 Unknown ELS command x%x "
5356 "received from NPORT x%x\n", cmd, did);
James Smart87af33f2007-10-27 13:37:43 -04005357 if (newnode)
James Smart98c9ea52007-10-27 13:37:33 -04005358 lpfc_nlp_put(ndlp);
dea31012005-04-17 16:05:31 -05005359 break;
5360 }
5361
5362 /* check if need to LS_RJT received ELS cmd */
5363 if (rjt_err) {
James Smart92d7f7b2007-06-17 19:56:38 -05005364 memset(&stat, 0, sizeof(stat));
James Smart858c9f62007-06-17 19:56:39 -05005365 stat.un.b.lsRjtRsnCode = rjt_err;
James.Smart@Emulex.Com1f679ca2005-06-25 10:34:27 -04005366 stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE;
James Smart858c9f62007-06-17 19:56:39 -05005367 lpfc_els_rsp_reject(vport, stat.un.lsRjtError, elsiocb, ndlp,
5368 NULL);
dea31012005-04-17 16:05:31 -05005369 }
5370
James Smarted957682007-06-17 19:56:37 -05005371 return;
5372
5373dropit:
James Smart98c9ea52007-10-27 13:37:33 -04005374 if (vport && !(vport->load_flag & FC_UNLOADING))
5375 lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
James Smarte8b62012007-08-02 11:10:09 -04005376 "(%d):0111 Dropping received ELS cmd "
James Smarted957682007-06-17 19:56:37 -05005377 "Data: x%x x%x x%x\n",
James Smart98c9ea52007-10-27 13:37:33 -04005378 vport->vpi, icmd->ulpStatus,
James Smarte8b62012007-08-02 11:10:09 -04005379 icmd->un.ulpWord[4], icmd->ulpTimeout);
James Smarted957682007-06-17 19:56:37 -05005380 phba->fc_stat.elsRcvDrop++;
5381}
5382
James Smarte59058c2008-08-24 21:49:00 -04005383/**
5384 * lpfc_find_vport_by_vpid: Find a vport on a HBA through vport identifier.
5385 * @phba: pointer to lpfc hba data structure.
5386 * @vpi: host virtual N_Port identifier.
5387 *
5388 * This routine finds a vport on a HBA (referred by @phba) through a
5389 * @vpi. The function walks the HBA's vport list and returns the address
5390 * of the vport with the matching @vpi.
5391 *
5392 * Return code
5393 * NULL - No vport with the matching @vpi found
5394 * Otherwise - Address to the vport with the matching @vpi.
5395 **/
James Smart92d7f7b2007-06-17 19:56:38 -05005396static struct lpfc_vport *
5397lpfc_find_vport_by_vpid(struct lpfc_hba *phba, uint16_t vpi)
5398{
5399 struct lpfc_vport *vport;
James Smart549e55c2007-08-02 11:09:51 -04005400 unsigned long flags;
James Smart92d7f7b2007-06-17 19:56:38 -05005401
James Smart549e55c2007-08-02 11:09:51 -04005402 spin_lock_irqsave(&phba->hbalock, flags);
James Smart92d7f7b2007-06-17 19:56:38 -05005403 list_for_each_entry(vport, &phba->port_list, listentry) {
James Smart549e55c2007-08-02 11:09:51 -04005404 if (vport->vpi == vpi) {
5405 spin_unlock_irqrestore(&phba->hbalock, flags);
James Smart92d7f7b2007-06-17 19:56:38 -05005406 return vport;
James Smart549e55c2007-08-02 11:09:51 -04005407 }
James Smart92d7f7b2007-06-17 19:56:38 -05005408 }
James Smart549e55c2007-08-02 11:09:51 -04005409 spin_unlock_irqrestore(&phba->hbalock, flags);
James Smart92d7f7b2007-06-17 19:56:38 -05005410 return NULL;
5411}
James Smarted957682007-06-17 19:56:37 -05005412
James Smarte59058c2008-08-24 21:49:00 -04005413/**
5414 * lpfc_els_unsol_event: Process an unsolicited event from an els sli ring.
5415 * @phba: pointer to lpfc hba data structure.
5416 * @pring: pointer to a SLI ring.
5417 * @elsiocb: pointer to lpfc els iocb data structure.
5418 *
5419 * This routine is used to process an unsolicited event received from a SLI
5420 * (Service Level Interface) ring. The actual processing of the data buffer
5421 * associated with the unsolicited event is done by invoking the routine
5422 * lpfc_els_unsol_buffer() after properly set up the iocb buffer from the
5423 * SLI ring on which the unsolicited event was received.
5424 **/
James Smarted957682007-06-17 19:56:37 -05005425void
5426lpfc_els_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
5427 struct lpfc_iocbq *elsiocb)
5428{
5429 struct lpfc_vport *vport = phba->pport;
James Smarted957682007-06-17 19:56:37 -05005430 IOCB_t *icmd = &elsiocb->iocb;
James Smarted957682007-06-17 19:56:37 -05005431 dma_addr_t paddr;
James Smart92d7f7b2007-06-17 19:56:38 -05005432 struct lpfc_dmabuf *bdeBuf1 = elsiocb->context2;
5433 struct lpfc_dmabuf *bdeBuf2 = elsiocb->context3;
James Smarted957682007-06-17 19:56:37 -05005434
James Smart92d7f7b2007-06-17 19:56:38 -05005435 elsiocb->context2 = NULL;
5436 elsiocb->context3 = NULL;
5437
5438 if (icmd->ulpStatus == IOSTAT_NEED_BUFFER) {
5439 lpfc_sli_hbqbuf_add_hbqs(phba, LPFC_ELS_HBQ);
5440 } else if (icmd->ulpStatus == IOSTAT_LOCAL_REJECT &&
5441 (icmd->un.ulpWord[4] & 0xff) == IOERR_RCV_BUFFER_WAITING) {
James Smarted957682007-06-17 19:56:37 -05005442 phba->fc_stat.NoRcvBuf++;
5443 /* Not enough posted buffers; Try posting more buffers */
James Smart92d7f7b2007-06-17 19:56:38 -05005444 if (!(phba->sli3_options & LPFC_SLI3_HBQ_ENABLED))
James Smart495a7142008-06-14 22:52:59 -04005445 lpfc_post_buffer(phba, pring, 0);
James Smarted957682007-06-17 19:56:37 -05005446 return;
5447 }
5448
James Smart92d7f7b2007-06-17 19:56:38 -05005449 if ((phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) &&
5450 (icmd->ulpCommand == CMD_IOCB_RCV_ELS64_CX ||
5451 icmd->ulpCommand == CMD_IOCB_RCV_SEQ64_CX)) {
5452 if (icmd->unsli3.rcvsli3.vpi == 0xffff)
5453 vport = phba->pport;
5454 else {
5455 uint16_t vpi = icmd->unsli3.rcvsli3.vpi;
5456 vport = lpfc_find_vport_by_vpid(phba, vpi);
5457 }
5458 }
James Smart7f5f3d02008-02-08 18:50:14 -05005459 /* If there are no BDEs associated
5460 * with this IOCB, there is nothing to do.
5461 */
James Smarted957682007-06-17 19:56:37 -05005462 if (icmd->ulpBdeCount == 0)
5463 return;
5464
James Smart7f5f3d02008-02-08 18:50:14 -05005465 /* type of ELS cmd is first 32bit word
5466 * in packet
5467 */
James Smarted957682007-06-17 19:56:37 -05005468 if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) {
James Smart92d7f7b2007-06-17 19:56:38 -05005469 elsiocb->context2 = bdeBuf1;
James Smarted957682007-06-17 19:56:37 -05005470 } else {
5471 paddr = getPaddr(icmd->un.cont64[0].addrHigh,
5472 icmd->un.cont64[0].addrLow);
James Smart92d7f7b2007-06-17 19:56:38 -05005473 elsiocb->context2 = lpfc_sli_ringpostbuf_get(phba, pring,
5474 paddr);
James Smarted957682007-06-17 19:56:37 -05005475 }
5476
James Smart92d7f7b2007-06-17 19:56:38 -05005477 lpfc_els_unsol_buffer(phba, pring, vport, elsiocb);
5478 /*
5479 * The different unsolicited event handlers would tell us
5480 * if they are done with "mp" by setting context2 to NULL.
5481 */
James Smart329f9bc2007-04-25 09:53:01 -04005482 lpfc_nlp_put(elsiocb->context1);
5483 elsiocb->context1 = NULL;
dea31012005-04-17 16:05:31 -05005484 if (elsiocb->context2) {
James Smart92d7f7b2007-06-17 19:56:38 -05005485 lpfc_in_buf_free(phba, (struct lpfc_dmabuf *)elsiocb->context2);
5486 elsiocb->context2 = NULL;
dea31012005-04-17 16:05:31 -05005487 }
James Smarted957682007-06-17 19:56:37 -05005488
5489 /* RCV_ELS64_CX provide for 2 BDEs - process 2nd if included */
James Smart92d7f7b2007-06-17 19:56:38 -05005490 if ((phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) &&
James Smarted957682007-06-17 19:56:37 -05005491 icmd->ulpBdeCount == 2) {
James Smart92d7f7b2007-06-17 19:56:38 -05005492 elsiocb->context2 = bdeBuf2;
5493 lpfc_els_unsol_buffer(phba, pring, vport, elsiocb);
James Smarted957682007-06-17 19:56:37 -05005494 /* free mp if we are done with it */
5495 if (elsiocb->context2) {
James Smart92d7f7b2007-06-17 19:56:38 -05005496 lpfc_in_buf_free(phba, elsiocb->context2);
5497 elsiocb->context2 = NULL;
James Smarted957682007-06-17 19:56:37 -05005498 }
dea31012005-04-17 16:05:31 -05005499 }
dea31012005-04-17 16:05:31 -05005500}
James Smart92d7f7b2007-06-17 19:56:38 -05005501
James Smarte59058c2008-08-24 21:49:00 -04005502/**
5503 * lpfc_do_scr_ns_plogi: Issue a plogi to the name server for scr.
5504 * @phba: pointer to lpfc hba data structure.
5505 * @vport: pointer to a virtual N_Port data structure.
5506 *
5507 * This routine issues a Port Login (PLOGI) to the Name Server with
5508 * State Change Request (SCR) for a @vport. This routine will create an
5509 * ndlp for the Name Server associated to the @vport if such node does
5510 * not already exist. The PLOGI to Name Server is issued by invoking the
5511 * lpfc_issue_els_plogi() routine. If Fabric-Device Management Interface
5512 * (FDMI) is configured to the @vport, a FDMI node will be created and
5513 * the PLOGI to FDMI is issued by invoking lpfc_issue_els_plogi() routine.
5514 **/
James Smart92d7f7b2007-06-17 19:56:38 -05005515void
5516lpfc_do_scr_ns_plogi(struct lpfc_hba *phba, struct lpfc_vport *vport)
5517{
5518 struct lpfc_nodelist *ndlp, *ndlp_fdmi;
5519
5520 ndlp = lpfc_findnode_did(vport, NameServer_DID);
5521 if (!ndlp) {
5522 ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL);
5523 if (!ndlp) {
5524 if (phba->fc_topology == TOPOLOGY_LOOP) {
5525 lpfc_disc_start(vport);
5526 return;
5527 }
5528 lpfc_vport_set_state(vport, FC_VPORT_FAILED);
James Smarte8b62012007-08-02 11:10:09 -04005529 lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
5530 "0251 NameServer login: no memory\n");
James Smart92d7f7b2007-06-17 19:56:38 -05005531 return;
5532 }
5533 lpfc_nlp_init(vport, ndlp, NameServer_DID);
James Smarte47c9092008-02-08 18:49:26 -05005534 } else if (!NLP_CHK_NODE_ACT(ndlp)) {
5535 ndlp = lpfc_enable_node(vport, ndlp, NLP_STE_UNUSED_NODE);
5536 if (!ndlp) {
5537 if (phba->fc_topology == TOPOLOGY_LOOP) {
5538 lpfc_disc_start(vport);
5539 return;
5540 }
5541 lpfc_vport_set_state(vport, FC_VPORT_FAILED);
5542 lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
5543 "0348 NameServer login: node freed\n");
5544 return;
5545 }
James Smart92d7f7b2007-06-17 19:56:38 -05005546 }
James Smart58da1ff2008-04-07 10:15:56 -04005547 ndlp->nlp_type |= NLP_FABRIC;
James Smart92d7f7b2007-06-17 19:56:38 -05005548
5549 lpfc_nlp_set_state(vport, ndlp, NLP_STE_PLOGI_ISSUE);
5550
5551 if (lpfc_issue_els_plogi(vport, ndlp->nlp_DID, 0)) {
5552 lpfc_vport_set_state(vport, FC_VPORT_FAILED);
James Smarte8b62012007-08-02 11:10:09 -04005553 lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
5554 "0252 Cannot issue NameServer login\n");
James Smart92d7f7b2007-06-17 19:56:38 -05005555 return;
5556 }
5557
James Smart3de2a652007-08-02 11:09:59 -04005558 if (vport->cfg_fdmi_on) {
James Smart92d7f7b2007-06-17 19:56:38 -05005559 ndlp_fdmi = mempool_alloc(phba->nlp_mem_pool,
5560 GFP_KERNEL);
5561 if (ndlp_fdmi) {
5562 lpfc_nlp_init(vport, ndlp_fdmi, FDMI_DID);
5563 ndlp_fdmi->nlp_type |= NLP_FABRIC;
James Smart58da1ff2008-04-07 10:15:56 -04005564 lpfc_nlp_set_state(vport, ndlp_fdmi,
5565 NLP_STE_PLOGI_ISSUE);
James Smart92d7f7b2007-06-17 19:56:38 -05005566 lpfc_issue_els_plogi(vport, ndlp_fdmi->nlp_DID,
5567 0);
5568 }
5569 }
5570 return;
5571}
5572
James Smarte59058c2008-08-24 21:49:00 -04005573/**
5574 * lpfc_cmpl_reg_new_vport: Completion callback function to register new vport.
5575 * @phba: pointer to lpfc hba data structure.
5576 * @pmb: pointer to the driver internal queue element for mailbox command.
5577 *
5578 * This routine is the completion callback function to register new vport
5579 * mailbox command. If the new vport mailbox command completes successfully,
5580 * the fabric registration login shall be performed on physical port (the
5581 * new vport created is actually a physical port, with VPI 0) or the port
5582 * login to Name Server for State Change Request (SCR) will be performed
5583 * on virtual port (real virtual port, with VPI greater than 0).
5584 **/
James Smart92d7f7b2007-06-17 19:56:38 -05005585static void
5586lpfc_cmpl_reg_new_vport(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
5587{
5588 struct lpfc_vport *vport = pmb->vport;
5589 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
5590 struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) pmb->context2;
5591 MAILBOX_t *mb = &pmb->mb;
5592
James Smart09372822008-01-11 01:52:54 -05005593 spin_lock_irq(shost->host_lock);
James Smart92d7f7b2007-06-17 19:56:38 -05005594 vport->fc_flag &= ~FC_VPORT_NEEDS_REG_VPI;
James Smart09372822008-01-11 01:52:54 -05005595 spin_unlock_irq(shost->host_lock);
James Smart92d7f7b2007-06-17 19:56:38 -05005596
5597 if (mb->mbxStatus) {
James Smarte8b62012007-08-02 11:10:09 -04005598 lpfc_printf_vlog(vport, KERN_ERR, LOG_MBOX,
5599 "0915 Register VPI failed: 0x%x\n",
5600 mb->mbxStatus);
James Smart92d7f7b2007-06-17 19:56:38 -05005601
5602 switch (mb->mbxStatus) {
5603 case 0x11: /* unsupported feature */
5604 case 0x9603: /* max_vpi exceeded */
James Smart7f5f3d02008-02-08 18:50:14 -05005605 case 0x9602: /* Link event since CLEAR_LA */
James Smart92d7f7b2007-06-17 19:56:38 -05005606 /* giving up on vport registration */
5607 lpfc_vport_set_state(vport, FC_VPORT_FAILED);
5608 spin_lock_irq(shost->host_lock);
5609 vport->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP);
5610 spin_unlock_irq(shost->host_lock);
5611 lpfc_can_disctmo(vport);
5612 break;
5613 default:
5614 /* Try to recover from this error */
5615 lpfc_mbx_unreg_vpi(vport);
James Smart09372822008-01-11 01:52:54 -05005616 spin_lock_irq(shost->host_lock);
James Smart92d7f7b2007-06-17 19:56:38 -05005617 vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI;
James Smart09372822008-01-11 01:52:54 -05005618 spin_unlock_irq(shost->host_lock);
James Smart7f5f3d02008-02-08 18:50:14 -05005619 if (vport->port_type == LPFC_PHYSICAL_PORT)
5620 lpfc_initial_flogi(vport);
5621 else
5622 lpfc_initial_fdisc(vport);
James Smart92d7f7b2007-06-17 19:56:38 -05005623 break;
5624 }
5625
5626 } else {
5627 if (vport == phba->pport)
5628 lpfc_issue_fabric_reglogin(vport);
5629 else
5630 lpfc_do_scr_ns_plogi(phba, vport);
5631 }
James Smartfa4066b2008-01-11 01:53:27 -05005632
5633 /* Now, we decrement the ndlp reference count held for this
5634 * callback function
5635 */
5636 lpfc_nlp_put(ndlp);
5637
James Smart92d7f7b2007-06-17 19:56:38 -05005638 mempool_free(pmb, phba->mbox_mem_pool);
5639 return;
5640}
5641
James Smarte59058c2008-08-24 21:49:00 -04005642/**
5643 * lpfc_register_new_vport: Register a new vport with a HBA.
5644 * @phba: pointer to lpfc hba data structure.
5645 * @vport: pointer to a host virtual N_Port data structure.
5646 * @ndlp: pointer to a node-list data structure.
5647 *
5648 * This routine registers the @vport as a new virtual port with a HBA.
5649 * It is done through a registering vpi mailbox command.
5650 **/
Adrian Bunka6ababd2007-11-05 18:07:33 +01005651static void
James Smart92d7f7b2007-06-17 19:56:38 -05005652lpfc_register_new_vport(struct lpfc_hba *phba, struct lpfc_vport *vport,
5653 struct lpfc_nodelist *ndlp)
5654{
James Smart09372822008-01-11 01:52:54 -05005655 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
James Smart92d7f7b2007-06-17 19:56:38 -05005656 LPFC_MBOXQ_t *mbox;
5657
5658 mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
5659 if (mbox) {
5660 lpfc_reg_vpi(phba, vport->vpi, vport->fc_myDID, mbox);
5661 mbox->vport = vport;
5662 mbox->context2 = lpfc_nlp_get(ndlp);
5663 mbox->mbox_cmpl = lpfc_cmpl_reg_new_vport;
James Smart0b727fe2007-10-27 13:37:25 -04005664 if (lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT)
James Smart92d7f7b2007-06-17 19:56:38 -05005665 == MBX_NOT_FINISHED) {
James Smartfa4066b2008-01-11 01:53:27 -05005666 /* mailbox command not success, decrement ndlp
5667 * reference count for this command
5668 */
5669 lpfc_nlp_put(ndlp);
James Smart92d7f7b2007-06-17 19:56:38 -05005670 mempool_free(mbox, phba->mbox_mem_pool);
James Smart92d7f7b2007-06-17 19:56:38 -05005671
James Smarte8b62012007-08-02 11:10:09 -04005672 lpfc_printf_vlog(vport, KERN_ERR, LOG_MBOX,
5673 "0253 Register VPI: Can't send mbox\n");
James Smartfa4066b2008-01-11 01:53:27 -05005674 goto mbox_err_exit;
James Smart92d7f7b2007-06-17 19:56:38 -05005675 }
5676 } else {
James Smarte8b62012007-08-02 11:10:09 -04005677 lpfc_printf_vlog(vport, KERN_ERR, LOG_MBOX,
5678 "0254 Register VPI: no memory\n");
James Smartfa4066b2008-01-11 01:53:27 -05005679 goto mbox_err_exit;
James Smart92d7f7b2007-06-17 19:56:38 -05005680 }
James Smartfa4066b2008-01-11 01:53:27 -05005681 return;
5682
5683mbox_err_exit:
5684 lpfc_vport_set_state(vport, FC_VPORT_FAILED);
5685 spin_lock_irq(shost->host_lock);
5686 vport->fc_flag &= ~FC_VPORT_NEEDS_REG_VPI;
5687 spin_unlock_irq(shost->host_lock);
5688 return;
James Smart92d7f7b2007-06-17 19:56:38 -05005689}
5690
James Smarte59058c2008-08-24 21:49:00 -04005691/**
5692 * lpfc_cmpl_els_fdisc: Completion function for fdisc iocb command.
5693 * @phba: pointer to lpfc hba data structure.
5694 * @cmdiocb: pointer to lpfc command iocb data structure.
5695 * @rspiocb: pointer to lpfc response iocb data structure.
5696 *
5697 * This routine is the completion callback function to a Fabric Discover
5698 * (FDISC) ELS command. Since all the FDISC ELS commands are issued
5699 * single threaded, each FDISC completion callback function will reset
5700 * the discovery timer for all vports such that the timers will not get
5701 * unnecessary timeout. The function checks the FDISC IOCB status. If error
5702 * detected, the vport will be set to FC_VPORT_FAILED state. Otherwise,the
5703 * vport will set to FC_VPORT_ACTIVE state. It then checks whether the DID
5704 * assigned to the vport has been changed with the completion of the FDISC
5705 * command. If so, both RPI (Remote Port Index) and VPI (Virtual Port Index)
5706 * are unregistered from the HBA, and then the lpfc_register_new_vport()
5707 * routine is invoked to register new vport with the HBA. Otherwise, the
5708 * lpfc_do_scr_ns_plogi() routine is invoked to issue a PLOGI to the Name
5709 * Server for State Change Request (SCR).
5710 **/
James Smart92d7f7b2007-06-17 19:56:38 -05005711static void
5712lpfc_cmpl_els_fdisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
5713 struct lpfc_iocbq *rspiocb)
5714{
5715 struct lpfc_vport *vport = cmdiocb->vport;
5716 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
5717 struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) cmdiocb->context1;
5718 struct lpfc_nodelist *np;
5719 struct lpfc_nodelist *next_np;
5720 IOCB_t *irsp = &rspiocb->iocb;
5721 struct lpfc_iocbq *piocb;
5722
James Smarte8b62012007-08-02 11:10:09 -04005723 lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
5724 "0123 FDISC completes. x%x/x%x prevDID: x%x\n",
5725 irsp->ulpStatus, irsp->un.ulpWord[4],
5726 vport->fc_prevDID);
James Smart92d7f7b2007-06-17 19:56:38 -05005727 /* Since all FDISCs are being single threaded, we
5728 * must reset the discovery timer for ALL vports
5729 * waiting to send FDISC when one completes.
5730 */
5731 list_for_each_entry(piocb, &phba->fabric_iocb_list, list) {
5732 lpfc_set_disctmo(piocb->vport);
5733 }
5734
James Smart858c9f62007-06-17 19:56:39 -05005735 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
5736 "FDISC cmpl: status:x%x/x%x prevdid:x%x",
5737 irsp->ulpStatus, irsp->un.ulpWord[4], vport->fc_prevDID);
5738
James Smart92d7f7b2007-06-17 19:56:38 -05005739 if (irsp->ulpStatus) {
5740 /* Check for retry */
5741 if (lpfc_els_retry(phba, cmdiocb, rspiocb))
5742 goto out;
James Smart92d7f7b2007-06-17 19:56:38 -05005743 /* FDISC failed */
James Smarte8b62012007-08-02 11:10:09 -04005744 lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
5745 "0124 FDISC failed. (%d/%d)\n",
5746 irsp->ulpStatus, irsp->un.ulpWord[4]);
James Smart92d7f7b2007-06-17 19:56:38 -05005747 if (vport->fc_vport->vport_state == FC_VPORT_INITIALIZING)
5748 lpfc_vport_set_state(vport, FC_VPORT_FAILED);
James Smart92d7f7b2007-06-17 19:56:38 -05005749 lpfc_nlp_put(ndlp);
5750 /* giving up on FDISC. Cancel discovery timer */
5751 lpfc_can_disctmo(vport);
5752 } else {
5753 spin_lock_irq(shost->host_lock);
5754 vport->fc_flag |= FC_FABRIC;
5755 if (vport->phba->fc_topology == TOPOLOGY_LOOP)
5756 vport->fc_flag |= FC_PUBLIC_LOOP;
5757 spin_unlock_irq(shost->host_lock);
5758
5759 vport->fc_myDID = irsp->un.ulpWord[4] & Mask_DID;
5760 lpfc_vport_set_state(vport, FC_VPORT_ACTIVE);
5761 if ((vport->fc_prevDID != vport->fc_myDID) &&
5762 !(vport->fc_flag & FC_VPORT_NEEDS_REG_VPI)) {
5763 /* If our NportID changed, we need to ensure all
5764 * remaining NPORTs get unreg_login'ed so we can
5765 * issue unreg_vpi.
5766 */
5767 list_for_each_entry_safe(np, next_np,
5768 &vport->fc_nodes, nlp_listp) {
James Smarte47c9092008-02-08 18:49:26 -05005769 if (!NLP_CHK_NODE_ACT(ndlp) ||
5770 (np->nlp_state != NLP_STE_NPR_NODE) ||
5771 !(np->nlp_flag & NLP_NPR_ADISC))
James Smart92d7f7b2007-06-17 19:56:38 -05005772 continue;
5773 spin_lock_irq(shost->host_lock);
5774 np->nlp_flag &= ~NLP_NPR_ADISC;
5775 spin_unlock_irq(shost->host_lock);
5776 lpfc_unreg_rpi(vport, np);
5777 }
5778 lpfc_mbx_unreg_vpi(vport);
James Smart09372822008-01-11 01:52:54 -05005779 spin_lock_irq(shost->host_lock);
James Smart92d7f7b2007-06-17 19:56:38 -05005780 vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI;
James Smart09372822008-01-11 01:52:54 -05005781 spin_unlock_irq(shost->host_lock);
James Smart92d7f7b2007-06-17 19:56:38 -05005782 }
5783
5784 if (vport->fc_flag & FC_VPORT_NEEDS_REG_VPI)
5785 lpfc_register_new_vport(phba, vport, ndlp);
5786 else
5787 lpfc_do_scr_ns_plogi(phba, vport);
5788
James Smartfa4066b2008-01-11 01:53:27 -05005789 /* Unconditionaly kick off releasing fabric node for vports */
5790 lpfc_nlp_put(ndlp);
James Smart92d7f7b2007-06-17 19:56:38 -05005791 }
5792
5793out:
5794 lpfc_els_free_iocb(phba, cmdiocb);
5795}
5796
James Smarte59058c2008-08-24 21:49:00 -04005797/**
5798 * lpfc_issue_els_fdisc: Issue a fdisc iocb command.
5799 * @vport: pointer to a virtual N_Port data structure.
5800 * @ndlp: pointer to a node-list data structure.
5801 * @retry: number of retries to the command IOCB.
5802 *
5803 * This routine prepares and issues a Fabric Discover (FDISC) IOCB to
5804 * a remote node (@ndlp) off a @vport. It uses the lpfc_issue_fabric_iocb()
5805 * routine to issue the IOCB, which makes sure only one outstanding fabric
5806 * IOCB will be sent off HBA at any given time.
5807 *
5808 * Note that, in lpfc_prep_els_iocb() routine, the reference count of ndlp
5809 * will be incremented by 1 for holding the ndlp and the reference to ndlp
5810 * will be stored into the context1 field of the IOCB for the completion
5811 * callback function to the FDISC ELS command.
5812 *
5813 * Return code
5814 * 0 - Successfully issued fdisc iocb command
5815 * 1 - Failed to issue fdisc iocb command
5816 **/
Adrian Bunka6ababd2007-11-05 18:07:33 +01005817static int
James Smart92d7f7b2007-06-17 19:56:38 -05005818lpfc_issue_els_fdisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
5819 uint8_t retry)
5820{
5821 struct lpfc_hba *phba = vport->phba;
5822 IOCB_t *icmd;
5823 struct lpfc_iocbq *elsiocb;
5824 struct serv_parm *sp;
5825 uint8_t *pcmd;
5826 uint16_t cmdsize;
5827 int did = ndlp->nlp_DID;
5828 int rc;
James Smart92d7f7b2007-06-17 19:56:38 -05005829
5830 cmdsize = (sizeof(uint32_t) + sizeof(struct serv_parm));
5831 elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp, did,
5832 ELS_CMD_FDISC);
5833 if (!elsiocb) {
James Smart92d7f7b2007-06-17 19:56:38 -05005834 lpfc_vport_set_state(vport, FC_VPORT_FAILED);
James Smarte8b62012007-08-02 11:10:09 -04005835 lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
5836 "0255 Issue FDISC: no IOCB\n");
James Smart92d7f7b2007-06-17 19:56:38 -05005837 return 1;
5838 }
5839
5840 icmd = &elsiocb->iocb;
5841 icmd->un.elsreq64.myID = 0;
5842 icmd->un.elsreq64.fl = 1;
5843
5844 /* For FDISC, Let FDISC rsp set the NPortID for this VPI */
5845 icmd->ulpCt_h = 1;
5846 icmd->ulpCt_l = 0;
5847
5848 pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
5849 *((uint32_t *) (pcmd)) = ELS_CMD_FDISC;
5850 pcmd += sizeof(uint32_t); /* CSP Word 1 */
5851 memcpy(pcmd, &vport->phba->pport->fc_sparam, sizeof(struct serv_parm));
5852 sp = (struct serv_parm *) pcmd;
5853 /* Setup CSPs accordingly for Fabric */
5854 sp->cmn.e_d_tov = 0;
5855 sp->cmn.w2.r_a_tov = 0;
5856 sp->cls1.classValid = 0;
5857 sp->cls2.seqDelivery = 1;
5858 sp->cls3.seqDelivery = 1;
5859
5860 pcmd += sizeof(uint32_t); /* CSP Word 2 */
5861 pcmd += sizeof(uint32_t); /* CSP Word 3 */
5862 pcmd += sizeof(uint32_t); /* CSP Word 4 */
5863 pcmd += sizeof(uint32_t); /* Port Name */
5864 memcpy(pcmd, &vport->fc_portname, 8);
5865 pcmd += sizeof(uint32_t); /* Node Name */
5866 pcmd += sizeof(uint32_t); /* Node Name */
5867 memcpy(pcmd, &vport->fc_nodename, 8);
5868
5869 lpfc_set_disctmo(vport);
5870
5871 phba->fc_stat.elsXmitFDISC++;
5872 elsiocb->iocb_cmpl = lpfc_cmpl_els_fdisc;
5873
James Smart858c9f62007-06-17 19:56:39 -05005874 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
5875 "Issue FDISC: did:x%x",
5876 did, 0, 0);
5877
James Smart92d7f7b2007-06-17 19:56:38 -05005878 rc = lpfc_issue_fabric_iocb(phba, elsiocb);
5879 if (rc == IOCB_ERROR) {
5880 lpfc_els_free_iocb(phba, elsiocb);
James Smart92d7f7b2007-06-17 19:56:38 -05005881 lpfc_vport_set_state(vport, FC_VPORT_FAILED);
James Smarte8b62012007-08-02 11:10:09 -04005882 lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
5883 "0256 Issue FDISC: Cannot send IOCB\n");
James Smart92d7f7b2007-06-17 19:56:38 -05005884 return 1;
5885 }
5886 lpfc_vport_set_state(vport, FC_VPORT_INITIALIZING);
5887 vport->port_state = LPFC_FDISC;
5888 return 0;
5889}
5890
James Smarte59058c2008-08-24 21:49:00 -04005891/**
5892 * lpfc_cmpl_els_npiv_logo: Completion function with vport logo.
5893 * @phba: pointer to lpfc hba data structure.
5894 * @cmdiocb: pointer to lpfc command iocb data structure.
5895 * @rspiocb: pointer to lpfc response iocb data structure.
5896 *
5897 * This routine is the completion callback function to the issuing of a LOGO
5898 * ELS command off a vport. It frees the command IOCB and then decrement the
5899 * reference count held on ndlp for this completion function, indicating that
5900 * the reference to the ndlp is no long needed. Note that the
5901 * lpfc_els_free_iocb() routine decrements the ndlp reference held for this
5902 * callback function and an additional explicit ndlp reference decrementation
5903 * will trigger the actual release of the ndlp.
5904 **/
James Smart92d7f7b2007-06-17 19:56:38 -05005905static void
5906lpfc_cmpl_els_npiv_logo(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
5907 struct lpfc_iocbq *rspiocb)
5908{
5909 struct lpfc_vport *vport = cmdiocb->vport;
James Smart858c9f62007-06-17 19:56:39 -05005910 IOCB_t *irsp;
James Smarte47c9092008-02-08 18:49:26 -05005911 struct lpfc_nodelist *ndlp;
5912 ndlp = (struct lpfc_nodelist *)cmdiocb->context1;
James Smart858c9f62007-06-17 19:56:39 -05005913
5914 irsp = &rspiocb->iocb;
5915 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
5916 "LOGO npiv cmpl: status:x%x/x%x did:x%x",
5917 irsp->ulpStatus, irsp->un.ulpWord[4], irsp->un.rcvels.remoteID);
James Smart92d7f7b2007-06-17 19:56:38 -05005918
5919 lpfc_els_free_iocb(phba, cmdiocb);
5920 vport->unreg_vpi_cmpl = VPORT_ERROR;
James Smarte47c9092008-02-08 18:49:26 -05005921
5922 /* Trigger the release of the ndlp after logo */
5923 lpfc_nlp_put(ndlp);
James Smart92d7f7b2007-06-17 19:56:38 -05005924}
5925
James Smarte59058c2008-08-24 21:49:00 -04005926/**
5927 * lpfc_issue_els_npiv_logo: Issue a logo off a vport.
5928 * @vport: pointer to a virtual N_Port data structure.
5929 * @ndlp: pointer to a node-list data structure.
5930 *
5931 * This routine issues a LOGO ELS command to an @ndlp off a @vport.
5932 *
5933 * Note that, in lpfc_prep_els_iocb() routine, the reference count of ndlp
5934 * will be incremented by 1 for holding the ndlp and the reference to ndlp
5935 * will be stored into the context1 field of the IOCB for the completion
5936 * callback function to the LOGO ELS command.
5937 *
5938 * Return codes
5939 * 0 - Successfully issued logo off the @vport
5940 * 1 - Failed to issue logo off the @vport
5941 **/
James Smart92d7f7b2007-06-17 19:56:38 -05005942int
5943lpfc_issue_els_npiv_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
5944{
5945 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
5946 struct lpfc_hba *phba = vport->phba;
5947 struct lpfc_sli_ring *pring = &phba->sli.ring[LPFC_ELS_RING];
5948 IOCB_t *icmd;
5949 struct lpfc_iocbq *elsiocb;
5950 uint8_t *pcmd;
5951 uint16_t cmdsize;
5952
5953 cmdsize = 2 * sizeof(uint32_t) + sizeof(struct lpfc_name);
5954 elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, 0, ndlp, ndlp->nlp_DID,
5955 ELS_CMD_LOGO);
5956 if (!elsiocb)
5957 return 1;
5958
5959 icmd = &elsiocb->iocb;
5960 pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
5961 *((uint32_t *) (pcmd)) = ELS_CMD_LOGO;
5962 pcmd += sizeof(uint32_t);
5963
5964 /* Fill in LOGO payload */
5965 *((uint32_t *) (pcmd)) = be32_to_cpu(vport->fc_myDID);
5966 pcmd += sizeof(uint32_t);
5967 memcpy(pcmd, &vport->fc_portname, sizeof(struct lpfc_name));
5968
James Smart858c9f62007-06-17 19:56:39 -05005969 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
5970 "Issue LOGO npiv did:x%x flg:x%x",
5971 ndlp->nlp_DID, ndlp->nlp_flag, 0);
5972
James Smart92d7f7b2007-06-17 19:56:38 -05005973 elsiocb->iocb_cmpl = lpfc_cmpl_els_npiv_logo;
5974 spin_lock_irq(shost->host_lock);
5975 ndlp->nlp_flag |= NLP_LOGO_SND;
5976 spin_unlock_irq(shost->host_lock);
5977 if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) {
5978 spin_lock_irq(shost->host_lock);
5979 ndlp->nlp_flag &= ~NLP_LOGO_SND;
5980 spin_unlock_irq(shost->host_lock);
5981 lpfc_els_free_iocb(phba, elsiocb);
5982 return 1;
5983 }
5984 return 0;
5985}
5986
James Smarte59058c2008-08-24 21:49:00 -04005987/**
5988 * lpfc_fabric_block_timeout: Handler function to the fabric block timer.
5989 * @ptr: holder for the timer function associated data.
5990 *
5991 * This routine is invoked by the fabric iocb block timer after
5992 * timeout. It posts the fabric iocb block timeout event by setting the
5993 * WORKER_FABRIC_BLOCK_TMO bit to work port event bitmap and then invokes
5994 * lpfc_worker_wake_up() routine to wake up the worker thread. It is for
5995 * the worker thread to invoke the lpfc_unblock_fabric_iocbs() on the
5996 * posted event WORKER_FABRIC_BLOCK_TMO.
5997 **/
James Smart92d7f7b2007-06-17 19:56:38 -05005998void
5999lpfc_fabric_block_timeout(unsigned long ptr)
6000{
6001 struct lpfc_hba *phba = (struct lpfc_hba *) ptr;
6002 unsigned long iflags;
6003 uint32_t tmo_posted;
James Smart5e9d9b82008-06-14 22:52:53 -04006004
James Smart92d7f7b2007-06-17 19:56:38 -05006005 spin_lock_irqsave(&phba->pport->work_port_lock, iflags);
6006 tmo_posted = phba->pport->work_port_events & WORKER_FABRIC_BLOCK_TMO;
6007 if (!tmo_posted)
6008 phba->pport->work_port_events |= WORKER_FABRIC_BLOCK_TMO;
6009 spin_unlock_irqrestore(&phba->pport->work_port_lock, iflags);
6010
James Smart5e9d9b82008-06-14 22:52:53 -04006011 if (!tmo_posted)
6012 lpfc_worker_wake_up(phba);
6013 return;
James Smart92d7f7b2007-06-17 19:56:38 -05006014}
6015
James Smarte59058c2008-08-24 21:49:00 -04006016/**
6017 * lpfc_resume_fabric_iocbs: Issue a fabric iocb from driver internal list.
6018 * @phba: pointer to lpfc hba data structure.
6019 *
6020 * This routine issues one fabric iocb from the driver internal list to
6021 * the HBA. It first checks whether it's ready to issue one fabric iocb to
6022 * the HBA (whether there is no outstanding fabric iocb). If so, it shall
6023 * remove one pending fabric iocb from the driver internal list and invokes
6024 * lpfc_sli_issue_iocb() routine to send the fabric iocb to the HBA.
6025 **/
James Smart92d7f7b2007-06-17 19:56:38 -05006026static void
6027lpfc_resume_fabric_iocbs(struct lpfc_hba *phba)
6028{
6029 struct lpfc_iocbq *iocb;
6030 unsigned long iflags;
6031 int ret;
6032 struct lpfc_sli_ring *pring = &phba->sli.ring[LPFC_ELS_RING];
6033 IOCB_t *cmd;
6034
6035repeat:
6036 iocb = NULL;
6037 spin_lock_irqsave(&phba->hbalock, iflags);
James Smart7f5f3d02008-02-08 18:50:14 -05006038 /* Post any pending iocb to the SLI layer */
James Smart92d7f7b2007-06-17 19:56:38 -05006039 if (atomic_read(&phba->fabric_iocb_count) == 0) {
6040 list_remove_head(&phba->fabric_iocb_list, iocb, typeof(*iocb),
6041 list);
6042 if (iocb)
James Smart7f5f3d02008-02-08 18:50:14 -05006043 /* Increment fabric iocb count to hold the position */
James Smart92d7f7b2007-06-17 19:56:38 -05006044 atomic_inc(&phba->fabric_iocb_count);
6045 }
6046 spin_unlock_irqrestore(&phba->hbalock, iflags);
6047 if (iocb) {
6048 iocb->fabric_iocb_cmpl = iocb->iocb_cmpl;
6049 iocb->iocb_cmpl = lpfc_cmpl_fabric_iocb;
6050 iocb->iocb_flag |= LPFC_IO_FABRIC;
6051
James Smart858c9f62007-06-17 19:56:39 -05006052 lpfc_debugfs_disc_trc(iocb->vport, LPFC_DISC_TRC_ELS_CMD,
6053 "Fabric sched1: ste:x%x",
6054 iocb->vport->port_state, 0, 0);
6055
James Smart92d7f7b2007-06-17 19:56:38 -05006056 ret = lpfc_sli_issue_iocb(phba, pring, iocb, 0);
6057
6058 if (ret == IOCB_ERROR) {
6059 iocb->iocb_cmpl = iocb->fabric_iocb_cmpl;
6060 iocb->fabric_iocb_cmpl = NULL;
6061 iocb->iocb_flag &= ~LPFC_IO_FABRIC;
6062 cmd = &iocb->iocb;
6063 cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
6064 cmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
6065 iocb->iocb_cmpl(phba, iocb, iocb);
6066
6067 atomic_dec(&phba->fabric_iocb_count);
6068 goto repeat;
6069 }
6070 }
6071
6072 return;
6073}
6074
James Smarte59058c2008-08-24 21:49:00 -04006075/**
6076 * lpfc_unblock_fabric_iocbs: Unblock issuing fabric iocb command.
6077 * @phba: pointer to lpfc hba data structure.
6078 *
6079 * This routine unblocks the issuing fabric iocb command. The function
6080 * will clear the fabric iocb block bit and then invoke the routine
6081 * lpfc_resume_fabric_iocbs() to issue one of the pending fabric iocb
6082 * from the driver internal fabric iocb list.
6083 **/
James Smart92d7f7b2007-06-17 19:56:38 -05006084void
6085lpfc_unblock_fabric_iocbs(struct lpfc_hba *phba)
6086{
6087 clear_bit(FABRIC_COMANDS_BLOCKED, &phba->bit_flags);
6088
6089 lpfc_resume_fabric_iocbs(phba);
6090 return;
6091}
6092
James Smarte59058c2008-08-24 21:49:00 -04006093/**
6094 * lpfc_block_fabric_iocbs: Block issuing fabric iocb command.
6095 * @phba: pointer to lpfc hba data structure.
6096 *
6097 * This routine blocks the issuing fabric iocb for a specified amount of
6098 * time (currently 100 ms). This is done by set the fabric iocb block bit
6099 * and set up a timeout timer for 100ms. When the block bit is set, no more
6100 * fabric iocb will be issued out of the HBA.
6101 **/
James Smart92d7f7b2007-06-17 19:56:38 -05006102static void
6103lpfc_block_fabric_iocbs(struct lpfc_hba *phba)
6104{
6105 int blocked;
6106
6107 blocked = test_and_set_bit(FABRIC_COMANDS_BLOCKED, &phba->bit_flags);
James Smart7f5f3d02008-02-08 18:50:14 -05006108 /* Start a timer to unblock fabric iocbs after 100ms */
James Smart92d7f7b2007-06-17 19:56:38 -05006109 if (!blocked)
6110 mod_timer(&phba->fabric_block_timer, jiffies + HZ/10 );
6111
6112 return;
6113}
6114
James Smarte59058c2008-08-24 21:49:00 -04006115/**
6116 * lpfc_cmpl_fabric_iocb: Completion callback function for fabric iocb.
6117 * @phba: pointer to lpfc hba data structure.
6118 * @cmdiocb: pointer to lpfc command iocb data structure.
6119 * @rspiocb: pointer to lpfc response iocb data structure.
6120 *
6121 * This routine is the callback function that is put to the fabric iocb's
6122 * callback function pointer (iocb->iocb_cmpl). The original iocb's callback
6123 * function pointer has been stored in iocb->fabric_iocb_cmpl. This callback
6124 * function first restores and invokes the original iocb's callback function
6125 * and then invokes the lpfc_resume_fabric_iocbs() routine to issue the next
6126 * fabric bound iocb from the driver internal fabric iocb list onto the wire.
6127 **/
James Smart92d7f7b2007-06-17 19:56:38 -05006128static void
6129lpfc_cmpl_fabric_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
6130 struct lpfc_iocbq *rspiocb)
6131{
6132 struct ls_rjt stat;
6133
6134 if ((cmdiocb->iocb_flag & LPFC_IO_FABRIC) != LPFC_IO_FABRIC)
6135 BUG();
6136
6137 switch (rspiocb->iocb.ulpStatus) {
6138 case IOSTAT_NPORT_RJT:
6139 case IOSTAT_FABRIC_RJT:
6140 if (rspiocb->iocb.un.ulpWord[4] & RJT_UNAVAIL_TEMP) {
6141 lpfc_block_fabric_iocbs(phba);
6142 }
6143 break;
6144
6145 case IOSTAT_NPORT_BSY:
6146 case IOSTAT_FABRIC_BSY:
6147 lpfc_block_fabric_iocbs(phba);
6148 break;
6149
6150 case IOSTAT_LS_RJT:
6151 stat.un.lsRjtError =
6152 be32_to_cpu(rspiocb->iocb.un.ulpWord[4]);
6153 if ((stat.un.b.lsRjtRsnCode == LSRJT_UNABLE_TPC) ||
6154 (stat.un.b.lsRjtRsnCode == LSRJT_LOGICAL_BSY))
6155 lpfc_block_fabric_iocbs(phba);
6156 break;
6157 }
6158
6159 if (atomic_read(&phba->fabric_iocb_count) == 0)
6160 BUG();
6161
6162 cmdiocb->iocb_cmpl = cmdiocb->fabric_iocb_cmpl;
6163 cmdiocb->fabric_iocb_cmpl = NULL;
6164 cmdiocb->iocb_flag &= ~LPFC_IO_FABRIC;
6165 cmdiocb->iocb_cmpl(phba, cmdiocb, rspiocb);
6166
6167 atomic_dec(&phba->fabric_iocb_count);
6168 if (!test_bit(FABRIC_COMANDS_BLOCKED, &phba->bit_flags)) {
James Smart7f5f3d02008-02-08 18:50:14 -05006169 /* Post any pending iocbs to HBA */
6170 lpfc_resume_fabric_iocbs(phba);
James Smart92d7f7b2007-06-17 19:56:38 -05006171 }
6172}
6173
James Smarte59058c2008-08-24 21:49:00 -04006174/**
6175 * lpfc_issue_fabric_iocb: Issue a fabric iocb command.
6176 * @phba: pointer to lpfc hba data structure.
6177 * @iocb: pointer to lpfc command iocb data structure.
6178 *
6179 * This routine is used as the top-level API for issuing a fabric iocb command
6180 * such as FLOGI and FDISC. To accommodate certain switch fabric, this driver
6181 * function makes sure that only one fabric bound iocb will be outstanding at
6182 * any given time. As such, this function will first check to see whether there
6183 * is already an outstanding fabric iocb on the wire. If so, it will put the
6184 * newly issued iocb onto the driver internal fabric iocb list, waiting to be
6185 * issued later. Otherwise, it will issue the iocb on the wire and update the
6186 * fabric iocb count it indicate that there is one fabric iocb on the wire.
6187 *
6188 * Note, this implementation has a potential sending out fabric IOCBs out of
6189 * order. The problem is caused by the construction of the "ready" boolen does
6190 * not include the condition that the internal fabric IOCB list is empty. As
6191 * such, it is possible a fabric IOCB issued by this routine might be "jump"
6192 * ahead of the fabric IOCBs in the internal list.
6193 *
6194 * Return code
6195 * IOCB_SUCCESS - either fabric iocb put on the list or issued successfully
6196 * IOCB_ERROR - failed to issue fabric iocb
6197 **/
Adrian Bunka6ababd2007-11-05 18:07:33 +01006198static int
James Smart92d7f7b2007-06-17 19:56:38 -05006199lpfc_issue_fabric_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *iocb)
6200{
6201 unsigned long iflags;
6202 struct lpfc_sli_ring *pring = &phba->sli.ring[LPFC_ELS_RING];
6203 int ready;
6204 int ret;
6205
6206 if (atomic_read(&phba->fabric_iocb_count) > 1)
6207 BUG();
6208
6209 spin_lock_irqsave(&phba->hbalock, iflags);
6210 ready = atomic_read(&phba->fabric_iocb_count) == 0 &&
6211 !test_bit(FABRIC_COMANDS_BLOCKED, &phba->bit_flags);
6212
James Smart7f5f3d02008-02-08 18:50:14 -05006213 if (ready)
6214 /* Increment fabric iocb count to hold the position */
6215 atomic_inc(&phba->fabric_iocb_count);
James Smart92d7f7b2007-06-17 19:56:38 -05006216 spin_unlock_irqrestore(&phba->hbalock, iflags);
6217 if (ready) {
6218 iocb->fabric_iocb_cmpl = iocb->iocb_cmpl;
6219 iocb->iocb_cmpl = lpfc_cmpl_fabric_iocb;
6220 iocb->iocb_flag |= LPFC_IO_FABRIC;
6221
James Smart858c9f62007-06-17 19:56:39 -05006222 lpfc_debugfs_disc_trc(iocb->vport, LPFC_DISC_TRC_ELS_CMD,
6223 "Fabric sched2: ste:x%x",
6224 iocb->vport->port_state, 0, 0);
6225
James Smart92d7f7b2007-06-17 19:56:38 -05006226 ret = lpfc_sli_issue_iocb(phba, pring, iocb, 0);
6227
6228 if (ret == IOCB_ERROR) {
6229 iocb->iocb_cmpl = iocb->fabric_iocb_cmpl;
6230 iocb->fabric_iocb_cmpl = NULL;
6231 iocb->iocb_flag &= ~LPFC_IO_FABRIC;
6232 atomic_dec(&phba->fabric_iocb_count);
6233 }
6234 } else {
6235 spin_lock_irqsave(&phba->hbalock, iflags);
6236 list_add_tail(&iocb->list, &phba->fabric_iocb_list);
6237 spin_unlock_irqrestore(&phba->hbalock, iflags);
6238 ret = IOCB_SUCCESS;
6239 }
6240 return ret;
6241}
6242
James Smarte59058c2008-08-24 21:49:00 -04006243/**
6244 * lpfc_fabric_abort_vport: Abort a vport's iocbs from driver fabric iocb list.
6245 * @vport: pointer to a virtual N_Port data structure.
6246 *
6247 * This routine aborts all the IOCBs associated with a @vport from the
6248 * driver internal fabric IOCB list. The list contains fabric IOCBs to be
6249 * issued to the ELS IOCB ring. This abort function walks the fabric IOCB
6250 * list, removes each IOCB associated with the @vport off the list, set the
6251 * status feild to IOSTAT_LOCAL_REJECT, and invokes the callback function
6252 * associated with the IOCB.
6253 **/
Adrian Bunka6ababd2007-11-05 18:07:33 +01006254static void lpfc_fabric_abort_vport(struct lpfc_vport *vport)
James Smart92d7f7b2007-06-17 19:56:38 -05006255{
6256 LIST_HEAD(completions);
6257 struct lpfc_hba *phba = vport->phba;
6258 struct lpfc_iocbq *tmp_iocb, *piocb;
6259 IOCB_t *cmd;
6260
6261 spin_lock_irq(&phba->hbalock);
6262 list_for_each_entry_safe(piocb, tmp_iocb, &phba->fabric_iocb_list,
6263 list) {
6264
6265 if (piocb->vport != vport)
6266 continue;
6267
6268 list_move_tail(&piocb->list, &completions);
6269 }
6270 spin_unlock_irq(&phba->hbalock);
6271
6272 while (!list_empty(&completions)) {
6273 piocb = list_get_first(&completions, struct lpfc_iocbq, list);
6274 list_del_init(&piocb->list);
6275
6276 cmd = &piocb->iocb;
6277 cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
6278 cmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
6279 (piocb->iocb_cmpl) (phba, piocb, piocb);
6280 }
6281}
6282
James Smarte59058c2008-08-24 21:49:00 -04006283/**
6284 * lpfc_fabric_abort_nport: Abort a ndlp's iocbs from driver fabric iocb list.
6285 * @ndlp: pointer to a node-list data structure.
6286 *
6287 * This routine aborts all the IOCBs associated with an @ndlp from the
6288 * driver internal fabric IOCB list. The list contains fabric IOCBs to be
6289 * issued to the ELS IOCB ring. This abort function walks the fabric IOCB
6290 * list, removes each IOCB associated with the @ndlp off the list, set the
6291 * status feild to IOSTAT_LOCAL_REJECT, and invokes the callback function
6292 * associated with the IOCB.
6293 **/
James Smart92d7f7b2007-06-17 19:56:38 -05006294void lpfc_fabric_abort_nport(struct lpfc_nodelist *ndlp)
6295{
6296 LIST_HEAD(completions);
6297 struct lpfc_hba *phba = ndlp->vport->phba;
6298 struct lpfc_iocbq *tmp_iocb, *piocb;
6299 struct lpfc_sli_ring *pring = &phba->sli.ring[LPFC_ELS_RING];
6300 IOCB_t *cmd;
6301
6302 spin_lock_irq(&phba->hbalock);
6303 list_for_each_entry_safe(piocb, tmp_iocb, &phba->fabric_iocb_list,
6304 list) {
6305 if ((lpfc_check_sli_ndlp(phba, pring, piocb, ndlp))) {
6306
6307 list_move_tail(&piocb->list, &completions);
6308 }
6309 }
6310 spin_unlock_irq(&phba->hbalock);
6311
6312 while (!list_empty(&completions)) {
6313 piocb = list_get_first(&completions, struct lpfc_iocbq, list);
6314 list_del_init(&piocb->list);
6315
6316 cmd = &piocb->iocb;
6317 cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
6318 cmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
6319 (piocb->iocb_cmpl) (phba, piocb, piocb);
6320 }
6321}
6322
James Smarte59058c2008-08-24 21:49:00 -04006323/**
6324 * lpfc_fabric_abort_hba: Abort all iocbs on driver fabric iocb list.
6325 * @phba: pointer to lpfc hba data structure.
6326 *
6327 * This routine aborts all the IOCBs currently on the driver internal
6328 * fabric IOCB list. The list contains fabric IOCBs to be issued to the ELS
6329 * IOCB ring. This function takes the entire IOCB list off the fabric IOCB
6330 * list, removes IOCBs off the list, set the status feild to
6331 * IOSTAT_LOCAL_REJECT, and invokes the callback function associated with
6332 * the IOCB.
6333 **/
James Smart92d7f7b2007-06-17 19:56:38 -05006334void lpfc_fabric_abort_hba(struct lpfc_hba *phba)
6335{
6336 LIST_HEAD(completions);
6337 struct lpfc_iocbq *piocb;
6338 IOCB_t *cmd;
6339
6340 spin_lock_irq(&phba->hbalock);
6341 list_splice_init(&phba->fabric_iocb_list, &completions);
6342 spin_unlock_irq(&phba->hbalock);
6343
6344 while (!list_empty(&completions)) {
6345 piocb = list_get_first(&completions, struct lpfc_iocbq, list);
6346 list_del_init(&piocb->list);
6347
6348 cmd = &piocb->iocb;
6349 cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
6350 cmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
6351 (piocb->iocb_cmpl) (phba, piocb, piocb);
6352 }
6353}