blob: f60c85d791c76950ab03d249934743e1d83da69c [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 Smart9413aff2007-04-25 09:53:35 -04004 * Copyright (C) 2004-2007 Emulex. All rights reserved. *
James.Smart@Emulex.Comc44ce172005-06-25 10:34:39 -04005 * EMULEX and SLI are trademarks of Emulex. *
dea31012005-04-17 16:05:31 -05006 * www.emulex.com *
James.Smart@Emulex.Comc44ce172005-06-25 10:34:39 -04007 * Portions Copyright (C) 2004-2005 Christoph Hellwig *
dea31012005-04-17 16:05:31 -05008 * *
9 * This program is free software; you can redistribute it and/or *
James.Smart@Emulex.Comc44ce172005-06-25 10:34:39 -040010 * modify it under the terms of version 2 of the GNU General *
11 * Public License as published by the Free Software Foundation. *
12 * This program is distributed in the hope that it will be useful. *
13 * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND *
14 * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, *
15 * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE *
16 * DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD *
17 * TO BE LEGALLY INVALID. See the GNU General Public License for *
18 * more details, a copy of which can be found in the file COPYING *
19 * included with this package. *
dea31012005-04-17 16:05:31 -050020 *******************************************************************/
21
dea31012005-04-17 16:05:31 -050022#include <linux/blkdev.h>
23#include <linux/pci.h>
24#include <linux/interrupt.h>
25
James.Smart@Emulex.Com91886522005-08-10 15:03:09 -040026#include <scsi/scsi.h>
dea31012005-04-17 16:05:31 -050027#include <scsi/scsi_device.h>
28#include <scsi/scsi_host.h>
29#include <scsi/scsi_transport_fc.h>
30
31#include "lpfc_hw.h"
32#include "lpfc_sli.h"
33#include "lpfc_disc.h"
34#include "lpfc_scsi.h"
35#include "lpfc.h"
36#include "lpfc_logmsg.h"
37#include "lpfc_crtn.h"
James Smart92d7f7b2007-06-17 19:56:38 -050038#include "lpfc_vport.h"
dea31012005-04-17 16:05:31 -050039
40static int lpfc_els_retry(struct lpfc_hba *, struct lpfc_iocbq *,
41 struct lpfc_iocbq *);
James Smart92d7f7b2007-06-17 19:56:38 -050042static void lpfc_cmpl_fabric_iocb(struct lpfc_hba *, struct lpfc_iocbq *,
43 struct lpfc_iocbq *);
44
dea31012005-04-17 16:05:31 -050045static int lpfc_max_els_tries = 3;
46
47static int
James Smart2e0fef82007-06-17 19:56:36 -050048lpfc_els_chk_latt(struct lpfc_vport *vport)
dea31012005-04-17 16:05:31 -050049{
James Smart2e0fef82007-06-17 19:56:36 -050050 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
51 struct lpfc_hba *phba = vport->phba;
dea31012005-04-17 16:05:31 -050052 uint32_t ha_copy;
dea31012005-04-17 16:05:31 -050053
James Smart2e0fef82007-06-17 19:56:36 -050054 if (vport->port_state >= LPFC_VPORT_READY ||
55 phba->link_state == LPFC_LINK_DOWN)
dea31012005-04-17 16:05:31 -050056 return 0;
57
58 /* Read the HBA Host Attention Register */
dea31012005-04-17 16:05:31 -050059 ha_copy = readl(phba->HAregaddr);
dea31012005-04-17 16:05:31 -050060
61 if (!(ha_copy & HA_LATT))
62 return 0;
63
64 /* Pending Link Event during Discovery */
James Smart92d7f7b2007-06-17 19:56:38 -050065 lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
66 "%d (%d):0237 Pending Link Event during "
dea31012005-04-17 16:05:31 -050067 "Discovery: State x%x\n",
James Smart92d7f7b2007-06-17 19:56:38 -050068 phba->brd_no, vport->vpi, phba->pport->port_state);
dea31012005-04-17 16:05:31 -050069
70 /* CLEAR_LA should re-enable link attention events and
71 * we should then imediately take a LATT event. The
72 * LATT processing should call lpfc_linkdown() which
73 * will cleanup any left over in-progress discovery
74 * events.
75 */
James Smart2e0fef82007-06-17 19:56:36 -050076 spin_lock_irq(shost->host_lock);
77 vport->fc_flag |= FC_ABORT_DISCOVERY;
78 spin_unlock_irq(shost->host_lock);
dea31012005-04-17 16:05:31 -050079
James Smart92d7f7b2007-06-17 19:56:38 -050080 if (phba->link_state != LPFC_CLEAR_LA)
James Smarted957682007-06-17 19:56:37 -050081 lpfc_issue_clear_la(phba, vport);
dea31012005-04-17 16:05:31 -050082
Jamie Wellnitzc9f87352006-02-28 19:25:23 -050083 return 1;
dea31012005-04-17 16:05:31 -050084}
85
86static struct lpfc_iocbq *
James Smart2e0fef82007-06-17 19:56:36 -050087lpfc_prep_els_iocb(struct lpfc_vport *vport, uint8_t expectRsp,
88 uint16_t cmdSize, uint8_t retry,
89 struct lpfc_nodelist *ndlp, uint32_t did,
90 uint32_t elscmd)
dea31012005-04-17 16:05:31 -050091{
James Smart2e0fef82007-06-17 19:56:36 -050092 struct lpfc_hba *phba = vport->phba;
James.Smart@Emulex.Com0bd4ca22005-10-28 20:30:02 -040093 struct lpfc_iocbq *elsiocb;
dea31012005-04-17 16:05:31 -050094 struct lpfc_dmabuf *pcmd, *prsp, *pbuflist;
95 struct ulp_bde64 *bpl;
96 IOCB_t *icmd;
97
dea31012005-04-17 16:05:31 -050098
James Smart2e0fef82007-06-17 19:56:36 -050099 if (!lpfc_is_link_up(phba))
100 return NULL;
dea31012005-04-17 16:05:31 -0500101
dea31012005-04-17 16:05:31 -0500102 /* Allocate buffer for command iocb */
James.Smart@Emulex.Com0bd4ca22005-10-28 20:30:02 -0400103 elsiocb = lpfc_sli_get_iocbq(phba);
dea31012005-04-17 16:05:31 -0500104
105 if (elsiocb == NULL)
106 return NULL;
dea31012005-04-17 16:05:31 -0500107 icmd = &elsiocb->iocb;
108
109 /* fill in BDEs for command */
110 /* Allocate buffer for command payload */
James Smart92d7f7b2007-06-17 19:56:38 -0500111 if (((pcmd = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL)) == 0) ||
dea31012005-04-17 16:05:31 -0500112 ((pcmd->virt = lpfc_mbuf_alloc(phba,
113 MEM_PRI, &(pcmd->phys))) == 0)) {
Jesper Juhlc9475cb2005-11-07 01:01:26 -0800114 kfree(pcmd);
dea31012005-04-17 16:05:31 -0500115
James Bottomley604a3e32005-10-29 10:28:33 -0500116 lpfc_sli_release_iocbq(phba, elsiocb);
dea31012005-04-17 16:05:31 -0500117 return NULL;
118 }
119
120 INIT_LIST_HEAD(&pcmd->list);
121
122 /* Allocate buffer for response payload */
123 if (expectRsp) {
James Smart92d7f7b2007-06-17 19:56:38 -0500124 prsp = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL);
dea31012005-04-17 16:05:31 -0500125 if (prsp)
126 prsp->virt = lpfc_mbuf_alloc(phba, MEM_PRI,
127 &prsp->phys);
128 if (prsp == 0 || prsp->virt == 0) {
Jesper Juhlc9475cb2005-11-07 01:01:26 -0800129 kfree(prsp);
dea31012005-04-17 16:05:31 -0500130 lpfc_mbuf_free(phba, pcmd->virt, pcmd->phys);
131 kfree(pcmd);
James Bottomley604a3e32005-10-29 10:28:33 -0500132 lpfc_sli_release_iocbq(phba, elsiocb);
dea31012005-04-17 16:05:31 -0500133 return NULL;
134 }
135 INIT_LIST_HEAD(&prsp->list);
136 } else {
137 prsp = NULL;
138 }
139
140 /* Allocate buffer for Buffer ptr list */
James Smart92d7f7b2007-06-17 19:56:38 -0500141 pbuflist = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL);
dea31012005-04-17 16:05:31 -0500142 if (pbuflist)
James Smarted957682007-06-17 19:56:37 -0500143 pbuflist->virt = lpfc_mbuf_alloc(phba, MEM_PRI,
144 &pbuflist->phys);
dea31012005-04-17 16:05:31 -0500145 if (pbuflist == 0 || pbuflist->virt == 0) {
James Bottomley604a3e32005-10-29 10:28:33 -0500146 lpfc_sli_release_iocbq(phba, elsiocb);
dea31012005-04-17 16:05:31 -0500147 lpfc_mbuf_free(phba, pcmd->virt, pcmd->phys);
148 lpfc_mbuf_free(phba, prsp->virt, prsp->phys);
149 kfree(pcmd);
150 kfree(prsp);
Jesper Juhlc9475cb2005-11-07 01:01:26 -0800151 kfree(pbuflist);
dea31012005-04-17 16:05:31 -0500152 return NULL;
153 }
154
155 INIT_LIST_HEAD(&pbuflist->list);
156
157 icmd->un.elsreq64.bdl.addrHigh = putPaddrHigh(pbuflist->phys);
158 icmd->un.elsreq64.bdl.addrLow = putPaddrLow(pbuflist->phys);
159 icmd->un.elsreq64.bdl.bdeFlags = BUFF_TYPE_BDL;
James Smart2e0fef82007-06-17 19:56:36 -0500160 icmd->un.elsreq64.remoteID = did; /* DID */
dea31012005-04-17 16:05:31 -0500161 if (expectRsp) {
James Smart92d7f7b2007-06-17 19:56:38 -0500162 icmd->un.elsreq64.bdl.bdeSize = (2 * sizeof(struct ulp_bde64));
dea31012005-04-17 16:05:31 -0500163 icmd->ulpCommand = CMD_ELS_REQUEST64_CR;
James Smart2680eea2007-04-25 09:52:55 -0400164 icmd->ulpTimeout = phba->fc_ratov * 2;
dea31012005-04-17 16:05:31 -0500165 } else {
James Smart92d7f7b2007-06-17 19:56:38 -0500166 icmd->un.elsreq64.bdl.bdeSize = sizeof(struct ulp_bde64);
dea31012005-04-17 16:05:31 -0500167 icmd->ulpCommand = CMD_XMIT_ELS_RSP64_CX;
168 }
dea31012005-04-17 16:05:31 -0500169 icmd->ulpBdeCount = 1;
170 icmd->ulpLe = 1;
171 icmd->ulpClass = CLASS3;
172
James Smart92d7f7b2007-06-17 19:56:38 -0500173 if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) {
174 icmd->un.elsreq64.myID = vport->fc_myDID;
175
176 /* For ELS_REQUEST64_CR, use the VPI by default */
177 icmd->ulpContext = vport->vpi;
178 icmd->ulpCt_h = 0;
179 icmd->ulpCt_l = 1;
180 }
181
dea31012005-04-17 16:05:31 -0500182 bpl = (struct ulp_bde64 *) pbuflist->virt;
183 bpl->addrLow = le32_to_cpu(putPaddrLow(pcmd->phys));
184 bpl->addrHigh = le32_to_cpu(putPaddrHigh(pcmd->phys));
185 bpl->tus.f.bdeSize = cmdSize;
186 bpl->tus.f.bdeFlags = 0;
187 bpl->tus.w = le32_to_cpu(bpl->tus.w);
188
189 if (expectRsp) {
190 bpl++;
191 bpl->addrLow = le32_to_cpu(putPaddrLow(prsp->phys));
192 bpl->addrHigh = le32_to_cpu(putPaddrHigh(prsp->phys));
193 bpl->tus.f.bdeSize = FCELSSIZE;
194 bpl->tus.f.bdeFlags = BUFF_USE_RCV;
195 bpl->tus.w = le32_to_cpu(bpl->tus.w);
196 }
197
198 /* Save for completion so we can release these resources */
James Smart92d7f7b2007-06-17 19:56:38 -0500199 if (elscmd != ELS_CMD_LS_RJT)
200 elsiocb->context1 = lpfc_nlp_get(ndlp);
James Smart329f9bc2007-04-25 09:53:01 -0400201 elsiocb->context2 = pcmd;
202 elsiocb->context3 = pbuflist;
dea31012005-04-17 16:05:31 -0500203 elsiocb->retry = retry;
James Smart2e0fef82007-06-17 19:56:36 -0500204 elsiocb->vport = vport;
dea31012005-04-17 16:05:31 -0500205 elsiocb->drvrTimeout = (phba->fc_ratov << 1) + LPFC_DRVR_TIMEOUT;
206
207 if (prsp) {
208 list_add(&prsp->list, &pcmd->list);
209 }
210
211 if (expectRsp) {
212 /* Xmit ELS command <elsCmd> to remote NPORT <did> */
213 lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
James Smart92d7f7b2007-06-17 19:56:38 -0500214 "%d (%d):0116 Xmit ELS command x%x to remote "
James Smart2e0fef82007-06-17 19:56:36 -0500215 "NPORT x%x I/O tag: x%x, port state: x%x\n",
James Smart92d7f7b2007-06-17 19:56:38 -0500216 phba->brd_no, vport->vpi, elscmd, did,
James Smart2e0fef82007-06-17 19:56:36 -0500217 elsiocb->iotag, vport->port_state);
dea31012005-04-17 16:05:31 -0500218 } else {
219 /* Xmit ELS response <elsCmd> to remote NPORT <did> */
220 lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
James Smart92d7f7b2007-06-17 19:56:38 -0500221 "%d (%d):0117 Xmit ELS response x%x to remote "
James Smart1dcb58e2007-04-25 09:51:30 -0400222 "NPORT x%x I/O tag: x%x, size: x%x\n",
James Smart92d7f7b2007-06-17 19:56:38 -0500223 phba->brd_no, vport->vpi, elscmd,
James Smart1dcb58e2007-04-25 09:51:30 -0400224 ndlp->nlp_DID, elsiocb->iotag, cmdSize);
dea31012005-04-17 16:05:31 -0500225 }
226
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500227 return elsiocb;
dea31012005-04-17 16:05:31 -0500228}
229
230
231static int
James Smart92d7f7b2007-06-17 19:56:38 -0500232lpfc_issue_fabric_reglogin(struct lpfc_vport *vport)
233{
234 struct lpfc_hba *phba = vport->phba;
235 LPFC_MBOXQ_t *mbox;
236 struct lpfc_dmabuf *mp;
237 struct lpfc_nodelist *ndlp;
238 struct serv_parm *sp;
239 int rc;
240
241 sp = &phba->fc_fabparam;
242 ndlp = lpfc_findnode_did(vport, Fabric_DID);
243 if (!ndlp)
244 goto fail;
245
246 mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
247 if (!mbox)
248 goto fail;
249
250 vport->port_state = LPFC_FABRIC_CFG_LINK;
251 lpfc_config_link(phba, mbox);
252 mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
253 mbox->vport = vport;
254
255 rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT | MBX_STOP_IOCB);
256 if (rc == MBX_NOT_FINISHED)
257 goto fail_free_mbox;
258
259 mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
260 if (!mbox)
261 goto fail;
262 rc = lpfc_reg_login(phba, vport->vpi, Fabric_DID, (uint8_t *)sp, mbox,
263 0);
264 if (rc)
265 goto fail_free_mbox;
266
267 mbox->mbox_cmpl = lpfc_mbx_cmpl_fabric_reg_login;
268 mbox->vport = vport;
269 mbox->context2 = lpfc_nlp_get(ndlp);
270
271 rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT | MBX_STOP_IOCB);
272 if (rc == MBX_NOT_FINISHED)
273 goto fail_issue_reg_login;
274
275 return 0;
276
277fail_issue_reg_login:
278 lpfc_nlp_put(ndlp);
279 mp = (struct lpfc_dmabuf *) mbox->context1;
280 lpfc_mbuf_free(phba, mp->virt, mp->phys);
281 kfree(mp);
282fail_free_mbox:
283 mempool_free(mbox, phba->mbox_mem_pool);
284
285fail:
286 lpfc_vport_set_state(vport, FC_VPORT_FAILED);
287 lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
288 "%d (%d):0249 Cannot issue Register Fabric login\n",
289 phba->brd_no, vport->vpi);
290 return -ENXIO;
291}
292
293static int
James Smart2e0fef82007-06-17 19:56:36 -0500294lpfc_cmpl_els_flogi_fabric(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
295 struct serv_parm *sp, IOCB_t *irsp)
dea31012005-04-17 16:05:31 -0500296{
James Smart2e0fef82007-06-17 19:56:36 -0500297 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
298 struct lpfc_hba *phba = vport->phba;
James Smart92d7f7b2007-06-17 19:56:38 -0500299 struct lpfc_nodelist *np;
300 struct lpfc_nodelist *next_np;
dea31012005-04-17 16:05:31 -0500301
James Smart2e0fef82007-06-17 19:56:36 -0500302 spin_lock_irq(shost->host_lock);
303 vport->fc_flag |= FC_FABRIC;
304 spin_unlock_irq(shost->host_lock);
dea31012005-04-17 16:05:31 -0500305
306 phba->fc_edtov = be32_to_cpu(sp->cmn.e_d_tov);
307 if (sp->cmn.edtovResolution) /* E_D_TOV ticks are in nanoseconds */
308 phba->fc_edtov = (phba->fc_edtov + 999999) / 1000000;
309
310 phba->fc_ratov = (be32_to_cpu(sp->cmn.w2.r_a_tov) + 999) / 1000;
311
312 if (phba->fc_topology == TOPOLOGY_LOOP) {
James Smart2e0fef82007-06-17 19:56:36 -0500313 spin_lock_irq(shost->host_lock);
314 vport->fc_flag |= FC_PUBLIC_LOOP;
315 spin_unlock_irq(shost->host_lock);
dea31012005-04-17 16:05:31 -0500316 } else {
317 /*
318 * If we are a N-port connected to a Fabric, fixup sparam's so
319 * logins to devices on remote loops work.
320 */
James Smart2e0fef82007-06-17 19:56:36 -0500321 vport->fc_sparam.cmn.altBbCredit = 1;
dea31012005-04-17 16:05:31 -0500322 }
323
James Smart2e0fef82007-06-17 19:56:36 -0500324 vport->fc_myDID = irsp->un.ulpWord[4] & Mask_DID;
dea31012005-04-17 16:05:31 -0500325 memcpy(&ndlp->nlp_portname, &sp->portName, sizeof(struct lpfc_name));
James Smart92d7f7b2007-06-17 19:56:38 -0500326 memcpy(&ndlp->nlp_nodename, &sp->nodeName, sizeof(struct lpfc_name));
dea31012005-04-17 16:05:31 -0500327 ndlp->nlp_class_sup = 0;
328 if (sp->cls1.classValid)
329 ndlp->nlp_class_sup |= FC_COS_CLASS1;
330 if (sp->cls2.classValid)
331 ndlp->nlp_class_sup |= FC_COS_CLASS2;
332 if (sp->cls3.classValid)
333 ndlp->nlp_class_sup |= FC_COS_CLASS3;
334 if (sp->cls4.classValid)
335 ndlp->nlp_class_sup |= FC_COS_CLASS4;
336 ndlp->nlp_maxframe = ((sp->cmn.bbRcvSizeMsb & 0x0F) << 8) |
337 sp->cmn.bbRcvSizeLsb;
338 memcpy(&phba->fc_fabparam, sp, sizeof(struct serv_parm));
339
James Smart92d7f7b2007-06-17 19:56:38 -0500340 if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) {
341 if (sp->cmn.response_multiple_NPort) {
342 lpfc_printf_log(phba, KERN_WARNING, LOG_ELS | LOG_VPORT,
343 "%d:1816 FLOGI NPIV supported, "
344 "response data 0x%x\n",
345 phba->brd_no,
346 sp->cmn.response_multiple_NPort);
347 phba->link_flag |= LS_NPIV_FAB_SUPPORTED;
348
349 } else {
350 /* Because we asked f/w for NPIV it still expects us
351 to call reg_vnpid atleast for the physcial host */
352 lpfc_printf_log(phba, KERN_WARNING, LOG_ELS | LOG_VPORT,
353 "%d:1817 Fabric does not support NPIV "
354 "- configuring single port mode.\n",
355 phba->brd_no);
356 phba->vpi_cnt = 1;
357 phba->link_flag &= ~LS_NPIV_FAB_SUPPORTED;
358 }
359 }
360
361 if ((vport->fc_prevDID != vport->fc_myDID) &&
362 !(vport->fc_flag & FC_VPORT_NEEDS_REG_VPI)) {
363
364 /* If our NportID changed, we need to ensure all
365 * remaining NPORTs get unreg_login'ed.
366 */
367 list_for_each_entry_safe(np, next_np,
368 &vport->fc_nodes, nlp_listp) {
369 if ((np->nlp_state != NLP_STE_NPR_NODE) ||
370 !(np->nlp_flag & NLP_NPR_ADISC))
371 continue;
372 spin_lock_irq(shost->host_lock);
373 np->nlp_flag &= ~NLP_NPR_ADISC;
374 spin_unlock_irq(shost->host_lock);
375 lpfc_unreg_rpi(vport, np);
376 }
377 if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) {
378 lpfc_mbx_unreg_vpi(vport);
379 vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI;
380 }
381 }
382
James Smart2e0fef82007-06-17 19:56:36 -0500383 ndlp->nlp_sid = irsp->un.ulpWord[4] & Mask_DID;
James Smart92d7f7b2007-06-17 19:56:38 -0500384 lpfc_nlp_set_state(vport, ndlp, NLP_STE_REG_LOGIN_ISSUE);
James Smart2e0fef82007-06-17 19:56:36 -0500385
James Smart92d7f7b2007-06-17 19:56:38 -0500386 if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED &&
387 vport->fc_flag & FC_VPORT_NEEDS_REG_VPI) {
388 lpfc_register_new_vport(phba, vport, ndlp);
389 return 0;
390 }
391 lpfc_issue_fabric_reglogin(vport);
dea31012005-04-17 16:05:31 -0500392 return 0;
dea31012005-04-17 16:05:31 -0500393}
394
395/*
396 * We FLOGIed into an NPort, initiate pt2pt protocol
397 */
398static int
James Smart2e0fef82007-06-17 19:56:36 -0500399lpfc_cmpl_els_flogi_nport(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
400 struct serv_parm *sp)
dea31012005-04-17 16:05:31 -0500401{
James Smart2e0fef82007-06-17 19:56:36 -0500402 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
403 struct lpfc_hba *phba = vport->phba;
dea31012005-04-17 16:05:31 -0500404 LPFC_MBOXQ_t *mbox;
405 int rc;
406
James Smart2e0fef82007-06-17 19:56:36 -0500407 spin_lock_irq(shost->host_lock);
408 vport->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP);
James Smart92d7f7b2007-06-17 19:56:38 -0500409 phba->vpi_cnt = 1;
James Smart2e0fef82007-06-17 19:56:36 -0500410 spin_unlock_irq(shost->host_lock);
dea31012005-04-17 16:05:31 -0500411
412 phba->fc_edtov = FF_DEF_EDTOV;
413 phba->fc_ratov = FF_DEF_RATOV;
James Smart2e0fef82007-06-17 19:56:36 -0500414 rc = memcmp(&vport->fc_portname, &sp->portName,
James Smart92d7f7b2007-06-17 19:56:38 -0500415 sizeof(vport->fc_portname));
dea31012005-04-17 16:05:31 -0500416 if (rc >= 0) {
417 /* This side will initiate the PLOGI */
James Smart2e0fef82007-06-17 19:56:36 -0500418 spin_lock_irq(shost->host_lock);
419 vport->fc_flag |= FC_PT2PT_PLOGI;
420 spin_unlock_irq(shost->host_lock);
dea31012005-04-17 16:05:31 -0500421
422 /*
423 * N_Port ID cannot be 0, set our to LocalID the other
424 * side will be RemoteID.
425 */
426
427 /* not equal */
428 if (rc)
James Smart2e0fef82007-06-17 19:56:36 -0500429 vport->fc_myDID = PT2PT_LocalID;
dea31012005-04-17 16:05:31 -0500430
431 mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
432 if (!mbox)
433 goto fail;
434
435 lpfc_config_link(phba, mbox);
436
437 mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
James Smarted957682007-06-17 19:56:37 -0500438 mbox->vport = vport;
dea31012005-04-17 16:05:31 -0500439 rc = lpfc_sli_issue_mbox(phba, mbox,
James Smart92d7f7b2007-06-17 19:56:38 -0500440 MBX_NOWAIT | MBX_STOP_IOCB);
dea31012005-04-17 16:05:31 -0500441 if (rc == MBX_NOT_FINISHED) {
442 mempool_free(mbox, phba->mbox_mem_pool);
443 goto fail;
444 }
James Smart329f9bc2007-04-25 09:53:01 -0400445 lpfc_nlp_put(ndlp);
dea31012005-04-17 16:05:31 -0500446
James Smart2e0fef82007-06-17 19:56:36 -0500447 ndlp = lpfc_findnode_did(vport, PT2PT_RemoteID);
dea31012005-04-17 16:05:31 -0500448 if (!ndlp) {
449 /*
450 * Cannot find existing Fabric ndlp, so allocate a
451 * new one
452 */
453 ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL);
454 if (!ndlp)
455 goto fail;
456
James Smart2e0fef82007-06-17 19:56:36 -0500457 lpfc_nlp_init(vport, ndlp, PT2PT_RemoteID);
dea31012005-04-17 16:05:31 -0500458 }
459
460 memcpy(&ndlp->nlp_portname, &sp->portName,
James Smart2e0fef82007-06-17 19:56:36 -0500461 sizeof(struct lpfc_name));
dea31012005-04-17 16:05:31 -0500462 memcpy(&ndlp->nlp_nodename, &sp->nodeName,
James Smart2e0fef82007-06-17 19:56:36 -0500463 sizeof(struct lpfc_name));
464 lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
465 spin_lock_irq(shost->host_lock);
dea31012005-04-17 16:05:31 -0500466 ndlp->nlp_flag |= NLP_NPR_2B_DISC;
James Smart2e0fef82007-06-17 19:56:36 -0500467 spin_unlock_irq(shost->host_lock);
dea31012005-04-17 16:05:31 -0500468 } else {
469 /* This side will wait for the PLOGI */
James Smart329f9bc2007-04-25 09:53:01 -0400470 lpfc_nlp_put(ndlp);
dea31012005-04-17 16:05:31 -0500471 }
472
James Smart2e0fef82007-06-17 19:56:36 -0500473 spin_lock_irq(shost->host_lock);
474 vport->fc_flag |= FC_PT2PT;
475 spin_unlock_irq(shost->host_lock);
dea31012005-04-17 16:05:31 -0500476
477 /* Start discovery - this should just do CLEAR_LA */
James Smart2e0fef82007-06-17 19:56:36 -0500478 lpfc_disc_start(vport);
dea31012005-04-17 16:05:31 -0500479 return 0;
James Smart92d7f7b2007-06-17 19:56:38 -0500480fail:
dea31012005-04-17 16:05:31 -0500481 return -ENXIO;
482}
483
484static void
James Smart329f9bc2007-04-25 09:53:01 -0400485lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
486 struct lpfc_iocbq *rspiocb)
dea31012005-04-17 16:05:31 -0500487{
James Smart2e0fef82007-06-17 19:56:36 -0500488 struct lpfc_vport *vport = cmdiocb->vport;
489 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
dea31012005-04-17 16:05:31 -0500490 IOCB_t *irsp = &rspiocb->iocb;
491 struct lpfc_nodelist *ndlp = cmdiocb->context1;
492 struct lpfc_dmabuf *pcmd = cmdiocb->context2, *prsp;
493 struct serv_parm *sp;
494 int rc;
495
496 /* Check to see if link went down during discovery */
James Smart2e0fef82007-06-17 19:56:36 -0500497 if (lpfc_els_chk_latt(vport)) {
James Smart329f9bc2007-04-25 09:53:01 -0400498 lpfc_nlp_put(ndlp);
dea31012005-04-17 16:05:31 -0500499 goto out;
500 }
501
502 if (irsp->ulpStatus) {
503 /* Check for retry */
James Smart2e0fef82007-06-17 19:56:36 -0500504 if (lpfc_els_retry(phba, cmdiocb, rspiocb))
dea31012005-04-17 16:05:31 -0500505 goto out;
James Smart2e0fef82007-06-17 19:56:36 -0500506
dea31012005-04-17 16:05:31 -0500507 /* FLOGI failed, so there is no fabric */
James Smart2e0fef82007-06-17 19:56:36 -0500508 spin_lock_irq(shost->host_lock);
509 vport->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP);
James Smart92d7f7b2007-06-17 19:56:38 -0500510 phba->vpi_cnt = 1;
James Smart2e0fef82007-06-17 19:56:36 -0500511 spin_unlock_irq(shost->host_lock);
dea31012005-04-17 16:05:31 -0500512
James Smart329f9bc2007-04-25 09:53:01 -0400513 /* If private loop, then allow max outstanding els to be
dea31012005-04-17 16:05:31 -0500514 * LPFC_MAX_DISC_THREADS (32). Scanning in the case of no
515 * alpa map would take too long otherwise.
516 */
517 if (phba->alpa_map[0] == 0) {
James Smart329f9bc2007-04-25 09:53:01 -0400518 phba->cfg_discovery_threads = LPFC_MAX_DISC_THREADS;
dea31012005-04-17 16:05:31 -0500519 }
520
521 /* FLOGI failure */
James Smart92d7f7b2007-06-17 19:56:38 -0500522 lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
523 "%d (%d):0100 FLOGI failure Data: x%x x%x "
524 "x%x\n",
525 phba->brd_no, vport->vpi,
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500526 irsp->ulpStatus, irsp->un.ulpWord[4],
527 irsp->ulpTimeout);
dea31012005-04-17 16:05:31 -0500528 goto flogifail;
529 }
530
531 /*
532 * The FLogI succeeded. Sync the data for the CPU before
533 * accessing it.
534 */
535 prsp = list_get_first(&pcmd->list, struct lpfc_dmabuf, list);
536
537 sp = prsp->virt + sizeof(uint32_t);
538
539 /* FLOGI completes successfully */
540 lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
James Smart92d7f7b2007-06-17 19:56:38 -0500541 "%d (%d):0101 FLOGI completes sucessfully "
dea31012005-04-17 16:05:31 -0500542 "Data: x%x x%x x%x x%x\n",
James Smart92d7f7b2007-06-17 19:56:38 -0500543 phba->brd_no, vport->vpi,
dea31012005-04-17 16:05:31 -0500544 irsp->un.ulpWord[4], sp->cmn.e_d_tov,
545 sp->cmn.w2.r_a_tov, sp->cmn.edtovResolution);
546
James Smart2e0fef82007-06-17 19:56:36 -0500547 if (vport->port_state == LPFC_FLOGI) {
dea31012005-04-17 16:05:31 -0500548 /*
549 * If Common Service Parameters indicate Nport
550 * we are point to point, if Fport we are Fabric.
551 */
552 if (sp->cmn.fPort)
James Smart2e0fef82007-06-17 19:56:36 -0500553 rc = lpfc_cmpl_els_flogi_fabric(vport, ndlp, sp, irsp);
dea31012005-04-17 16:05:31 -0500554 else
James Smart2e0fef82007-06-17 19:56:36 -0500555 rc = lpfc_cmpl_els_flogi_nport(vport, ndlp, sp);
dea31012005-04-17 16:05:31 -0500556
557 if (!rc)
558 goto out;
559 }
560
561flogifail:
James Smart329f9bc2007-04-25 09:53:01 -0400562 lpfc_nlp_put(ndlp);
James Smart92d7f7b2007-06-17 19:56:38 -0500563 phba->vpi_cnt = 1;
dea31012005-04-17 16:05:31 -0500564
565 if (irsp->ulpStatus != IOSTAT_LOCAL_REJECT ||
566 (irsp->un.ulpWord[4] != IOERR_SLI_ABORTED &&
567 irsp->un.ulpWord[4] != IOERR_SLI_DOWN)) {
568 /* FLOGI failed, so just use loop map to make discovery list */
James Smart2e0fef82007-06-17 19:56:36 -0500569 lpfc_disc_list_loopmap(vport);
dea31012005-04-17 16:05:31 -0500570
571 /* Start discovery */
James Smart2e0fef82007-06-17 19:56:36 -0500572 lpfc_disc_start(vport);
dea31012005-04-17 16:05:31 -0500573 }
574
575out:
576 lpfc_els_free_iocb(phba, cmdiocb);
577}
578
579static int
James Smart2e0fef82007-06-17 19:56:36 -0500580lpfc_issue_els_flogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
dea31012005-04-17 16:05:31 -0500581 uint8_t retry)
582{
James Smart2e0fef82007-06-17 19:56:36 -0500583 struct lpfc_hba *phba = vport->phba;
dea31012005-04-17 16:05:31 -0500584 struct serv_parm *sp;
585 IOCB_t *icmd;
586 struct lpfc_iocbq *elsiocb;
587 struct lpfc_sli_ring *pring;
588 uint8_t *pcmd;
589 uint16_t cmdsize;
590 uint32_t tmo;
591 int rc;
592
593 pring = &phba->sli.ring[LPFC_ELS_RING];
594
James Smart92d7f7b2007-06-17 19:56:38 -0500595 cmdsize = (sizeof(uint32_t) + sizeof(struct serv_parm));
James Smart2e0fef82007-06-17 19:56:36 -0500596 elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp,
597 ndlp->nlp_DID, ELS_CMD_FLOGI);
James Smart92d7f7b2007-06-17 19:56:38 -0500598
James Smart488d1462006-03-07 15:02:37 -0500599 if (!elsiocb)
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500600 return 1;
dea31012005-04-17 16:05:31 -0500601
602 icmd = &elsiocb->iocb;
603 pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
604
605 /* For FLOGI request, remainder of payload is service parameters */
606 *((uint32_t *) (pcmd)) = ELS_CMD_FLOGI;
James Smart92d7f7b2007-06-17 19:56:38 -0500607 pcmd += sizeof(uint32_t);
608 memcpy(pcmd, &vport->fc_sparam, sizeof(struct serv_parm));
dea31012005-04-17 16:05:31 -0500609 sp = (struct serv_parm *) pcmd;
610
611 /* Setup CSPs accordingly for Fabric */
612 sp->cmn.e_d_tov = 0;
613 sp->cmn.w2.r_a_tov = 0;
614 sp->cls1.classValid = 0;
615 sp->cls2.seqDelivery = 1;
616 sp->cls3.seqDelivery = 1;
617 if (sp->cmn.fcphLow < FC_PH3)
618 sp->cmn.fcphLow = FC_PH3;
619 if (sp->cmn.fcphHigh < FC_PH3)
620 sp->cmn.fcphHigh = FC_PH3;
621
James Smart92d7f7b2007-06-17 19:56:38 -0500622 if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) {
623 sp->cmn.request_multiple_Nport = 1;
624
625 /* For FLOGI, Let FLOGI rsp set the NPortID for VPI 0 */
626 icmd->ulpCt_h = 1;
627 icmd->ulpCt_l = 0;
628 }
629
dea31012005-04-17 16:05:31 -0500630 tmo = phba->fc_ratov;
631 phba->fc_ratov = LPFC_DISC_FLOGI_TMO;
James Smart2e0fef82007-06-17 19:56:36 -0500632 lpfc_set_disctmo(vport);
dea31012005-04-17 16:05:31 -0500633 phba->fc_ratov = tmo;
634
635 phba->fc_stat.elsXmitFLOGI++;
636 elsiocb->iocb_cmpl = lpfc_cmpl_els_flogi;
James Smart92d7f7b2007-06-17 19:56:38 -0500637 rc = lpfc_issue_fabric_iocb(phba, elsiocb);
dea31012005-04-17 16:05:31 -0500638 if (rc == IOCB_ERROR) {
639 lpfc_els_free_iocb(phba, elsiocb);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500640 return 1;
dea31012005-04-17 16:05:31 -0500641 }
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500642 return 0;
dea31012005-04-17 16:05:31 -0500643}
644
645int
James Smart2e0fef82007-06-17 19:56:36 -0500646lpfc_els_abort_flogi(struct lpfc_hba *phba)
dea31012005-04-17 16:05:31 -0500647{
648 struct lpfc_sli_ring *pring;
649 struct lpfc_iocbq *iocb, *next_iocb;
650 struct lpfc_nodelist *ndlp;
651 IOCB_t *icmd;
652
653 /* Abort outstanding I/O on NPort <nlp_DID> */
654 lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
655 "%d:0201 Abort outstanding I/O on NPort x%x\n",
656 phba->brd_no, Fabric_DID);
657
658 pring = &phba->sli.ring[LPFC_ELS_RING];
659
660 /*
661 * Check the txcmplq for an iocb that matches the nport the driver is
662 * searching for.
663 */
James Smart2e0fef82007-06-17 19:56:36 -0500664 spin_lock_irq(&phba->hbalock);
dea31012005-04-17 16:05:31 -0500665 list_for_each_entry_safe(iocb, next_iocb, &pring->txcmplq, list) {
666 icmd = &iocb->iocb;
James Smart2e0fef82007-06-17 19:56:36 -0500667 if (icmd->ulpCommand == CMD_ELS_REQUEST64_CR &&
668 icmd->un.elsreq64.bdl.ulpIoTag32) {
dea31012005-04-17 16:05:31 -0500669 ndlp = (struct lpfc_nodelist *)(iocb->context1);
James Smart92d7f7b2007-06-17 19:56:38 -0500670 if (ndlp && (ndlp->nlp_DID == Fabric_DID)) {
James Smart07951072007-04-25 09:51:38 -0400671 lpfc_sli_issue_abort_iotag(phba, pring, iocb);
James Smart92d7f7b2007-06-17 19:56:38 -0500672 }
dea31012005-04-17 16:05:31 -0500673 }
674 }
James Smart2e0fef82007-06-17 19:56:36 -0500675 spin_unlock_irq(&phba->hbalock);
dea31012005-04-17 16:05:31 -0500676
677 return 0;
678}
679
680int
James Smart2e0fef82007-06-17 19:56:36 -0500681lpfc_initial_flogi(struct lpfc_vport *vport)
dea31012005-04-17 16:05:31 -0500682{
James Smart2e0fef82007-06-17 19:56:36 -0500683 struct lpfc_hba *phba = vport->phba;
dea31012005-04-17 16:05:31 -0500684 struct lpfc_nodelist *ndlp;
685
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500686 /* First look for the Fabric ndlp */
James Smart2e0fef82007-06-17 19:56:36 -0500687 ndlp = lpfc_findnode_did(vport, Fabric_DID);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500688 if (!ndlp) {
dea31012005-04-17 16:05:31 -0500689 /* Cannot find existing Fabric ndlp, so allocate a new one */
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500690 ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL);
691 if (!ndlp)
692 return 0;
James Smart2e0fef82007-06-17 19:56:36 -0500693 lpfc_nlp_init(vport, ndlp, Fabric_DID);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500694 } else {
James Smart2e0fef82007-06-17 19:56:36 -0500695 lpfc_dequeue_node(vport, ndlp);
dea31012005-04-17 16:05:31 -0500696 }
James Smart2e0fef82007-06-17 19:56:36 -0500697 if (lpfc_issue_els_flogi(vport, ndlp, 0)) {
James Smart329f9bc2007-04-25 09:53:01 -0400698 lpfc_nlp_put(ndlp);
dea31012005-04-17 16:05:31 -0500699 }
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500700 return 1;
dea31012005-04-17 16:05:31 -0500701}
702
James Smart92d7f7b2007-06-17 19:56:38 -0500703int
704lpfc_initial_fdisc(struct lpfc_vport *vport)
705{
706 struct lpfc_hba *phba = vport->phba;
707 struct lpfc_nodelist *ndlp;
708
709 /* First look for the Fabric ndlp */
710 ndlp = lpfc_findnode_did(vport, Fabric_DID);
711 if (!ndlp) {
712 /* Cannot find existing Fabric ndlp, so allocate a new one */
713 ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL);
714 if (!ndlp)
715 return 0;
716 lpfc_nlp_init(vport, ndlp, Fabric_DID);
717 } else {
718 lpfc_dequeue_node(vport, ndlp);
719 }
720 if (lpfc_issue_els_fdisc(vport, ndlp, 0)) {
721 lpfc_nlp_put(ndlp);
722 }
723 return 1;
724}
dea31012005-04-17 16:05:31 -0500725static void
James Smart2e0fef82007-06-17 19:56:36 -0500726lpfc_more_plogi(struct lpfc_vport *vport)
dea31012005-04-17 16:05:31 -0500727{
728 int sentplogi;
James Smart2e0fef82007-06-17 19:56:36 -0500729 struct lpfc_hba *phba = vport->phba;
dea31012005-04-17 16:05:31 -0500730
James Smart2e0fef82007-06-17 19:56:36 -0500731 if (vport->num_disc_nodes)
732 vport->num_disc_nodes--;
dea31012005-04-17 16:05:31 -0500733
734 /* Continue discovery with <num_disc_nodes> PLOGIs to go */
735 lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
James Smart92d7f7b2007-06-17 19:56:38 -0500736 "%d (%d):0232 Continue discovery with %d PLOGIs to go "
dea31012005-04-17 16:05:31 -0500737 "Data: x%x x%x x%x\n",
James Smart92d7f7b2007-06-17 19:56:38 -0500738 phba->brd_no, vport->vpi, vport->num_disc_nodes,
James Smart2e0fef82007-06-17 19:56:36 -0500739 vport->fc_plogi_cnt, vport->fc_flag, vport->port_state);
dea31012005-04-17 16:05:31 -0500740
741 /* Check to see if there are more PLOGIs to be sent */
James Smart2e0fef82007-06-17 19:56:36 -0500742 if (vport->fc_flag & FC_NLP_MORE)
743 /* go thru NPR nodes and issue any remaining ELS PLOGIs */
744 sentplogi = lpfc_els_disc_plogi(vport);
745
dea31012005-04-17 16:05:31 -0500746 return;
747}
748
James Smart488d1462006-03-07 15:02:37 -0500749static struct lpfc_nodelist *
James Smart92d7f7b2007-06-17 19:56:38 -0500750lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t *prsp,
James Smart488d1462006-03-07 15:02:37 -0500751 struct lpfc_nodelist *ndlp)
752{
James Smart2e0fef82007-06-17 19:56:36 -0500753 struct lpfc_vport *vport = ndlp->vport;
James Smart488d1462006-03-07 15:02:37 -0500754 struct lpfc_nodelist *new_ndlp;
James Smart488d1462006-03-07 15:02:37 -0500755 struct serv_parm *sp;
James Smart92d7f7b2007-06-17 19:56:38 -0500756 uint8_t name[sizeof(struct lpfc_name)];
James Smart488d1462006-03-07 15:02:37 -0500757 uint32_t rc;
758
James Smart2fb9bd82006-12-02 13:33:57 -0500759 /* Fabric nodes can have the same WWPN so we don't bother searching
760 * by WWPN. Just return the ndlp that was given to us.
761 */
762 if (ndlp->nlp_type & NLP_FABRIC)
763 return ndlp;
764
James Smart92d7f7b2007-06-17 19:56:38 -0500765 sp = (struct serv_parm *) ((uint8_t *) prsp + sizeof(uint32_t));
James Smart685f0bf2007-04-25 09:53:08 -0400766 memset(name, 0, sizeof(struct lpfc_name));
James Smart488d1462006-03-07 15:02:37 -0500767
James Smart685f0bf2007-04-25 09:53:08 -0400768 /* Now we find out if the NPort we are logging into, matches the WWPN
James Smart488d1462006-03-07 15:02:37 -0500769 * we have for that ndlp. If not, we have some work to do.
770 */
James Smart2e0fef82007-06-17 19:56:36 -0500771 new_ndlp = lpfc_findnode_wwpn(vport, &sp->portName);
James Smart488d1462006-03-07 15:02:37 -0500772
James Smart92795652006-07-06 15:50:02 -0400773 if (new_ndlp == ndlp)
James Smart488d1462006-03-07 15:02:37 -0500774 return ndlp;
James Smart488d1462006-03-07 15:02:37 -0500775
776 if (!new_ndlp) {
James Smart2e0fef82007-06-17 19:56:36 -0500777 rc = memcmp(&ndlp->nlp_portname, name,
778 sizeof(struct lpfc_name));
James Smart92795652006-07-06 15:50:02 -0400779 if (!rc)
780 return ndlp;
James Smart488d1462006-03-07 15:02:37 -0500781 new_ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_ATOMIC);
782 if (!new_ndlp)
783 return ndlp;
784
James Smart2e0fef82007-06-17 19:56:36 -0500785 lpfc_nlp_init(vport, new_ndlp, ndlp->nlp_DID);
James Smart488d1462006-03-07 15:02:37 -0500786 }
787
James Smart2e0fef82007-06-17 19:56:36 -0500788 lpfc_unreg_rpi(vport, new_ndlp);
James Smart488d1462006-03-07 15:02:37 -0500789 new_ndlp->nlp_DID = ndlp->nlp_DID;
James Smart92795652006-07-06 15:50:02 -0400790 new_ndlp->nlp_prev_state = ndlp->nlp_prev_state;
James Smart2e0fef82007-06-17 19:56:36 -0500791 lpfc_nlp_set_state(vport, new_ndlp, ndlp->nlp_state);
James Smart488d1462006-03-07 15:02:37 -0500792
James Smart2e0fef82007-06-17 19:56:36 -0500793 /* Move this back to NPR state */
James Smartde0c5b32007-04-25 09:52:27 -0400794 if (memcmp(&ndlp->nlp_portname, name, sizeof(struct lpfc_name)) == 0)
James Smart2e0fef82007-06-17 19:56:36 -0500795 lpfc_drop_node(vport, ndlp);
James Smart92795652006-07-06 15:50:02 -0400796 else {
James Smart2e0fef82007-06-17 19:56:36 -0500797 lpfc_unreg_rpi(vport, ndlp);
James Smart92795652006-07-06 15:50:02 -0400798 ndlp->nlp_DID = 0; /* Two ndlps cannot have the same did */
James Smart2e0fef82007-06-17 19:56:36 -0500799 lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
James Smart92795652006-07-06 15:50:02 -0400800 }
James Smart488d1462006-03-07 15:02:37 -0500801 return new_ndlp;
802}
803
dea31012005-04-17 16:05:31 -0500804static void
James Smart2e0fef82007-06-17 19:56:36 -0500805lpfc_cmpl_els_plogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
806 struct lpfc_iocbq *rspiocb)
dea31012005-04-17 16:05:31 -0500807{
James Smart2e0fef82007-06-17 19:56:36 -0500808 struct lpfc_vport *vport = cmdiocb->vport;
809 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
dea31012005-04-17 16:05:31 -0500810 IOCB_t *irsp;
dea31012005-04-17 16:05:31 -0500811 struct lpfc_nodelist *ndlp;
James Smart92795652006-07-06 15:50:02 -0400812 struct lpfc_dmabuf *prsp;
dea31012005-04-17 16:05:31 -0500813 int disc, rc, did, type;
814
dea31012005-04-17 16:05:31 -0500815 /* we pass cmdiocb to state machine which needs rspiocb as well */
816 cmdiocb->context_un.rsp_iocb = rspiocb;
817
818 irsp = &rspiocb->iocb;
James Smart2e0fef82007-06-17 19:56:36 -0500819 ndlp = lpfc_findnode_did(vport, irsp->un.elsreq64.remoteID);
James Smarted957682007-06-17 19:56:37 -0500820 if (!ndlp) {
James Smart92d7f7b2007-06-17 19:56:38 -0500821 lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
822 "%d (%d):0136 PLOGI completes to NPort x%x "
823 "with no ndlp. Data: x%x x%x x%x\n",
824 phba->brd_no, vport->vpi, irsp->un.elsreq64.remoteID,
825 irsp->ulpStatus, irsp->un.ulpWord[4], irsp->ulpIoTag);
James Smart488d1462006-03-07 15:02:37 -0500826 goto out;
James Smarted957682007-06-17 19:56:37 -0500827 }
dea31012005-04-17 16:05:31 -0500828
829 /* Since ndlp can be freed in the disc state machine, note if this node
830 * is being used during discovery.
831 */
James Smart2e0fef82007-06-17 19:56:36 -0500832 spin_lock_irq(shost->host_lock);
dea31012005-04-17 16:05:31 -0500833 disc = (ndlp->nlp_flag & NLP_NPR_2B_DISC);
James Smart488d1462006-03-07 15:02:37 -0500834 ndlp->nlp_flag &= ~NLP_NPR_2B_DISC;
James Smart2e0fef82007-06-17 19:56:36 -0500835 spin_unlock_irq(shost->host_lock);
dea31012005-04-17 16:05:31 -0500836 rc = 0;
837
838 /* PLOGI completes to NPort <nlp_DID> */
839 lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
James Smart92d7f7b2007-06-17 19:56:38 -0500840 "%d (%d):0102 PLOGI completes to NPort x%x "
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500841 "Data: x%x x%x x%x x%x x%x\n",
James Smart92d7f7b2007-06-17 19:56:38 -0500842 phba->brd_no, vport->vpi, ndlp->nlp_DID,
843 irsp->ulpStatus, irsp->un.ulpWord[4],
844 irsp->ulpTimeout, disc, vport->num_disc_nodes);
dea31012005-04-17 16:05:31 -0500845
846 /* Check to see if link went down during discovery */
James Smart2e0fef82007-06-17 19:56:36 -0500847 if (lpfc_els_chk_latt(vport)) {
848 spin_lock_irq(shost->host_lock);
dea31012005-04-17 16:05:31 -0500849 ndlp->nlp_flag |= NLP_NPR_2B_DISC;
James Smart2e0fef82007-06-17 19:56:36 -0500850 spin_unlock_irq(shost->host_lock);
dea31012005-04-17 16:05:31 -0500851 goto out;
852 }
853
854 /* ndlp could be freed in DSM, save these values now */
855 type = ndlp->nlp_type;
856 did = ndlp->nlp_DID;
857
858 if (irsp->ulpStatus) {
859 /* Check for retry */
860 if (lpfc_els_retry(phba, cmdiocb, rspiocb)) {
861 /* ELS command is being retried */
862 if (disc) {
James Smart2e0fef82007-06-17 19:56:36 -0500863 spin_lock_irq(shost->host_lock);
dea31012005-04-17 16:05:31 -0500864 ndlp->nlp_flag |= NLP_NPR_2B_DISC;
James Smart2e0fef82007-06-17 19:56:36 -0500865 spin_unlock_irq(shost->host_lock);
dea31012005-04-17 16:05:31 -0500866 }
867 goto out;
868 }
869
870 /* PLOGI failed */
James Smart92d7f7b2007-06-17 19:56:38 -0500871 if (ndlp->nlp_DID == NameServer_DID) {
872 lpfc_vport_set_state(vport, FC_VPORT_FAILED);
873 lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
874 "%d (%d):0250 Nameserver login error: "
875 "0x%x / 0x%x\n",
876 phba->brd_no, vport->vpi,
877 irsp->ulpStatus, irsp->un.ulpWord[4]);
878 }
879
dea31012005-04-17 16:05:31 -0500880 /* Do not call DSM for lpfc_els_abort'ed ELS cmds */
881 if ((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) &&
James Smart92d7f7b2007-06-17 19:56:38 -0500882 ((irsp->un.ulpWord[4] == IOERR_SLI_ABORTED) ||
883 (irsp->un.ulpWord[4] == IOERR_LINK_DOWN) ||
884 (irsp->un.ulpWord[4] == IOERR_SLI_DOWN))) {
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500885 rc = NLP_STE_FREED_NODE;
Jamie Wellnitz2fe165b2006-02-28 19:25:31 -0500886 } else {
James Smart2e0fef82007-06-17 19:56:36 -0500887 rc = lpfc_disc_state_machine(vport, ndlp, cmdiocb,
James Smart92d7f7b2007-06-17 19:56:38 -0500888 NLP_EVT_CMPL_PLOGI);
dea31012005-04-17 16:05:31 -0500889 }
890 } else {
891 /* Good status, call state machine */
James Smart92795652006-07-06 15:50:02 -0400892 prsp = list_entry(((struct lpfc_dmabuf *)
James Smart92d7f7b2007-06-17 19:56:38 -0500893 cmdiocb->context2)->list.next,
894 struct lpfc_dmabuf, list);
895 ndlp = lpfc_plogi_confirm_nport(phba, prsp->virt, ndlp);
James Smart2e0fef82007-06-17 19:56:36 -0500896 rc = lpfc_disc_state_machine(vport, ndlp, cmdiocb,
James Smart92d7f7b2007-06-17 19:56:38 -0500897 NLP_EVT_CMPL_PLOGI);
dea31012005-04-17 16:05:31 -0500898 }
899
James Smart2e0fef82007-06-17 19:56:36 -0500900 if (disc && vport->num_disc_nodes) {
dea31012005-04-17 16:05:31 -0500901 /* Check to see if there are more PLOGIs to be sent */
James Smart2e0fef82007-06-17 19:56:36 -0500902 lpfc_more_plogi(vport);
dea31012005-04-17 16:05:31 -0500903
James Smart2e0fef82007-06-17 19:56:36 -0500904 if (vport->num_disc_nodes == 0) {
905 spin_lock_irq(shost->host_lock);
906 vport->fc_flag &= ~FC_NDISC_ACTIVE;
907 spin_unlock_irq(shost->host_lock);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500908
James Smart2e0fef82007-06-17 19:56:36 -0500909 lpfc_can_disctmo(vport);
910 if (vport->fc_flag & FC_RSCN_MODE) {
James Smart10d4e952006-04-15 11:53:15 -0400911 /*
912 * Check to see if more RSCNs came in while
913 * we were processing this one.
914 */
James Smart2e0fef82007-06-17 19:56:36 -0500915 if ((vport->fc_rscn_id_cnt == 0) &&
916 (!(vport->fc_flag & FC_RSCN_DISCOVERY))) {
917 spin_lock_irq(shost->host_lock);
918 vport->fc_flag &= ~FC_RSCN_MODE;
919 spin_unlock_irq(shost->host_lock);
James Smart10d4e952006-04-15 11:53:15 -0400920 } else {
James Smart2e0fef82007-06-17 19:56:36 -0500921 lpfc_els_handle_rscn(vport);
James Smart10d4e952006-04-15 11:53:15 -0400922 }
dea31012005-04-17 16:05:31 -0500923 }
924 }
925 }
926
927out:
928 lpfc_els_free_iocb(phba, cmdiocb);
929 return;
930}
931
932int
James Smart2e0fef82007-06-17 19:56:36 -0500933lpfc_issue_els_plogi(struct lpfc_vport *vport, uint32_t did, uint8_t retry)
dea31012005-04-17 16:05:31 -0500934{
James Smart2e0fef82007-06-17 19:56:36 -0500935 struct lpfc_hba *phba = vport->phba;
dea31012005-04-17 16:05:31 -0500936 struct serv_parm *sp;
937 IOCB_t *icmd;
938 struct lpfc_iocbq *elsiocb;
939 struct lpfc_sli_ring *pring;
940 struct lpfc_sli *psli;
941 uint8_t *pcmd;
942 uint16_t cmdsize;
James Smart92d7f7b2007-06-17 19:56:38 -0500943 int ret;
dea31012005-04-17 16:05:31 -0500944
945 psli = &phba->sli;
946 pring = &psli->ring[LPFC_ELS_RING]; /* ELS ring */
947
James Smart92d7f7b2007-06-17 19:56:38 -0500948 cmdsize = (sizeof(uint32_t) + sizeof(struct serv_parm));
James Smart2e0fef82007-06-17 19:56:36 -0500949 elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, NULL, did,
950 ELS_CMD_PLOGI);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500951 if (!elsiocb)
952 return 1;
dea31012005-04-17 16:05:31 -0500953
954 icmd = &elsiocb->iocb;
955 pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
956
957 /* For PLOGI request, remainder of payload is service parameters */
958 *((uint32_t *) (pcmd)) = ELS_CMD_PLOGI;
James Smart92d7f7b2007-06-17 19:56:38 -0500959 pcmd += sizeof(uint32_t);
960 memcpy(pcmd, &vport->fc_sparam, sizeof(struct serv_parm));
dea31012005-04-17 16:05:31 -0500961 sp = (struct serv_parm *) pcmd;
962
963 if (sp->cmn.fcphLow < FC_PH_4_3)
964 sp->cmn.fcphLow = FC_PH_4_3;
965
966 if (sp->cmn.fcphHigh < FC_PH3)
967 sp->cmn.fcphHigh = FC_PH3;
968
969 phba->fc_stat.elsXmitPLOGI++;
970 elsiocb->iocb_cmpl = lpfc_cmpl_els_plogi;
James Smart92d7f7b2007-06-17 19:56:38 -0500971 ret = lpfc_sli_issue_iocb(phba, pring, elsiocb, 0);
972
973 if (ret == IOCB_ERROR) {
dea31012005-04-17 16:05:31 -0500974 lpfc_els_free_iocb(phba, elsiocb);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500975 return 1;
dea31012005-04-17 16:05:31 -0500976 }
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500977 return 0;
dea31012005-04-17 16:05:31 -0500978}
979
980static void
James Smart2e0fef82007-06-17 19:56:36 -0500981lpfc_cmpl_els_prli(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
982 struct lpfc_iocbq *rspiocb)
dea31012005-04-17 16:05:31 -0500983{
James Smart2e0fef82007-06-17 19:56:36 -0500984 struct lpfc_vport *vport = cmdiocb->vport;
985 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
dea31012005-04-17 16:05:31 -0500986 IOCB_t *irsp;
987 struct lpfc_sli *psli;
988 struct lpfc_nodelist *ndlp;
989
990 psli = &phba->sli;
991 /* we pass cmdiocb to state machine which needs rspiocb as well */
992 cmdiocb->context_un.rsp_iocb = rspiocb;
993
994 irsp = &(rspiocb->iocb);
995 ndlp = (struct lpfc_nodelist *) cmdiocb->context1;
James Smart2e0fef82007-06-17 19:56:36 -0500996 spin_lock_irq(shost->host_lock);
dea31012005-04-17 16:05:31 -0500997 ndlp->nlp_flag &= ~NLP_PRLI_SND;
James Smart2e0fef82007-06-17 19:56:36 -0500998 spin_unlock_irq(shost->host_lock);
dea31012005-04-17 16:05:31 -0500999
1000 /* PRLI completes to NPort <nlp_DID> */
1001 lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
James Smart92d7f7b2007-06-17 19:56:38 -05001002 "%d (%d):0103 PRLI completes to NPort x%x "
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001003 "Data: x%x x%x x%x x%x\n",
James Smart92d7f7b2007-06-17 19:56:38 -05001004 phba->brd_no, vport->vpi, ndlp->nlp_DID,
1005 irsp->ulpStatus, irsp->un.ulpWord[4], irsp->ulpTimeout,
James Smart2e0fef82007-06-17 19:56:36 -05001006 vport->num_disc_nodes);
dea31012005-04-17 16:05:31 -05001007
James Smart2e0fef82007-06-17 19:56:36 -05001008 vport->fc_prli_sent--;
dea31012005-04-17 16:05:31 -05001009 /* Check to see if link went down during discovery */
James Smart2e0fef82007-06-17 19:56:36 -05001010 if (lpfc_els_chk_latt(vport))
dea31012005-04-17 16:05:31 -05001011 goto out;
1012
1013 if (irsp->ulpStatus) {
1014 /* Check for retry */
1015 if (lpfc_els_retry(phba, cmdiocb, rspiocb)) {
1016 /* ELS command is being retried */
1017 goto out;
1018 }
1019 /* PRLI failed */
1020 /* Do not call DSM for lpfc_els_abort'ed ELS cmds */
1021 if ((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) &&
James Smart92d7f7b2007-06-17 19:56:38 -05001022 ((irsp->un.ulpWord[4] == IOERR_SLI_ABORTED) ||
1023 (irsp->un.ulpWord[4] == IOERR_LINK_DOWN) ||
1024 (irsp->un.ulpWord[4] == IOERR_SLI_DOWN))) {
dea31012005-04-17 16:05:31 -05001025 goto out;
Jamie Wellnitz2fe165b2006-02-28 19:25:31 -05001026 } else {
James Smart2e0fef82007-06-17 19:56:36 -05001027 lpfc_disc_state_machine(vport, ndlp, cmdiocb,
James Smart92d7f7b2007-06-17 19:56:38 -05001028 NLP_EVT_CMPL_PRLI);
dea31012005-04-17 16:05:31 -05001029 }
1030 } else {
1031 /* Good status, call state machine */
James Smart2e0fef82007-06-17 19:56:36 -05001032 lpfc_disc_state_machine(vport, ndlp, cmdiocb,
James Smart92d7f7b2007-06-17 19:56:38 -05001033 NLP_EVT_CMPL_PRLI);
dea31012005-04-17 16:05:31 -05001034 }
1035
1036out:
1037 lpfc_els_free_iocb(phba, cmdiocb);
1038 return;
1039}
1040
1041int
James Smart2e0fef82007-06-17 19:56:36 -05001042lpfc_issue_els_prli(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
dea31012005-04-17 16:05:31 -05001043 uint8_t retry)
1044{
James Smart2e0fef82007-06-17 19:56:36 -05001045 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
1046 struct lpfc_hba *phba = vport->phba;
dea31012005-04-17 16:05:31 -05001047 PRLI *npr;
1048 IOCB_t *icmd;
1049 struct lpfc_iocbq *elsiocb;
1050 struct lpfc_sli_ring *pring;
1051 struct lpfc_sli *psli;
1052 uint8_t *pcmd;
1053 uint16_t cmdsize;
1054
1055 psli = &phba->sli;
1056 pring = &psli->ring[LPFC_ELS_RING]; /* ELS ring */
1057
James Smart92d7f7b2007-06-17 19:56:38 -05001058 cmdsize = (sizeof(uint32_t) + sizeof(PRLI));
James Smart2e0fef82007-06-17 19:56:36 -05001059 elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp,
1060 ndlp->nlp_DID, ELS_CMD_PRLI);
James Smart488d1462006-03-07 15:02:37 -05001061 if (!elsiocb)
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001062 return 1;
dea31012005-04-17 16:05:31 -05001063
1064 icmd = &elsiocb->iocb;
1065 pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
1066
1067 /* For PRLI request, remainder of payload is service parameters */
James Smart92d7f7b2007-06-17 19:56:38 -05001068 memset(pcmd, 0, (sizeof(PRLI) + sizeof(uint32_t)));
dea31012005-04-17 16:05:31 -05001069 *((uint32_t *) (pcmd)) = ELS_CMD_PRLI;
James Smart92d7f7b2007-06-17 19:56:38 -05001070 pcmd += sizeof(uint32_t);
dea31012005-04-17 16:05:31 -05001071
1072 /* For PRLI, remainder of payload is PRLI parameter page */
1073 npr = (PRLI *) pcmd;
1074 /*
1075 * If our firmware version is 3.20 or later,
1076 * set the following bits for FC-TAPE support.
1077 */
1078 if (phba->vpd.rev.feaLevelHigh >= 0x02) {
1079 npr->ConfmComplAllowed = 1;
1080 npr->Retry = 1;
1081 npr->TaskRetryIdReq = 1;
1082 }
1083 npr->estabImagePair = 1;
1084 npr->readXferRdyDis = 1;
1085
1086 /* For FCP support */
1087 npr->prliType = PRLI_FCP_TYPE;
1088 npr->initiatorFunc = 1;
1089
1090 phba->fc_stat.elsXmitPRLI++;
1091 elsiocb->iocb_cmpl = lpfc_cmpl_els_prli;
James Smart2e0fef82007-06-17 19:56:36 -05001092 spin_lock_irq(shost->host_lock);
dea31012005-04-17 16:05:31 -05001093 ndlp->nlp_flag |= NLP_PRLI_SND;
James Smart2e0fef82007-06-17 19:56:36 -05001094 spin_unlock_irq(shost->host_lock);
dea31012005-04-17 16:05:31 -05001095 if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) {
James Smart2e0fef82007-06-17 19:56:36 -05001096 spin_lock_irq(shost->host_lock);
dea31012005-04-17 16:05:31 -05001097 ndlp->nlp_flag &= ~NLP_PRLI_SND;
James Smart2e0fef82007-06-17 19:56:36 -05001098 spin_unlock_irq(shost->host_lock);
dea31012005-04-17 16:05:31 -05001099 lpfc_els_free_iocb(phba, elsiocb);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001100 return 1;
dea31012005-04-17 16:05:31 -05001101 }
James Smart2e0fef82007-06-17 19:56:36 -05001102 vport->fc_prli_sent++;
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001103 return 0;
dea31012005-04-17 16:05:31 -05001104}
1105
1106static void
James Smart2e0fef82007-06-17 19:56:36 -05001107lpfc_more_adisc(struct lpfc_vport *vport)
dea31012005-04-17 16:05:31 -05001108{
1109 int sentadisc;
James Smart2e0fef82007-06-17 19:56:36 -05001110 struct lpfc_hba *phba = vport->phba;
dea31012005-04-17 16:05:31 -05001111
James Smart2e0fef82007-06-17 19:56:36 -05001112 if (vport->num_disc_nodes)
1113 vport->num_disc_nodes--;
dea31012005-04-17 16:05:31 -05001114
1115 /* Continue discovery with <num_disc_nodes> ADISCs to go */
1116 lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
James Smart92d7f7b2007-06-17 19:56:38 -05001117 "%d (%d):0210 Continue discovery with %d ADISCs to go "
dea31012005-04-17 16:05:31 -05001118 "Data: x%x x%x x%x\n",
James Smart92d7f7b2007-06-17 19:56:38 -05001119 phba->brd_no, vport->vpi, vport->num_disc_nodes,
James Smart2e0fef82007-06-17 19:56:36 -05001120 vport->fc_adisc_cnt, vport->fc_flag, vport->port_state);
dea31012005-04-17 16:05:31 -05001121
1122 /* Check to see if there are more ADISCs to be sent */
James Smart2e0fef82007-06-17 19:56:36 -05001123 if (vport->fc_flag & FC_NLP_MORE) {
1124 lpfc_set_disctmo(vport);
1125 /* go thru NPR nodes and issue any remaining ELS ADISCs */
1126 sentadisc = lpfc_els_disc_adisc(vport);
dea31012005-04-17 16:05:31 -05001127 }
1128 return;
1129}
1130
1131static void
James Smart2e0fef82007-06-17 19:56:36 -05001132lpfc_rscn_disc(struct lpfc_vport *vport)
dea31012005-04-17 16:05:31 -05001133{
James Smart2e0fef82007-06-17 19:56:36 -05001134 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
1135
dea31012005-04-17 16:05:31 -05001136 /* RSCN discovery */
James Smart2e0fef82007-06-17 19:56:36 -05001137 /* go thru NPR nodes and issue ELS PLOGIs */
1138 if (vport->fc_npr_cnt)
1139 if (lpfc_els_disc_plogi(vport))
dea31012005-04-17 16:05:31 -05001140 return;
James Smart2e0fef82007-06-17 19:56:36 -05001141
1142 if (vport->fc_flag & FC_RSCN_MODE) {
dea31012005-04-17 16:05:31 -05001143 /* Check to see if more RSCNs came in while we were
1144 * processing this one.
1145 */
James Smart2e0fef82007-06-17 19:56:36 -05001146 if ((vport->fc_rscn_id_cnt == 0) &&
1147 (!(vport->fc_flag & FC_RSCN_DISCOVERY))) {
1148 spin_lock_irq(shost->host_lock);
1149 vport->fc_flag &= ~FC_RSCN_MODE;
1150 spin_unlock_irq(shost->host_lock);
dea31012005-04-17 16:05:31 -05001151 } else {
James Smart2e0fef82007-06-17 19:56:36 -05001152 lpfc_els_handle_rscn(vport);
dea31012005-04-17 16:05:31 -05001153 }
1154 }
1155}
1156
1157static void
James Smart2e0fef82007-06-17 19:56:36 -05001158lpfc_cmpl_els_adisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
1159 struct lpfc_iocbq *rspiocb)
dea31012005-04-17 16:05:31 -05001160{
James Smart2e0fef82007-06-17 19:56:36 -05001161 struct lpfc_vport *vport = cmdiocb->vport;
1162 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
dea31012005-04-17 16:05:31 -05001163 IOCB_t *irsp;
dea31012005-04-17 16:05:31 -05001164 struct lpfc_nodelist *ndlp;
James Smart2e0fef82007-06-17 19:56:36 -05001165 int disc;
dea31012005-04-17 16:05:31 -05001166
1167 /* we pass cmdiocb to state machine which needs rspiocb as well */
1168 cmdiocb->context_un.rsp_iocb = rspiocb;
1169
1170 irsp = &(rspiocb->iocb);
1171 ndlp = (struct lpfc_nodelist *) cmdiocb->context1;
dea31012005-04-17 16:05:31 -05001172
1173 /* Since ndlp can be freed in the disc state machine, note if this node
1174 * is being used during discovery.
1175 */
James Smart2e0fef82007-06-17 19:56:36 -05001176 spin_lock_irq(shost->host_lock);
dea31012005-04-17 16:05:31 -05001177 disc = (ndlp->nlp_flag & NLP_NPR_2B_DISC);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001178 ndlp->nlp_flag &= ~(NLP_ADISC_SND | NLP_NPR_2B_DISC);
James Smart2e0fef82007-06-17 19:56:36 -05001179 spin_unlock_irq(shost->host_lock);
dea31012005-04-17 16:05:31 -05001180
1181 /* ADISC completes to NPort <nlp_DID> */
1182 lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
James Smart92d7f7b2007-06-17 19:56:38 -05001183 "%d (%d):0104 ADISC completes to NPort x%x "
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001184 "Data: x%x x%x x%x x%x x%x\n",
James Smart92d7f7b2007-06-17 19:56:38 -05001185 phba->brd_no, vport->vpi, ndlp->nlp_DID,
1186 irsp->ulpStatus, irsp->un.ulpWord[4], irsp->ulpTimeout,
1187 disc, vport->num_disc_nodes);
dea31012005-04-17 16:05:31 -05001188
1189 /* Check to see if link went down during discovery */
James Smart2e0fef82007-06-17 19:56:36 -05001190 if (lpfc_els_chk_latt(vport)) {
1191 spin_lock_irq(shost->host_lock);
dea31012005-04-17 16:05:31 -05001192 ndlp->nlp_flag |= NLP_NPR_2B_DISC;
James Smart2e0fef82007-06-17 19:56:36 -05001193 spin_unlock_irq(shost->host_lock);
dea31012005-04-17 16:05:31 -05001194 goto out;
1195 }
1196
1197 if (irsp->ulpStatus) {
1198 /* Check for retry */
1199 if (lpfc_els_retry(phba, cmdiocb, rspiocb)) {
1200 /* ELS command is being retried */
1201 if (disc) {
James Smart2e0fef82007-06-17 19:56:36 -05001202 spin_lock_irq(shost->host_lock);
dea31012005-04-17 16:05:31 -05001203 ndlp->nlp_flag |= NLP_NPR_2B_DISC;
James Smart2e0fef82007-06-17 19:56:36 -05001204 spin_unlock_irq(shost->host_lock);
1205 lpfc_set_disctmo(vport);
dea31012005-04-17 16:05:31 -05001206 }
1207 goto out;
1208 }
1209 /* ADISC failed */
1210 /* Do not call DSM for lpfc_els_abort'ed ELS cmds */
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001211 if ((irsp->ulpStatus != IOSTAT_LOCAL_REJECT) ||
1212 ((irsp->un.ulpWord[4] != IOERR_SLI_ABORTED) &&
1213 (irsp->un.ulpWord[4] != IOERR_LINK_DOWN) &&
1214 (irsp->un.ulpWord[4] != IOERR_SLI_DOWN))) {
James Smart2e0fef82007-06-17 19:56:36 -05001215 lpfc_disc_state_machine(vport, ndlp, cmdiocb,
dea31012005-04-17 16:05:31 -05001216 NLP_EVT_CMPL_ADISC);
1217 }
1218 } else {
1219 /* Good status, call state machine */
James Smart2e0fef82007-06-17 19:56:36 -05001220 lpfc_disc_state_machine(vport, ndlp, cmdiocb,
dea31012005-04-17 16:05:31 -05001221 NLP_EVT_CMPL_ADISC);
1222 }
1223
James Smart2e0fef82007-06-17 19:56:36 -05001224 if (disc && vport->num_disc_nodes) {
dea31012005-04-17 16:05:31 -05001225 /* Check to see if there are more ADISCs to be sent */
James Smart2e0fef82007-06-17 19:56:36 -05001226 lpfc_more_adisc(vport);
dea31012005-04-17 16:05:31 -05001227
1228 /* Check to see if we are done with ADISC authentication */
James Smart2e0fef82007-06-17 19:56:36 -05001229 if (vport->num_disc_nodes == 0) {
James Smart92d7f7b2007-06-17 19:56:38 -05001230 /* If we get here, there is nothing left to ADISC */
1231 /*
1232 * For NPIV, cmpl_reg_vpi will set port_state to READY,
1233 * and continue discovery.
1234 */
1235 if ((phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) &&
1236 !(vport->fc_flag & FC_RSCN_MODE)) {
1237 lpfc_issue_reg_vpi(phba, vport);
1238 goto out;
1239 }
1240 /*
1241 * For SLI2, we need to set port_state to READY
1242 * and continue discovery.
1243 */
1244 if (vport->port_state < LPFC_VPORT_READY) {
1245 /* If we get here, there is nothing to ADISC */
James Smarted957682007-06-17 19:56:37 -05001246 if (vport->port_type == LPFC_PHYSICAL_PORT)
James Smart2e0fef82007-06-17 19:56:36 -05001247 lpfc_issue_clear_la(phba, vport);
James Smart92d7f7b2007-06-17 19:56:38 -05001248
1249 if (!(vport->fc_flag & FC_ABORT_DISCOVERY)) {
1250 vport->num_disc_nodes = 0;
1251 /* go thru NPR list, issue ELS PLOGIs */
1252 if (vport->fc_npr_cnt)
1253 lpfc_els_disc_plogi(vport);
1254
1255 if (!vport->num_disc_nodes) {
1256 spin_lock_irq(shost->host_lock);
1257 vport->fc_flag &=
1258 ~FC_NDISC_ACTIVE;
1259 spin_unlock_irq(
1260 shost->host_lock);
1261 lpfc_can_disctmo(vport);
1262 }
1263 }
1264 vport->port_state = LPFC_VPORT_READY;
dea31012005-04-17 16:05:31 -05001265 } else {
James Smart2e0fef82007-06-17 19:56:36 -05001266 lpfc_rscn_disc(vport);
dea31012005-04-17 16:05:31 -05001267 }
1268 }
1269 }
dea31012005-04-17 16:05:31 -05001270out:
1271 lpfc_els_free_iocb(phba, cmdiocb);
1272 return;
1273}
1274
1275int
James Smart2e0fef82007-06-17 19:56:36 -05001276lpfc_issue_els_adisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
dea31012005-04-17 16:05:31 -05001277 uint8_t retry)
1278{
James Smart2e0fef82007-06-17 19:56:36 -05001279 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
1280 struct lpfc_hba *phba = vport->phba;
dea31012005-04-17 16:05:31 -05001281 ADISC *ap;
1282 IOCB_t *icmd;
1283 struct lpfc_iocbq *elsiocb;
James Smart2e0fef82007-06-17 19:56:36 -05001284 struct lpfc_sli *psli = &phba->sli;
1285 struct lpfc_sli_ring *pring = &psli->ring[LPFC_ELS_RING];
dea31012005-04-17 16:05:31 -05001286 uint8_t *pcmd;
1287 uint16_t cmdsize;
1288
James Smart92d7f7b2007-06-17 19:56:38 -05001289 cmdsize = (sizeof(uint32_t) + sizeof(ADISC));
James Smart2e0fef82007-06-17 19:56:36 -05001290 elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp,
1291 ndlp->nlp_DID, ELS_CMD_ADISC);
James Smart488d1462006-03-07 15:02:37 -05001292 if (!elsiocb)
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001293 return 1;
dea31012005-04-17 16:05:31 -05001294
1295 icmd = &elsiocb->iocb;
1296 pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
1297
1298 /* For ADISC request, remainder of payload is service parameters */
1299 *((uint32_t *) (pcmd)) = ELS_CMD_ADISC;
James Smart92d7f7b2007-06-17 19:56:38 -05001300 pcmd += sizeof(uint32_t);
dea31012005-04-17 16:05:31 -05001301
1302 /* Fill in ADISC payload */
1303 ap = (ADISC *) pcmd;
1304 ap->hardAL_PA = phba->fc_pref_ALPA;
James Smart92d7f7b2007-06-17 19:56:38 -05001305 memcpy(&ap->portName, &vport->fc_portname, sizeof(struct lpfc_name));
1306 memcpy(&ap->nodeName, &vport->fc_nodename, sizeof(struct lpfc_name));
James Smart2e0fef82007-06-17 19:56:36 -05001307 ap->DID = be32_to_cpu(vport->fc_myDID);
dea31012005-04-17 16:05:31 -05001308
1309 phba->fc_stat.elsXmitADISC++;
1310 elsiocb->iocb_cmpl = lpfc_cmpl_els_adisc;
James Smart2e0fef82007-06-17 19:56:36 -05001311 spin_lock_irq(shost->host_lock);
dea31012005-04-17 16:05:31 -05001312 ndlp->nlp_flag |= NLP_ADISC_SND;
James Smart2e0fef82007-06-17 19:56:36 -05001313 spin_unlock_irq(shost->host_lock);
dea31012005-04-17 16:05:31 -05001314 if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) {
James Smart2e0fef82007-06-17 19:56:36 -05001315 spin_lock_irq(shost->host_lock);
dea31012005-04-17 16:05:31 -05001316 ndlp->nlp_flag &= ~NLP_ADISC_SND;
James Smart2e0fef82007-06-17 19:56:36 -05001317 spin_unlock_irq(shost->host_lock);
dea31012005-04-17 16:05:31 -05001318 lpfc_els_free_iocb(phba, elsiocb);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001319 return 1;
dea31012005-04-17 16:05:31 -05001320 }
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001321 return 0;
dea31012005-04-17 16:05:31 -05001322}
1323
1324static void
James Smart2e0fef82007-06-17 19:56:36 -05001325lpfc_cmpl_els_logo(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
1326 struct lpfc_iocbq *rspiocb)
dea31012005-04-17 16:05:31 -05001327{
James Smart2e0fef82007-06-17 19:56:36 -05001328 struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) cmdiocb->context1;
1329 struct lpfc_vport *vport = ndlp->vport;
1330 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
dea31012005-04-17 16:05:31 -05001331 IOCB_t *irsp;
1332 struct lpfc_sli *psli;
dea31012005-04-17 16:05:31 -05001333
1334 psli = &phba->sli;
1335 /* we pass cmdiocb to state machine which needs rspiocb as well */
1336 cmdiocb->context_un.rsp_iocb = rspiocb;
1337
1338 irsp = &(rspiocb->iocb);
James Smart2e0fef82007-06-17 19:56:36 -05001339 spin_lock_irq(shost->host_lock);
dea31012005-04-17 16:05:31 -05001340 ndlp->nlp_flag &= ~NLP_LOGO_SND;
James Smart2e0fef82007-06-17 19:56:36 -05001341 spin_unlock_irq(shost->host_lock);
dea31012005-04-17 16:05:31 -05001342
1343 /* LOGO completes to NPort <nlp_DID> */
1344 lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
James Smart92d7f7b2007-06-17 19:56:38 -05001345 "%d (%d):0105 LOGO completes to NPort x%x "
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001346 "Data: x%x x%x x%x x%x\n",
James Smart92d7f7b2007-06-17 19:56:38 -05001347 phba->brd_no, vport->vpi, ndlp->nlp_DID,
1348 irsp->ulpStatus, irsp->un.ulpWord[4], irsp->ulpTimeout,
James Smart2e0fef82007-06-17 19:56:36 -05001349 vport->num_disc_nodes);
dea31012005-04-17 16:05:31 -05001350
1351 /* Check to see if link went down during discovery */
James Smart2e0fef82007-06-17 19:56:36 -05001352 if (lpfc_els_chk_latt(vport))
dea31012005-04-17 16:05:31 -05001353 goto out;
1354
James Smart92d7f7b2007-06-17 19:56:38 -05001355 if (ndlp->nlp_flag & NLP_TARGET_REMOVE) {
1356 /* NLP_EVT_DEVICE_RM should unregister the RPI
1357 * which should abort all outstanding IOs.
1358 */
1359 lpfc_disc_state_machine(vport, ndlp, cmdiocb,
1360 NLP_EVT_DEVICE_RM);
1361 goto out;
1362 }
1363
dea31012005-04-17 16:05:31 -05001364 if (irsp->ulpStatus) {
1365 /* Check for retry */
James Smart2e0fef82007-06-17 19:56:36 -05001366 if (lpfc_els_retry(phba, cmdiocb, rspiocb))
dea31012005-04-17 16:05:31 -05001367 /* ELS command is being retried */
1368 goto out;
dea31012005-04-17 16:05:31 -05001369 /* LOGO failed */
1370 /* Do not call DSM for lpfc_els_abort'ed ELS cmds */
1371 if ((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) &&
James Smart92d7f7b2007-06-17 19:56:38 -05001372 ((irsp->un.ulpWord[4] == IOERR_SLI_ABORTED) ||
1373 (irsp->un.ulpWord[4] == IOERR_LINK_DOWN) ||
1374 (irsp->un.ulpWord[4] == IOERR_SLI_DOWN))) {
dea31012005-04-17 16:05:31 -05001375 goto out;
Jamie Wellnitz2fe165b2006-02-28 19:25:31 -05001376 } else {
James Smart2e0fef82007-06-17 19:56:36 -05001377 lpfc_disc_state_machine(vport, ndlp, cmdiocb,
James Smart92d7f7b2007-06-17 19:56:38 -05001378 NLP_EVT_CMPL_LOGO);
dea31012005-04-17 16:05:31 -05001379 }
1380 } else {
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05001381 /* Good status, call state machine.
1382 * This will unregister the rpi if needed.
1383 */
James Smart2e0fef82007-06-17 19:56:36 -05001384 lpfc_disc_state_machine(vport, ndlp, cmdiocb,
James Smart92d7f7b2007-06-17 19:56:38 -05001385 NLP_EVT_CMPL_LOGO);
dea31012005-04-17 16:05:31 -05001386 }
1387
1388out:
1389 lpfc_els_free_iocb(phba, cmdiocb);
1390 return;
1391}
1392
1393int
James Smart2e0fef82007-06-17 19:56:36 -05001394lpfc_issue_els_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
dea31012005-04-17 16:05:31 -05001395 uint8_t retry)
1396{
James Smart2e0fef82007-06-17 19:56:36 -05001397 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
1398 struct lpfc_hba *phba = vport->phba;
dea31012005-04-17 16:05:31 -05001399 IOCB_t *icmd;
1400 struct lpfc_iocbq *elsiocb;
1401 struct lpfc_sli_ring *pring;
1402 struct lpfc_sli *psli;
1403 uint8_t *pcmd;
1404 uint16_t cmdsize;
James Smart92d7f7b2007-06-17 19:56:38 -05001405 int rc;
dea31012005-04-17 16:05:31 -05001406
1407 psli = &phba->sli;
1408 pring = &psli->ring[LPFC_ELS_RING];
1409
James Smart92d7f7b2007-06-17 19:56:38 -05001410 cmdsize = (2 * sizeof(uint32_t)) + sizeof(struct lpfc_name);
James Smart2e0fef82007-06-17 19:56:36 -05001411 elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp,
1412 ndlp->nlp_DID, ELS_CMD_LOGO);
James Smart488d1462006-03-07 15:02:37 -05001413 if (!elsiocb)
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001414 return 1;
dea31012005-04-17 16:05:31 -05001415
1416 icmd = &elsiocb->iocb;
1417 pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
1418 *((uint32_t *) (pcmd)) = ELS_CMD_LOGO;
James Smart92d7f7b2007-06-17 19:56:38 -05001419 pcmd += sizeof(uint32_t);
dea31012005-04-17 16:05:31 -05001420
1421 /* Fill in LOGO payload */
James Smart2e0fef82007-06-17 19:56:36 -05001422 *((uint32_t *) (pcmd)) = be32_to_cpu(vport->fc_myDID);
James Smart92d7f7b2007-06-17 19:56:38 -05001423 pcmd += sizeof(uint32_t);
1424 memcpy(pcmd, &vport->fc_portname, sizeof(struct lpfc_name));
dea31012005-04-17 16:05:31 -05001425
1426 phba->fc_stat.elsXmitLOGO++;
1427 elsiocb->iocb_cmpl = lpfc_cmpl_els_logo;
James Smart2e0fef82007-06-17 19:56:36 -05001428 spin_lock_irq(shost->host_lock);
dea31012005-04-17 16:05:31 -05001429 ndlp->nlp_flag |= NLP_LOGO_SND;
James Smart2e0fef82007-06-17 19:56:36 -05001430 spin_unlock_irq(shost->host_lock);
James Smart92d7f7b2007-06-17 19:56:38 -05001431 rc = lpfc_sli_issue_iocb(phba, pring, elsiocb, 0);
1432
1433 if (rc == IOCB_ERROR) {
James Smart2e0fef82007-06-17 19:56:36 -05001434 spin_lock_irq(shost->host_lock);
dea31012005-04-17 16:05:31 -05001435 ndlp->nlp_flag &= ~NLP_LOGO_SND;
James Smart2e0fef82007-06-17 19:56:36 -05001436 spin_unlock_irq(shost->host_lock);
dea31012005-04-17 16:05:31 -05001437 lpfc_els_free_iocb(phba, elsiocb);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001438 return 1;
dea31012005-04-17 16:05:31 -05001439 }
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001440 return 0;
dea31012005-04-17 16:05:31 -05001441}
1442
1443static void
James Smart2e0fef82007-06-17 19:56:36 -05001444lpfc_cmpl_els_cmd(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
1445 struct lpfc_iocbq *rspiocb)
dea31012005-04-17 16:05:31 -05001446{
James Smart2e0fef82007-06-17 19:56:36 -05001447 struct lpfc_vport *vport = cmdiocb->vport;
dea31012005-04-17 16:05:31 -05001448 IOCB_t *irsp;
1449
1450 irsp = &rspiocb->iocb;
1451
1452 /* ELS cmd tag <ulpIoTag> completes */
James Smart92d7f7b2007-06-17 19:56:38 -05001453 lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
1454 "%d (%d):0106 ELS cmd tag x%x completes Data: x%x x%x "
1455 "x%x\n",
1456 phba->brd_no, vport->vpi,
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001457 irsp->ulpIoTag, irsp->ulpStatus,
1458 irsp->un.ulpWord[4], irsp->ulpTimeout);
dea31012005-04-17 16:05:31 -05001459
1460 /* Check to see if link went down during discovery */
James Smart2e0fef82007-06-17 19:56:36 -05001461 lpfc_els_chk_latt(vport);
dea31012005-04-17 16:05:31 -05001462 lpfc_els_free_iocb(phba, cmdiocb);
1463 return;
1464}
1465
1466int
James Smart2e0fef82007-06-17 19:56:36 -05001467lpfc_issue_els_scr(struct lpfc_vport *vport, uint32_t nportid, uint8_t retry)
dea31012005-04-17 16:05:31 -05001468{
James Smart2e0fef82007-06-17 19:56:36 -05001469 struct lpfc_hba *phba = vport->phba;
dea31012005-04-17 16:05:31 -05001470 IOCB_t *icmd;
1471 struct lpfc_iocbq *elsiocb;
1472 struct lpfc_sli_ring *pring;
1473 struct lpfc_sli *psli;
1474 uint8_t *pcmd;
1475 uint16_t cmdsize;
1476 struct lpfc_nodelist *ndlp;
1477
1478 psli = &phba->sli;
1479 pring = &psli->ring[LPFC_ELS_RING]; /* ELS ring */
James Smart92d7f7b2007-06-17 19:56:38 -05001480 cmdsize = (sizeof(uint32_t) + sizeof(SCR));
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001481 ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL);
1482 if (!ndlp)
1483 return 1;
dea31012005-04-17 16:05:31 -05001484
James Smart2e0fef82007-06-17 19:56:36 -05001485 lpfc_nlp_init(vport, ndlp, nportid);
dea31012005-04-17 16:05:31 -05001486
James Smart2e0fef82007-06-17 19:56:36 -05001487 elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp,
1488 ndlp->nlp_DID, ELS_CMD_SCR);
1489
James Smart488d1462006-03-07 15:02:37 -05001490 if (!elsiocb) {
James Smart329f9bc2007-04-25 09:53:01 -04001491 lpfc_nlp_put(ndlp);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001492 return 1;
dea31012005-04-17 16:05:31 -05001493 }
1494
1495 icmd = &elsiocb->iocb;
1496 pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
1497
1498 *((uint32_t *) (pcmd)) = ELS_CMD_SCR;
James Smart92d7f7b2007-06-17 19:56:38 -05001499 pcmd += sizeof(uint32_t);
dea31012005-04-17 16:05:31 -05001500
1501 /* For SCR, remainder of payload is SCR parameter page */
James Smart92d7f7b2007-06-17 19:56:38 -05001502 memset(pcmd, 0, sizeof(SCR));
dea31012005-04-17 16:05:31 -05001503 ((SCR *) pcmd)->Function = SCR_FUNC_FULL;
1504
1505 phba->fc_stat.elsXmitSCR++;
1506 elsiocb->iocb_cmpl = lpfc_cmpl_els_cmd;
dea31012005-04-17 16:05:31 -05001507 if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) {
James Smart329f9bc2007-04-25 09:53:01 -04001508 lpfc_nlp_put(ndlp);
dea31012005-04-17 16:05:31 -05001509 lpfc_els_free_iocb(phba, elsiocb);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001510 return 1;
dea31012005-04-17 16:05:31 -05001511 }
James Smart329f9bc2007-04-25 09:53:01 -04001512 lpfc_nlp_put(ndlp);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001513 return 0;
dea31012005-04-17 16:05:31 -05001514}
1515
1516static int
James Smart2e0fef82007-06-17 19:56:36 -05001517lpfc_issue_els_farpr(struct lpfc_vport *vport, uint32_t nportid, uint8_t retry)
dea31012005-04-17 16:05:31 -05001518{
James Smart2e0fef82007-06-17 19:56:36 -05001519 struct lpfc_hba *phba = vport->phba;
dea31012005-04-17 16:05:31 -05001520 IOCB_t *icmd;
1521 struct lpfc_iocbq *elsiocb;
1522 struct lpfc_sli_ring *pring;
1523 struct lpfc_sli *psli;
1524 FARP *fp;
1525 uint8_t *pcmd;
1526 uint32_t *lp;
1527 uint16_t cmdsize;
1528 struct lpfc_nodelist *ondlp;
1529 struct lpfc_nodelist *ndlp;
1530
1531 psli = &phba->sli;
1532 pring = &psli->ring[LPFC_ELS_RING]; /* ELS ring */
James Smart92d7f7b2007-06-17 19:56:38 -05001533 cmdsize = (sizeof(uint32_t) + sizeof(FARP));
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001534 ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL);
1535 if (!ndlp)
1536 return 1;
dea31012005-04-17 16:05:31 -05001537
James Smart2e0fef82007-06-17 19:56:36 -05001538 lpfc_nlp_init(vport, ndlp, nportid);
1539
1540 elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp,
1541 ndlp->nlp_DID, ELS_CMD_RNID);
James Smart488d1462006-03-07 15:02:37 -05001542 if (!elsiocb) {
James Smart329f9bc2007-04-25 09:53:01 -04001543 lpfc_nlp_put(ndlp);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001544 return 1;
dea31012005-04-17 16:05:31 -05001545 }
1546
1547 icmd = &elsiocb->iocb;
1548 pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
1549
1550 *((uint32_t *) (pcmd)) = ELS_CMD_FARPR;
James Smart92d7f7b2007-06-17 19:56:38 -05001551 pcmd += sizeof(uint32_t);
dea31012005-04-17 16:05:31 -05001552
1553 /* Fill in FARPR payload */
1554 fp = (FARP *) (pcmd);
James Smart92d7f7b2007-06-17 19:56:38 -05001555 memset(fp, 0, sizeof(FARP));
dea31012005-04-17 16:05:31 -05001556 lp = (uint32_t *) pcmd;
1557 *lp++ = be32_to_cpu(nportid);
James Smart2e0fef82007-06-17 19:56:36 -05001558 *lp++ = be32_to_cpu(vport->fc_myDID);
dea31012005-04-17 16:05:31 -05001559 fp->Rflags = 0;
1560 fp->Mflags = (FARP_MATCH_PORT | FARP_MATCH_NODE);
1561
James Smart92d7f7b2007-06-17 19:56:38 -05001562 memcpy(&fp->RportName, &vport->fc_portname, sizeof(struct lpfc_name));
1563 memcpy(&fp->RnodeName, &vport->fc_nodename, sizeof(struct lpfc_name));
James Smart2e0fef82007-06-17 19:56:36 -05001564 ondlp = lpfc_findnode_did(vport, nportid);
1565 if (ondlp) {
dea31012005-04-17 16:05:31 -05001566 memcpy(&fp->OportName, &ondlp->nlp_portname,
James Smart92d7f7b2007-06-17 19:56:38 -05001567 sizeof(struct lpfc_name));
dea31012005-04-17 16:05:31 -05001568 memcpy(&fp->OnodeName, &ondlp->nlp_nodename,
James Smart92d7f7b2007-06-17 19:56:38 -05001569 sizeof(struct lpfc_name));
dea31012005-04-17 16:05:31 -05001570 }
1571
1572 phba->fc_stat.elsXmitFARPR++;
1573 elsiocb->iocb_cmpl = lpfc_cmpl_els_cmd;
dea31012005-04-17 16:05:31 -05001574 if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) {
James Smart329f9bc2007-04-25 09:53:01 -04001575 lpfc_nlp_put(ndlp);
dea31012005-04-17 16:05:31 -05001576 lpfc_els_free_iocb(phba, elsiocb);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001577 return 1;
dea31012005-04-17 16:05:31 -05001578 }
James Smart329f9bc2007-04-25 09:53:01 -04001579 lpfc_nlp_put(ndlp);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001580 return 0;
dea31012005-04-17 16:05:31 -05001581}
1582
James Smarted957682007-06-17 19:56:37 -05001583static void
1584lpfc_end_rscn(struct lpfc_vport *vport)
1585{
1586 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
1587
1588 if (vport->fc_flag & FC_RSCN_MODE) {
1589 /*
1590 * Check to see if more RSCNs came in while we were
1591 * processing this one.
1592 */
1593 if (vport->fc_rscn_id_cnt ||
1594 (vport->fc_flag & FC_RSCN_DISCOVERY) != 0)
1595 lpfc_els_handle_rscn(vport);
1596 else {
1597 spin_lock_irq(shost->host_lock);
1598 vport->fc_flag &= ~FC_RSCN_MODE;
1599 spin_unlock_irq(shost->host_lock);
1600 }
1601 }
1602}
1603
dea31012005-04-17 16:05:31 -05001604void
James Smart2e0fef82007-06-17 19:56:36 -05001605lpfc_cancel_retry_delay_tmo(struct lpfc_vport *vport, struct lpfc_nodelist *nlp)
James Smartfdcebe22006-03-07 15:04:01 -05001606{
James Smart2e0fef82007-06-17 19:56:36 -05001607 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
1608
1609 spin_lock_irq(shost->host_lock);
James Smartfdcebe22006-03-07 15:04:01 -05001610 nlp->nlp_flag &= ~NLP_DELAY_TMO;
James Smart2e0fef82007-06-17 19:56:36 -05001611 spin_unlock_irq(shost->host_lock);
James Smartfdcebe22006-03-07 15:04:01 -05001612 del_timer_sync(&nlp->nlp_delayfunc);
1613 nlp->nlp_last_elscmd = 0;
1614
1615 if (!list_empty(&nlp->els_retry_evt.evt_listp))
1616 list_del_init(&nlp->els_retry_evt.evt_listp);
1617
1618 if (nlp->nlp_flag & NLP_NPR_2B_DISC) {
James Smart2e0fef82007-06-17 19:56:36 -05001619 spin_lock_irq(shost->host_lock);
James Smartfdcebe22006-03-07 15:04:01 -05001620 nlp->nlp_flag &= ~NLP_NPR_2B_DISC;
James Smart2e0fef82007-06-17 19:56:36 -05001621 spin_unlock_irq(shost->host_lock);
1622 if (vport->num_disc_nodes) {
James Smartfdcebe22006-03-07 15:04:01 -05001623 /* Check to see if there are more
1624 * PLOGIs to be sent
1625 */
James Smart2e0fef82007-06-17 19:56:36 -05001626 lpfc_more_plogi(vport);
James Smartfdcebe22006-03-07 15:04:01 -05001627
James Smart2e0fef82007-06-17 19:56:36 -05001628 if (vport->num_disc_nodes == 0) {
1629 spin_lock_irq(shost->host_lock);
1630 vport->fc_flag &= ~FC_NDISC_ACTIVE;
1631 spin_unlock_irq(shost->host_lock);
1632 lpfc_can_disctmo(vport);
James Smarted957682007-06-17 19:56:37 -05001633 lpfc_end_rscn(vport);
James Smartfdcebe22006-03-07 15:04:01 -05001634 }
1635 }
1636 }
1637 return;
1638}
1639
1640void
dea31012005-04-17 16:05:31 -05001641lpfc_els_retry_delay(unsigned long ptr)
1642{
James Smart2e0fef82007-06-17 19:56:36 -05001643 struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) ptr;
1644 struct lpfc_vport *vport = ndlp->vport;
James Smart2e0fef82007-06-17 19:56:36 -05001645 struct lpfc_hba *phba = vport->phba;
James Smart92d7f7b2007-06-17 19:56:38 -05001646 unsigned long flags;
James Smart2e0fef82007-06-17 19:56:36 -05001647 struct lpfc_work_evt *evtp = &ndlp->els_retry_evt;
dea31012005-04-17 16:05:31 -05001648
James Smart2e0fef82007-06-17 19:56:36 -05001649 ndlp = (struct lpfc_nodelist *) ptr;
1650 phba = ndlp->vport->phba;
dea31012005-04-17 16:05:31 -05001651 evtp = &ndlp->els_retry_evt;
1652
James Smart92d7f7b2007-06-17 19:56:38 -05001653 spin_lock_irqsave(&phba->hbalock, flags);
dea31012005-04-17 16:05:31 -05001654 if (!list_empty(&evtp->evt_listp)) {
James Smart92d7f7b2007-06-17 19:56:38 -05001655 spin_unlock_irqrestore(&phba->hbalock, flags);
dea31012005-04-17 16:05:31 -05001656 return;
1657 }
1658
1659 evtp->evt_arg1 = ndlp;
1660 evtp->evt = LPFC_EVT_ELS_RETRY;
1661 list_add_tail(&evtp->evt_listp, &phba->work_list);
1662 if (phba->work_wait)
James Smart92d7f7b2007-06-17 19:56:38 -05001663 lpfc_worker_wake_up(phba);
dea31012005-04-17 16:05:31 -05001664
James Smart92d7f7b2007-06-17 19:56:38 -05001665 spin_unlock_irqrestore(&phba->hbalock, flags);
dea31012005-04-17 16:05:31 -05001666 return;
1667}
1668
1669void
1670lpfc_els_retry_delay_handler(struct lpfc_nodelist *ndlp)
1671{
James Smart2e0fef82007-06-17 19:56:36 -05001672 struct lpfc_vport *vport = ndlp->vport;
1673 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
1674 uint32_t cmd, did, retry;
dea31012005-04-17 16:05:31 -05001675
James Smart2e0fef82007-06-17 19:56:36 -05001676 spin_lock_irq(shost->host_lock);
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05001677 did = ndlp->nlp_DID;
1678 cmd = ndlp->nlp_last_elscmd;
1679 ndlp->nlp_last_elscmd = 0;
dea31012005-04-17 16:05:31 -05001680
1681 if (!(ndlp->nlp_flag & NLP_DELAY_TMO)) {
James Smart2e0fef82007-06-17 19:56:36 -05001682 spin_unlock_irq(shost->host_lock);
dea31012005-04-17 16:05:31 -05001683 return;
1684 }
1685
1686 ndlp->nlp_flag &= ~NLP_DELAY_TMO;
James Smart2e0fef82007-06-17 19:56:36 -05001687 spin_unlock_irq(shost->host_lock);
James Smart1a169682006-03-07 15:04:06 -05001688 /*
1689 * If a discovery event readded nlp_delayfunc after timer
1690 * firing and before processing the timer, cancel the
1691 * nlp_delayfunc.
1692 */
1693 del_timer_sync(&ndlp->nlp_delayfunc);
dea31012005-04-17 16:05:31 -05001694 retry = ndlp->nlp_retry;
1695
1696 switch (cmd) {
1697 case ELS_CMD_FLOGI:
James Smart2e0fef82007-06-17 19:56:36 -05001698 lpfc_issue_els_flogi(vport, ndlp, retry);
dea31012005-04-17 16:05:31 -05001699 break;
1700 case ELS_CMD_PLOGI:
James Smart2e0fef82007-06-17 19:56:36 -05001701 if (!lpfc_issue_els_plogi(vport, ndlp->nlp_DID, retry)) {
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05001702 ndlp->nlp_prev_state = ndlp->nlp_state;
James Smart2e0fef82007-06-17 19:56:36 -05001703 lpfc_nlp_set_state(vport, ndlp, NLP_STE_PLOGI_ISSUE);
Jamie Wellnitz6ad42532006-02-28 19:25:16 -05001704 }
dea31012005-04-17 16:05:31 -05001705 break;
1706 case ELS_CMD_ADISC:
James Smart2e0fef82007-06-17 19:56:36 -05001707 if (!lpfc_issue_els_adisc(vport, ndlp, retry)) {
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05001708 ndlp->nlp_prev_state = ndlp->nlp_state;
James Smart2e0fef82007-06-17 19:56:36 -05001709 lpfc_nlp_set_state(vport, ndlp, NLP_STE_ADISC_ISSUE);
Jamie Wellnitz6ad42532006-02-28 19:25:16 -05001710 }
dea31012005-04-17 16:05:31 -05001711 break;
1712 case ELS_CMD_PRLI:
James Smart2e0fef82007-06-17 19:56:36 -05001713 if (!lpfc_issue_els_prli(vport, ndlp, retry)) {
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05001714 ndlp->nlp_prev_state = ndlp->nlp_state;
James Smart2e0fef82007-06-17 19:56:36 -05001715 lpfc_nlp_set_state(vport, ndlp, NLP_STE_PRLI_ISSUE);
Jamie Wellnitz6ad42532006-02-28 19:25:16 -05001716 }
dea31012005-04-17 16:05:31 -05001717 break;
1718 case ELS_CMD_LOGO:
James Smart2e0fef82007-06-17 19:56:36 -05001719 if (!lpfc_issue_els_logo(vport, ndlp, retry)) {
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05001720 ndlp->nlp_prev_state = ndlp->nlp_state;
James Smart2e0fef82007-06-17 19:56:36 -05001721 lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
Jamie Wellnitz6ad42532006-02-28 19:25:16 -05001722 }
dea31012005-04-17 16:05:31 -05001723 break;
James Smart92d7f7b2007-06-17 19:56:38 -05001724 case ELS_CMD_FDISC:
1725 lpfc_issue_els_fdisc(vport, ndlp, retry);
1726 break;
dea31012005-04-17 16:05:31 -05001727 }
1728 return;
1729}
1730
1731static int
James Smart2e0fef82007-06-17 19:56:36 -05001732lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
1733 struct lpfc_iocbq *rspiocb)
dea31012005-04-17 16:05:31 -05001734{
James Smart2e0fef82007-06-17 19:56:36 -05001735 struct lpfc_vport *vport = cmdiocb->vport;
1736 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
1737 IOCB_t *irsp = &rspiocb->iocb;
1738 struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) cmdiocb->context1;
1739 struct lpfc_dmabuf *pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
dea31012005-04-17 16:05:31 -05001740 uint32_t *elscmd;
1741 struct ls_rjt stat;
James Smart2e0fef82007-06-17 19:56:36 -05001742 int retry = 0, maxretry = lpfc_max_els_tries, delay = 0;
1743 uint32_t cmd = 0;
James Smart488d1462006-03-07 15:02:37 -05001744 uint32_t did;
dea31012005-04-17 16:05:31 -05001745
James Smart488d1462006-03-07 15:02:37 -05001746
dea31012005-04-17 16:05:31 -05001747 /* Note: context2 may be 0 for internal driver abort
1748 * of delays ELS command.
1749 */
1750
1751 if (pcmd && pcmd->virt) {
1752 elscmd = (uint32_t *) (pcmd->virt);
1753 cmd = *elscmd++;
1754 }
1755
James Smart329f9bc2007-04-25 09:53:01 -04001756 if (ndlp)
James Smart488d1462006-03-07 15:02:37 -05001757 did = ndlp->nlp_DID;
1758 else {
1759 /* We should only hit this case for retrying PLOGI */
1760 did = irsp->un.elsreq64.remoteID;
James Smart2e0fef82007-06-17 19:56:36 -05001761 ndlp = lpfc_findnode_did(vport, did);
James Smart488d1462006-03-07 15:02:37 -05001762 if (!ndlp && (cmd != ELS_CMD_PLOGI))
1763 return 1;
1764 }
1765
dea31012005-04-17 16:05:31 -05001766 switch (irsp->ulpStatus) {
1767 case IOSTAT_FCP_RSP_ERROR:
1768 case IOSTAT_REMOTE_STOP:
1769 break;
1770
1771 case IOSTAT_LOCAL_REJECT:
1772 switch ((irsp->un.ulpWord[4] & 0xff)) {
1773 case IOERR_LOOP_OPEN_FAILURE:
James Smart2e0fef82007-06-17 19:56:36 -05001774 if (cmd == ELS_CMD_PLOGI && cmdiocb->retry == 0)
James Smart92d7f7b2007-06-17 19:56:38 -05001775 delay = 1000;
dea31012005-04-17 16:05:31 -05001776 retry = 1;
1777 break;
1778
1779 case IOERR_SEQUENCE_TIMEOUT:
1780 retry = 1;
dea31012005-04-17 16:05:31 -05001781 break;
1782
James Smart92d7f7b2007-06-17 19:56:38 -05001783 case IOERR_ILLEGAL_COMMAND:
1784 if ((phba->sli3_options & LPFC_SLI3_VPORT_TEARDOWN) &&
1785 (cmd == ELS_CMD_FDISC)) {
1786 lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
1787 "%d (%d):0124 FDISC failed (3/6) retrying...\n",
1788 phba->brd_no, vport->vpi);
1789 lpfc_mbx_unreg_vpi(vport);
1790 retry = 1;
1791 /* Always retry for this case */
1792 cmdiocb->retry = 0;
1793 }
1794 break;
1795
dea31012005-04-17 16:05:31 -05001796 case IOERR_NO_RESOURCES:
James Smart92d7f7b2007-06-17 19:56:38 -05001797 delay = 100;
dea31012005-04-17 16:05:31 -05001798 retry = 1;
1799 break;
1800
1801 case IOERR_INVALID_RPI:
1802 retry = 1;
1803 break;
1804 }
1805 break;
1806
1807 case IOSTAT_NPORT_RJT:
1808 case IOSTAT_FABRIC_RJT:
1809 if (irsp->un.ulpWord[4] & RJT_UNAVAIL_TEMP) {
1810 retry = 1;
1811 break;
1812 }
1813 break;
1814
1815 case IOSTAT_NPORT_BSY:
1816 case IOSTAT_FABRIC_BSY:
1817 retry = 1;
1818 break;
1819
1820 case IOSTAT_LS_RJT:
1821 stat.un.lsRjtError = be32_to_cpu(irsp->un.ulpWord[4]);
1822 /* Added for Vendor specifc support
1823 * Just keep retrying for these Rsn / Exp codes
1824 */
1825 switch (stat.un.b.lsRjtRsnCode) {
1826 case LSRJT_UNABLE_TPC:
1827 if (stat.un.b.lsRjtRsnCodeExp ==
1828 LSEXP_CMD_IN_PROGRESS) {
1829 if (cmd == ELS_CMD_PLOGI) {
James Smart92d7f7b2007-06-17 19:56:38 -05001830 delay = 1000;
dea31012005-04-17 16:05:31 -05001831 maxretry = 48;
1832 }
1833 retry = 1;
1834 break;
1835 }
1836 if (cmd == ELS_CMD_PLOGI) {
James Smart92d7f7b2007-06-17 19:56:38 -05001837 delay = 1000;
dea31012005-04-17 16:05:31 -05001838 maxretry = lpfc_max_els_tries + 1;
1839 retry = 1;
1840 break;
1841 }
James Smart92d7f7b2007-06-17 19:56:38 -05001842 if ((phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) &&
1843 (cmd == ELS_CMD_FDISC) &&
1844 (stat.un.b.lsRjtRsnCodeExp == LSEXP_OUT_OF_RESOURCE)){
1845 lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
1846 "%d (%d):0125 FDISC Failed (x%x)."
1847 " Fabric out of resources\n",
1848 phba->brd_no, vport->vpi, stat.un.lsRjtError);
1849 lpfc_vport_set_state(vport,
1850 FC_VPORT_NO_FABRIC_RSCS);
1851 }
dea31012005-04-17 16:05:31 -05001852 break;
1853
1854 case LSRJT_LOGICAL_BSY:
1855 if (cmd == ELS_CMD_PLOGI) {
James Smart92d7f7b2007-06-17 19:56:38 -05001856 delay = 1000;
dea31012005-04-17 16:05:31 -05001857 maxretry = 48;
James Smart92d7f7b2007-06-17 19:56:38 -05001858 } else if (cmd == ELS_CMD_FDISC) {
1859 /* Always retry for this case */
1860 cmdiocb->retry = 0;
dea31012005-04-17 16:05:31 -05001861 }
1862 retry = 1;
1863 break;
James Smart92d7f7b2007-06-17 19:56:38 -05001864
1865 case LSRJT_LOGICAL_ERR:
1866 case LSRJT_PROTOCOL_ERR:
1867 if ((phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) &&
1868 (cmd == ELS_CMD_FDISC) &&
1869 ((stat.un.b.lsRjtRsnCodeExp == LSEXP_INVALID_PNAME) ||
1870 (stat.un.b.lsRjtRsnCodeExp == LSEXP_INVALID_NPORT_ID))
1871 ) {
1872 lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
1873 "%d (%d):0123 FDISC Failed (x%x)."
1874 " Fabric Detected Bad WWN\n",
1875 phba->brd_no, vport->vpi, stat.un.lsRjtError);
1876 lpfc_vport_set_state(vport,
1877 FC_VPORT_FABRIC_REJ_WWN);
1878 }
1879 break;
dea31012005-04-17 16:05:31 -05001880 }
1881 break;
1882
1883 case IOSTAT_INTERMED_RSP:
1884 case IOSTAT_BA_RJT:
1885 break;
1886
1887 default:
1888 break;
1889 }
1890
James Smart488d1462006-03-07 15:02:37 -05001891 if (did == FDMI_DID)
dea31012005-04-17 16:05:31 -05001892 retry = 1;
dea31012005-04-17 16:05:31 -05001893
1894 if ((++cmdiocb->retry) >= maxretry) {
1895 phba->fc_stat.elsRetryExceeded++;
1896 retry = 0;
1897 }
1898
James Smarted957682007-06-17 19:56:37 -05001899 if ((vport->load_flag & FC_UNLOADING) != 0)
1900 retry = 0;
1901
dea31012005-04-17 16:05:31 -05001902 if (retry) {
1903
1904 /* Retry ELS command <elsCmd> to remote NPORT <did> */
1905 lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
James Smart92d7f7b2007-06-17 19:56:38 -05001906 "%d (%d):0107 Retry ELS command x%x to remote "
dea31012005-04-17 16:05:31 -05001907 "NPORT x%x Data: x%x x%x\n",
James Smart92d7f7b2007-06-17 19:56:38 -05001908 phba->brd_no, vport->vpi,
James Smart488d1462006-03-07 15:02:37 -05001909 cmd, did, cmdiocb->retry, delay);
dea31012005-04-17 16:05:31 -05001910
1911 if ((cmd == ELS_CMD_PLOGI) || (cmd == ELS_CMD_ADISC)) {
1912 /* If discovery / RSCN timer is running, reset it */
James Smart2e0fef82007-06-17 19:56:36 -05001913 if (timer_pending(&vport->fc_disctmo) ||
James Smart92d7f7b2007-06-17 19:56:38 -05001914 (vport->fc_flag & FC_RSCN_MODE))
James Smart2e0fef82007-06-17 19:56:36 -05001915 lpfc_set_disctmo(vport);
dea31012005-04-17 16:05:31 -05001916 }
1917
1918 phba->fc_stat.elsXmitRetry++;
James Smart488d1462006-03-07 15:02:37 -05001919 if (ndlp && delay) {
dea31012005-04-17 16:05:31 -05001920 phba->fc_stat.elsDelayRetry++;
1921 ndlp->nlp_retry = cmdiocb->retry;
1922
James Smart92d7f7b2007-06-17 19:56:38 -05001923 /* delay is specified in milliseconds */
1924 mod_timer(&ndlp->nlp_delayfunc,
1925 jiffies + msecs_to_jiffies(delay));
James Smart2e0fef82007-06-17 19:56:36 -05001926 spin_lock_irq(shost->host_lock);
dea31012005-04-17 16:05:31 -05001927 ndlp->nlp_flag |= NLP_DELAY_TMO;
James Smart2e0fef82007-06-17 19:56:36 -05001928 spin_unlock_irq(shost->host_lock);
dea31012005-04-17 16:05:31 -05001929
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05001930 ndlp->nlp_prev_state = ndlp->nlp_state;
James Smart2e0fef82007-06-17 19:56:36 -05001931 lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
dea31012005-04-17 16:05:31 -05001932 ndlp->nlp_last_elscmd = cmd;
1933
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001934 return 1;
dea31012005-04-17 16:05:31 -05001935 }
1936 switch (cmd) {
1937 case ELS_CMD_FLOGI:
James Smart2e0fef82007-06-17 19:56:36 -05001938 lpfc_issue_els_flogi(vport, ndlp, cmdiocb->retry);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001939 return 1;
James Smart92d7f7b2007-06-17 19:56:38 -05001940 case ELS_CMD_FDISC:
1941 lpfc_issue_els_fdisc(vport, ndlp, cmdiocb->retry);
1942 return 1;
dea31012005-04-17 16:05:31 -05001943 case ELS_CMD_PLOGI:
James Smart488d1462006-03-07 15:02:37 -05001944 if (ndlp) {
1945 ndlp->nlp_prev_state = ndlp->nlp_state;
James Smart2e0fef82007-06-17 19:56:36 -05001946 lpfc_nlp_set_state(vport, ndlp,
James Smartde0c5b32007-04-25 09:52:27 -04001947 NLP_STE_PLOGI_ISSUE);
James Smart488d1462006-03-07 15:02:37 -05001948 }
James Smart2e0fef82007-06-17 19:56:36 -05001949 lpfc_issue_els_plogi(vport, did, cmdiocb->retry);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001950 return 1;
dea31012005-04-17 16:05:31 -05001951 case ELS_CMD_ADISC:
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05001952 ndlp->nlp_prev_state = ndlp->nlp_state;
James Smart2e0fef82007-06-17 19:56:36 -05001953 lpfc_nlp_set_state(vport, ndlp, NLP_STE_ADISC_ISSUE);
1954 lpfc_issue_els_adisc(vport, ndlp, cmdiocb->retry);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001955 return 1;
dea31012005-04-17 16:05:31 -05001956 case ELS_CMD_PRLI:
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05001957 ndlp->nlp_prev_state = ndlp->nlp_state;
James Smart2e0fef82007-06-17 19:56:36 -05001958 lpfc_nlp_set_state(vport, ndlp, NLP_STE_PRLI_ISSUE);
1959 lpfc_issue_els_prli(vport, ndlp, cmdiocb->retry);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001960 return 1;
dea31012005-04-17 16:05:31 -05001961 case ELS_CMD_LOGO:
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05001962 ndlp->nlp_prev_state = ndlp->nlp_state;
James Smart2e0fef82007-06-17 19:56:36 -05001963 lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
1964 lpfc_issue_els_logo(vport, ndlp, cmdiocb->retry);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001965 return 1;
dea31012005-04-17 16:05:31 -05001966 }
1967 }
1968
1969 /* No retry ELS command <elsCmd> to remote NPORT <did> */
1970 lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
James Smart92d7f7b2007-06-17 19:56:38 -05001971 "%d (%d):0108 No retry ELS command x%x to remote "
1972 "NPORT x%x Data: x%x\n",
1973 phba->brd_no, vport->vpi,
James Smart488d1462006-03-07 15:02:37 -05001974 cmd, did, cmdiocb->retry);
dea31012005-04-17 16:05:31 -05001975
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05001976 return 0;
dea31012005-04-17 16:05:31 -05001977}
1978
1979int
James Smart329f9bc2007-04-25 09:53:01 -04001980lpfc_els_free_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *elsiocb)
dea31012005-04-17 16:05:31 -05001981{
1982 struct lpfc_dmabuf *buf_ptr, *buf_ptr1;
1983
James Smart329f9bc2007-04-25 09:53:01 -04001984 if (elsiocb->context1) {
1985 lpfc_nlp_put(elsiocb->context1);
1986 elsiocb->context1 = NULL;
1987 }
dea31012005-04-17 16:05:31 -05001988 /* context2 = cmd, context2->next = rsp, context3 = bpl */
1989 if (elsiocb->context2) {
1990 buf_ptr1 = (struct lpfc_dmabuf *) elsiocb->context2;
1991 /* Free the response before processing the command. */
1992 if (!list_empty(&buf_ptr1->list)) {
1993 list_remove_head(&buf_ptr1->list, buf_ptr,
1994 struct lpfc_dmabuf,
1995 list);
1996 lpfc_mbuf_free(phba, buf_ptr->virt, buf_ptr->phys);
1997 kfree(buf_ptr);
1998 }
1999 lpfc_mbuf_free(phba, buf_ptr1->virt, buf_ptr1->phys);
2000 kfree(buf_ptr1);
2001 }
2002
2003 if (elsiocb->context3) {
2004 buf_ptr = (struct lpfc_dmabuf *) elsiocb->context3;
2005 lpfc_mbuf_free(phba, buf_ptr->virt, buf_ptr->phys);
2006 kfree(buf_ptr);
2007 }
James Bottomley604a3e32005-10-29 10:28:33 -05002008 lpfc_sli_release_iocbq(phba, elsiocb);
dea31012005-04-17 16:05:31 -05002009 return 0;
2010}
2011
2012static void
James Smart2e0fef82007-06-17 19:56:36 -05002013lpfc_cmpl_els_logo_acc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
2014 struct lpfc_iocbq *rspiocb)
dea31012005-04-17 16:05:31 -05002015{
James Smart2e0fef82007-06-17 19:56:36 -05002016 struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) cmdiocb->context1;
2017 struct lpfc_vport *vport = cmdiocb->vport;
dea31012005-04-17 16:05:31 -05002018
2019 /* ACC to LOGO completes to NPort <nlp_DID> */
2020 lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
James Smart92d7f7b2007-06-17 19:56:38 -05002021 "%d (%d):0109 ACC to LOGO completes to NPort x%x "
dea31012005-04-17 16:05:31 -05002022 "Data: x%x x%x x%x\n",
James Smart92d7f7b2007-06-17 19:56:38 -05002023 phba->brd_no, vport->vpi, ndlp->nlp_DID,
2024 ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi);
dea31012005-04-17 16:05:31 -05002025
dea31012005-04-17 16:05:31 -05002026 switch (ndlp->nlp_state) {
2027 case NLP_STE_UNUSED_NODE: /* node is just allocated */
James Smart2e0fef82007-06-17 19:56:36 -05002028 lpfc_drop_node(vport, ndlp);
dea31012005-04-17 16:05:31 -05002029 break;
2030 case NLP_STE_NPR_NODE: /* NPort Recovery mode */
James Smart2e0fef82007-06-17 19:56:36 -05002031 lpfc_unreg_rpi(vport, ndlp);
dea31012005-04-17 16:05:31 -05002032 break;
2033 default:
2034 break;
2035 }
2036 lpfc_els_free_iocb(phba, cmdiocb);
2037 return;
2038}
2039
2040static void
James Smart329f9bc2007-04-25 09:53:01 -04002041lpfc_cmpl_els_acc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
2042 struct lpfc_iocbq *rspiocb)
dea31012005-04-17 16:05:31 -05002043{
James Smart2e0fef82007-06-17 19:56:36 -05002044 struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) cmdiocb->context1;
2045 struct lpfc_vport *vport = ndlp ? ndlp->vport : NULL;
2046 struct Scsi_Host *shost = vport ? lpfc_shost_from_vport(vport) : NULL;
James Smart33ccf8d2006-08-17 11:57:58 -04002047 IOCB_t *irsp;
dea31012005-04-17 16:05:31 -05002048 LPFC_MBOXQ_t *mbox = NULL;
James Smart2e0fef82007-06-17 19:56:36 -05002049 struct lpfc_dmabuf *mp = NULL;
dea31012005-04-17 16:05:31 -05002050
James Smart33ccf8d2006-08-17 11:57:58 -04002051 irsp = &rspiocb->iocb;
2052
dea31012005-04-17 16:05:31 -05002053 if (cmdiocb->context_un.mbox)
2054 mbox = cmdiocb->context_un.mbox;
2055
dea31012005-04-17 16:05:31 -05002056 /* Check to see if link went down during discovery */
James Smart2e0fef82007-06-17 19:56:36 -05002057 if (!ndlp || lpfc_els_chk_latt(vport)) {
dea31012005-04-17 16:05:31 -05002058 if (mbox) {
James Smart14691152006-12-02 13:34:28 -05002059 mp = (struct lpfc_dmabuf *) mbox->context1;
2060 if (mp) {
2061 lpfc_mbuf_free(phba, mp->virt, mp->phys);
2062 kfree(mp);
2063 }
James Smart329f9bc2007-04-25 09:53:01 -04002064 mempool_free(mbox, phba->mbox_mem_pool);
dea31012005-04-17 16:05:31 -05002065 }
2066 goto out;
2067 }
2068
2069 /* ELS response tag <ulpIoTag> completes */
2070 lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
James Smart92d7f7b2007-06-17 19:56:38 -05002071 "%d (%d):0110 ELS response tag x%x completes "
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002072 "Data: x%x x%x x%x x%x x%x x%x x%x\n",
James Smart92d7f7b2007-06-17 19:56:38 -05002073 phba->brd_no, vport->vpi,
dea31012005-04-17 16:05:31 -05002074 cmdiocb->iocb.ulpIoTag, rspiocb->iocb.ulpStatus,
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002075 rspiocb->iocb.un.ulpWord[4], rspiocb->iocb.ulpTimeout,
James Smart2e0fef82007-06-17 19:56:36 -05002076 ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state,
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002077 ndlp->nlp_rpi);
dea31012005-04-17 16:05:31 -05002078
2079 if (mbox) {
2080 if ((rspiocb->iocb.ulpStatus == 0)
2081 && (ndlp->nlp_flag & NLP_ACC_REGLOGIN)) {
James Smart2e0fef82007-06-17 19:56:36 -05002082 lpfc_unreg_rpi(vport, ndlp);
dea31012005-04-17 16:05:31 -05002083 mbox->mbox_cmpl = lpfc_mbx_cmpl_reg_login;
James Smart329f9bc2007-04-25 09:53:01 -04002084 mbox->context2 = lpfc_nlp_get(ndlp);
James Smart2e0fef82007-06-17 19:56:36 -05002085 mbox->vport = vport;
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05002086 ndlp->nlp_prev_state = ndlp->nlp_state;
James Smart2e0fef82007-06-17 19:56:36 -05002087 lpfc_nlp_set_state(vport, ndlp,
2088 NLP_STE_REG_LOGIN_ISSUE);
dea31012005-04-17 16:05:31 -05002089 if (lpfc_sli_issue_mbox(phba, mbox,
2090 (MBX_NOWAIT | MBX_STOP_IOCB))
2091 != MBX_NOT_FINISHED) {
2092 goto out;
2093 }
James Smart329f9bc2007-04-25 09:53:01 -04002094 lpfc_nlp_put(ndlp);
dea31012005-04-17 16:05:31 -05002095 /* NOTE: we should have messages for unsuccessful
2096 reglogin */
dea31012005-04-17 16:05:31 -05002097 } else {
James Smart33ccf8d2006-08-17 11:57:58 -04002098 /* Do not call NO_LIST for lpfc_els_abort'ed ELS cmds */
2099 if (!((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) &&
2100 ((irsp->un.ulpWord[4] == IOERR_SLI_ABORTED) ||
2101 (irsp->un.ulpWord[4] == IOERR_LINK_DOWN) ||
2102 (irsp->un.ulpWord[4] == IOERR_SLI_DOWN)))) {
2103 if (ndlp->nlp_flag & NLP_ACC_REGLOGIN) {
James Smart2e0fef82007-06-17 19:56:36 -05002104 lpfc_drop_node(vport, ndlp);
James Smart33ccf8d2006-08-17 11:57:58 -04002105 ndlp = NULL;
2106 }
dea31012005-04-17 16:05:31 -05002107 }
2108 }
James Smart14691152006-12-02 13:34:28 -05002109 mp = (struct lpfc_dmabuf *) mbox->context1;
2110 if (mp) {
2111 lpfc_mbuf_free(phba, mp->virt, mp->phys);
2112 kfree(mp);
2113 }
2114 mempool_free(mbox, phba->mbox_mem_pool);
dea31012005-04-17 16:05:31 -05002115 }
2116out:
2117 if (ndlp) {
James Smart2e0fef82007-06-17 19:56:36 -05002118 spin_lock_irq(shost->host_lock);
dea31012005-04-17 16:05:31 -05002119 ndlp->nlp_flag &= ~NLP_ACC_REGLOGIN;
James Smart2e0fef82007-06-17 19:56:36 -05002120 spin_unlock_irq(shost->host_lock);
dea31012005-04-17 16:05:31 -05002121 }
2122 lpfc_els_free_iocb(phba, cmdiocb);
2123 return;
2124}
2125
2126int
James Smart2e0fef82007-06-17 19:56:36 -05002127lpfc_els_rsp_acc(struct lpfc_vport *vport, uint32_t flag,
2128 struct lpfc_iocbq *oldiocb, struct lpfc_nodelist *ndlp,
2129 LPFC_MBOXQ_t *mbox, uint8_t newnode)
dea31012005-04-17 16:05:31 -05002130{
James Smart2e0fef82007-06-17 19:56:36 -05002131 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
2132 struct lpfc_hba *phba = vport->phba;
dea31012005-04-17 16:05:31 -05002133 IOCB_t *icmd;
2134 IOCB_t *oldcmd;
2135 struct lpfc_iocbq *elsiocb;
2136 struct lpfc_sli_ring *pring;
2137 struct lpfc_sli *psli;
2138 uint8_t *pcmd;
2139 uint16_t cmdsize;
2140 int rc;
James Smart82d9a2a2006-04-15 11:53:05 -04002141 ELS_PKT *els_pkt_ptr;
dea31012005-04-17 16:05:31 -05002142
2143 psli = &phba->sli;
2144 pring = &psli->ring[LPFC_ELS_RING]; /* ELS ring */
2145 oldcmd = &oldiocb->iocb;
2146
2147 switch (flag) {
2148 case ELS_CMD_ACC:
James Smart92d7f7b2007-06-17 19:56:38 -05002149 cmdsize = sizeof(uint32_t);
James Smart2e0fef82007-06-17 19:56:36 -05002150 elsiocb = lpfc_prep_els_iocb(vport, 0, cmdsize, oldiocb->retry,
2151 ndlp, ndlp->nlp_DID, ELS_CMD_ACC);
James Smart488d1462006-03-07 15:02:37 -05002152 if (!elsiocb) {
James Smart2e0fef82007-06-17 19:56:36 -05002153 spin_lock_irq(shost->host_lock);
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05002154 ndlp->nlp_flag &= ~NLP_LOGO_ACC;
James Smart2e0fef82007-06-17 19:56:36 -05002155 spin_unlock_irq(shost->host_lock);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002156 return 1;
dea31012005-04-17 16:05:31 -05002157 }
James Smart2e0fef82007-06-17 19:56:36 -05002158
dea31012005-04-17 16:05:31 -05002159 icmd = &elsiocb->iocb;
2160 icmd->ulpContext = oldcmd->ulpContext; /* Xri */
2161 pcmd = (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
2162 *((uint32_t *) (pcmd)) = ELS_CMD_ACC;
James Smart92d7f7b2007-06-17 19:56:38 -05002163 pcmd += sizeof(uint32_t);
dea31012005-04-17 16:05:31 -05002164 break;
2165 case ELS_CMD_PLOGI:
James Smart92d7f7b2007-06-17 19:56:38 -05002166 cmdsize = (sizeof(struct serv_parm) + sizeof(uint32_t));
James Smart2e0fef82007-06-17 19:56:36 -05002167 elsiocb = lpfc_prep_els_iocb(vport, 0, cmdsize, oldiocb->retry,
2168 ndlp, ndlp->nlp_DID, ELS_CMD_ACC);
James Smart488d1462006-03-07 15:02:37 -05002169 if (!elsiocb)
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002170 return 1;
James Smart488d1462006-03-07 15:02:37 -05002171
dea31012005-04-17 16:05:31 -05002172 icmd = &elsiocb->iocb;
2173 icmd->ulpContext = oldcmd->ulpContext; /* Xri */
2174 pcmd = (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
2175
2176 if (mbox)
2177 elsiocb->context_un.mbox = mbox;
2178
2179 *((uint32_t *) (pcmd)) = ELS_CMD_ACC;
James Smart92d7f7b2007-06-17 19:56:38 -05002180 pcmd += sizeof(uint32_t);
2181 memcpy(pcmd, &vport->fc_sparam, sizeof(struct serv_parm));
dea31012005-04-17 16:05:31 -05002182 break;
James Smart82d9a2a2006-04-15 11:53:05 -04002183 case ELS_CMD_PRLO:
James Smart92d7f7b2007-06-17 19:56:38 -05002184 cmdsize = sizeof(uint32_t) + sizeof(PRLO);
James Smart2e0fef82007-06-17 19:56:36 -05002185 elsiocb = lpfc_prep_els_iocb(vport, 0, cmdsize, oldiocb->retry,
James Smart82d9a2a2006-04-15 11:53:05 -04002186 ndlp, ndlp->nlp_DID, ELS_CMD_PRLO);
2187 if (!elsiocb)
2188 return 1;
2189
2190 icmd = &elsiocb->iocb;
2191 icmd->ulpContext = oldcmd->ulpContext; /* Xri */
2192 pcmd = (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
2193
2194 memcpy(pcmd, ((struct lpfc_dmabuf *) oldiocb->context2)->virt,
James Smart92d7f7b2007-06-17 19:56:38 -05002195 sizeof(uint32_t) + sizeof(PRLO));
James Smart82d9a2a2006-04-15 11:53:05 -04002196 *((uint32_t *) (pcmd)) = ELS_CMD_PRLO_ACC;
2197 els_pkt_ptr = (ELS_PKT *) pcmd;
2198 els_pkt_ptr->un.prlo.acceptRspCode = PRLO_REQ_EXECUTED;
2199 break;
dea31012005-04-17 16:05:31 -05002200 default:
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002201 return 1;
dea31012005-04-17 16:05:31 -05002202 }
2203
James Smart329f9bc2007-04-25 09:53:01 -04002204 if (newnode) {
2205 lpfc_nlp_put(ndlp);
dea31012005-04-17 16:05:31 -05002206 elsiocb->context1 = NULL;
James Smart329f9bc2007-04-25 09:53:01 -04002207 }
dea31012005-04-17 16:05:31 -05002208
2209 /* Xmit ELS ACC response tag <ulpIoTag> */
2210 lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
James Smart92d7f7b2007-06-17 19:56:38 -05002211 "%d (%d):0128 Xmit ELS ACC response tag x%x, XRI: x%x, "
James Smart1dcb58e2007-04-25 09:51:30 -04002212 "DID: x%x, nlp_flag: x%x nlp_state: x%x RPI: x%x\n",
James Smart92d7f7b2007-06-17 19:56:38 -05002213 phba->brd_no, vport->vpi, elsiocb->iotag,
dea31012005-04-17 16:05:31 -05002214 elsiocb->iocb.ulpContext, ndlp->nlp_DID,
2215 ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi);
2216
2217 if (ndlp->nlp_flag & NLP_LOGO_ACC) {
James Smart2e0fef82007-06-17 19:56:36 -05002218 spin_lock_irq(shost->host_lock);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002219 ndlp->nlp_flag &= ~NLP_LOGO_ACC;
James Smart2e0fef82007-06-17 19:56:36 -05002220 spin_unlock_irq(shost->host_lock);
dea31012005-04-17 16:05:31 -05002221 elsiocb->iocb_cmpl = lpfc_cmpl_els_logo_acc;
2222 } else {
2223 elsiocb->iocb_cmpl = lpfc_cmpl_els_acc;
2224 }
2225
2226 phba->fc_stat.elsXmitACC++;
dea31012005-04-17 16:05:31 -05002227 rc = lpfc_sli_issue_iocb(phba, pring, elsiocb, 0);
dea31012005-04-17 16:05:31 -05002228 if (rc == IOCB_ERROR) {
2229 lpfc_els_free_iocb(phba, elsiocb);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002230 return 1;
dea31012005-04-17 16:05:31 -05002231 }
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002232 return 0;
dea31012005-04-17 16:05:31 -05002233}
2234
2235int
James Smart2e0fef82007-06-17 19:56:36 -05002236lpfc_els_rsp_reject(struct lpfc_vport *vport, uint32_t rejectError,
2237 struct lpfc_iocbq *oldiocb, struct lpfc_nodelist *ndlp)
dea31012005-04-17 16:05:31 -05002238{
James Smart2e0fef82007-06-17 19:56:36 -05002239 struct lpfc_hba *phba = vport->phba;
dea31012005-04-17 16:05:31 -05002240 IOCB_t *icmd;
2241 IOCB_t *oldcmd;
2242 struct lpfc_iocbq *elsiocb;
2243 struct lpfc_sli_ring *pring;
2244 struct lpfc_sli *psli;
2245 uint8_t *pcmd;
2246 uint16_t cmdsize;
2247 int rc;
2248
2249 psli = &phba->sli;
2250 pring = &psli->ring[LPFC_ELS_RING]; /* ELS ring */
2251
James Smart92d7f7b2007-06-17 19:56:38 -05002252 cmdsize = 2 * sizeof(uint32_t);
James Smart2e0fef82007-06-17 19:56:36 -05002253 elsiocb = lpfc_prep_els_iocb(vport, 0, cmdsize, oldiocb->retry, ndlp,
2254 ndlp->nlp_DID, ELS_CMD_LS_RJT);
James Smart488d1462006-03-07 15:02:37 -05002255 if (!elsiocb)
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002256 return 1;
dea31012005-04-17 16:05:31 -05002257
2258 icmd = &elsiocb->iocb;
2259 oldcmd = &oldiocb->iocb;
2260 icmd->ulpContext = oldcmd->ulpContext; /* Xri */
2261 pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
2262
2263 *((uint32_t *) (pcmd)) = ELS_CMD_LS_RJT;
James Smart92d7f7b2007-06-17 19:56:38 -05002264 pcmd += sizeof(uint32_t);
dea31012005-04-17 16:05:31 -05002265 *((uint32_t *) (pcmd)) = rejectError;
2266
2267 /* Xmit ELS RJT <err> response tag <ulpIoTag> */
2268 lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
James Smart92d7f7b2007-06-17 19:56:38 -05002269 "%d (%d):0129 Xmit ELS RJT x%x response tag x%x "
2270 "xri x%x, did x%x, nlp_flag x%x, nlp_state x%x, "
2271 "rpi x%x\n",
2272 phba->brd_no, vport->vpi, rejectError, elsiocb->iotag,
dea31012005-04-17 16:05:31 -05002273 elsiocb->iocb.ulpContext, ndlp->nlp_DID,
2274 ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi);
2275
2276 phba->fc_stat.elsXmitLSRJT++;
2277 elsiocb->iocb_cmpl = lpfc_cmpl_els_acc;
dea31012005-04-17 16:05:31 -05002278 rc = lpfc_sli_issue_iocb(phba, pring, elsiocb, 0);
dea31012005-04-17 16:05:31 -05002279 if (rc == IOCB_ERROR) {
2280 lpfc_els_free_iocb(phba, elsiocb);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002281 return 1;
dea31012005-04-17 16:05:31 -05002282 }
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002283 return 0;
dea31012005-04-17 16:05:31 -05002284}
2285
2286int
James Smart2e0fef82007-06-17 19:56:36 -05002287lpfc_els_rsp_adisc_acc(struct lpfc_vport *vport, struct lpfc_iocbq *oldiocb,
2288 struct lpfc_nodelist *ndlp)
dea31012005-04-17 16:05:31 -05002289{
James Smart2e0fef82007-06-17 19:56:36 -05002290 struct lpfc_hba *phba = vport->phba;
2291 struct lpfc_sli *psli = &phba->sli;
2292 struct lpfc_sli_ring *pring = &psli->ring[LPFC_ELS_RING];
dea31012005-04-17 16:05:31 -05002293 ADISC *ap;
James Smart2e0fef82007-06-17 19:56:36 -05002294 IOCB_t *icmd, *oldcmd;
dea31012005-04-17 16:05:31 -05002295 struct lpfc_iocbq *elsiocb;
dea31012005-04-17 16:05:31 -05002296 uint8_t *pcmd;
2297 uint16_t cmdsize;
2298 int rc;
2299
James Smart92d7f7b2007-06-17 19:56:38 -05002300 cmdsize = sizeof(uint32_t) + sizeof(ADISC);
James Smart2e0fef82007-06-17 19:56:36 -05002301 elsiocb = lpfc_prep_els_iocb(vport, 0, cmdsize, oldiocb->retry, ndlp,
2302 ndlp->nlp_DID, ELS_CMD_ACC);
James Smart488d1462006-03-07 15:02:37 -05002303 if (!elsiocb)
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002304 return 1;
dea31012005-04-17 16:05:31 -05002305
dea31012005-04-17 16:05:31 -05002306 icmd = &elsiocb->iocb;
2307 oldcmd = &oldiocb->iocb;
2308 icmd->ulpContext = oldcmd->ulpContext; /* Xri */
James Smart5b8bd0c2007-04-25 09:52:49 -04002309
2310 /* Xmit ADISC ACC response tag <ulpIoTag> */
2311 lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
James Smart92d7f7b2007-06-17 19:56:38 -05002312 "%d (%d):0130 Xmit ADISC ACC response iotag x%x xri: "
James Smart5b8bd0c2007-04-25 09:52:49 -04002313 "x%x, did x%x, nlp_flag x%x, nlp_state x%x rpi x%x\n",
James Smart92d7f7b2007-06-17 19:56:38 -05002314 phba->brd_no, vport->vpi, elsiocb->iotag,
James Smart5b8bd0c2007-04-25 09:52:49 -04002315 elsiocb->iocb.ulpContext, ndlp->nlp_DID,
2316 ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi);
2317
dea31012005-04-17 16:05:31 -05002318 pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
2319
2320 *((uint32_t *) (pcmd)) = ELS_CMD_ACC;
James Smart92d7f7b2007-06-17 19:56:38 -05002321 pcmd += sizeof(uint32_t);
dea31012005-04-17 16:05:31 -05002322
2323 ap = (ADISC *) (pcmd);
2324 ap->hardAL_PA = phba->fc_pref_ALPA;
James Smart92d7f7b2007-06-17 19:56:38 -05002325 memcpy(&ap->portName, &vport->fc_portname, sizeof(struct lpfc_name));
2326 memcpy(&ap->nodeName, &vport->fc_nodename, sizeof(struct lpfc_name));
James Smart2e0fef82007-06-17 19:56:36 -05002327 ap->DID = be32_to_cpu(vport->fc_myDID);
dea31012005-04-17 16:05:31 -05002328
2329 phba->fc_stat.elsXmitACC++;
2330 elsiocb->iocb_cmpl = lpfc_cmpl_els_acc;
dea31012005-04-17 16:05:31 -05002331 rc = lpfc_sli_issue_iocb(phba, pring, elsiocb, 0);
dea31012005-04-17 16:05:31 -05002332 if (rc == IOCB_ERROR) {
2333 lpfc_els_free_iocb(phba, elsiocb);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002334 return 1;
dea31012005-04-17 16:05:31 -05002335 }
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002336 return 0;
dea31012005-04-17 16:05:31 -05002337}
2338
2339int
James Smart2e0fef82007-06-17 19:56:36 -05002340lpfc_els_rsp_prli_acc(struct lpfc_vport *vport, struct lpfc_iocbq *oldiocb,
James Smart5b8bd0c2007-04-25 09:52:49 -04002341 struct lpfc_nodelist *ndlp)
dea31012005-04-17 16:05:31 -05002342{
James Smart2e0fef82007-06-17 19:56:36 -05002343 struct lpfc_hba *phba = vport->phba;
dea31012005-04-17 16:05:31 -05002344 PRLI *npr;
2345 lpfc_vpd_t *vpd;
2346 IOCB_t *icmd;
2347 IOCB_t *oldcmd;
2348 struct lpfc_iocbq *elsiocb;
2349 struct lpfc_sli_ring *pring;
2350 struct lpfc_sli *psli;
2351 uint8_t *pcmd;
2352 uint16_t cmdsize;
2353 int rc;
2354
2355 psli = &phba->sli;
2356 pring = &psli->ring[LPFC_ELS_RING]; /* ELS ring */
2357
James Smart92d7f7b2007-06-17 19:56:38 -05002358 cmdsize = sizeof(uint32_t) + sizeof(PRLI);
James Smart2e0fef82007-06-17 19:56:36 -05002359 elsiocb = lpfc_prep_els_iocb(vport, 0, cmdsize, oldiocb->retry, ndlp,
James Smart92d7f7b2007-06-17 19:56:38 -05002360 ndlp->nlp_DID, (ELS_CMD_ACC | (ELS_CMD_PRLI & ~ELS_RSP_MASK)));
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002361 if (!elsiocb)
2362 return 1;
dea31012005-04-17 16:05:31 -05002363
dea31012005-04-17 16:05:31 -05002364 icmd = &elsiocb->iocb;
2365 oldcmd = &oldiocb->iocb;
2366 icmd->ulpContext = oldcmd->ulpContext; /* Xri */
James Smart5b8bd0c2007-04-25 09:52:49 -04002367
2368 /* Xmit PRLI ACC response tag <ulpIoTag> */
2369 lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
James Smart92d7f7b2007-06-17 19:56:38 -05002370 "%d (%d):0131 Xmit PRLI ACC response tag x%x xri x%x, "
James Smart5b8bd0c2007-04-25 09:52:49 -04002371 "did x%x, nlp_flag x%x, nlp_state x%x, rpi x%x\n",
James Smart92d7f7b2007-06-17 19:56:38 -05002372 phba->brd_no, vport->vpi, elsiocb->iotag,
James Smart5b8bd0c2007-04-25 09:52:49 -04002373 elsiocb->iocb.ulpContext, ndlp->nlp_DID,
2374 ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi);
2375
dea31012005-04-17 16:05:31 -05002376 pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
2377
2378 *((uint32_t *) (pcmd)) = (ELS_CMD_ACC | (ELS_CMD_PRLI & ~ELS_RSP_MASK));
James Smart92d7f7b2007-06-17 19:56:38 -05002379 pcmd += sizeof(uint32_t);
dea31012005-04-17 16:05:31 -05002380
2381 /* For PRLI, remainder of payload is PRLI parameter page */
James Smart92d7f7b2007-06-17 19:56:38 -05002382 memset(pcmd, 0, sizeof(PRLI));
dea31012005-04-17 16:05:31 -05002383
2384 npr = (PRLI *) pcmd;
2385 vpd = &phba->vpd;
2386 /*
2387 * If our firmware version is 3.20 or later,
2388 * set the following bits for FC-TAPE support.
2389 */
2390 if (vpd->rev.feaLevelHigh >= 0x02) {
2391 npr->ConfmComplAllowed = 1;
2392 npr->Retry = 1;
2393 npr->TaskRetryIdReq = 1;
2394 }
2395
2396 npr->acceptRspCode = PRLI_REQ_EXECUTED;
2397 npr->estabImagePair = 1;
2398 npr->readXferRdyDis = 1;
2399 npr->ConfmComplAllowed = 1;
2400
2401 npr->prliType = PRLI_FCP_TYPE;
2402 npr->initiatorFunc = 1;
2403
2404 phba->fc_stat.elsXmitACC++;
2405 elsiocb->iocb_cmpl = lpfc_cmpl_els_acc;
2406
dea31012005-04-17 16:05:31 -05002407 rc = lpfc_sli_issue_iocb(phba, pring, elsiocb, 0);
dea31012005-04-17 16:05:31 -05002408 if (rc == IOCB_ERROR) {
2409 lpfc_els_free_iocb(phba, elsiocb);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002410 return 1;
dea31012005-04-17 16:05:31 -05002411 }
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002412 return 0;
dea31012005-04-17 16:05:31 -05002413}
2414
2415static int
James Smart2e0fef82007-06-17 19:56:36 -05002416lpfc_els_rsp_rnid_acc(struct lpfc_vport *vport, uint8_t format,
James Smart329f9bc2007-04-25 09:53:01 -04002417 struct lpfc_iocbq *oldiocb, struct lpfc_nodelist *ndlp)
dea31012005-04-17 16:05:31 -05002418{
James Smart2e0fef82007-06-17 19:56:36 -05002419 struct lpfc_hba *phba = vport->phba;
dea31012005-04-17 16:05:31 -05002420 RNID *rn;
James Smart2e0fef82007-06-17 19:56:36 -05002421 IOCB_t *icmd, *oldcmd;
dea31012005-04-17 16:05:31 -05002422 struct lpfc_iocbq *elsiocb;
2423 struct lpfc_sli_ring *pring;
2424 struct lpfc_sli *psli;
2425 uint8_t *pcmd;
2426 uint16_t cmdsize;
2427 int rc;
2428
2429 psli = &phba->sli;
2430 pring = &psli->ring[LPFC_ELS_RING];
2431
James Smart92d7f7b2007-06-17 19:56:38 -05002432 cmdsize = sizeof(uint32_t) + sizeof(uint32_t)
2433 + (2 * sizeof(struct lpfc_name));
dea31012005-04-17 16:05:31 -05002434 if (format)
James Smart92d7f7b2007-06-17 19:56:38 -05002435 cmdsize += sizeof(RNID_TOP_DISC);
dea31012005-04-17 16:05:31 -05002436
James Smart2e0fef82007-06-17 19:56:36 -05002437 elsiocb = lpfc_prep_els_iocb(vport, 0, cmdsize, oldiocb->retry, ndlp,
2438 ndlp->nlp_DID, ELS_CMD_ACC);
James Smart488d1462006-03-07 15:02:37 -05002439 if (!elsiocb)
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002440 return 1;
dea31012005-04-17 16:05:31 -05002441
dea31012005-04-17 16:05:31 -05002442 icmd = &elsiocb->iocb;
2443 oldcmd = &oldiocb->iocb;
2444 icmd->ulpContext = oldcmd->ulpContext; /* Xri */
James Smart5b8bd0c2007-04-25 09:52:49 -04002445
2446 /* Xmit RNID ACC response tag <ulpIoTag> */
2447 lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
James Smart92d7f7b2007-06-17 19:56:38 -05002448 "%d (%d):0132 Xmit RNID ACC response tag x%x "
James Smart5b8bd0c2007-04-25 09:52:49 -04002449 "xri x%x\n",
James Smart92d7f7b2007-06-17 19:56:38 -05002450 phba->brd_no, vport->vpi, elsiocb->iotag,
James Smart5b8bd0c2007-04-25 09:52:49 -04002451 elsiocb->iocb.ulpContext);
2452
dea31012005-04-17 16:05:31 -05002453 pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
2454
2455 *((uint32_t *) (pcmd)) = ELS_CMD_ACC;
James Smart92d7f7b2007-06-17 19:56:38 -05002456 pcmd += sizeof(uint32_t);
dea31012005-04-17 16:05:31 -05002457
James Smart92d7f7b2007-06-17 19:56:38 -05002458 memset(pcmd, 0, sizeof(RNID));
dea31012005-04-17 16:05:31 -05002459 rn = (RNID *) (pcmd);
2460 rn->Format = format;
James Smart92d7f7b2007-06-17 19:56:38 -05002461 rn->CommonLen = (2 * sizeof(struct lpfc_name));
2462 memcpy(&rn->portName, &vport->fc_portname, sizeof(struct lpfc_name));
2463 memcpy(&rn->nodeName, &vport->fc_nodename, sizeof(struct lpfc_name));
dea31012005-04-17 16:05:31 -05002464 switch (format) {
2465 case 0:
2466 rn->SpecificLen = 0;
2467 break;
2468 case RNID_TOPOLOGY_DISC:
James Smart92d7f7b2007-06-17 19:56:38 -05002469 rn->SpecificLen = sizeof(RNID_TOP_DISC);
dea31012005-04-17 16:05:31 -05002470 memcpy(&rn->un.topologyDisc.portName,
James Smart92d7f7b2007-06-17 19:56:38 -05002471 &vport->fc_portname, sizeof(struct lpfc_name));
dea31012005-04-17 16:05:31 -05002472 rn->un.topologyDisc.unitType = RNID_HBA;
2473 rn->un.topologyDisc.physPort = 0;
2474 rn->un.topologyDisc.attachedNodes = 0;
2475 break;
2476 default:
2477 rn->CommonLen = 0;
2478 rn->SpecificLen = 0;
2479 break;
2480 }
2481
2482 phba->fc_stat.elsXmitACC++;
2483 elsiocb->iocb_cmpl = lpfc_cmpl_els_acc;
James Smart329f9bc2007-04-25 09:53:01 -04002484 lpfc_nlp_put(ndlp);
dea31012005-04-17 16:05:31 -05002485 elsiocb->context1 = NULL; /* Don't need ndlp for cmpl,
2486 * it could be freed */
2487
dea31012005-04-17 16:05:31 -05002488 rc = lpfc_sli_issue_iocb(phba, pring, elsiocb, 0);
dea31012005-04-17 16:05:31 -05002489 if (rc == IOCB_ERROR) {
2490 lpfc_els_free_iocb(phba, elsiocb);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002491 return 1;
dea31012005-04-17 16:05:31 -05002492 }
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002493 return 0;
dea31012005-04-17 16:05:31 -05002494}
2495
2496int
James Smart2e0fef82007-06-17 19:56:36 -05002497lpfc_els_disc_adisc(struct lpfc_vport *vport)
dea31012005-04-17 16:05:31 -05002498{
James Smart2e0fef82007-06-17 19:56:36 -05002499 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
dea31012005-04-17 16:05:31 -05002500 struct lpfc_nodelist *ndlp, *next_ndlp;
James Smart2e0fef82007-06-17 19:56:36 -05002501 int sentadisc = 0;
dea31012005-04-17 16:05:31 -05002502
James Smart685f0bf2007-04-25 09:53:08 -04002503 /* go thru NPR nodes and issue any remaining ELS ADISCs */
James Smart2e0fef82007-06-17 19:56:36 -05002504 list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) {
James Smart685f0bf2007-04-25 09:53:08 -04002505 if (ndlp->nlp_state == NLP_STE_NPR_NODE &&
2506 (ndlp->nlp_flag & NLP_NPR_2B_DISC) != 0 &&
2507 (ndlp->nlp_flag & NLP_NPR_ADISC) != 0) {
James Smart2e0fef82007-06-17 19:56:36 -05002508 spin_lock_irq(shost->host_lock);
James Smart685f0bf2007-04-25 09:53:08 -04002509 ndlp->nlp_flag &= ~NLP_NPR_ADISC;
James Smart2e0fef82007-06-17 19:56:36 -05002510 spin_unlock_irq(shost->host_lock);
James Smart685f0bf2007-04-25 09:53:08 -04002511 ndlp->nlp_prev_state = ndlp->nlp_state;
James Smart2e0fef82007-06-17 19:56:36 -05002512 lpfc_nlp_set_state(vport, ndlp, NLP_STE_ADISC_ISSUE);
2513 lpfc_issue_els_adisc(vport, ndlp, 0);
James Smart685f0bf2007-04-25 09:53:08 -04002514 sentadisc++;
James Smart2e0fef82007-06-17 19:56:36 -05002515 vport->num_disc_nodes++;
2516 if (vport->num_disc_nodes >=
2517 vport->phba->cfg_discovery_threads) {
2518 spin_lock_irq(shost->host_lock);
2519 vport->fc_flag |= FC_NLP_MORE;
2520 spin_unlock_irq(shost->host_lock);
James Smart685f0bf2007-04-25 09:53:08 -04002521 break;
dea31012005-04-17 16:05:31 -05002522 }
2523 }
2524 }
2525 if (sentadisc == 0) {
James Smart2e0fef82007-06-17 19:56:36 -05002526 spin_lock_irq(shost->host_lock);
2527 vport->fc_flag &= ~FC_NLP_MORE;
2528 spin_unlock_irq(shost->host_lock);
dea31012005-04-17 16:05:31 -05002529 }
Jamie Wellnitz2fe165b2006-02-28 19:25:31 -05002530 return sentadisc;
dea31012005-04-17 16:05:31 -05002531}
2532
2533int
James Smart2e0fef82007-06-17 19:56:36 -05002534lpfc_els_disc_plogi(struct lpfc_vport *vport)
dea31012005-04-17 16:05:31 -05002535{
James Smart2e0fef82007-06-17 19:56:36 -05002536 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
dea31012005-04-17 16:05:31 -05002537 struct lpfc_nodelist *ndlp, *next_ndlp;
James Smart2e0fef82007-06-17 19:56:36 -05002538 int sentplogi = 0;
dea31012005-04-17 16:05:31 -05002539
James Smart2e0fef82007-06-17 19:56:36 -05002540 /* go thru NPR nodes and issue any remaining ELS PLOGIs */
2541 list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) {
James Smart685f0bf2007-04-25 09:53:08 -04002542 if (ndlp->nlp_state == NLP_STE_NPR_NODE &&
2543 (ndlp->nlp_flag & NLP_NPR_2B_DISC) != 0 &&
2544 (ndlp->nlp_flag & NLP_DELAY_TMO) == 0 &&
2545 (ndlp->nlp_flag & NLP_NPR_ADISC) == 0) {
2546 ndlp->nlp_prev_state = ndlp->nlp_state;
James Smart2e0fef82007-06-17 19:56:36 -05002547 lpfc_nlp_set_state(vport, ndlp, NLP_STE_PLOGI_ISSUE);
2548 lpfc_issue_els_plogi(vport, ndlp->nlp_DID, 0);
James Smart685f0bf2007-04-25 09:53:08 -04002549 sentplogi++;
James Smart2e0fef82007-06-17 19:56:36 -05002550 vport->num_disc_nodes++;
2551 if (vport->num_disc_nodes >=
2552 vport->phba->cfg_discovery_threads) {
2553 spin_lock_irq(shost->host_lock);
2554 vport->fc_flag |= FC_NLP_MORE;
2555 spin_unlock_irq(shost->host_lock);
James Smart685f0bf2007-04-25 09:53:08 -04002556 break;
dea31012005-04-17 16:05:31 -05002557 }
2558 }
2559 }
2560 if (sentplogi == 0) {
James Smart2e0fef82007-06-17 19:56:36 -05002561 spin_lock_irq(shost->host_lock);
2562 vport->fc_flag &= ~FC_NLP_MORE;
2563 spin_unlock_irq(shost->host_lock);
dea31012005-04-17 16:05:31 -05002564 }
Jamie Wellnitz2fe165b2006-02-28 19:25:31 -05002565 return sentplogi;
dea31012005-04-17 16:05:31 -05002566}
2567
James Smart92d7f7b2007-06-17 19:56:38 -05002568void
James Smart2e0fef82007-06-17 19:56:36 -05002569lpfc_els_flush_rscn(struct lpfc_vport *vport)
dea31012005-04-17 16:05:31 -05002570{
James Smart2e0fef82007-06-17 19:56:36 -05002571 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
2572 struct lpfc_hba *phba = vport->phba;
dea31012005-04-17 16:05:31 -05002573 int i;
2574
James Smart2e0fef82007-06-17 19:56:36 -05002575 for (i = 0; i < vport->fc_rscn_id_cnt; i++) {
James Smart92d7f7b2007-06-17 19:56:38 -05002576 lpfc_in_buf_free(phba, vport->fc_rscn_id_list[i]);
James Smart2e0fef82007-06-17 19:56:36 -05002577 vport->fc_rscn_id_list[i] = NULL;
dea31012005-04-17 16:05:31 -05002578 }
James Smart2e0fef82007-06-17 19:56:36 -05002579 spin_lock_irq(shost->host_lock);
2580 vport->fc_rscn_id_cnt = 0;
2581 vport->fc_flag &= ~(FC_RSCN_MODE | FC_RSCN_DISCOVERY);
2582 spin_unlock_irq(shost->host_lock);
2583 lpfc_can_disctmo(vport);
dea31012005-04-17 16:05:31 -05002584}
2585
2586int
James Smart2e0fef82007-06-17 19:56:36 -05002587lpfc_rscn_payload_check(struct lpfc_vport *vport, uint32_t did)
dea31012005-04-17 16:05:31 -05002588{
2589 D_ID ns_did;
2590 D_ID rscn_did;
dea31012005-04-17 16:05:31 -05002591 uint32_t *lp;
James Smart92d7f7b2007-06-17 19:56:38 -05002592 uint32_t payload_len, i;
James Smart2e0fef82007-06-17 19:56:36 -05002593 struct lpfc_hba *phba = vport->phba;
dea31012005-04-17 16:05:31 -05002594
2595 ns_did.un.word = did;
dea31012005-04-17 16:05:31 -05002596
2597 /* Never match fabric nodes for RSCNs */
2598 if ((did & Fabric_DID_MASK) == Fabric_DID_MASK)
James Smart2e0fef82007-06-17 19:56:36 -05002599 return 0;
dea31012005-04-17 16:05:31 -05002600
2601 /* If we are doing a FULL RSCN rediscovery, match everything */
James Smart2e0fef82007-06-17 19:56:36 -05002602 if (vport->fc_flag & FC_RSCN_DISCOVERY)
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002603 return did;
dea31012005-04-17 16:05:31 -05002604
James Smart2e0fef82007-06-17 19:56:36 -05002605 for (i = 0; i < vport->fc_rscn_id_cnt; i++) {
James Smart92d7f7b2007-06-17 19:56:38 -05002606 lp = vport->fc_rscn_id_list[i]->virt;
2607 payload_len = be32_to_cpu(*lp++ & ~ELS_CMD_MASK);
2608 payload_len -= sizeof(uint32_t); /* take off word 0 */
dea31012005-04-17 16:05:31 -05002609 while (payload_len) {
James Smart92d7f7b2007-06-17 19:56:38 -05002610 rscn_did.un.word = be32_to_cpu(*lp++);
2611 payload_len -= sizeof(uint32_t);
dea31012005-04-17 16:05:31 -05002612 switch (rscn_did.un.b.resv) {
2613 case 0: /* Single N_Port ID effected */
James Smart2e0fef82007-06-17 19:56:36 -05002614 if (ns_did.un.word == rscn_did.un.word)
James Smart92d7f7b2007-06-17 19:56:38 -05002615 return did;
dea31012005-04-17 16:05:31 -05002616 break;
2617 case 1: /* Whole N_Port Area effected */
2618 if ((ns_did.un.b.domain == rscn_did.un.b.domain)
2619 && (ns_did.un.b.area == rscn_did.un.b.area))
James Smart92d7f7b2007-06-17 19:56:38 -05002620 return did;
dea31012005-04-17 16:05:31 -05002621 break;
2622 case 2: /* Whole N_Port Domain effected */
2623 if (ns_did.un.b.domain == rscn_did.un.b.domain)
James Smart92d7f7b2007-06-17 19:56:38 -05002624 return did;
dea31012005-04-17 16:05:31 -05002625 break;
2626 default:
James Smart2e0fef82007-06-17 19:56:36 -05002627 /* Unknown Identifier in RSCN node */
dea31012005-04-17 16:05:31 -05002628 lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
James Smart92d7f7b2007-06-17 19:56:38 -05002629 "%d (%d):0217 Unknown "
2630 "Identifier in RSCN payload "
2631 "Data: x%x\n",
2632 phba->brd_no, vport->vpi,
2633 rscn_did.un.word);
2634 case 3: /* Whole Fabric effected */
2635 return did;
dea31012005-04-17 16:05:31 -05002636 }
2637 }
James Smart92d7f7b2007-06-17 19:56:38 -05002638 }
2639 return 0;
dea31012005-04-17 16:05:31 -05002640}
2641
2642static int
James Smart2e0fef82007-06-17 19:56:36 -05002643lpfc_rscn_recovery_check(struct lpfc_vport *vport)
dea31012005-04-17 16:05:31 -05002644{
James Smart685f0bf2007-04-25 09:53:08 -04002645 struct lpfc_nodelist *ndlp = NULL;
dea31012005-04-17 16:05:31 -05002646
2647 /* Look at all nodes effected by pending RSCNs and move
James Smart685f0bf2007-04-25 09:53:08 -04002648 * them to NPR state.
dea31012005-04-17 16:05:31 -05002649 */
James Smart685f0bf2007-04-25 09:53:08 -04002650
James Smart2e0fef82007-06-17 19:56:36 -05002651 list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) {
James Smart685f0bf2007-04-25 09:53:08 -04002652 if (ndlp->nlp_state == NLP_STE_UNUSED_NODE ||
James Smart2e0fef82007-06-17 19:56:36 -05002653 lpfc_rscn_payload_check(vport, ndlp->nlp_DID) == 0)
dea31012005-04-17 16:05:31 -05002654 continue;
2655
James Smart2e0fef82007-06-17 19:56:36 -05002656 lpfc_disc_state_machine(vport, ndlp, NULL,
James Smart92d7f7b2007-06-17 19:56:38 -05002657 NLP_EVT_DEVICE_RECOVERY);
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05002658
James Smart685f0bf2007-04-25 09:53:08 -04002659 /*
2660 * Make sure NLP_DELAY_TMO is NOT running after a device
2661 * recovery event.
2662 */
2663 if (ndlp->nlp_flag & NLP_DELAY_TMO)
James Smart2e0fef82007-06-17 19:56:36 -05002664 lpfc_cancel_retry_delay_tmo(vport, ndlp);
dea31012005-04-17 16:05:31 -05002665 }
James Smart685f0bf2007-04-25 09:53:08 -04002666
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002667 return 0;
dea31012005-04-17 16:05:31 -05002668}
2669
2670static int
James Smart2e0fef82007-06-17 19:56:36 -05002671lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
2672 struct lpfc_nodelist *ndlp, uint8_t newnode)
dea31012005-04-17 16:05:31 -05002673{
James Smart2e0fef82007-06-17 19:56:36 -05002674 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
2675 struct lpfc_hba *phba = vport->phba;
dea31012005-04-17 16:05:31 -05002676 struct lpfc_dmabuf *pcmd;
James Smart92d7f7b2007-06-17 19:56:38 -05002677 struct lpfc_vport *next_vport;
2678 uint32_t *lp, *datap;
dea31012005-04-17 16:05:31 -05002679 IOCB_t *icmd;
James Smart92d7f7b2007-06-17 19:56:38 -05002680 uint32_t payload_len, length, nportid, *cmd;
2681 int rscn_cnt = vport->fc_rscn_id_cnt;
2682 int rscn_id = 0, hba_id = 0;
James Smartd2873e42006-08-18 17:46:43 -04002683 int i;
dea31012005-04-17 16:05:31 -05002684
2685 icmd = &cmdiocb->iocb;
2686 pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
2687 lp = (uint32_t *) pcmd->virt;
2688
James Smart92d7f7b2007-06-17 19:56:38 -05002689 payload_len = be32_to_cpu(*lp++ & ~ELS_CMD_MASK);
2690 payload_len -= sizeof(uint32_t); /* take off word 0 */
dea31012005-04-17 16:05:31 -05002691
2692 /* RSCN received */
James Smarted957682007-06-17 19:56:37 -05002693 lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
James Smart92d7f7b2007-06-17 19:56:38 -05002694 "%d (%d):0214 RSCN received Data: x%x x%x x%x x%x\n",
2695 phba->brd_no, vport->vpi, vport->fc_flag, payload_len,
2696 *lp, rscn_cnt);
dea31012005-04-17 16:05:31 -05002697
James Smartd2873e42006-08-18 17:46:43 -04002698 for (i = 0; i < payload_len/sizeof(uint32_t); i++)
James Smart2e0fef82007-06-17 19:56:36 -05002699 fc_host_post_event(shost, fc_get_event_number(),
James Smartd2873e42006-08-18 17:46:43 -04002700 FCH_EVT_RSCN, lp[i]);
2701
dea31012005-04-17 16:05:31 -05002702 /* If we are about to begin discovery, just ACC the RSCN.
2703 * Discovery processing will satisfy it.
2704 */
James Smart2e0fef82007-06-17 19:56:36 -05002705 if (vport->port_state <= LPFC_NS_QRY) {
2706 lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL,
James Smart92d7f7b2007-06-17 19:56:38 -05002707 newnode);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002708 return 0;
dea31012005-04-17 16:05:31 -05002709 }
2710
James Smart92d7f7b2007-06-17 19:56:38 -05002711 /* If this RSCN just contains NPortIDs for other vports on this HBA,
2712 * just ACC and ignore it.
2713 */
2714 if ((phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) &&
2715 !(phba->cfg_peer_port_login)) {
2716 i = payload_len;
2717 datap = lp;
2718 while (i > 0) {
2719 nportid = *datap++;
2720 nportid = ((be32_to_cpu(nportid)) & Mask_DID);
2721 i -= sizeof(uint32_t);
2722 rscn_id++;
2723 list_for_each_entry(next_vport, &phba->port_list,
2724 listentry) {
2725 if (nportid == next_vport->fc_myDID) {
2726 hba_id++;
2727 break;
2728 }
2729 }
2730 }
2731 if (rscn_id == hba_id) {
2732 /* ALL NPortIDs in RSCN are on HBA */
2733 lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
2734 "%d (%d):0214 Ignore RSCN Data: x%x x%x x%x x%x\n",
2735 phba->brd_no, vport->vpi, vport->fc_flag, payload_len,
2736 *lp, rscn_cnt);
2737 lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb,
2738 ndlp, NULL, newnode);
2739 return 0;
2740 }
2741 }
2742
dea31012005-04-17 16:05:31 -05002743 /* If we are already processing an RSCN, save the received
2744 * RSCN payload buffer, cmdiocb->context2 to process later.
2745 */
James Smart2e0fef82007-06-17 19:56:36 -05002746 if (vport->fc_flag & (FC_RSCN_MODE | FC_NDISC_ACTIVE)) {
James Smart92d7f7b2007-06-17 19:56:38 -05002747 vport->fc_flag |= FC_RSCN_DEFERRED;
2748 if ((rscn_cnt < FC_MAX_HOLD_RSCN) &&
James Smart2e0fef82007-06-17 19:56:36 -05002749 !(vport->fc_flag & FC_RSCN_DISCOVERY)) {
2750 spin_lock_irq(shost->host_lock);
2751 vport->fc_flag |= FC_RSCN_MODE;
2752 spin_unlock_irq(shost->host_lock);
James Smart92d7f7b2007-06-17 19:56:38 -05002753 if (rscn_cnt) {
2754 cmd = vport->fc_rscn_id_list[rscn_cnt-1]->virt;
2755 length = be32_to_cpu(*cmd & ~ELS_CMD_MASK);
2756 }
2757 if ((rscn_cnt) &&
2758 (payload_len + length <= LPFC_BPL_SIZE)) {
2759 *cmd &= ELS_CMD_MASK;
2760 *cmd |= be32_to_cpu(payload_len + length);
2761 memcpy(((uint8_t *)cmd) + length, lp,
2762 payload_len);
2763 } else {
2764 vport->fc_rscn_id_list[rscn_cnt] = pcmd;
2765 vport->fc_rscn_id_cnt++;
2766 /* If we zero, cmdiocb->context2, the calling
2767 * routine will not try to free it.
2768 */
2769 cmdiocb->context2 = NULL;
2770 }
dea31012005-04-17 16:05:31 -05002771
2772 /* Deferred RSCN */
2773 lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
James Smart92d7f7b2007-06-17 19:56:38 -05002774 "%d (%d):0235 Deferred RSCN "
dea31012005-04-17 16:05:31 -05002775 "Data: x%x x%x x%x\n",
James Smart92d7f7b2007-06-17 19:56:38 -05002776 phba->brd_no, vport->vpi,
2777 vport->fc_rscn_id_cnt, vport->fc_flag,
James Smart2e0fef82007-06-17 19:56:36 -05002778 vport->port_state);
dea31012005-04-17 16:05:31 -05002779 } else {
James Smart2e0fef82007-06-17 19:56:36 -05002780 spin_lock_irq(shost->host_lock);
2781 vport->fc_flag |= FC_RSCN_DISCOVERY;
2782 spin_unlock_irq(shost->host_lock);
dea31012005-04-17 16:05:31 -05002783 /* ReDiscovery RSCN */
2784 lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
James Smart92d7f7b2007-06-17 19:56:38 -05002785 "%d (%d):0234 ReDiscovery RSCN "
dea31012005-04-17 16:05:31 -05002786 "Data: x%x x%x x%x\n",
James Smart92d7f7b2007-06-17 19:56:38 -05002787 phba->brd_no, vport->vpi,
2788 vport->fc_rscn_id_cnt, vport->fc_flag,
James Smart2e0fef82007-06-17 19:56:36 -05002789 vport->port_state);
dea31012005-04-17 16:05:31 -05002790 }
2791 /* Send back ACC */
James Smart2e0fef82007-06-17 19:56:36 -05002792 lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL,
dea31012005-04-17 16:05:31 -05002793 newnode);
2794
2795 /* send RECOVERY event for ALL nodes that match RSCN payload */
James Smart2e0fef82007-06-17 19:56:36 -05002796 lpfc_rscn_recovery_check(vport);
James Smart92d7f7b2007-06-17 19:56:38 -05002797 vport->fc_flag &= ~FC_RSCN_DEFERRED;
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002798 return 0;
dea31012005-04-17 16:05:31 -05002799 }
2800
James Smart2e0fef82007-06-17 19:56:36 -05002801 spin_lock_irq(shost->host_lock);
2802 vport->fc_flag |= FC_RSCN_MODE;
2803 spin_unlock_irq(shost->host_lock);
2804 vport->fc_rscn_id_list[vport->fc_rscn_id_cnt++] = pcmd;
dea31012005-04-17 16:05:31 -05002805 /*
2806 * If we zero, cmdiocb->context2, the calling routine will
2807 * not try to free it.
2808 */
2809 cmdiocb->context2 = NULL;
2810
James Smart2e0fef82007-06-17 19:56:36 -05002811 lpfc_set_disctmo(vport);
dea31012005-04-17 16:05:31 -05002812
2813 /* Send back ACC */
James Smart2e0fef82007-06-17 19:56:36 -05002814 lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL, newnode);
dea31012005-04-17 16:05:31 -05002815
2816 /* send RECOVERY event for ALL nodes that match RSCN payload */
James Smart2e0fef82007-06-17 19:56:36 -05002817 lpfc_rscn_recovery_check(vport);
dea31012005-04-17 16:05:31 -05002818
James Smart2e0fef82007-06-17 19:56:36 -05002819 return lpfc_els_handle_rscn(vport);
dea31012005-04-17 16:05:31 -05002820}
2821
2822int
James Smart2e0fef82007-06-17 19:56:36 -05002823lpfc_els_handle_rscn(struct lpfc_vport *vport)
dea31012005-04-17 16:05:31 -05002824{
2825 struct lpfc_nodelist *ndlp;
James Smart2e0fef82007-06-17 19:56:36 -05002826 struct lpfc_hba *phba = vport->phba;
dea31012005-04-17 16:05:31 -05002827
James Smart92d7f7b2007-06-17 19:56:38 -05002828 /* Ignore RSCN if the port is being torn down. */
2829 if (vport->load_flag & FC_UNLOADING) {
2830 lpfc_els_flush_rscn(vport);
2831 return 0;
2832 }
2833
dea31012005-04-17 16:05:31 -05002834 /* Start timer for RSCN processing */
James Smart2e0fef82007-06-17 19:56:36 -05002835 lpfc_set_disctmo(vport);
dea31012005-04-17 16:05:31 -05002836
2837 /* RSCN processed */
James Smarted957682007-06-17 19:56:37 -05002838 lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
James Smart92d7f7b2007-06-17 19:56:38 -05002839 "%d (%d):0215 RSCN processed Data: x%x x%x x%x x%x\n",
2840 phba->brd_no, vport->vpi,
James Smart2e0fef82007-06-17 19:56:36 -05002841 vport->fc_flag, 0, vport->fc_rscn_id_cnt,
2842 vport->port_state);
dea31012005-04-17 16:05:31 -05002843
2844 /* To process RSCN, first compare RSCN data with NameServer */
James Smart2e0fef82007-06-17 19:56:36 -05002845 vport->fc_ns_retry = 0;
2846 ndlp = lpfc_findnode_did(vport, NameServer_DID);
James Smart685f0bf2007-04-25 09:53:08 -04002847 if (ndlp && ndlp->nlp_state == NLP_STE_UNMAPPED_NODE) {
dea31012005-04-17 16:05:31 -05002848 /* Good ndlp, issue CT Request to NameServer */
James Smart92d7f7b2007-06-17 19:56:38 -05002849 if (lpfc_ns_cmd(vport, SLI_CTNS_GID_FT, 0, 0) == 0)
dea31012005-04-17 16:05:31 -05002850 /* Wait for NameServer query cmpl before we can
2851 continue */
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002852 return 1;
dea31012005-04-17 16:05:31 -05002853 } else {
2854 /* If login to NameServer does not exist, issue one */
2855 /* Good status, issue PLOGI to NameServer */
James Smart2e0fef82007-06-17 19:56:36 -05002856 ndlp = lpfc_findnode_did(vport, NameServer_DID);
2857 if (ndlp)
dea31012005-04-17 16:05:31 -05002858 /* Wait for NameServer login cmpl before we can
2859 continue */
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002860 return 1;
James Smart2e0fef82007-06-17 19:56:36 -05002861
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002862 ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL);
2863 if (!ndlp) {
James Smart2e0fef82007-06-17 19:56:36 -05002864 lpfc_els_flush_rscn(vport);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002865 return 0;
dea31012005-04-17 16:05:31 -05002866 } else {
James Smart2e0fef82007-06-17 19:56:36 -05002867 lpfc_nlp_init(vport, ndlp, NameServer_DID);
dea31012005-04-17 16:05:31 -05002868 ndlp->nlp_type |= NLP_FABRIC;
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05002869 ndlp->nlp_prev_state = ndlp->nlp_state;
James Smart2e0fef82007-06-17 19:56:36 -05002870 lpfc_nlp_set_state(vport, ndlp, NLP_STE_PLOGI_ISSUE);
2871 lpfc_issue_els_plogi(vport, NameServer_DID, 0);
dea31012005-04-17 16:05:31 -05002872 /* Wait for NameServer login cmpl before we can
2873 continue */
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002874 return 1;
dea31012005-04-17 16:05:31 -05002875 }
2876 }
2877
James Smart2e0fef82007-06-17 19:56:36 -05002878 lpfc_els_flush_rscn(vport);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002879 return 0;
dea31012005-04-17 16:05:31 -05002880}
2881
2882static int
James Smart2e0fef82007-06-17 19:56:36 -05002883lpfc_els_rcv_flogi(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
2884 struct lpfc_nodelist *ndlp, uint8_t newnode)
dea31012005-04-17 16:05:31 -05002885{
James Smart2e0fef82007-06-17 19:56:36 -05002886 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
2887 struct lpfc_hba *phba = vport->phba;
dea31012005-04-17 16:05:31 -05002888 struct lpfc_dmabuf *pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
2889 uint32_t *lp = (uint32_t *) pcmd->virt;
2890 IOCB_t *icmd = &cmdiocb->iocb;
2891 struct serv_parm *sp;
2892 LPFC_MBOXQ_t *mbox;
2893 struct ls_rjt stat;
2894 uint32_t cmd, did;
2895 int rc;
2896
2897 cmd = *lp++;
2898 sp = (struct serv_parm *) lp;
2899
2900 /* FLOGI received */
2901
James Smart2e0fef82007-06-17 19:56:36 -05002902 lpfc_set_disctmo(vport);
dea31012005-04-17 16:05:31 -05002903
2904 if (phba->fc_topology == TOPOLOGY_LOOP) {
2905 /* We should never receive a FLOGI in loop mode, ignore it */
2906 did = icmd->un.elsreq64.remoteID;
2907
2908 /* An FLOGI ELS command <elsCmd> was received from DID <did> in
2909 Loop Mode */
2910 lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
James Smart92d7f7b2007-06-17 19:56:38 -05002911 "%d (%d):0113 An FLOGI ELS command x%x was "
2912 "received from DID x%x in Loop Mode\n",
2913 phba->brd_no, vport->vpi, cmd, did);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002914 return 1;
dea31012005-04-17 16:05:31 -05002915 }
2916
2917 did = Fabric_DID;
2918
James Smart2e0fef82007-06-17 19:56:36 -05002919 if ((lpfc_check_sparm(vport, ndlp, sp, CLASS3))) {
dea31012005-04-17 16:05:31 -05002920 /* For a FLOGI we accept, then if our portname is greater
2921 * then the remote portname we initiate Nport login.
2922 */
2923
James Smart2e0fef82007-06-17 19:56:36 -05002924 rc = memcmp(&vport->fc_portname, &sp->portName,
James Smart92d7f7b2007-06-17 19:56:38 -05002925 sizeof(struct lpfc_name));
dea31012005-04-17 16:05:31 -05002926
2927 if (!rc) {
James Smart2e0fef82007-06-17 19:56:36 -05002928 mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
2929 if (!mbox)
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002930 return 1;
James Smart2e0fef82007-06-17 19:56:36 -05002931
dea31012005-04-17 16:05:31 -05002932 lpfc_linkdown(phba);
2933 lpfc_init_link(phba, mbox,
2934 phba->cfg_topology,
2935 phba->cfg_link_speed);
2936 mbox->mb.un.varInitLnk.lipsr_AL_PA = 0;
2937 mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
James Smarted957682007-06-17 19:56:37 -05002938 mbox->vport = vport;
dea31012005-04-17 16:05:31 -05002939 rc = lpfc_sli_issue_mbox
2940 (phba, mbox, (MBX_NOWAIT | MBX_STOP_IOCB));
James Smart5b8bd0c2007-04-25 09:52:49 -04002941 lpfc_set_loopback_flag(phba);
dea31012005-04-17 16:05:31 -05002942 if (rc == MBX_NOT_FINISHED) {
James Smart329f9bc2007-04-25 09:53:01 -04002943 mempool_free(mbox, phba->mbox_mem_pool);
dea31012005-04-17 16:05:31 -05002944 }
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002945 return 1;
Jamie Wellnitz2fe165b2006-02-28 19:25:31 -05002946 } else if (rc > 0) { /* greater than */
James Smart2e0fef82007-06-17 19:56:36 -05002947 spin_lock_irq(shost->host_lock);
2948 vport->fc_flag |= FC_PT2PT_PLOGI;
2949 spin_unlock_irq(shost->host_lock);
dea31012005-04-17 16:05:31 -05002950 }
James Smart2e0fef82007-06-17 19:56:36 -05002951 spin_lock_irq(shost->host_lock);
2952 vport->fc_flag |= FC_PT2PT;
2953 vport->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP);
2954 spin_unlock_irq(shost->host_lock);
dea31012005-04-17 16:05:31 -05002955 } else {
2956 /* Reject this request because invalid parameters */
2957 stat.un.b.lsRjtRsvd0 = 0;
2958 stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
2959 stat.un.b.lsRjtRsnCodeExp = LSEXP_SPARM_OPTIONS;
2960 stat.un.b.vendorUnique = 0;
James Smart2e0fef82007-06-17 19:56:36 -05002961 lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002962 return 1;
dea31012005-04-17 16:05:31 -05002963 }
2964
2965 /* Send back ACC */
James Smart2e0fef82007-06-17 19:56:36 -05002966 lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb, ndlp, NULL, newnode);
dea31012005-04-17 16:05:31 -05002967
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05002968 return 0;
dea31012005-04-17 16:05:31 -05002969}
2970
2971static int
James Smart2e0fef82007-06-17 19:56:36 -05002972lpfc_els_rcv_rnid(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
2973 struct lpfc_nodelist *ndlp)
dea31012005-04-17 16:05:31 -05002974{
2975 struct lpfc_dmabuf *pcmd;
2976 uint32_t *lp;
2977 IOCB_t *icmd;
2978 RNID *rn;
2979 struct ls_rjt stat;
2980 uint32_t cmd, did;
2981
2982 icmd = &cmdiocb->iocb;
2983 did = icmd->un.elsreq64.remoteID;
2984 pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
2985 lp = (uint32_t *) pcmd->virt;
2986
2987 cmd = *lp++;
2988 rn = (RNID *) lp;
2989
2990 /* RNID received */
2991
2992 switch (rn->Format) {
2993 case 0:
2994 case RNID_TOPOLOGY_DISC:
2995 /* Send back ACC */
James Smart2e0fef82007-06-17 19:56:36 -05002996 lpfc_els_rsp_rnid_acc(vport, rn->Format, cmdiocb, ndlp);
dea31012005-04-17 16:05:31 -05002997 break;
2998 default:
2999 /* Reject this request because format not supported */
3000 stat.un.b.lsRjtRsvd0 = 0;
3001 stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
3002 stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA;
3003 stat.un.b.vendorUnique = 0;
James Smart2e0fef82007-06-17 19:56:36 -05003004 lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp);
dea31012005-04-17 16:05:31 -05003005 }
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05003006 return 0;
dea31012005-04-17 16:05:31 -05003007}
3008
3009static int
James Smart2e0fef82007-06-17 19:56:36 -05003010lpfc_els_rcv_lirr(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
3011 struct lpfc_nodelist *ndlp)
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05003012{
3013 struct ls_rjt stat;
3014
3015 /* For now, unconditionally reject this command */
3016 stat.un.b.lsRjtRsvd0 = 0;
3017 stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
3018 stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA;
3019 stat.un.b.vendorUnique = 0;
James Smart2e0fef82007-06-17 19:56:36 -05003020 lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp);
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05003021 return 0;
3022}
3023
Jamie Wellnitz082c0262006-02-28 19:25:30 -05003024static void
James Smart329f9bc2007-04-25 09:53:01 -04003025lpfc_els_rsp_rps_acc(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05003026{
James Smart2e0fef82007-06-17 19:56:36 -05003027 struct lpfc_sli *psli = &phba->sli;
3028 struct lpfc_sli_ring *pring = &psli->ring[LPFC_ELS_RING];
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05003029 MAILBOX_t *mb;
3030 IOCB_t *icmd;
3031 RPS_RSP *rps_rsp;
3032 uint8_t *pcmd;
3033 struct lpfc_iocbq *elsiocb;
3034 struct lpfc_nodelist *ndlp;
3035 uint16_t xri, status;
3036 uint32_t cmdsize;
3037
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05003038 mb = &pmb->mb;
3039
3040 ndlp = (struct lpfc_nodelist *) pmb->context2;
3041 xri = (uint16_t) ((unsigned long)(pmb->context1));
Randy Dunlap041976f2006-06-25 01:58:51 -07003042 pmb->context1 = NULL;
3043 pmb->context2 = NULL;
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05003044
3045 if (mb->mbxStatus) {
James Smart329f9bc2007-04-25 09:53:01 -04003046 mempool_free(pmb, phba->mbox_mem_pool);
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05003047 return;
3048 }
3049
3050 cmdsize = sizeof(RPS_RSP) + sizeof(uint32_t);
James Smart329f9bc2007-04-25 09:53:01 -04003051 mempool_free(pmb, phba->mbox_mem_pool);
James Smart2e0fef82007-06-17 19:56:36 -05003052 elsiocb = lpfc_prep_els_iocb(phba->pport, 0, cmdsize,
3053 lpfc_max_els_tries, ndlp,
3054 ndlp->nlp_DID, ELS_CMD_ACC);
James Smart329f9bc2007-04-25 09:53:01 -04003055 lpfc_nlp_put(ndlp);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05003056 if (!elsiocb)
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05003057 return;
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05003058
3059 icmd = &elsiocb->iocb;
3060 icmd->ulpContext = xri;
3061
3062 pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
3063 *((uint32_t *) (pcmd)) = ELS_CMD_ACC;
James Smart92d7f7b2007-06-17 19:56:38 -05003064 pcmd += sizeof(uint32_t); /* Skip past command */
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05003065 rps_rsp = (RPS_RSP *)pcmd;
3066
3067 if (phba->fc_topology != TOPOLOGY_LOOP)
3068 status = 0x10;
3069 else
3070 status = 0x8;
James Smart2e0fef82007-06-17 19:56:36 -05003071 if (phba->pport->fc_flag & FC_FABRIC)
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05003072 status |= 0x4;
3073
3074 rps_rsp->rsvd1 = 0;
3075 rps_rsp->portStatus = be16_to_cpu(status);
3076 rps_rsp->linkFailureCnt = be32_to_cpu(mb->un.varRdLnk.linkFailureCnt);
3077 rps_rsp->lossSyncCnt = be32_to_cpu(mb->un.varRdLnk.lossSyncCnt);
3078 rps_rsp->lossSignalCnt = be32_to_cpu(mb->un.varRdLnk.lossSignalCnt);
3079 rps_rsp->primSeqErrCnt = be32_to_cpu(mb->un.varRdLnk.primSeqErrCnt);
3080 rps_rsp->invalidXmitWord = be32_to_cpu(mb->un.varRdLnk.invalidXmitWord);
3081 rps_rsp->crcCnt = be32_to_cpu(mb->un.varRdLnk.crcCnt);
3082
3083 /* Xmit ELS RPS ACC response tag <ulpIoTag> */
3084 lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
James Smart92d7f7b2007-06-17 19:56:38 -05003085 "%d (%d):0118 Xmit ELS RPS ACC response tag x%x "
3086 "xri x%x, did x%x, nlp_flag x%x, nlp_state x%x, "
3087 "rpi x%x\n",
3088 phba->brd_no, ndlp->vport->vpi, elsiocb->iotag,
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05003089 elsiocb->iocb.ulpContext, ndlp->nlp_DID,
3090 ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi);
3091
3092 elsiocb->iocb_cmpl = lpfc_cmpl_els_acc;
3093 phba->fc_stat.elsXmitACC++;
James Smarted957682007-06-17 19:56:37 -05003094 if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR)
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05003095 lpfc_els_free_iocb(phba, elsiocb);
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05003096 return;
3097}
3098
3099static int
James Smart2e0fef82007-06-17 19:56:36 -05003100lpfc_els_rcv_rps(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
3101 struct lpfc_nodelist *ndlp)
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05003102{
James Smart2e0fef82007-06-17 19:56:36 -05003103 struct lpfc_hba *phba = vport->phba;
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05003104 uint32_t *lp;
3105 uint8_t flag;
3106 LPFC_MBOXQ_t *mbox;
3107 struct lpfc_dmabuf *pcmd;
3108 RPS *rps;
3109 struct ls_rjt stat;
3110
Jamie Wellnitz2fe165b2006-02-28 19:25:31 -05003111 if ((ndlp->nlp_state != NLP_STE_UNMAPPED_NODE) &&
3112 (ndlp->nlp_state != NLP_STE_MAPPED_NODE)) {
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05003113 stat.un.b.lsRjtRsvd0 = 0;
3114 stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
3115 stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA;
3116 stat.un.b.vendorUnique = 0;
James Smart2e0fef82007-06-17 19:56:36 -05003117 lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp);
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05003118 }
3119
3120 pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
3121 lp = (uint32_t *) pcmd->virt;
3122 flag = (be32_to_cpu(*lp++) & 0xf);
3123 rps = (RPS *) lp;
3124
3125 if ((flag == 0) ||
3126 ((flag == 1) && (be32_to_cpu(rps->un.portNum) == 0)) ||
James Smart2e0fef82007-06-17 19:56:36 -05003127 ((flag == 2) && (memcmp(&rps->un.portName, &vport->fc_portname,
James Smart92d7f7b2007-06-17 19:56:38 -05003128 sizeof(struct lpfc_name)) == 0))) {
James Smart2e0fef82007-06-17 19:56:36 -05003129
James Smart92d7f7b2007-06-17 19:56:38 -05003130 printk("Fix me....\n");
3131 dump_stack();
James Smart2e0fef82007-06-17 19:56:36 -05003132 mbox = mempool_alloc(phba->mbox_mem_pool, GFP_ATOMIC);
3133 if (mbox) {
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05003134 lpfc_read_lnk_stat(phba, mbox);
3135 mbox->context1 =
James Smart92d7f7b2007-06-17 19:56:38 -05003136 (void *)((unsigned long) cmdiocb->iocb.ulpContext);
James Smart329f9bc2007-04-25 09:53:01 -04003137 mbox->context2 = lpfc_nlp_get(ndlp);
James Smart92d7f7b2007-06-17 19:56:38 -05003138 mbox->vport = vport;
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05003139 mbox->mbox_cmpl = lpfc_els_rsp_rps_acc;
3140 if (lpfc_sli_issue_mbox (phba, mbox,
James Smart2e0fef82007-06-17 19:56:36 -05003141 (MBX_NOWAIT | MBX_STOP_IOCB)) != MBX_NOT_FINISHED)
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05003142 /* Mbox completion will send ELS Response */
3143 return 0;
James Smart2e0fef82007-06-17 19:56:36 -05003144
James Smart329f9bc2007-04-25 09:53:01 -04003145 lpfc_nlp_put(ndlp);
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05003146 mempool_free(mbox, phba->mbox_mem_pool);
3147 }
3148 }
3149 stat.un.b.lsRjtRsvd0 = 0;
3150 stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
3151 stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA;
3152 stat.un.b.vendorUnique = 0;
James Smart2e0fef82007-06-17 19:56:36 -05003153 lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp);
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05003154 return 0;
3155}
3156
Jamie Wellnitz082c0262006-02-28 19:25:30 -05003157static int
James Smart2e0fef82007-06-17 19:56:36 -05003158lpfc_els_rsp_rpl_acc(struct lpfc_vport *vport, uint16_t cmdsize,
3159 struct lpfc_iocbq *oldiocb, struct lpfc_nodelist *ndlp)
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05003160{
James Smart2e0fef82007-06-17 19:56:36 -05003161 struct lpfc_hba *phba = vport->phba;
3162 IOCB_t *icmd, *oldcmd;
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05003163 RPL_RSP rpl_rsp;
3164 struct lpfc_iocbq *elsiocb;
James Smart2e0fef82007-06-17 19:56:36 -05003165 struct lpfc_sli *psli = &phba->sli;
3166 struct lpfc_sli_ring *pring = &psli->ring[LPFC_ELS_RING];
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05003167 uint8_t *pcmd;
3168
James Smart2e0fef82007-06-17 19:56:36 -05003169 elsiocb = lpfc_prep_els_iocb(vport, 0, cmdsize, oldiocb->retry, ndlp,
3170 ndlp->nlp_DID, ELS_CMD_ACC);
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05003171
James Smart488d1462006-03-07 15:02:37 -05003172 if (!elsiocb)
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05003173 return 1;
James Smart488d1462006-03-07 15:02:37 -05003174
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05003175 icmd = &elsiocb->iocb;
3176 oldcmd = &oldiocb->iocb;
3177 icmd->ulpContext = oldcmd->ulpContext; /* Xri */
3178
3179 pcmd = (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
3180 *((uint32_t *) (pcmd)) = ELS_CMD_ACC;
James Smart92d7f7b2007-06-17 19:56:38 -05003181 pcmd += sizeof(uint16_t);
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05003182 *((uint16_t *)(pcmd)) = be16_to_cpu(cmdsize);
3183 pcmd += sizeof(uint16_t);
3184
3185 /* Setup the RPL ACC payload */
3186 rpl_rsp.listLen = be32_to_cpu(1);
3187 rpl_rsp.index = 0;
3188 rpl_rsp.port_num_blk.portNum = 0;
James Smart2e0fef82007-06-17 19:56:36 -05003189 rpl_rsp.port_num_blk.portID = be32_to_cpu(vport->fc_myDID);
3190 memcpy(&rpl_rsp.port_num_blk.portName, &vport->fc_portname,
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05003191 sizeof(struct lpfc_name));
3192
3193 memcpy(pcmd, &rpl_rsp, cmdsize - sizeof(uint32_t));
3194
3195
3196 /* Xmit ELS RPL ACC response tag <ulpIoTag> */
3197 lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
James Smart92d7f7b2007-06-17 19:56:38 -05003198 "%d (%d):0120 Xmit ELS RPL ACC response tag x%x "
3199 "xri x%x, did x%x, nlp_flag x%x, nlp_state x%x, "
3200 "rpi x%x\n",
3201 phba->brd_no, vport->vpi, elsiocb->iotag,
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05003202 elsiocb->iocb.ulpContext, ndlp->nlp_DID,
3203 ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi);
3204
3205 elsiocb->iocb_cmpl = lpfc_cmpl_els_acc;
3206
3207 phba->fc_stat.elsXmitACC++;
3208 if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) {
3209 lpfc_els_free_iocb(phba, elsiocb);
3210 return 1;
3211 }
3212 return 0;
3213}
3214
3215static int
James Smart2e0fef82007-06-17 19:56:36 -05003216lpfc_els_rcv_rpl(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
3217 struct lpfc_nodelist *ndlp)
dea31012005-04-17 16:05:31 -05003218{
3219 struct lpfc_dmabuf *pcmd;
3220 uint32_t *lp;
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05003221 uint32_t maxsize;
3222 uint16_t cmdsize;
3223 RPL *rpl;
3224 struct ls_rjt stat;
dea31012005-04-17 16:05:31 -05003225
Jamie Wellnitz2fe165b2006-02-28 19:25:31 -05003226 if ((ndlp->nlp_state != NLP_STE_UNMAPPED_NODE) &&
3227 (ndlp->nlp_state != NLP_STE_MAPPED_NODE)) {
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05003228 stat.un.b.lsRjtRsvd0 = 0;
3229 stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
3230 stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA;
3231 stat.un.b.vendorUnique = 0;
James Smart2e0fef82007-06-17 19:56:36 -05003232 lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp);
dea31012005-04-17 16:05:31 -05003233 }
3234
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05003235 pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
3236 lp = (uint32_t *) pcmd->virt;
3237 rpl = (RPL *) (lp + 1);
3238
3239 maxsize = be32_to_cpu(rpl->maxsize);
3240
3241 /* We support only one port */
3242 if ((rpl->index == 0) &&
3243 ((maxsize == 0) ||
3244 ((maxsize * sizeof(uint32_t)) >= sizeof(RPL_RSP)))) {
3245 cmdsize = sizeof(uint32_t) + sizeof(RPL_RSP);
Jamie Wellnitz2fe165b2006-02-28 19:25:31 -05003246 } else {
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05003247 cmdsize = sizeof(uint32_t) + maxsize * sizeof(uint32_t);
3248 }
James Smart2e0fef82007-06-17 19:56:36 -05003249 lpfc_els_rsp_rpl_acc(vport, cmdsize, cmdiocb, ndlp);
dea31012005-04-17 16:05:31 -05003250
3251 return 0;
3252}
3253
3254static int
James Smart2e0fef82007-06-17 19:56:36 -05003255lpfc_els_rcv_farp(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
3256 struct lpfc_nodelist *ndlp)
dea31012005-04-17 16:05:31 -05003257{
James Smart2e0fef82007-06-17 19:56:36 -05003258 struct lpfc_hba *phba = vport->phba;
dea31012005-04-17 16:05:31 -05003259 struct lpfc_dmabuf *pcmd;
3260 uint32_t *lp;
3261 IOCB_t *icmd;
3262 FARP *fp;
3263 uint32_t cmd, cnt, did;
3264
3265 icmd = &cmdiocb->iocb;
3266 did = icmd->un.elsreq64.remoteID;
3267 pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
3268 lp = (uint32_t *) pcmd->virt;
3269
3270 cmd = *lp++;
3271 fp = (FARP *) lp;
3272
3273 /* FARP-REQ received from DID <did> */
James Smarted957682007-06-17 19:56:37 -05003274 lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
James Smart92d7f7b2007-06-17 19:56:38 -05003275 "%d (%d):0601 FARP-REQ received from DID x%x\n",
3276 phba->brd_no, vport->vpi, did);
dea31012005-04-17 16:05:31 -05003277
3278 /* We will only support match on WWPN or WWNN */
3279 if (fp->Mflags & ~(FARP_MATCH_NODE | FARP_MATCH_PORT)) {
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05003280 return 0;
dea31012005-04-17 16:05:31 -05003281 }
3282
3283 cnt = 0;
3284 /* If this FARP command is searching for my portname */
3285 if (fp->Mflags & FARP_MATCH_PORT) {
James Smart2e0fef82007-06-17 19:56:36 -05003286 if (memcmp(&fp->RportName, &vport->fc_portname,
James Smart92d7f7b2007-06-17 19:56:38 -05003287 sizeof(struct lpfc_name)) == 0)
dea31012005-04-17 16:05:31 -05003288 cnt = 1;
3289 }
3290
3291 /* If this FARP command is searching for my nodename */
3292 if (fp->Mflags & FARP_MATCH_NODE) {
James Smart2e0fef82007-06-17 19:56:36 -05003293 if (memcmp(&fp->RnodeName, &vport->fc_nodename,
James Smart92d7f7b2007-06-17 19:56:38 -05003294 sizeof(struct lpfc_name)) == 0)
dea31012005-04-17 16:05:31 -05003295 cnt = 1;
3296 }
3297
3298 if (cnt) {
3299 if ((ndlp->nlp_state == NLP_STE_UNMAPPED_NODE) ||
3300 (ndlp->nlp_state == NLP_STE_MAPPED_NODE)) {
3301 /* Log back into the node before sending the FARP. */
3302 if (fp->Rflags & FARP_REQUEST_PLOGI) {
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05003303 ndlp->nlp_prev_state = ndlp->nlp_state;
James Smart2e0fef82007-06-17 19:56:36 -05003304 lpfc_nlp_set_state(vport, ndlp,
James Smartde0c5b32007-04-25 09:52:27 -04003305 NLP_STE_PLOGI_ISSUE);
James Smart2e0fef82007-06-17 19:56:36 -05003306 lpfc_issue_els_plogi(vport, ndlp->nlp_DID, 0);
dea31012005-04-17 16:05:31 -05003307 }
3308
3309 /* Send a FARP response to that node */
James Smart2e0fef82007-06-17 19:56:36 -05003310 if (fp->Rflags & FARP_REQUEST_FARPR)
3311 lpfc_issue_els_farpr(vport, did, 0);
dea31012005-04-17 16:05:31 -05003312 }
3313 }
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05003314 return 0;
dea31012005-04-17 16:05:31 -05003315}
3316
3317static int
James Smart2e0fef82007-06-17 19:56:36 -05003318lpfc_els_rcv_farpr(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
3319 struct lpfc_nodelist *ndlp)
dea31012005-04-17 16:05:31 -05003320{
3321 struct lpfc_dmabuf *pcmd;
3322 uint32_t *lp;
3323 IOCB_t *icmd;
3324 uint32_t cmd, did;
James Smart2e0fef82007-06-17 19:56:36 -05003325 struct lpfc_hba *phba = vport->phba;
dea31012005-04-17 16:05:31 -05003326
3327 icmd = &cmdiocb->iocb;
3328 did = icmd->un.elsreq64.remoteID;
3329 pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
3330 lp = (uint32_t *) pcmd->virt;
3331
3332 cmd = *lp++;
3333 /* FARP-RSP received from DID <did> */
James Smarted957682007-06-17 19:56:37 -05003334 lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
James Smart92d7f7b2007-06-17 19:56:38 -05003335 "%d (%d):0600 FARP-RSP received from DID x%x\n",
3336 phba->brd_no, vport->vpi, did);
dea31012005-04-17 16:05:31 -05003337 /* ACCEPT the Farp resp request */
James Smart2e0fef82007-06-17 19:56:36 -05003338 lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0);
dea31012005-04-17 16:05:31 -05003339
3340 return 0;
3341}
3342
3343static int
James Smart2e0fef82007-06-17 19:56:36 -05003344lpfc_els_rcv_fan(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
3345 struct lpfc_nodelist *fan_ndlp)
dea31012005-04-17 16:05:31 -05003346{
3347 struct lpfc_dmabuf *pcmd;
3348 uint32_t *lp;
3349 IOCB_t *icmd;
dea31012005-04-17 16:05:31 -05003350 uint32_t cmd, did;
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05003351 FAN *fp;
3352 struct lpfc_nodelist *ndlp, *next_ndlp;
James Smart2e0fef82007-06-17 19:56:36 -05003353 struct lpfc_hba *phba = vport->phba;
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05003354
3355 /* FAN received */
James Smarted957682007-06-17 19:56:37 -05003356 lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
James Smart92d7f7b2007-06-17 19:56:38 -05003357 "%d (%d):0265 FAN received\n",
3358 phba->brd_no, vport->vpi);
dea31012005-04-17 16:05:31 -05003359
3360 icmd = &cmdiocb->iocb;
3361 did = icmd->un.elsreq64.remoteID;
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05003362 pcmd = (struct lpfc_dmabuf *)cmdiocb->context2;
3363 lp = (uint32_t *)pcmd->virt;
dea31012005-04-17 16:05:31 -05003364
3365 cmd = *lp++;
James Smart92d7f7b2007-06-17 19:56:38 -05003366 fp = (FAN *) lp;
dea31012005-04-17 16:05:31 -05003367
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05003368 /* FAN received; Fan does not have a reply sequence */
dea31012005-04-17 16:05:31 -05003369
James Smart2e0fef82007-06-17 19:56:36 -05003370 if (phba->pport->port_state == LPFC_LOCAL_CFG_LINK) {
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05003371 if ((memcmp(&phba->fc_fabparam.nodeName, &fp->FnodeName,
3372 sizeof(struct lpfc_name)) != 0) ||
3373 (memcmp(&phba->fc_fabparam.portName, &fp->FportName,
3374 sizeof(struct lpfc_name)) != 0)) {
3375 /*
3376 * This node has switched fabrics. FLOGI is required
3377 * Clean up the old rpi's
dea31012005-04-17 16:05:31 -05003378 */
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05003379
3380 list_for_each_entry_safe(ndlp, next_ndlp,
James Smart2e0fef82007-06-17 19:56:36 -05003381 &vport->fc_nodes, nlp_listp) {
James Smart685f0bf2007-04-25 09:53:08 -04003382 if (ndlp->nlp_state != NLP_STE_NPR_NODE)
3383 continue;
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05003384 if (ndlp->nlp_type & NLP_FABRIC) {
3385 /*
3386 * Clean up old Fabric, Nameserver and
3387 * other NLP_FABRIC logins
3388 */
James Smart2e0fef82007-06-17 19:56:36 -05003389 lpfc_drop_node(vport, ndlp);
Jamie Wellnitz2fe165b2006-02-28 19:25:31 -05003390 } else if (!(ndlp->nlp_flag & NLP_NPR_ADISC)) {
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05003391 /* Fail outstanding I/O now since this
3392 * device is marked for PLOGI
3393 */
James Smart2e0fef82007-06-17 19:56:36 -05003394 lpfc_unreg_rpi(vport, ndlp);
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05003395 }
3396 }
3397
James Smart2e0fef82007-06-17 19:56:36 -05003398 vport->port_state = LPFC_FLOGI;
3399 lpfc_set_disctmo(vport);
3400 lpfc_initial_flogi(vport);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05003401 return 0;
dea31012005-04-17 16:05:31 -05003402 }
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05003403 /* Discovery not needed,
3404 * move the nodes to their original state.
3405 */
James Smart2e0fef82007-06-17 19:56:36 -05003406 list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes,
James Smart685f0bf2007-04-25 09:53:08 -04003407 nlp_listp) {
3408 if (ndlp->nlp_state != NLP_STE_NPR_NODE)
3409 continue;
dea31012005-04-17 16:05:31 -05003410
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05003411 switch (ndlp->nlp_prev_state) {
3412 case NLP_STE_UNMAPPED_NODE:
3413 ndlp->nlp_prev_state = NLP_STE_NPR_NODE;
James Smart2e0fef82007-06-17 19:56:36 -05003414 lpfc_nlp_set_state(vport, ndlp,
James Smartde0c5b32007-04-25 09:52:27 -04003415 NLP_STE_UNMAPPED_NODE);
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05003416 break;
3417
3418 case NLP_STE_MAPPED_NODE:
3419 ndlp->nlp_prev_state = NLP_STE_NPR_NODE;
James Smart2e0fef82007-06-17 19:56:36 -05003420 lpfc_nlp_set_state(vport, ndlp,
James Smartde0c5b32007-04-25 09:52:27 -04003421 NLP_STE_MAPPED_NODE);
Jamie Wellnitz5024ab12006-02-28 19:25:28 -05003422 break;
3423
3424 default:
3425 break;
3426 }
3427 }
3428
3429 /* Start discovery - this should just do CLEAR_LA */
James Smart2e0fef82007-06-17 19:56:36 -05003430 lpfc_disc_start(vport);
dea31012005-04-17 16:05:31 -05003431 }
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05003432 return 0;
dea31012005-04-17 16:05:31 -05003433}
3434
3435void
3436lpfc_els_timeout(unsigned long ptr)
3437{
James Smart2e0fef82007-06-17 19:56:36 -05003438 struct lpfc_vport *vport = (struct lpfc_vport *) ptr;
3439 struct lpfc_hba *phba = vport->phba;
dea31012005-04-17 16:05:31 -05003440 unsigned long iflag;
3441
James Smart2e0fef82007-06-17 19:56:36 -05003442 spin_lock_irqsave(&vport->work_port_lock, iflag);
3443 if ((vport->work_port_events & WORKER_ELS_TMO) == 0) {
3444 vport->work_port_events |= WORKER_ELS_TMO;
James Smart92d7f7b2007-06-17 19:56:38 -05003445 spin_unlock_irqrestore(&vport->work_port_lock, iflag);
3446
3447 spin_lock_irqsave(&phba->hbalock, iflag);
dea31012005-04-17 16:05:31 -05003448 if (phba->work_wait)
James Smart92d7f7b2007-06-17 19:56:38 -05003449 lpfc_worker_wake_up(phba);
3450 spin_unlock_irqrestore(&phba->hbalock, iflag);
dea31012005-04-17 16:05:31 -05003451 }
James Smart92d7f7b2007-06-17 19:56:38 -05003452 else
3453 spin_unlock_irqrestore(&vport->work_port_lock, iflag);
dea31012005-04-17 16:05:31 -05003454 return;
3455}
3456
3457void
James Smart2e0fef82007-06-17 19:56:36 -05003458lpfc_els_timeout_handler(struct lpfc_vport *vport)
dea31012005-04-17 16:05:31 -05003459{
James Smart2e0fef82007-06-17 19:56:36 -05003460 struct lpfc_hba *phba = vport->phba;
dea31012005-04-17 16:05:31 -05003461 struct lpfc_sli_ring *pring;
3462 struct lpfc_iocbq *tmp_iocb, *piocb;
3463 IOCB_t *cmd = NULL;
3464 struct lpfc_dmabuf *pcmd;
James Smart2e0fef82007-06-17 19:56:36 -05003465 uint32_t els_command = 0;
dea31012005-04-17 16:05:31 -05003466 uint32_t timeout;
James Smart2e0fef82007-06-17 19:56:36 -05003467 uint32_t remote_ID = 0xffffffff;
dea31012005-04-17 16:05:31 -05003468
dea31012005-04-17 16:05:31 -05003469 /* If the timer is already canceled do nothing */
James Smart2e0fef82007-06-17 19:56:36 -05003470 if ((vport->work_port_events & WORKER_ELS_TMO) == 0) {
dea31012005-04-17 16:05:31 -05003471 return;
3472 }
James Smart2e0fef82007-06-17 19:56:36 -05003473 spin_lock_irq(&phba->hbalock);
dea31012005-04-17 16:05:31 -05003474 timeout = (uint32_t)(phba->fc_ratov << 1);
3475
3476 pring = &phba->sli.ring[LPFC_ELS_RING];
dea31012005-04-17 16:05:31 -05003477
3478 list_for_each_entry_safe(piocb, tmp_iocb, &pring->txcmplq, list) {
3479 cmd = &piocb->iocb;
3480
James Smart2e0fef82007-06-17 19:56:36 -05003481 if ((piocb->iocb_flag & LPFC_IO_LIBDFC) != 0 ||
3482 piocb->iocb.ulpCommand == CMD_ABORT_XRI_CN ||
3483 piocb->iocb.ulpCommand == CMD_CLOSE_XRI_CN)
dea31012005-04-17 16:05:31 -05003484 continue;
James Smart2e0fef82007-06-17 19:56:36 -05003485
3486 if (piocb->vport != vport)
3487 continue;
3488
dea31012005-04-17 16:05:31 -05003489 pcmd = (struct lpfc_dmabuf *) piocb->context2;
James Smart2e0fef82007-06-17 19:56:36 -05003490 if (pcmd)
3491 els_command = *(uint32_t *) (pcmd->virt);
dea31012005-04-17 16:05:31 -05003492
James Smart92d7f7b2007-06-17 19:56:38 -05003493 if (els_command == ELS_CMD_FARP ||
3494 els_command == ELS_CMD_FARPR ||
3495 els_command == ELS_CMD_FDISC)
dea31012005-04-17 16:05:31 -05003496 continue;
James Smart92d7f7b2007-06-17 19:56:38 -05003497
3498 if (vport != piocb->vport)
3499 continue;
dea31012005-04-17 16:05:31 -05003500
3501 if (piocb->drvrTimeout > 0) {
James Smart92d7f7b2007-06-17 19:56:38 -05003502 if (piocb->drvrTimeout >= timeout)
dea31012005-04-17 16:05:31 -05003503 piocb->drvrTimeout -= timeout;
James Smart92d7f7b2007-06-17 19:56:38 -05003504 else
dea31012005-04-17 16:05:31 -05003505 piocb->drvrTimeout = 0;
dea31012005-04-17 16:05:31 -05003506 continue;
3507 }
3508
James Smart2e0fef82007-06-17 19:56:36 -05003509 remote_ID = 0xffffffff;
3510 if (cmd->ulpCommand != CMD_GEN_REQUEST64_CR)
dea31012005-04-17 16:05:31 -05003511 remote_ID = cmd->un.elsreq64.remoteID;
James Smart2e0fef82007-06-17 19:56:36 -05003512 else {
3513 struct lpfc_nodelist *ndlp;
3514 ndlp = __lpfc_findnode_rpi(vport, cmd->ulpContext);
3515 if (ndlp)
3516 remote_ID = ndlp->nlp_DID;
dea31012005-04-17 16:05:31 -05003517 }
3518
James Smart92d7f7b2007-06-17 19:56:38 -05003519 lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
3520 "%d (%d):0127 ELS timeout Data: x%x x%x x%x "
3521 "x%x\n",
3522 phba->brd_no, vport->vpi, els_command,
dea31012005-04-17 16:05:31 -05003523 remote_ID, cmd->ulpCommand, cmd->ulpIoTag);
3524
James Smart07951072007-04-25 09:51:38 -04003525 lpfc_sli_issue_abort_iotag(phba, pring, piocb);
dea31012005-04-17 16:05:31 -05003526 }
James Smart2e0fef82007-06-17 19:56:36 -05003527 spin_unlock_irq(&phba->hbalock);
James Smart5a0e3262006-07-06 15:49:16 -04003528
James Smart2e0fef82007-06-17 19:56:36 -05003529 if (phba->sli.ring[LPFC_ELS_RING].txcmplq_cnt)
3530 mod_timer(&vport->els_tmofunc, jiffies + HZ * timeout);
dea31012005-04-17 16:05:31 -05003531}
3532
3533void
James Smart2e0fef82007-06-17 19:56:36 -05003534lpfc_els_flush_cmd(struct lpfc_vport *vport)
dea31012005-04-17 16:05:31 -05003535{
James Smart2534ba72007-04-25 09:52:20 -04003536 LIST_HEAD(completions);
James Smart2e0fef82007-06-17 19:56:36 -05003537 struct lpfc_hba *phba = vport->phba;
James Smart329f9bc2007-04-25 09:53:01 -04003538 struct lpfc_sli_ring *pring = &phba->sli.ring[LPFC_ELS_RING];
dea31012005-04-17 16:05:31 -05003539 struct lpfc_iocbq *tmp_iocb, *piocb;
3540 IOCB_t *cmd = NULL;
James Smart92d7f7b2007-06-17 19:56:38 -05003541 struct lpfc_dmabuf *pcmd;
3542 uint32_t *elscmd;
3543 uint32_t els_command;
3544
3545 lpfc_fabric_abort_vport(vport);
dea31012005-04-17 16:05:31 -05003546
James Smart2e0fef82007-06-17 19:56:36 -05003547 spin_lock_irq(&phba->hbalock);
dea31012005-04-17 16:05:31 -05003548 list_for_each_entry_safe(piocb, tmp_iocb, &pring->txq, list) {
3549 cmd = &piocb->iocb;
3550
3551 if (piocb->iocb_flag & LPFC_IO_LIBDFC) {
3552 continue;
3553 }
3554
3555 /* Do not flush out the QUE_RING and ABORT/CLOSE iocbs */
James Smart329f9bc2007-04-25 09:53:01 -04003556 if (cmd->ulpCommand == CMD_QUE_RING_BUF_CN ||
3557 cmd->ulpCommand == CMD_QUE_RING_BUF64_CN ||
3558 cmd->ulpCommand == CMD_CLOSE_XRI_CN ||
3559 cmd->ulpCommand == CMD_ABORT_XRI_CN)
dea31012005-04-17 16:05:31 -05003560 continue;
dea31012005-04-17 16:05:31 -05003561
James Smart92d7f7b2007-06-17 19:56:38 -05003562 pcmd = (struct lpfc_dmabuf *) piocb->context2;
3563 elscmd = (uint32_t *) (pcmd->virt);
3564 els_command = *elscmd;
3565
James Smart2e0fef82007-06-17 19:56:36 -05003566 if (piocb->vport != vport)
3567 continue;
3568
James Smart2534ba72007-04-25 09:52:20 -04003569 list_move_tail(&piocb->list, &completions);
James Smart1dcb58e2007-04-25 09:51:30 -04003570 pring->txq_cnt--;
dea31012005-04-17 16:05:31 -05003571 }
3572
3573 list_for_each_entry_safe(piocb, tmp_iocb, &pring->txcmplq, list) {
dea31012005-04-17 16:05:31 -05003574 if (piocb->iocb_flag & LPFC_IO_LIBDFC) {
3575 continue;
3576 }
dea31012005-04-17 16:05:31 -05003577
James Smart2e0fef82007-06-17 19:56:36 -05003578 if (piocb->vport != vport)
3579 continue;
3580
James Smart07951072007-04-25 09:51:38 -04003581 lpfc_sli_issue_abort_iotag(phba, pring, piocb);
dea31012005-04-17 16:05:31 -05003582 }
James Smart2e0fef82007-06-17 19:56:36 -05003583 spin_unlock_irq(&phba->hbalock);
James Smart2534ba72007-04-25 09:52:20 -04003584
James Smart2e0fef82007-06-17 19:56:36 -05003585 while (!list_empty(&completions)) {
James Smart2534ba72007-04-25 09:52:20 -04003586 piocb = list_get_first(&completions, struct lpfc_iocbq, list);
3587 cmd = &piocb->iocb;
James Smart92d7f7b2007-06-17 19:56:38 -05003588 list_del_init(&piocb->list);
James Smart2534ba72007-04-25 09:52:20 -04003589
James Smart2e0fef82007-06-17 19:56:36 -05003590 if (!piocb->iocb_cmpl)
3591 lpfc_sli_release_iocbq(phba, piocb);
3592 else {
James Smart2534ba72007-04-25 09:52:20 -04003593 cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
3594 cmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
3595 (piocb->iocb_cmpl) (phba, piocb, piocb);
James Smart2e0fef82007-06-17 19:56:36 -05003596 }
James Smart2534ba72007-04-25 09:52:20 -04003597 }
3598
dea31012005-04-17 16:05:31 -05003599 return;
3600}
3601
James Smarted957682007-06-17 19:56:37 -05003602static void
3603lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
James Smart92d7f7b2007-06-17 19:56:38 -05003604 struct lpfc_vport *vport, struct lpfc_iocbq *elsiocb)
dea31012005-04-17 16:05:31 -05003605{
dea31012005-04-17 16:05:31 -05003606 struct lpfc_nodelist *ndlp;
dea31012005-04-17 16:05:31 -05003607 struct ls_rjt stat;
James Smart92d7f7b2007-06-17 19:56:38 -05003608 uint32_t *payload;
James Smart2e0fef82007-06-17 19:56:36 -05003609 uint32_t cmd, did, newnode, rjt_err = 0;
James Smarted957682007-06-17 19:56:37 -05003610 IOCB_t *icmd = &elsiocb->iocb;
dea31012005-04-17 16:05:31 -05003611
James Smart92d7f7b2007-06-17 19:56:38 -05003612 if (vport == NULL || elsiocb->context2 == NULL)
dea31012005-04-17 16:05:31 -05003613 goto dropit;
James Smart2e0fef82007-06-17 19:56:36 -05003614
dea31012005-04-17 16:05:31 -05003615 newnode = 0;
James Smart92d7f7b2007-06-17 19:56:38 -05003616 payload = ((struct lpfc_dmabuf *)elsiocb->context2)->virt;
3617 cmd = *payload;
James Smarted957682007-06-17 19:56:37 -05003618 if ((phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) == 0)
3619 lpfc_post_buffer(phba, pring, 1, 1);
dea31012005-04-17 16:05:31 -05003620
James Smarted957682007-06-17 19:56:37 -05003621 if (icmd->ulpStatus)
dea31012005-04-17 16:05:31 -05003622 goto dropit;
dea31012005-04-17 16:05:31 -05003623
3624 /* Check to see if link went down during discovery */
James Smarted957682007-06-17 19:56:37 -05003625 if (lpfc_els_chk_latt(vport))
dea31012005-04-17 16:05:31 -05003626 goto dropit;
dea31012005-04-17 16:05:31 -05003627
James Smart92d7f7b2007-06-17 19:56:38 -05003628 /* Ignore traffic recevied during vport shutdown. */
3629 if (vport->load_flag & FC_UNLOADING)
3630 goto dropit;
3631
dea31012005-04-17 16:05:31 -05003632 did = icmd->un.rcvels.remoteID;
James Smart2e0fef82007-06-17 19:56:36 -05003633 ndlp = lpfc_findnode_did(vport, did);
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05003634 if (!ndlp) {
dea31012005-04-17 16:05:31 -05003635 /* Cannot find existing Fabric ndlp, so allocate a new one */
Jamie Wellnitzc9f87352006-02-28 19:25:23 -05003636 ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL);
James Smarted957682007-06-17 19:56:37 -05003637 if (!ndlp)
dea31012005-04-17 16:05:31 -05003638 goto dropit;
dea31012005-04-17 16:05:31 -05003639
James Smart2e0fef82007-06-17 19:56:36 -05003640 lpfc_nlp_init(vport, ndlp, did);
dea31012005-04-17 16:05:31 -05003641 newnode = 1;
3642 if ((did & Fabric_DID_MASK) == Fabric_DID_MASK) {
3643 ndlp->nlp_type |= NLP_FABRIC;
3644 }
James Smart2e0fef82007-06-17 19:56:36 -05003645 lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNUSED_NODE);
dea31012005-04-17 16:05:31 -05003646 }
3647
3648 phba->fc_stat.elsRcvFrame++;
James Smart329f9bc2007-04-25 09:53:01 -04003649 if (elsiocb->context1)
3650 lpfc_nlp_put(elsiocb->context1);
3651 elsiocb->context1 = lpfc_nlp_get(ndlp);
James Smart2e0fef82007-06-17 19:56:36 -05003652 elsiocb->vport = vport;
dea31012005-04-17 16:05:31 -05003653
3654 if ((cmd & ELS_CMD_MASK) == ELS_CMD_RSCN) {
3655 cmd &= ELS_CMD_MASK;
3656 }
3657 /* ELS command <elsCmd> received from NPORT <did> */
3658 lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
James Smart92d7f7b2007-06-17 19:56:38 -05003659 "%d (%d):0112 ELS command x%x received from NPORT x%x "
3660 "Data: x%x\n", phba->brd_no, vport->vpi, cmd, did,
James Smarted957682007-06-17 19:56:37 -05003661 vport->port_state);
dea31012005-04-17 16:05:31 -05003662
3663 switch (cmd) {
3664 case ELS_CMD_PLOGI:
3665 phba->fc_stat.elsRcvPLOGI++;
James Smart92d7f7b2007-06-17 19:56:38 -05003666 if ((vport->port_state < LPFC_DISC_AUTH) ||
3667 ((vport->port_type == LPFC_NPIV_PORT &&
3668 phba->cfg_vport_restrict_login))) {
3669 rjt_err = 2;
dea31012005-04-17 16:05:31 -05003670 break;
3671 }
James Smart92d7f7b2007-06-17 19:56:38 -05003672 ndlp = lpfc_plogi_confirm_nport(phba, payload, ndlp);
James Smart2e0fef82007-06-17 19:56:36 -05003673 lpfc_disc_state_machine(vport, ndlp, elsiocb,
3674 NLP_EVT_RCV_PLOGI);
dea31012005-04-17 16:05:31 -05003675 break;
3676 case ELS_CMD_FLOGI:
3677 phba->fc_stat.elsRcvFLOGI++;
James Smart2e0fef82007-06-17 19:56:36 -05003678 lpfc_els_rcv_flogi(vport, elsiocb, ndlp, newnode);
James Smartde0c5b32007-04-25 09:52:27 -04003679 if (newnode)
James Smart2e0fef82007-06-17 19:56:36 -05003680 lpfc_drop_node(vport, ndlp);
dea31012005-04-17 16:05:31 -05003681 break;
3682 case ELS_CMD_LOGO:
3683 phba->fc_stat.elsRcvLOGO++;
James Smart2e0fef82007-06-17 19:56:36 -05003684 if (vport->port_state < LPFC_DISC_AUTH) {
James.Smart@Emulex.Com1f679ca2005-06-25 10:34:27 -04003685 rjt_err = 1;
dea31012005-04-17 16:05:31 -05003686 break;
3687 }
James Smart2e0fef82007-06-17 19:56:36 -05003688 lpfc_disc_state_machine(vport, ndlp, elsiocb, NLP_EVT_RCV_LOGO);
dea31012005-04-17 16:05:31 -05003689 break;
3690 case ELS_CMD_PRLO:
3691 phba->fc_stat.elsRcvPRLO++;
James Smart2e0fef82007-06-17 19:56:36 -05003692 if (vport->port_state < LPFC_DISC_AUTH) {
James.Smart@Emulex.Com1f679ca2005-06-25 10:34:27 -04003693 rjt_err = 1;
dea31012005-04-17 16:05:31 -05003694 break;
3695 }
James Smart2e0fef82007-06-17 19:56:36 -05003696 lpfc_disc_state_machine(vport, ndlp, elsiocb, NLP_EVT_RCV_PRLO);
dea31012005-04-17 16:05:31 -05003697 break;
3698 case ELS_CMD_RSCN:
3699 phba->fc_stat.elsRcvRSCN++;
James Smart2e0fef82007-06-17 19:56:36 -05003700 lpfc_els_rcv_rscn(vport, elsiocb, ndlp, newnode);
James Smartde0c5b32007-04-25 09:52:27 -04003701 if (newnode)
James Smart2e0fef82007-06-17 19:56:36 -05003702 lpfc_drop_node(vport, ndlp);
dea31012005-04-17 16:05:31 -05003703 break;
3704 case ELS_CMD_ADISC:
3705 phba->fc_stat.elsRcvADISC++;
James Smart2e0fef82007-06-17 19:56:36 -05003706 if (vport->port_state < LPFC_DISC_AUTH) {
James.Smart@Emulex.Com1f679ca2005-06-25 10:34:27 -04003707 rjt_err = 1;
dea31012005-04-17 16:05:31 -05003708 break;
3709 }
James Smart2e0fef82007-06-17 19:56:36 -05003710 lpfc_disc_state_machine(vport, ndlp, elsiocb,
3711 NLP_EVT_RCV_ADISC);
dea31012005-04-17 16:05:31 -05003712 break;
3713 case ELS_CMD_PDISC:
3714 phba->fc_stat.elsRcvPDISC++;
James Smart2e0fef82007-06-17 19:56:36 -05003715 if (vport->port_state < LPFC_DISC_AUTH) {
James.Smart@Emulex.Com1f679ca2005-06-25 10:34:27 -04003716 rjt_err = 1;
dea31012005-04-17 16:05:31 -05003717 break;
3718 }
James Smart2e0fef82007-06-17 19:56:36 -05003719 lpfc_disc_state_machine(vport, ndlp, elsiocb,
3720 NLP_EVT_RCV_PDISC);
dea31012005-04-17 16:05:31 -05003721 break;
3722 case ELS_CMD_FARPR:
3723 phba->fc_stat.elsRcvFARPR++;
James Smart2e0fef82007-06-17 19:56:36 -05003724 lpfc_els_rcv_farpr(vport, elsiocb, ndlp);
dea31012005-04-17 16:05:31 -05003725 break;
3726 case ELS_CMD_FARP:
3727 phba->fc_stat.elsRcvFARP++;
James Smart2e0fef82007-06-17 19:56:36 -05003728 lpfc_els_rcv_farp(vport, elsiocb, ndlp);
dea31012005-04-17 16:05:31 -05003729 break;
3730 case ELS_CMD_FAN:
3731 phba->fc_stat.elsRcvFAN++;
James Smart2e0fef82007-06-17 19:56:36 -05003732 lpfc_els_rcv_fan(vport, elsiocb, ndlp);
dea31012005-04-17 16:05:31 -05003733 break;
dea31012005-04-17 16:05:31 -05003734 case ELS_CMD_PRLI:
3735 phba->fc_stat.elsRcvPRLI++;
James Smart2e0fef82007-06-17 19:56:36 -05003736 if (vport->port_state < LPFC_DISC_AUTH) {
James.Smart@Emulex.Com1f679ca2005-06-25 10:34:27 -04003737 rjt_err = 1;
dea31012005-04-17 16:05:31 -05003738 break;
3739 }
James Smart2e0fef82007-06-17 19:56:36 -05003740 lpfc_disc_state_machine(vport, ndlp, elsiocb, NLP_EVT_RCV_PRLI);
dea31012005-04-17 16:05:31 -05003741 break;
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05003742 case ELS_CMD_LIRR:
3743 phba->fc_stat.elsRcvLIRR++;
James Smart2e0fef82007-06-17 19:56:36 -05003744 lpfc_els_rcv_lirr(vport, elsiocb, ndlp);
James Smartde0c5b32007-04-25 09:52:27 -04003745 if (newnode)
James Smart2e0fef82007-06-17 19:56:36 -05003746 lpfc_drop_node(vport, ndlp);
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05003747 break;
3748 case ELS_CMD_RPS:
3749 phba->fc_stat.elsRcvRPS++;
James Smart2e0fef82007-06-17 19:56:36 -05003750 lpfc_els_rcv_rps(vport, elsiocb, ndlp);
James Smartde0c5b32007-04-25 09:52:27 -04003751 if (newnode)
James Smart2e0fef82007-06-17 19:56:36 -05003752 lpfc_drop_node(vport, ndlp);
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05003753 break;
3754 case ELS_CMD_RPL:
3755 phba->fc_stat.elsRcvRPL++;
James Smart2e0fef82007-06-17 19:56:36 -05003756 lpfc_els_rcv_rpl(vport, elsiocb, ndlp);
James Smartde0c5b32007-04-25 09:52:27 -04003757 if (newnode)
James Smart2e0fef82007-06-17 19:56:36 -05003758 lpfc_drop_node(vport, ndlp);
Jamie Wellnitz7bb3b132006-02-28 19:25:15 -05003759 break;
dea31012005-04-17 16:05:31 -05003760 case ELS_CMD_RNID:
3761 phba->fc_stat.elsRcvRNID++;
James Smart2e0fef82007-06-17 19:56:36 -05003762 lpfc_els_rcv_rnid(vport, elsiocb, ndlp);
James Smartde0c5b32007-04-25 09:52:27 -04003763 if (newnode)
James Smart2e0fef82007-06-17 19:56:36 -05003764 lpfc_drop_node(vport, ndlp);
dea31012005-04-17 16:05:31 -05003765 break;
3766 default:
3767 /* Unsupported ELS command, reject */
James Smart92d7f7b2007-06-17 19:56:38 -05003768 rjt_err = 2;
dea31012005-04-17 16:05:31 -05003769
3770 /* Unknown ELS command <elsCmd> received from NPORT <did> */
3771 lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
James Smart92d7f7b2007-06-17 19:56:38 -05003772 "%d (%d):0115 Unknown ELS command x%x "
James Smarted957682007-06-17 19:56:37 -05003773 "received from NPORT x%x\n",
James Smart92d7f7b2007-06-17 19:56:38 -05003774 phba->brd_no, vport->vpi, cmd, did);
James Smartde0c5b32007-04-25 09:52:27 -04003775 if (newnode)
James Smart2e0fef82007-06-17 19:56:36 -05003776 lpfc_drop_node(vport, ndlp);
dea31012005-04-17 16:05:31 -05003777 break;
3778 }
3779
3780 /* check if need to LS_RJT received ELS cmd */
3781 if (rjt_err) {
James Smart92d7f7b2007-06-17 19:56:38 -05003782 memset(&stat, 0, sizeof(stat));
3783 if (rjt_err == 1)
3784 stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
3785 else
3786 stat.un.b.lsRjtRsnCode = LSRJT_INVALID_CMD;
James.Smart@Emulex.Com1f679ca2005-06-25 10:34:27 -04003787 stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE;
James Smart2e0fef82007-06-17 19:56:36 -05003788 lpfc_els_rsp_reject(vport, stat.un.lsRjtError, elsiocb, ndlp);
James Smart92d7f7b2007-06-17 19:56:38 -05003789 if (newnode)
3790 lpfc_drop_node(vport, ndlp);
dea31012005-04-17 16:05:31 -05003791 }
3792
James Smarted957682007-06-17 19:56:37 -05003793 return;
3794
3795dropit:
3796 lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
James Smart92d7f7b2007-06-17 19:56:38 -05003797 "%d (%d):0111 Dropping received ELS cmd "
James Smarted957682007-06-17 19:56:37 -05003798 "Data: x%x x%x x%x\n",
James Smart92d7f7b2007-06-17 19:56:38 -05003799 phba->brd_no, vport ? vport->vpi : 0xffff,
James Smarted957682007-06-17 19:56:37 -05003800 icmd->ulpStatus, icmd->un.ulpWord[4],
3801 icmd->ulpTimeout);
3802 phba->fc_stat.elsRcvDrop++;
3803}
3804
James Smart92d7f7b2007-06-17 19:56:38 -05003805static struct lpfc_vport *
3806lpfc_find_vport_by_vpid(struct lpfc_hba *phba, uint16_t vpi)
3807{
3808 struct lpfc_vport *vport;
3809
3810 list_for_each_entry(vport, &phba->port_list, listentry) {
3811 if (vport->vpi == vpi)
3812 return vport;
3813 }
3814 return NULL;
3815}
James Smarted957682007-06-17 19:56:37 -05003816
3817void
3818lpfc_els_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
3819 struct lpfc_iocbq *elsiocb)
3820{
3821 struct lpfc_vport *vport = phba->pport;
James Smarted957682007-06-17 19:56:37 -05003822 IOCB_t *icmd = &elsiocb->iocb;
James Smarted957682007-06-17 19:56:37 -05003823 dma_addr_t paddr;
James Smart92d7f7b2007-06-17 19:56:38 -05003824 struct lpfc_dmabuf *bdeBuf1 = elsiocb->context2;
3825 struct lpfc_dmabuf *bdeBuf2 = elsiocb->context3;
James Smarted957682007-06-17 19:56:37 -05003826
James Smart92d7f7b2007-06-17 19:56:38 -05003827 elsiocb->context2 = NULL;
3828 elsiocb->context3 = NULL;
3829
3830 if (icmd->ulpStatus == IOSTAT_NEED_BUFFER) {
3831 lpfc_sli_hbqbuf_add_hbqs(phba, LPFC_ELS_HBQ);
3832 } else if (icmd->ulpStatus == IOSTAT_LOCAL_REJECT &&
3833 (icmd->un.ulpWord[4] & 0xff) == IOERR_RCV_BUFFER_WAITING) {
James Smarted957682007-06-17 19:56:37 -05003834 phba->fc_stat.NoRcvBuf++;
3835 /* Not enough posted buffers; Try posting more buffers */
James Smart92d7f7b2007-06-17 19:56:38 -05003836 if (!(phba->sli3_options & LPFC_SLI3_HBQ_ENABLED))
James Smarted957682007-06-17 19:56:37 -05003837 lpfc_post_buffer(phba, pring, 0, 1);
3838 return;
3839 }
3840
James Smart92d7f7b2007-06-17 19:56:38 -05003841 if ((phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) &&
3842 (icmd->ulpCommand == CMD_IOCB_RCV_ELS64_CX ||
3843 icmd->ulpCommand == CMD_IOCB_RCV_SEQ64_CX)) {
3844 if (icmd->unsli3.rcvsli3.vpi == 0xffff)
3845 vport = phba->pport;
3846 else {
3847 uint16_t vpi = icmd->unsli3.rcvsli3.vpi;
3848 vport = lpfc_find_vport_by_vpid(phba, vpi);
3849 }
3850 }
3851 /* If there are no BDEs associated
3852 * with this IOCB, there is nothing to do.
3853 */
James Smarted957682007-06-17 19:56:37 -05003854 if (icmd->ulpBdeCount == 0)
3855 return;
3856
James Smart92d7f7b2007-06-17 19:56:38 -05003857 /* type of ELS cmd is first 32bit word
3858 * in packet
3859 */
James Smarted957682007-06-17 19:56:37 -05003860 if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) {
James Smart92d7f7b2007-06-17 19:56:38 -05003861 elsiocb->context2 = bdeBuf1;
James Smarted957682007-06-17 19:56:37 -05003862 } else {
3863 paddr = getPaddr(icmd->un.cont64[0].addrHigh,
3864 icmd->un.cont64[0].addrLow);
James Smart92d7f7b2007-06-17 19:56:38 -05003865 elsiocb->context2 = lpfc_sli_ringpostbuf_get(phba, pring,
3866 paddr);
James Smarted957682007-06-17 19:56:37 -05003867 }
3868
James Smart92d7f7b2007-06-17 19:56:38 -05003869 lpfc_els_unsol_buffer(phba, pring, vport, elsiocb);
3870 /*
3871 * The different unsolicited event handlers would tell us
3872 * if they are done with "mp" by setting context2 to NULL.
3873 */
James Smart329f9bc2007-04-25 09:53:01 -04003874 lpfc_nlp_put(elsiocb->context1);
3875 elsiocb->context1 = NULL;
dea31012005-04-17 16:05:31 -05003876 if (elsiocb->context2) {
James Smart92d7f7b2007-06-17 19:56:38 -05003877 lpfc_in_buf_free(phba, (struct lpfc_dmabuf *)elsiocb->context2);
3878 elsiocb->context2 = NULL;
dea31012005-04-17 16:05:31 -05003879 }
James Smarted957682007-06-17 19:56:37 -05003880
3881 /* RCV_ELS64_CX provide for 2 BDEs - process 2nd if included */
James Smart92d7f7b2007-06-17 19:56:38 -05003882 if ((phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) &&
James Smarted957682007-06-17 19:56:37 -05003883 icmd->ulpBdeCount == 2) {
James Smart92d7f7b2007-06-17 19:56:38 -05003884 elsiocb->context2 = bdeBuf2;
3885 lpfc_els_unsol_buffer(phba, pring, vport, elsiocb);
James Smarted957682007-06-17 19:56:37 -05003886 /* free mp if we are done with it */
3887 if (elsiocb->context2) {
James Smart92d7f7b2007-06-17 19:56:38 -05003888 lpfc_in_buf_free(phba, elsiocb->context2);
3889 elsiocb->context2 = NULL;
James Smarted957682007-06-17 19:56:37 -05003890 }
dea31012005-04-17 16:05:31 -05003891 }
dea31012005-04-17 16:05:31 -05003892}
James Smart92d7f7b2007-06-17 19:56:38 -05003893
3894void
3895lpfc_do_scr_ns_plogi(struct lpfc_hba *phba, struct lpfc_vport *vport)
3896{
3897 struct lpfc_nodelist *ndlp, *ndlp_fdmi;
3898
3899 ndlp = lpfc_findnode_did(vport, NameServer_DID);
3900 if (!ndlp) {
3901 ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL);
3902 if (!ndlp) {
3903 if (phba->fc_topology == TOPOLOGY_LOOP) {
3904 lpfc_disc_start(vport);
3905 return;
3906 }
3907 lpfc_vport_set_state(vport, FC_VPORT_FAILED);
3908 lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
3909 "%d (%d):0251 NameServer login: no memory\n",
3910 phba->brd_no, vport->vpi);
3911 return;
3912 }
3913 lpfc_nlp_init(vport, ndlp, NameServer_DID);
3914 ndlp->nlp_type |= NLP_FABRIC;
3915 }
3916
3917 lpfc_nlp_set_state(vport, ndlp, NLP_STE_PLOGI_ISSUE);
3918
3919 if (lpfc_issue_els_plogi(vport, ndlp->nlp_DID, 0)) {
3920 lpfc_vport_set_state(vport, FC_VPORT_FAILED);
3921 lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
3922 "%d (%d):0252 Cannot issue NameServer login\n",
3923 phba->brd_no, vport->vpi);
3924 return;
3925 }
3926
3927 if (phba->cfg_fdmi_on) {
3928 ndlp_fdmi = mempool_alloc(phba->nlp_mem_pool,
3929 GFP_KERNEL);
3930 if (ndlp_fdmi) {
3931 lpfc_nlp_init(vport, ndlp_fdmi, FDMI_DID);
3932 ndlp_fdmi->nlp_type |= NLP_FABRIC;
3933 ndlp_fdmi->nlp_state =
3934 NLP_STE_PLOGI_ISSUE;
3935 lpfc_issue_els_plogi(vport, ndlp_fdmi->nlp_DID,
3936 0);
3937 }
3938 }
3939 return;
3940}
3941
3942static void
3943lpfc_cmpl_reg_new_vport(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
3944{
3945 struct lpfc_vport *vport = pmb->vport;
3946 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
3947 struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) pmb->context2;
3948 MAILBOX_t *mb = &pmb->mb;
3949
3950 vport->fc_flag &= ~FC_VPORT_NEEDS_REG_VPI;
3951 lpfc_nlp_put(ndlp);
3952
3953 if (mb->mbxStatus) {
3954 lpfc_printf_log(phba, KERN_ERR, LOG_MBOX,
3955 "%d (%d):0915 Register VPI failed: 0x%x\n",
3956 phba->brd_no, vport->vpi, mb->mbxStatus);
3957
3958 switch (mb->mbxStatus) {
3959 case 0x11: /* unsupported feature */
3960 case 0x9603: /* max_vpi exceeded */
3961 /* giving up on vport registration */
3962 lpfc_vport_set_state(vport, FC_VPORT_FAILED);
3963 spin_lock_irq(shost->host_lock);
3964 vport->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP);
3965 spin_unlock_irq(shost->host_lock);
3966 lpfc_can_disctmo(vport);
3967 break;
3968 default:
3969 /* Try to recover from this error */
3970 lpfc_mbx_unreg_vpi(vport);
3971 vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI;
3972 lpfc_initial_fdisc(vport);
3973 break;
3974 }
3975
3976 } else {
3977 if (vport == phba->pport)
3978 lpfc_issue_fabric_reglogin(vport);
3979 else
3980 lpfc_do_scr_ns_plogi(phba, vport);
3981 }
3982 mempool_free(pmb, phba->mbox_mem_pool);
3983 return;
3984}
3985
3986void
3987lpfc_register_new_vport(struct lpfc_hba *phba, struct lpfc_vport *vport,
3988 struct lpfc_nodelist *ndlp)
3989{
3990 LPFC_MBOXQ_t *mbox;
3991
3992 mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
3993 if (mbox) {
3994 lpfc_reg_vpi(phba, vport->vpi, vport->fc_myDID, mbox);
3995 mbox->vport = vport;
3996 mbox->context2 = lpfc_nlp_get(ndlp);
3997 mbox->mbox_cmpl = lpfc_cmpl_reg_new_vport;
3998 if (lpfc_sli_issue_mbox(phba, mbox,
3999 MBX_NOWAIT | MBX_STOP_IOCB)
4000 == MBX_NOT_FINISHED) {
4001 mempool_free(mbox, phba->mbox_mem_pool);
4002 vport->fc_flag &= ~FC_VPORT_NEEDS_REG_VPI;
4003
4004 lpfc_vport_set_state(vport, FC_VPORT_FAILED);
4005
4006 lpfc_printf_log(phba, KERN_ERR, LOG_MBOX,
4007 "%d (%d):0253 Register VPI: Cannot send mbox\n",
4008 phba->brd_no, vport->vpi);
4009 }
4010 } else {
4011 lpfc_vport_set_state(vport, FC_VPORT_FAILED);
4012
4013 lpfc_printf_log(phba, KERN_ERR, LOG_MBOX,
4014 "%d (%d):0254 Register VPI: no memory\n",
4015 phba->brd_no, vport->vpi);
4016
4017 vport->fc_flag &= ~FC_VPORT_NEEDS_REG_VPI;
4018 lpfc_nlp_put(ndlp);
4019 }
4020}
4021
4022static void
4023lpfc_cmpl_els_fdisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
4024 struct lpfc_iocbq *rspiocb)
4025{
4026 struct lpfc_vport *vport = cmdiocb->vport;
4027 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
4028 struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) cmdiocb->context1;
4029 struct lpfc_nodelist *np;
4030 struct lpfc_nodelist *next_np;
4031 IOCB_t *irsp = &rspiocb->iocb;
4032 struct lpfc_iocbq *piocb;
4033
4034 lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
4035 "%d (%d):0123 FDISC completes. x%x/x%x prevDID: x%x\n",
4036 phba->brd_no, vport->vpi,
4037 irsp->ulpStatus, irsp->un.ulpWord[4], vport->fc_prevDID);
4038
4039 /* Since all FDISCs are being single threaded, we
4040 * must reset the discovery timer for ALL vports
4041 * waiting to send FDISC when one completes.
4042 */
4043 list_for_each_entry(piocb, &phba->fabric_iocb_list, list) {
4044 lpfc_set_disctmo(piocb->vport);
4045 }
4046
4047 if (irsp->ulpStatus) {
4048 /* Check for retry */
4049 if (lpfc_els_retry(phba, cmdiocb, rspiocb))
4050 goto out;
4051
4052 /* FDISC failed */
4053 lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
4054 "%d (%d):0124 FDISC failed. (%d/%d)\n",
4055 phba->brd_no, vport->vpi,
4056 irsp->ulpStatus, irsp->un.ulpWord[4]);
4057 if (vport->fc_vport->vport_state == FC_VPORT_INITIALIZING)
4058 lpfc_vport_set_state(vport, FC_VPORT_FAILED);
4059
4060 lpfc_nlp_put(ndlp);
4061 /* giving up on FDISC. Cancel discovery timer */
4062 lpfc_can_disctmo(vport);
4063 } else {
4064 spin_lock_irq(shost->host_lock);
4065 vport->fc_flag |= FC_FABRIC;
4066 if (vport->phba->fc_topology == TOPOLOGY_LOOP)
4067 vport->fc_flag |= FC_PUBLIC_LOOP;
4068 spin_unlock_irq(shost->host_lock);
4069
4070 vport->fc_myDID = irsp->un.ulpWord[4] & Mask_DID;
4071 lpfc_vport_set_state(vport, FC_VPORT_ACTIVE);
4072 if ((vport->fc_prevDID != vport->fc_myDID) &&
4073 !(vport->fc_flag & FC_VPORT_NEEDS_REG_VPI)) {
4074 /* If our NportID changed, we need to ensure all
4075 * remaining NPORTs get unreg_login'ed so we can
4076 * issue unreg_vpi.
4077 */
4078 list_for_each_entry_safe(np, next_np,
4079 &vport->fc_nodes, nlp_listp) {
4080 if (np->nlp_state != NLP_STE_NPR_NODE
4081 || !(np->nlp_flag & NLP_NPR_ADISC))
4082 continue;
4083 spin_lock_irq(shost->host_lock);
4084 np->nlp_flag &= ~NLP_NPR_ADISC;
4085 spin_unlock_irq(shost->host_lock);
4086 lpfc_unreg_rpi(vport, np);
4087 }
4088 lpfc_mbx_unreg_vpi(vport);
4089 vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI;
4090 }
4091
4092 if (vport->fc_flag & FC_VPORT_NEEDS_REG_VPI)
4093 lpfc_register_new_vport(phba, vport, ndlp);
4094 else
4095 lpfc_do_scr_ns_plogi(phba, vport);
4096
4097 lpfc_nlp_put(ndlp); /* Free Fabric ndlp for vports */
4098 }
4099
4100out:
4101 lpfc_els_free_iocb(phba, cmdiocb);
4102}
4103
4104int
4105lpfc_issue_els_fdisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
4106 uint8_t retry)
4107{
4108 struct lpfc_hba *phba = vport->phba;
4109 IOCB_t *icmd;
4110 struct lpfc_iocbq *elsiocb;
4111 struct serv_parm *sp;
4112 uint8_t *pcmd;
4113 uint16_t cmdsize;
4114 int did = ndlp->nlp_DID;
4115 int rc;
4116 int new_ndlp = 0;
4117
4118 cmdsize = (sizeof(uint32_t) + sizeof(struct serv_parm));
4119 elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp, did,
4120 ELS_CMD_FDISC);
4121 if (!elsiocb) {
4122 if (new_ndlp)
4123 mempool_free(ndlp, phba->nlp_mem_pool);
4124 lpfc_vport_set_state(vport, FC_VPORT_FAILED);
4125
4126 lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
4127 "%d (%d):0255 Issue FDISC: no IOCB\n",
4128 phba->brd_no, vport->vpi);
4129 return 1;
4130 }
4131
4132 icmd = &elsiocb->iocb;
4133 icmd->un.elsreq64.myID = 0;
4134 icmd->un.elsreq64.fl = 1;
4135
4136 /* For FDISC, Let FDISC rsp set the NPortID for this VPI */
4137 icmd->ulpCt_h = 1;
4138 icmd->ulpCt_l = 0;
4139
4140 pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
4141 *((uint32_t *) (pcmd)) = ELS_CMD_FDISC;
4142 pcmd += sizeof(uint32_t); /* CSP Word 1 */
4143 memcpy(pcmd, &vport->phba->pport->fc_sparam, sizeof(struct serv_parm));
4144 sp = (struct serv_parm *) pcmd;
4145 /* Setup CSPs accordingly for Fabric */
4146 sp->cmn.e_d_tov = 0;
4147 sp->cmn.w2.r_a_tov = 0;
4148 sp->cls1.classValid = 0;
4149 sp->cls2.seqDelivery = 1;
4150 sp->cls3.seqDelivery = 1;
4151
4152 pcmd += sizeof(uint32_t); /* CSP Word 2 */
4153 pcmd += sizeof(uint32_t); /* CSP Word 3 */
4154 pcmd += sizeof(uint32_t); /* CSP Word 4 */
4155 pcmd += sizeof(uint32_t); /* Port Name */
4156 memcpy(pcmd, &vport->fc_portname, 8);
4157 pcmd += sizeof(uint32_t); /* Node Name */
4158 pcmd += sizeof(uint32_t); /* Node Name */
4159 memcpy(pcmd, &vport->fc_nodename, 8);
4160
4161 lpfc_set_disctmo(vport);
4162
4163 phba->fc_stat.elsXmitFDISC++;
4164 elsiocb->iocb_cmpl = lpfc_cmpl_els_fdisc;
4165
4166 rc = lpfc_issue_fabric_iocb(phba, elsiocb);
4167 if (rc == IOCB_ERROR) {
4168 lpfc_els_free_iocb(phba, elsiocb);
4169 if (new_ndlp)
4170 mempool_free(ndlp, phba->nlp_mem_pool);
4171 lpfc_vport_set_state(vport, FC_VPORT_FAILED);
4172
4173 lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
4174 "%d (%d):0256 Issue FDISC: Cannot send IOCB\n",
4175 phba->brd_no, vport->vpi);
4176
4177 return 1;
4178 }
4179 lpfc_vport_set_state(vport, FC_VPORT_INITIALIZING);
4180 vport->port_state = LPFC_FDISC;
4181 return 0;
4182}
4183
4184static void
4185lpfc_cmpl_els_npiv_logo(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
4186 struct lpfc_iocbq *rspiocb)
4187{
4188 struct lpfc_vport *vport = cmdiocb->vport;
4189
4190 lpfc_els_free_iocb(phba, cmdiocb);
4191 vport->unreg_vpi_cmpl = VPORT_ERROR;
4192}
4193
4194int
4195lpfc_issue_els_npiv_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
4196{
4197 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
4198 struct lpfc_hba *phba = vport->phba;
4199 struct lpfc_sli_ring *pring = &phba->sli.ring[LPFC_ELS_RING];
4200 IOCB_t *icmd;
4201 struct lpfc_iocbq *elsiocb;
4202 uint8_t *pcmd;
4203 uint16_t cmdsize;
4204
4205 cmdsize = 2 * sizeof(uint32_t) + sizeof(struct lpfc_name);
4206 elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, 0, ndlp, ndlp->nlp_DID,
4207 ELS_CMD_LOGO);
4208 if (!elsiocb)
4209 return 1;
4210
4211 icmd = &elsiocb->iocb;
4212 pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
4213 *((uint32_t *) (pcmd)) = ELS_CMD_LOGO;
4214 pcmd += sizeof(uint32_t);
4215
4216 /* Fill in LOGO payload */
4217 *((uint32_t *) (pcmd)) = be32_to_cpu(vport->fc_myDID);
4218 pcmd += sizeof(uint32_t);
4219 memcpy(pcmd, &vport->fc_portname, sizeof(struct lpfc_name));
4220
4221 elsiocb->iocb_cmpl = lpfc_cmpl_els_npiv_logo;
4222 spin_lock_irq(shost->host_lock);
4223 ndlp->nlp_flag |= NLP_LOGO_SND;
4224 spin_unlock_irq(shost->host_lock);
4225 if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) {
4226 spin_lock_irq(shost->host_lock);
4227 ndlp->nlp_flag &= ~NLP_LOGO_SND;
4228 spin_unlock_irq(shost->host_lock);
4229 lpfc_els_free_iocb(phba, elsiocb);
4230 return 1;
4231 }
4232 return 0;
4233}
4234
4235void
4236lpfc_fabric_block_timeout(unsigned long ptr)
4237{
4238 struct lpfc_hba *phba = (struct lpfc_hba *) ptr;
4239 unsigned long iflags;
4240 uint32_t tmo_posted;
4241 spin_lock_irqsave(&phba->pport->work_port_lock, iflags);
4242 tmo_posted = phba->pport->work_port_events & WORKER_FABRIC_BLOCK_TMO;
4243 if (!tmo_posted)
4244 phba->pport->work_port_events |= WORKER_FABRIC_BLOCK_TMO;
4245 spin_unlock_irqrestore(&phba->pport->work_port_lock, iflags);
4246
4247 if (!tmo_posted) {
4248 spin_lock_irqsave(&phba->hbalock, iflags);
4249 if (phba->work_wait)
4250 lpfc_worker_wake_up(phba);
4251 spin_unlock_irqrestore(&phba->hbalock, iflags);
4252 }
4253}
4254
4255static void
4256lpfc_resume_fabric_iocbs(struct lpfc_hba *phba)
4257{
4258 struct lpfc_iocbq *iocb;
4259 unsigned long iflags;
4260 int ret;
4261 struct lpfc_sli_ring *pring = &phba->sli.ring[LPFC_ELS_RING];
4262 IOCB_t *cmd;
4263
4264repeat:
4265 iocb = NULL;
4266 spin_lock_irqsave(&phba->hbalock, iflags);
4267 /* Post any pending iocb to the SLI layer */
4268 if (atomic_read(&phba->fabric_iocb_count) == 0) {
4269 list_remove_head(&phba->fabric_iocb_list, iocb, typeof(*iocb),
4270 list);
4271 if (iocb)
4272 atomic_inc(&phba->fabric_iocb_count);
4273 }
4274 spin_unlock_irqrestore(&phba->hbalock, iflags);
4275 if (iocb) {
4276 iocb->fabric_iocb_cmpl = iocb->iocb_cmpl;
4277 iocb->iocb_cmpl = lpfc_cmpl_fabric_iocb;
4278 iocb->iocb_flag |= LPFC_IO_FABRIC;
4279
4280 ret = lpfc_sli_issue_iocb(phba, pring, iocb, 0);
4281
4282 if (ret == IOCB_ERROR) {
4283 iocb->iocb_cmpl = iocb->fabric_iocb_cmpl;
4284 iocb->fabric_iocb_cmpl = NULL;
4285 iocb->iocb_flag &= ~LPFC_IO_FABRIC;
4286 cmd = &iocb->iocb;
4287 cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
4288 cmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
4289 iocb->iocb_cmpl(phba, iocb, iocb);
4290
4291 atomic_dec(&phba->fabric_iocb_count);
4292 goto repeat;
4293 }
4294 }
4295
4296 return;
4297}
4298
4299void
4300lpfc_unblock_fabric_iocbs(struct lpfc_hba *phba)
4301{
4302 clear_bit(FABRIC_COMANDS_BLOCKED, &phba->bit_flags);
4303
4304 lpfc_resume_fabric_iocbs(phba);
4305 return;
4306}
4307
4308static void
4309lpfc_block_fabric_iocbs(struct lpfc_hba *phba)
4310{
4311 int blocked;
4312
4313 blocked = test_and_set_bit(FABRIC_COMANDS_BLOCKED, &phba->bit_flags);
4314 /* Start a timer to unblock fabric
4315 * iocbs after 100ms
4316 */
4317 if (!blocked)
4318 mod_timer(&phba->fabric_block_timer, jiffies + HZ/10 );
4319
4320 return;
4321}
4322
4323static void
4324lpfc_cmpl_fabric_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
4325 struct lpfc_iocbq *rspiocb)
4326{
4327 struct ls_rjt stat;
4328
4329 if ((cmdiocb->iocb_flag & LPFC_IO_FABRIC) != LPFC_IO_FABRIC)
4330 BUG();
4331
4332 switch (rspiocb->iocb.ulpStatus) {
4333 case IOSTAT_NPORT_RJT:
4334 case IOSTAT_FABRIC_RJT:
4335 if (rspiocb->iocb.un.ulpWord[4] & RJT_UNAVAIL_TEMP) {
4336 lpfc_block_fabric_iocbs(phba);
4337 }
4338 break;
4339
4340 case IOSTAT_NPORT_BSY:
4341 case IOSTAT_FABRIC_BSY:
4342 lpfc_block_fabric_iocbs(phba);
4343 break;
4344
4345 case IOSTAT_LS_RJT:
4346 stat.un.lsRjtError =
4347 be32_to_cpu(rspiocb->iocb.un.ulpWord[4]);
4348 if ((stat.un.b.lsRjtRsnCode == LSRJT_UNABLE_TPC) ||
4349 (stat.un.b.lsRjtRsnCode == LSRJT_LOGICAL_BSY))
4350 lpfc_block_fabric_iocbs(phba);
4351 break;
4352 }
4353
4354 if (atomic_read(&phba->fabric_iocb_count) == 0)
4355 BUG();
4356
4357 cmdiocb->iocb_cmpl = cmdiocb->fabric_iocb_cmpl;
4358 cmdiocb->fabric_iocb_cmpl = NULL;
4359 cmdiocb->iocb_flag &= ~LPFC_IO_FABRIC;
4360 cmdiocb->iocb_cmpl(phba, cmdiocb, rspiocb);
4361
4362 atomic_dec(&phba->fabric_iocb_count);
4363 if (!test_bit(FABRIC_COMANDS_BLOCKED, &phba->bit_flags)) {
4364 /* Post any pending iocbs to HBA */
4365 lpfc_resume_fabric_iocbs(phba);
4366 }
4367}
4368
4369int
4370lpfc_issue_fabric_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *iocb)
4371{
4372 unsigned long iflags;
4373 struct lpfc_sli_ring *pring = &phba->sli.ring[LPFC_ELS_RING];
4374 int ready;
4375 int ret;
4376
4377 if (atomic_read(&phba->fabric_iocb_count) > 1)
4378 BUG();
4379
4380 spin_lock_irqsave(&phba->hbalock, iflags);
4381 ready = atomic_read(&phba->fabric_iocb_count) == 0 &&
4382 !test_bit(FABRIC_COMANDS_BLOCKED, &phba->bit_flags);
4383
4384 spin_unlock_irqrestore(&phba->hbalock, iflags);
4385 if (ready) {
4386 iocb->fabric_iocb_cmpl = iocb->iocb_cmpl;
4387 iocb->iocb_cmpl = lpfc_cmpl_fabric_iocb;
4388 iocb->iocb_flag |= LPFC_IO_FABRIC;
4389
4390 atomic_inc(&phba->fabric_iocb_count);
4391 ret = lpfc_sli_issue_iocb(phba, pring, iocb, 0);
4392
4393 if (ret == IOCB_ERROR) {
4394 iocb->iocb_cmpl = iocb->fabric_iocb_cmpl;
4395 iocb->fabric_iocb_cmpl = NULL;
4396 iocb->iocb_flag &= ~LPFC_IO_FABRIC;
4397 atomic_dec(&phba->fabric_iocb_count);
4398 }
4399 } else {
4400 spin_lock_irqsave(&phba->hbalock, iflags);
4401 list_add_tail(&iocb->list, &phba->fabric_iocb_list);
4402 spin_unlock_irqrestore(&phba->hbalock, iflags);
4403 ret = IOCB_SUCCESS;
4404 }
4405 return ret;
4406}
4407
4408
4409void lpfc_fabric_abort_vport(struct lpfc_vport *vport)
4410{
4411 LIST_HEAD(completions);
4412 struct lpfc_hba *phba = vport->phba;
4413 struct lpfc_iocbq *tmp_iocb, *piocb;
4414 IOCB_t *cmd;
4415
4416 spin_lock_irq(&phba->hbalock);
4417 list_for_each_entry_safe(piocb, tmp_iocb, &phba->fabric_iocb_list,
4418 list) {
4419
4420 if (piocb->vport != vport)
4421 continue;
4422
4423 list_move_tail(&piocb->list, &completions);
4424 }
4425 spin_unlock_irq(&phba->hbalock);
4426
4427 while (!list_empty(&completions)) {
4428 piocb = list_get_first(&completions, struct lpfc_iocbq, list);
4429 list_del_init(&piocb->list);
4430
4431 cmd = &piocb->iocb;
4432 cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
4433 cmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
4434 (piocb->iocb_cmpl) (phba, piocb, piocb);
4435 }
4436}
4437
4438void lpfc_fabric_abort_nport(struct lpfc_nodelist *ndlp)
4439{
4440 LIST_HEAD(completions);
4441 struct lpfc_hba *phba = ndlp->vport->phba;
4442 struct lpfc_iocbq *tmp_iocb, *piocb;
4443 struct lpfc_sli_ring *pring = &phba->sli.ring[LPFC_ELS_RING];
4444 IOCB_t *cmd;
4445
4446 spin_lock_irq(&phba->hbalock);
4447 list_for_each_entry_safe(piocb, tmp_iocb, &phba->fabric_iocb_list,
4448 list) {
4449 if ((lpfc_check_sli_ndlp(phba, pring, piocb, ndlp))) {
4450
4451 list_move_tail(&piocb->list, &completions);
4452 }
4453 }
4454 spin_unlock_irq(&phba->hbalock);
4455
4456 while (!list_empty(&completions)) {
4457 piocb = list_get_first(&completions, struct lpfc_iocbq, list);
4458 list_del_init(&piocb->list);
4459
4460 cmd = &piocb->iocb;
4461 cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
4462 cmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
4463 (piocb->iocb_cmpl) (phba, piocb, piocb);
4464 }
4465}
4466
4467void lpfc_fabric_abort_hba(struct lpfc_hba *phba)
4468{
4469 LIST_HEAD(completions);
4470 struct lpfc_iocbq *piocb;
4471 IOCB_t *cmd;
4472
4473 spin_lock_irq(&phba->hbalock);
4474 list_splice_init(&phba->fabric_iocb_list, &completions);
4475 spin_unlock_irq(&phba->hbalock);
4476
4477 while (!list_empty(&completions)) {
4478 piocb = list_get_first(&completions, struct lpfc_iocbq, list);
4479 list_del_init(&piocb->list);
4480
4481 cmd = &piocb->iocb;
4482 cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
4483 cmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
4484 (piocb->iocb_cmpl) (phba, piocb, piocb);
4485 }
4486}
4487
4488
4489void lpfc_fabric_abort_flogi(struct lpfc_hba *phba)
4490{
4491 LIST_HEAD(completions);
4492 struct lpfc_iocbq *tmp_iocb, *piocb;
4493 IOCB_t *cmd;
4494 struct lpfc_nodelist *ndlp;
4495
4496 spin_lock_irq(&phba->hbalock);
4497 list_for_each_entry_safe(piocb, tmp_iocb, &phba->fabric_iocb_list,
4498 list) {
4499
4500 cmd = &piocb->iocb;
4501 ndlp = (struct lpfc_nodelist *) piocb->context1;
4502 if (cmd->ulpCommand == CMD_ELS_REQUEST64_CR &&
4503 ndlp != NULL &&
4504 ndlp->nlp_DID == Fabric_DID)
4505 list_move_tail(&piocb->list, &completions);
4506 }
4507 spin_unlock_irq(&phba->hbalock);
4508
4509 while (!list_empty(&completions)) {
4510 piocb = list_get_first(&completions, struct lpfc_iocbq, list);
4511 list_del_init(&piocb->list);
4512
4513 cmd = &piocb->iocb;
4514 cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
4515 cmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
4516 (piocb->iocb_cmpl) (phba, piocb, piocb);
4517 }
4518}
4519
4520