blob: 7649903d4134f62eaf3ac05bd05ed1b254b875ab [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 Smart0d041212019-01-28 11:14:41 -08004 * Copyright (C) 2017-2019 Broadcom. All Rights Reserved. The term *
James Smart4ae2ebd2018-06-26 08:24:31 -07005 * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
James Smart50611572016-03-31 14:12:34 -07006 * Copyright (C) 2004-2016 Emulex. All rights reserved. *
James.Smart@Emulex.Comc44ce172005-06-25 10:34:39 -04007 * EMULEX and SLI are trademarks of Emulex. *
James Smartd080abe2017-02-12 13:52:39 -08008 * www.broadcom.com *
dea31012005-04-17 16:05:31 -05009 * *
10 * This program is free software; you can redistribute it and/or *
James.Smart@Emulex.Comc44ce172005-06-25 10:34:39 -040011 * modify it under the terms of version 2 of the GNU General *
12 * Public License as published by the Free Software Foundation. *
13 * This program is distributed in the hope that it will be useful. *
14 * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND *
15 * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, *
16 * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE *
17 * DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD *
18 * TO BE LEGALLY INVALID. See the GNU General Public License for *
19 * more details, a copy of which can be found in the file COPYING *
20 * included with this package. *
dea31012005-04-17 16:05:31 -050021 *******************************************************************/
22
23/*
James Smart09372822008-01-11 01:52:54 -050024 * Fibre Channel SCSI LAN Device Driver CT support: FC Generic Services FC-GS
dea31012005-04-17 16:05:31 -050025 */
26
27#include <linux/blkdev.h>
28#include <linux/pci.h>
29#include <linux/interrupt.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090030#include <linux/slab.h>
dea31012005-04-17 16:05:31 -050031#include <linux/utsname.h>
32
James.Smart@Emulex.Com91886522005-08-10 15:03:09 -040033#include <scsi/scsi.h>
dea31012005-04-17 16:05:31 -050034#include <scsi/scsi_device.h>
35#include <scsi/scsi_host.h>
James.Smart@Emulex.Comf888ba32005-08-10 15:03:01 -040036#include <scsi/scsi_transport_fc.h>
James Smart6a9c52c2009-10-02 15:16:51 -040037#include <scsi/fc/fc_fs.h>
dea31012005-04-17 16:05:31 -050038
James Smartda0436e2009-05-22 14:51:39 -040039#include "lpfc_hw4.h"
dea31012005-04-17 16:05:31 -050040#include "lpfc_hw.h"
41#include "lpfc_sli.h"
James Smartda0436e2009-05-22 14:51:39 -040042#include "lpfc_sli4.h"
James Smartea2151b2008-09-07 11:52:10 -040043#include "lpfc_nl.h"
dea31012005-04-17 16:05:31 -050044#include "lpfc_disc.h"
dea31012005-04-17 16:05:31 -050045#include "lpfc.h"
James Smarta0f2d3e2017-02-12 13:52:31 -080046#include "lpfc_scsi.h"
47#include "lpfc_nvme.h"
dea31012005-04-17 16:05:31 -050048#include "lpfc_logmsg.h"
49#include "lpfc_crtn.h"
50#include "lpfc_version.h"
James Smart92d7f7b2007-06-17 19:56:38 -050051#include "lpfc_vport.h"
James Smart858c9f62007-06-17 19:56:39 -050052#include "lpfc_debugfs.h"
dea31012005-04-17 16:05:31 -050053
James Smarta085e872015-12-16 18:12:02 -050054/* FDMI Port Speed definitions - FC-GS-7 */
55#define HBA_PORTSPEED_1GFC 0x00000001 /* 1G FC */
56#define HBA_PORTSPEED_2GFC 0x00000002 /* 2G FC */
57#define HBA_PORTSPEED_4GFC 0x00000008 /* 4G FC */
58#define HBA_PORTSPEED_10GFC 0x00000004 /* 10G FC */
59#define HBA_PORTSPEED_8GFC 0x00000010 /* 8G FC */
60#define HBA_PORTSPEED_16GFC 0x00000020 /* 16G FC */
61#define HBA_PORTSPEED_32GFC 0x00000040 /* 32G FC */
62#define HBA_PORTSPEED_20GFC 0x00000080 /* 20G FC */
63#define HBA_PORTSPEED_40GFC 0x00000100 /* 40G FC */
64#define HBA_PORTSPEED_128GFC 0x00000200 /* 128G FC */
65#define HBA_PORTSPEED_64GFC 0x00000400 /* 64G FC */
66#define HBA_PORTSPEED_256GFC 0x00000800 /* 256G FC */
67#define HBA_PORTSPEED_UNKNOWN 0x00008000 /* Unknown */
68#define HBA_PORTSPEED_10GE 0x00010000 /* 10G E */
69#define HBA_PORTSPEED_40GE 0x00020000 /* 40G E */
70#define HBA_PORTSPEED_100GE 0x00040000 /* 100G E */
71#define HBA_PORTSPEED_25GE 0x00080000 /* 25G E */
72#define HBA_PORTSPEED_50GE 0x00100000 /* 50G E */
73#define HBA_PORTSPEED_400GE 0x00200000 /* 400G E */
dea31012005-04-17 16:05:31 -050074
75#define FOURBYTES 4
76
77
78static char *lpfc_release_version = LPFC_DRIVER_VERSION;
79
James Smarted957682007-06-17 19:56:37 -050080static void
81lpfc_ct_ignore_hbq_buffer(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq,
James Smart92d7f7b2007-06-17 19:56:38 -050082 struct lpfc_dmabuf *mp, uint32_t size)
James Smarted957682007-06-17 19:56:37 -050083{
James Smarted957682007-06-17 19:56:37 -050084 if (!mp) {
James Smart9c2face2008-01-11 01:53:18 -050085 lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
James Smart97eab632008-04-07 10:16:05 -040086 "0146 Ignoring unsolicited CT No HBQ "
James Smart9c2face2008-01-11 01:53:18 -050087 "status = x%x\n",
88 piocbq->iocb.ulpStatus);
James Smarted957682007-06-17 19:56:37 -050089 }
James Smart9c2face2008-01-11 01:53:18 -050090 lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
91 "0145 Ignoring unsolicted CT HBQ Size:%d "
92 "status = x%x\n",
93 size, piocbq->iocb.ulpStatus);
94}
95
96static void
97lpfc_ct_unsol_buffer(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq,
98 struct lpfc_dmabuf *mp, uint32_t size)
99{
100 lpfc_ct_ignore_hbq_buffer(phba, piocbq, mp, size);
James Smarted957682007-06-17 19:56:37 -0500101}
102
dea31012005-04-17 16:05:31 -0500103void
James Smart2e0fef82007-06-17 19:56:36 -0500104lpfc_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
105 struct lpfc_iocbq *piocbq)
dea31012005-04-17 16:05:31 -0500106{
James Smarted957682007-06-17 19:56:37 -0500107 struct lpfc_dmabuf *mp = NULL;
dea31012005-04-17 16:05:31 -0500108 IOCB_t *icmd = &piocbq->iocb;
James Smarted957682007-06-17 19:56:37 -0500109 int i;
110 struct lpfc_iocbq *iocbq;
111 dma_addr_t paddr;
112 uint32_t size;
James Smart9c2face2008-01-11 01:53:18 -0500113 struct list_head head;
114 struct lpfc_dmabuf *bdeBuf;
James Smart92d7f7b2007-06-17 19:56:38 -0500115
James Smart4fede782010-01-26 23:08:55 -0500116 if (lpfc_bsg_ct_unsol_event(phba, pring, piocbq) == 0)
117 return;
James Smartf1c3b0f2009-07-19 10:01:32 -0400118
James Smart92d7f7b2007-06-17 19:56:38 -0500119 if (unlikely(icmd->ulpStatus == IOSTAT_NEED_BUFFER)) {
120 lpfc_sli_hbqbuf_add_hbqs(phba, LPFC_ELS_HBQ);
121 } else if ((icmd->ulpStatus == IOSTAT_LOCAL_REJECT) &&
James Smarte3d2b802012-08-14 14:25:43 -0400122 ((icmd->un.ulpWord[4] & IOERR_PARAM_MASK) ==
123 IOERR_RCV_BUFFER_WAITING)) {
dea31012005-04-17 16:05:31 -0500124 /* Not enough posted buffers; Try posting more buffers */
125 phba->fc_stat.NoRcvBuf++;
James Smart92d7f7b2007-06-17 19:56:38 -0500126 if (!(phba->sli3_options & LPFC_SLI3_HBQ_ENABLED))
James Smart495a7142008-06-14 22:52:59 -0400127 lpfc_post_buffer(phba, pring, 2);
dea31012005-04-17 16:05:31 -0500128 return;
129 }
130
131 /* If there are no BDEs associated with this IOCB,
132 * there is nothing to do.
133 */
134 if (icmd->ulpBdeCount == 0)
135 return;
136
James Smarted957682007-06-17 19:56:37 -0500137 if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) {
James Smart9c2face2008-01-11 01:53:18 -0500138 INIT_LIST_HEAD(&head);
139 list_add_tail(&head, &piocbq->list);
140 list_for_each_entry(iocbq, &head, list) {
James Smarted957682007-06-17 19:56:37 -0500141 icmd = &iocbq->iocb;
James Smart9c2face2008-01-11 01:53:18 -0500142 if (icmd->ulpBdeCount == 0)
James Smarted957682007-06-17 19:56:37 -0500143 continue;
James Smart9c2face2008-01-11 01:53:18 -0500144 bdeBuf = iocbq->context2;
145 iocbq->context2 = NULL;
James Smarted957682007-06-17 19:56:37 -0500146 size = icmd->un.cont64[0].tus.f.bdeSize;
James Smart9c2face2008-01-11 01:53:18 -0500147 lpfc_ct_unsol_buffer(phba, piocbq, bdeBuf, size);
148 lpfc_in_buf_free(phba, bdeBuf);
James Smarted957682007-06-17 19:56:37 -0500149 if (icmd->ulpBdeCount == 2) {
James Smart9c2face2008-01-11 01:53:18 -0500150 bdeBuf = iocbq->context3;
151 iocbq->context3 = NULL;
152 size = icmd->unsli3.rcvsli3.bde2.tus.f.bdeSize;
153 lpfc_ct_unsol_buffer(phba, piocbq, bdeBuf,
154 size);
155 lpfc_in_buf_free(phba, bdeBuf);
James Smarted957682007-06-17 19:56:37 -0500156 }
dea31012005-04-17 16:05:31 -0500157 }
James Smart9c2face2008-01-11 01:53:18 -0500158 list_del(&head);
James Smarted957682007-06-17 19:56:37 -0500159 } else {
James Smartd7c255b2008-08-24 21:50:00 -0400160 INIT_LIST_HEAD(&head);
161 list_add_tail(&head, &piocbq->list);
162 list_for_each_entry(iocbq, &head, list) {
James Smarted957682007-06-17 19:56:37 -0500163 icmd = &iocbq->iocb;
James Smart9c2face2008-01-11 01:53:18 -0500164 if (icmd->ulpBdeCount == 0)
James Smartd7c255b2008-08-24 21:50:00 -0400165 lpfc_ct_unsol_buffer(phba, iocbq, NULL, 0);
James Smarted957682007-06-17 19:56:37 -0500166 for (i = 0; i < icmd->ulpBdeCount; i++) {
167 paddr = getPaddr(icmd->un.cont64[i].addrHigh,
168 icmd->un.cont64[i].addrLow);
169 mp = lpfc_sli_ringpostbuf_get(phba, pring,
170 paddr);
171 size = icmd->un.cont64[i].tus.f.bdeSize;
James Smartd7c255b2008-08-24 21:50:00 -0400172 lpfc_ct_unsol_buffer(phba, iocbq, mp, size);
James Smart92d7f7b2007-06-17 19:56:38 -0500173 lpfc_in_buf_free(phba, mp);
James Smarted957682007-06-17 19:56:37 -0500174 }
James Smart495a7142008-06-14 22:52:59 -0400175 lpfc_post_buffer(phba, pring, i);
dea31012005-04-17 16:05:31 -0500176 }
James Smartd7c255b2008-08-24 21:50:00 -0400177 list_del(&head);
dea31012005-04-17 16:05:31 -0500178 }
dea31012005-04-17 16:05:31 -0500179}
180
James Smart6669f9b2009-10-02 15:16:45 -0400181/**
James Smart6dd9e312013-01-03 15:43:37 -0500182 * lpfc_ct_handle_unsol_abort - ct upper level protocol abort handler
James Smart6669f9b2009-10-02 15:16:45 -0400183 * @phba: Pointer to HBA context object.
James Smart6dd9e312013-01-03 15:43:37 -0500184 * @dmabuf: pointer to a dmabuf that describes the FC sequence
James Smart6669f9b2009-10-02 15:16:45 -0400185 *
James Smart6dd9e312013-01-03 15:43:37 -0500186 * This function serves as the upper level protocol abort handler for CT
187 * protocol.
188 *
189 * Return 1 if abort has been handled, 0 otherwise.
James Smart6669f9b2009-10-02 15:16:45 -0400190 **/
James Smart6dd9e312013-01-03 15:43:37 -0500191int
192lpfc_ct_handle_unsol_abort(struct lpfc_hba *phba, struct hbq_dmabuf *dmabuf)
James Smart6669f9b2009-10-02 15:16:45 -0400193{
James Smart6dd9e312013-01-03 15:43:37 -0500194 int handled;
James Smart6669f9b2009-10-02 15:16:45 -0400195
James Smart6dd9e312013-01-03 15:43:37 -0500196 /* CT upper level goes through BSG */
197 handled = lpfc_bsg_ct_unsol_abort(phba, dmabuf);
James Smart6669f9b2009-10-02 15:16:45 -0400198
James Smart6dd9e312013-01-03 15:43:37 -0500199 return handled;
James Smart6669f9b2009-10-02 15:16:45 -0400200}
201
dea31012005-04-17 16:05:31 -0500202static void
James Smart2e0fef82007-06-17 19:56:36 -0500203lpfc_free_ct_rsp(struct lpfc_hba *phba, struct lpfc_dmabuf *mlist)
dea31012005-04-17 16:05:31 -0500204{
205 struct lpfc_dmabuf *mlast, *next_mlast;
206
207 list_for_each_entry_safe(mlast, next_mlast, &mlist->list, list) {
208 lpfc_mbuf_free(phba, mlast->virt, mlast->phys);
209 list_del(&mlast->list);
210 kfree(mlast);
211 }
212 lpfc_mbuf_free(phba, mlist->virt, mlist->phys);
213 kfree(mlist);
214 return;
215}
216
217static struct lpfc_dmabuf *
James Smart2e0fef82007-06-17 19:56:36 -0500218lpfc_alloc_ct_rsp(struct lpfc_hba *phba, int cmdcode, struct ulp_bde64 *bpl,
dea31012005-04-17 16:05:31 -0500219 uint32_t size, int *entries)
220{
221 struct lpfc_dmabuf *mlist = NULL;
222 struct lpfc_dmabuf *mp;
223 int cnt, i = 0;
224
James Smart09372822008-01-11 01:52:54 -0500225 /* We get chunks of FCELSSIZE */
dea31012005-04-17 16:05:31 -0500226 cnt = size > FCELSSIZE ? FCELSSIZE: size;
227
228 while (size) {
229 /* Allocate buffer for rsp payload */
230 mp = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL);
231 if (!mp) {
232 if (mlist)
233 lpfc_free_ct_rsp(phba, mlist);
234 return NULL;
235 }
236
237 INIT_LIST_HEAD(&mp->list);
238
James Smart92d7f7b2007-06-17 19:56:38 -0500239 if (cmdcode == be16_to_cpu(SLI_CTNS_GID_FT) ||
240 cmdcode == be16_to_cpu(SLI_CTNS_GFF_ID))
dea31012005-04-17 16:05:31 -0500241 mp->virt = lpfc_mbuf_alloc(phba, MEM_PRI, &(mp->phys));
242 else
243 mp->virt = lpfc_mbuf_alloc(phba, 0, &(mp->phys));
244
245 if (!mp->virt) {
246 kfree(mp);
Eric Sesterhenn0b3a82d2006-10-10 14:41:43 -0700247 if (mlist)
248 lpfc_free_ct_rsp(phba, mlist);
dea31012005-04-17 16:05:31 -0500249 return NULL;
250 }
251
252 /* Queue it to a linked list */
253 if (!mlist)
254 mlist = mp;
255 else
256 list_add_tail(&mp->list, &mlist->list);
257
James Smart34b02dc2008-08-24 21:49:55 -0400258 bpl->tus.f.bdeFlags = BUFF_TYPE_BDE_64I;
dea31012005-04-17 16:05:31 -0500259 /* build buffer ptr list for IOCB */
James Smart92d7f7b2007-06-17 19:56:38 -0500260 bpl->addrLow = le32_to_cpu(putPaddrLow(mp->phys) );
261 bpl->addrHigh = le32_to_cpu(putPaddrHigh(mp->phys) );
dea31012005-04-17 16:05:31 -0500262 bpl->tus.f.bdeSize = (uint16_t) cnt;
263 bpl->tus.w = le32_to_cpu(bpl->tus.w);
264 bpl++;
265
266 i++;
267 size -= cnt;
268 }
269
270 *entries = i;
271 return mlist;
272}
273
James Smart858c9f62007-06-17 19:56:39 -0500274int
275lpfc_ct_free_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *ctiocb)
276{
277 struct lpfc_dmabuf *buf_ptr;
278
James Smart51ef4c22007-08-02 11:10:31 -0400279 if (ctiocb->context_un.ndlp) {
280 lpfc_nlp_put(ctiocb->context_un.ndlp);
281 ctiocb->context_un.ndlp = NULL;
282 }
James Smart858c9f62007-06-17 19:56:39 -0500283 if (ctiocb->context1) {
284 buf_ptr = (struct lpfc_dmabuf *) ctiocb->context1;
285 lpfc_mbuf_free(phba, buf_ptr->virt, buf_ptr->phys);
286 kfree(buf_ptr);
287 ctiocb->context1 = NULL;
288 }
289 if (ctiocb->context2) {
290 lpfc_free_ct_rsp(phba, (struct lpfc_dmabuf *) ctiocb->context2);
291 ctiocb->context2 = NULL;
292 }
293
294 if (ctiocb->context3) {
295 buf_ptr = (struct lpfc_dmabuf *) ctiocb->context3;
296 lpfc_mbuf_free(phba, buf_ptr->virt, buf_ptr->phys);
297 kfree(buf_ptr);
Felipe Pena1109c942013-10-15 21:29:50 -0300298 ctiocb->context3 = NULL;
James Smart858c9f62007-06-17 19:56:39 -0500299 }
300 lpfc_sli_release_iocbq(phba, ctiocb);
301 return 0;
302}
303
James Smart4258e982015-12-16 18:11:58 -0500304/**
305 * lpfc_gen_req - Build and issue a GEN_REQUEST command to the SLI Layer
306 * @vport: pointer to a host virtual N_Port data structure.
307 * @bmp: Pointer to BPL for SLI command
308 * @inp: Pointer to data buffer for response data.
309 * @outp: Pointer to data buffer that hold the CT command.
310 * @cmpl: completion routine to call when command completes
311 * @ndlp: Destination NPort nodelist entry
312 *
313 * This function as the final part for issuing a CT command.
314 */
dea31012005-04-17 16:05:31 -0500315static int
James Smart2e0fef82007-06-17 19:56:36 -0500316lpfc_gen_req(struct lpfc_vport *vport, struct lpfc_dmabuf *bmp,
dea31012005-04-17 16:05:31 -0500317 struct lpfc_dmabuf *inp, struct lpfc_dmabuf *outp,
318 void (*cmpl) (struct lpfc_hba *, struct lpfc_iocbq *,
319 struct lpfc_iocbq *),
320 struct lpfc_nodelist *ndlp, uint32_t usr_flg, uint32_t num_entry,
James Smart92d7f7b2007-06-17 19:56:38 -0500321 uint32_t tmo, uint8_t retry)
dea31012005-04-17 16:05:31 -0500322{
James Smart2e0fef82007-06-17 19:56:36 -0500323 struct lpfc_hba *phba = vport->phba;
dea31012005-04-17 16:05:31 -0500324 IOCB_t *icmd;
James.Smart@Emulex.Com0bd4ca22005-10-28 20:30:02 -0400325 struct lpfc_iocbq *geniocb;
James Smart92d7f7b2007-06-17 19:56:38 -0500326 int rc;
dea31012005-04-17 16:05:31 -0500327
328 /* Allocate buffer for command iocb */
James.Smart@Emulex.Com0bd4ca22005-10-28 20:30:02 -0400329 geniocb = lpfc_sli_get_iocbq(phba);
dea31012005-04-17 16:05:31 -0500330
331 if (geniocb == NULL)
332 return 1;
dea31012005-04-17 16:05:31 -0500333
334 icmd = &geniocb->iocb;
335 icmd->un.genreq64.bdl.ulpIoTag32 = 0;
336 icmd->un.genreq64.bdl.addrHigh = putPaddrHigh(bmp->phys);
337 icmd->un.genreq64.bdl.addrLow = putPaddrLow(bmp->phys);
James Smart34b02dc2008-08-24 21:49:55 -0400338 icmd->un.genreq64.bdl.bdeFlags = BUFF_TYPE_BLP_64;
James Smart4258e982015-12-16 18:11:58 -0500339 icmd->un.genreq64.bdl.bdeSize = (num_entry * sizeof(struct ulp_bde64));
dea31012005-04-17 16:05:31 -0500340
341 if (usr_flg)
342 geniocb->context3 = NULL;
343 else
344 geniocb->context3 = (uint8_t *) bmp;
345
346 /* Save for completion so we can release these resources */
347 geniocb->context1 = (uint8_t *) inp;
348 geniocb->context2 = (uint8_t *) outp;
James Smarte47c9092008-02-08 18:49:26 -0500349 geniocb->context_un.ndlp = lpfc_nlp_get(ndlp);
dea31012005-04-17 16:05:31 -0500350
351 /* Fill in payload, bp points to frame payload */
352 icmd->ulpCommand = CMD_GEN_REQUEST64_CR;
353
354 /* Fill in rest of iocb */
355 icmd->un.genreq64.w5.hcsw.Fctl = (SI | LA);
356 icmd->un.genreq64.w5.hcsw.Dfctl = 0;
James Smart6a9c52c2009-10-02 15:16:51 -0400357 icmd->un.genreq64.w5.hcsw.Rctl = FC_RCTL_DD_UNSOL_CTL;
358 icmd->un.genreq64.w5.hcsw.Type = FC_TYPE_CT;
dea31012005-04-17 16:05:31 -0500359
Jamie Wellnitzc9f8735b2006-02-28 19:25:23 -0500360 if (!tmo) {
361 /* FC spec states we need 3 * ratov for CT requests */
362 tmo = (3 * phba->fc_ratov);
363 }
dea31012005-04-17 16:05:31 -0500364 icmd->ulpTimeout = tmo;
365 icmd->ulpBdeCount = 1;
366 icmd->ulpLe = 1;
367 icmd->ulpClass = CLASS3;
368 icmd->ulpContext = ndlp->nlp_rpi;
James Smart6d368e52011-05-24 11:44:12 -0400369 if (phba->sli_rev == LPFC_SLI_REV4)
370 icmd->ulpContext = phba->sli4_hba.rpi_ids[ndlp->nlp_rpi];
dea31012005-04-17 16:05:31 -0500371
James Smart92d7f7b2007-06-17 19:56:38 -0500372 if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) {
373 /* For GEN_REQUEST64_CR, use the RPI */
374 icmd->ulpCt_h = 0;
375 icmd->ulpCt_l = 0;
376 }
377
dea31012005-04-17 16:05:31 -0500378 /* Issue GEN REQ IOCB for NPORT <did> */
James Smarte8b62012007-08-02 11:10:09 -0400379 lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
380 "0119 Issue GEN REQ IOCB to NPORT x%x "
381 "Data: x%x x%x\n",
382 ndlp->nlp_DID, icmd->ulpIoTag,
383 vport->port_state);
dea31012005-04-17 16:05:31 -0500384 geniocb->iocb_cmpl = cmpl;
385 geniocb->drvrTimeout = icmd->ulpTimeout + LPFC_DRVR_TIMEOUT;
James Smart2e0fef82007-06-17 19:56:36 -0500386 geniocb->vport = vport;
James Smart92d7f7b2007-06-17 19:56:38 -0500387 geniocb->retry = retry;
James Smart3772a992009-05-22 14:50:54 -0400388 rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, geniocb, 0);
James Smart92d7f7b2007-06-17 19:56:38 -0500389
390 if (rc == IOCB_ERROR) {
James Bottomley604a3e32005-10-29 10:28:33 -0500391 lpfc_sli_release_iocbq(phba, geniocb);
dea31012005-04-17 16:05:31 -0500392 return 1;
393 }
dea31012005-04-17 16:05:31 -0500394
395 return 0;
396}
397
James Smart4258e982015-12-16 18:11:58 -0500398/**
399 * lpfc_ct_cmd - Build and issue a CT command
400 * @vport: pointer to a host virtual N_Port data structure.
401 * @inmp: Pointer to data buffer for response data.
402 * @bmp: Pointer to BPL for SLI command
403 * @ndlp: Destination NPort nodelist entry
404 * @cmpl: completion routine to call when command completes
405 *
406 * This function is called for issuing a CT command.
407 */
dea31012005-04-17 16:05:31 -0500408static int
James Smart2e0fef82007-06-17 19:56:36 -0500409lpfc_ct_cmd(struct lpfc_vport *vport, struct lpfc_dmabuf *inmp,
dea31012005-04-17 16:05:31 -0500410 struct lpfc_dmabuf *bmp, struct lpfc_nodelist *ndlp,
411 void (*cmpl) (struct lpfc_hba *, struct lpfc_iocbq *,
412 struct lpfc_iocbq *),
James Smart92d7f7b2007-06-17 19:56:38 -0500413 uint32_t rsp_size, uint8_t retry)
dea31012005-04-17 16:05:31 -0500414{
James Smart2e0fef82007-06-17 19:56:36 -0500415 struct lpfc_hba *phba = vport->phba;
dea31012005-04-17 16:05:31 -0500416 struct ulp_bde64 *bpl = (struct ulp_bde64 *) bmp->virt;
417 struct lpfc_dmabuf *outmp;
418 int cnt = 0, status;
419 int cmdcode = ((struct lpfc_sli_ct_request *) inmp->virt)->
420 CommandResponse.bits.CmdRsp;
421
422 bpl++; /* Skip past ct request */
423
424 /* Put buffer(s) for ct rsp in bpl */
425 outmp = lpfc_alloc_ct_rsp(phba, cmdcode, bpl, rsp_size, &cnt);
426 if (!outmp)
427 return -ENOMEM;
James Smart6a9c52c2009-10-02 15:16:51 -0400428 /*
429 * Form the CT IOCB. The total number of BDEs in this IOCB
430 * is the single command plus response count from
431 * lpfc_alloc_ct_rsp.
432 */
433 cnt += 1;
James Smart2e0fef82007-06-17 19:56:36 -0500434 status = lpfc_gen_req(vport, bmp, inmp, outmp, cmpl, ndlp, 0,
James Smart6a9c52c2009-10-02 15:16:51 -0400435 cnt, 0, retry);
dea31012005-04-17 16:05:31 -0500436 if (status) {
437 lpfc_free_ct_rsp(phba, outmp);
438 return -ENOMEM;
439 }
440 return 0;
441}
442
James Smart549e55c2007-08-02 11:09:51 -0400443struct lpfc_vport *
James Smart92d7f7b2007-06-17 19:56:38 -0500444lpfc_find_vport_by_did(struct lpfc_hba *phba, uint32_t did) {
James Smart92d7f7b2007-06-17 19:56:38 -0500445 struct lpfc_vport *vport_curr;
James Smart549e55c2007-08-02 11:09:51 -0400446 unsigned long flags;
James Smart92d7f7b2007-06-17 19:56:38 -0500447
James Smart523128e2018-09-10 10:30:46 -0700448 spin_lock_irqsave(&phba->port_list_lock, flags);
James Smart92d7f7b2007-06-17 19:56:38 -0500449 list_for_each_entry(vport_curr, &phba->port_list, listentry) {
James Smart549e55c2007-08-02 11:09:51 -0400450 if ((vport_curr->fc_myDID) && (vport_curr->fc_myDID == did)) {
James Smart523128e2018-09-10 10:30:46 -0700451 spin_unlock_irqrestore(&phba->port_list_lock, flags);
James Smart92d7f7b2007-06-17 19:56:38 -0500452 return vport_curr;
James Smart549e55c2007-08-02 11:09:51 -0400453 }
James Smart92d7f7b2007-06-17 19:56:38 -0500454 }
James Smart523128e2018-09-10 10:30:46 -0700455 spin_unlock_irqrestore(&phba->port_list_lock, flags);
James Smart92d7f7b2007-06-17 19:56:38 -0500456 return NULL;
457}
458
James Smarta0f2d3e2017-02-12 13:52:31 -0800459static void
460lpfc_prep_node_fc4type(struct lpfc_vport *vport, uint32_t Did, uint8_t fc4_type)
461{
462 struct lpfc_nodelist *ndlp;
463
464 if ((vport->port_type != LPFC_NPIV_PORT) ||
465 !(vport->ct_flags & FC_CT_RFF_ID) || !vport->cfg_restrict_login) {
466
467 ndlp = lpfc_setup_disc_node(vport, Did);
468
469 if (ndlp && NLP_CHK_NODE_ACT(ndlp)) {
James Smartbd2cdd52017-02-12 13:52:33 -0800470 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT,
471 "Parse GID_FTrsp: did:x%x flg:x%x x%x",
472 Did, ndlp->nlp_flag, vport->fc_flag);
473
James Smarta0f2d3e2017-02-12 13:52:31 -0800474 /* By default, the driver expects to support FCP FC4 */
475 if (fc4_type == FC_TYPE_FCP)
476 ndlp->nlp_fc4_type |= NLP_FC4_FCP;
477
478 if (fc4_type == FC_TYPE_NVME)
479 ndlp->nlp_fc4_type |= NLP_FC4_NVME;
480
481 lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
482 "0238 Process x%06x NameServer Rsp "
James Smart96d156f2019-08-14 16:56:46 -0700483 "Data: x%x x%x x%x x%x x%x\n", Did,
James Smarta0f2d3e2017-02-12 13:52:31 -0800484 ndlp->nlp_flag, ndlp->nlp_fc4_type,
James Smart96d156f2019-08-14 16:56:46 -0700485 ndlp->nlp_state, vport->fc_flag,
James Smarta0f2d3e2017-02-12 13:52:31 -0800486 vport->fc_rscn_id_cnt);
James Smart96d156f2019-08-14 16:56:46 -0700487
488 /* if ndlp needs to be discovered and prior
489 * state of ndlp hit devloss, change state to
490 * allow rediscovery.
491 */
492 if (ndlp->nlp_flag & NLP_NPR_2B_DISC &&
493 ndlp->nlp_state == NLP_STE_UNUSED_NODE) {
494 lpfc_nlp_set_state(vport, ndlp,
495 NLP_STE_NPR_NODE);
496 }
James Smartbd2cdd52017-02-12 13:52:33 -0800497 } else {
498 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT,
499 "Skip1 GID_FTrsp: did:x%x flg:x%x cnt:%d",
500 Did, vport->fc_flag, vport->fc_rscn_id_cnt);
501
James Smarta0f2d3e2017-02-12 13:52:31 -0800502 lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
503 "0239 Skip x%06x NameServer Rsp "
504 "Data: x%x x%x\n", Did,
505 vport->fc_flag,
506 vport->fc_rscn_id_cnt);
James Smartbd2cdd52017-02-12 13:52:33 -0800507 }
James Smarta0f2d3e2017-02-12 13:52:31 -0800508 } else {
509 if (!(vport->fc_flag & FC_RSCN_MODE) ||
510 lpfc_rscn_payload_check(vport, Did)) {
James Smartbd2cdd52017-02-12 13:52:33 -0800511 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT,
512 "Query GID_FTrsp: did:x%x flg:x%x cnt:%d",
513 Did, vport->fc_flag, vport->fc_rscn_id_cnt);
514
James Smarta0f2d3e2017-02-12 13:52:31 -0800515 /*
James Smartb57ab7462017-06-01 21:07:08 -0700516 * This NPortID was previously a FCP/NVMe target,
James Smarta0f2d3e2017-02-12 13:52:31 -0800517 * Don't even bother to send GFF_ID.
518 */
519 ndlp = lpfc_findnode_did(vport, Did);
James Smartb57ab7462017-06-01 21:07:08 -0700520 if (ndlp && NLP_CHK_NODE_ACT(ndlp) &&
521 (ndlp->nlp_type &
522 (NLP_FCP_TARGET | NLP_NVME_TARGET))) {
523 if (fc4_type == FC_TYPE_FCP)
524 ndlp->nlp_fc4_type |= NLP_FC4_FCP;
525 if (fc4_type == FC_TYPE_NVME)
526 ndlp->nlp_fc4_type |= NLP_FC4_NVME;
527 lpfc_setup_disc_node(vport, Did);
528 } else if (lpfc_ns_cmd(vport, SLI_CTNS_GFF_ID,
529 0, Did) == 0)
530 vport->num_disc_nodes++;
531 else
532 lpfc_setup_disc_node(vport, Did);
James Smartbd2cdd52017-02-12 13:52:33 -0800533 } else {
534 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT,
535 "Skip2 GID_FTrsp: did:x%x flg:x%x cnt:%d",
536 Did, vport->fc_flag, vport->fc_rscn_id_cnt);
537
James Smarta0f2d3e2017-02-12 13:52:31 -0800538 lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
539 "0245 Skip x%06x NameServer Rsp "
540 "Data: x%x x%x\n", Did,
541 vport->fc_flag,
542 vport->fc_rscn_id_cnt);
James Smartbd2cdd52017-02-12 13:52:33 -0800543 }
James Smarta0f2d3e2017-02-12 13:52:31 -0800544 }
545}
546
James Smart1c5b12f2017-04-21 16:05:03 -0700547static void
548lpfc_ns_rsp_audit_did(struct lpfc_vport *vport, uint32_t Did, uint8_t fc4_type)
549{
550 struct lpfc_hba *phba = vport->phba;
551 struct lpfc_nodelist *ndlp = NULL;
552 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
James Smart72ca6b22018-12-13 15:17:56 -0800553 char *str;
James Smart1c5b12f2017-04-21 16:05:03 -0700554
James Smart72ca6b22018-12-13 15:17:56 -0800555 if (phba->cfg_ns_query == LPFC_NS_QUERY_GID_FT)
556 str = "GID_FT";
557 else
558 str = "GID_PT";
559 lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
560 "6430 Process %s rsp for %08x type %x %s %s\n",
561 str, Did, fc4_type,
562 (fc4_type == FC_TYPE_FCP) ? "FCP" : " ",
563 (fc4_type == FC_TYPE_NVME) ? "NVME" : " ");
James Smart1c5b12f2017-04-21 16:05:03 -0700564 /*
565 * To conserve rpi's, filter out addresses for other
566 * vports on the same physical HBAs.
567 */
568 if (Did != vport->fc_myDID &&
569 (!lpfc_find_vport_by_did(phba, Did) ||
570 vport->cfg_peer_port_login)) {
571 if (!phba->nvmet_support) {
572 /* FCPI/NVMEI path. Process Did */
573 lpfc_prep_node_fc4type(vport, Did, fc4_type);
574 return;
575 }
576 /* NVMET path. NVMET only cares about NVMEI nodes. */
577 list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) {
578 if (ndlp->nlp_type != NLP_NVME_INITIATOR ||
579 ndlp->nlp_state != NLP_STE_UNMAPPED_NODE)
580 continue;
581 spin_lock_irq(shost->host_lock);
582 if (ndlp->nlp_DID == Did)
583 ndlp->nlp_flag &= ~NLP_NVMET_RECOV;
584 else
585 ndlp->nlp_flag |= NLP_NVMET_RECOV;
586 spin_unlock_irq(shost->host_lock);
587 }
588 }
589}
590
dea31012005-04-17 16:05:31 -0500591static int
James Smarta0f2d3e2017-02-12 13:52:31 -0800592lpfc_ns_rsp(struct lpfc_vport *vport, struct lpfc_dmabuf *mp, uint8_t fc4_type,
593 uint32_t Size)
dea31012005-04-17 16:05:31 -0500594{
595 struct lpfc_sli_ct_request *Response =
596 (struct lpfc_sli_ct_request *) mp->virt;
dea31012005-04-17 16:05:31 -0500597 struct lpfc_dmabuf *mlast, *next_mp;
598 uint32_t *ctptr = (uint32_t *) & Response->un.gid.PortType;
James Smart2e0fef82007-06-17 19:56:36 -0500599 uint32_t Did, CTentry;
dea31012005-04-17 16:05:31 -0500600 int Cnt;
601 struct list_head head;
James Smart1c5b12f2017-04-21 16:05:03 -0700602 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
603 struct lpfc_nodelist *ndlp = NULL;
dea31012005-04-17 16:05:31 -0500604
James Smart2e0fef82007-06-17 19:56:36 -0500605 lpfc_set_disctmo(vport);
James Smart92d7f7b2007-06-17 19:56:38 -0500606 vport->num_disc_nodes = 0;
James Smart0ff10d42008-01-11 01:52:36 -0500607 vport->fc_ns_retry = 0;
dea31012005-04-17 16:05:31 -0500608
dea31012005-04-17 16:05:31 -0500609
610 list_add_tail(&head, &mp->list);
611 list_for_each_entry_safe(mp, next_mp, &head, list) {
612 mlast = mp;
613
James Smart7054a602007-04-25 09:52:34 -0400614 Cnt = Size > FCELSSIZE ? FCELSSIZE : Size;
615
dea31012005-04-17 16:05:31 -0500616 Size -= Cnt;
617
James Smart1dcb58e2007-04-25 09:51:30 -0400618 if (!ctptr) {
dea31012005-04-17 16:05:31 -0500619 ctptr = (uint32_t *) mlast->virt;
James Smart1dcb58e2007-04-25 09:51:30 -0400620 } else
dea31012005-04-17 16:05:31 -0500621 Cnt -= 16; /* subtract length of CT header */
622
623 /* Loop through entire NameServer list of DIDs */
James Smart4258e982015-12-16 18:11:58 -0500624 while (Cnt >= sizeof(uint32_t)) {
dea31012005-04-17 16:05:31 -0500625 /* Get next DID from NameServer List */
626 CTentry = *ctptr++;
627 Did = ((be32_to_cpu(CTentry)) & Mask_DID);
James Smart1c5b12f2017-04-21 16:05:03 -0700628 lpfc_ns_rsp_audit_did(vport, Did, fc4_type);
James Smart76b2c342015-04-07 15:07:19 -0400629 if (CTentry & (cpu_to_be32(SLI_CT_LAST_ENTRY)))
dea31012005-04-17 16:05:31 -0500630 goto nsout1;
James Smarta0f2d3e2017-02-12 13:52:31 -0800631
James Smart4258e982015-12-16 18:11:58 -0500632 Cnt -= sizeof(uint32_t);
dea31012005-04-17 16:05:31 -0500633 }
634 ctptr = NULL;
635
636 }
637
James Smart1c5b12f2017-04-21 16:05:03 -0700638 /* All GID_FT entries processed. If the driver is running in
639 * in target mode, put impacted nodes into recovery and drop
640 * the RPI to flush outstanding IO.
641 */
642 if (vport->phba->nvmet_support) {
643 list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) {
644 if (!(ndlp->nlp_flag & NLP_NVMET_RECOV))
645 continue;
646 lpfc_disc_state_machine(vport, ndlp, NULL,
647 NLP_EVT_DEVICE_RECOVERY);
648 spin_lock_irq(shost->host_lock);
649 ndlp->nlp_flag &= ~NLP_NVMET_RECOV;
Dan Carpenter0d618cf2017-05-04 00:22:16 +0300650 spin_unlock_irq(shost->host_lock);
James Smart1c5b12f2017-04-21 16:05:03 -0700651 }
652 }
653
dea31012005-04-17 16:05:31 -0500654nsout1:
655 list_del(&head);
dea31012005-04-17 16:05:31 -0500656 return 0;
657}
658
dea31012005-04-17 16:05:31 -0500659static void
James Smart2e0fef82007-06-17 19:56:36 -0500660lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
661 struct lpfc_iocbq *rspiocb)
dea31012005-04-17 16:05:31 -0500662{
James Smart2e0fef82007-06-17 19:56:36 -0500663 struct lpfc_vport *vport = cmdiocb->vport;
James Smart92d7f7b2007-06-17 19:56:38 -0500664 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
dea31012005-04-17 16:05:31 -0500665 IOCB_t *irsp;
dea31012005-04-17 16:05:31 -0500666 struct lpfc_dmabuf *outp;
James Smarta0f2d3e2017-02-12 13:52:31 -0800667 struct lpfc_dmabuf *inp;
dea31012005-04-17 16:05:31 -0500668 struct lpfc_sli_ct_request *CTrsp;
James Smarta0f2d3e2017-02-12 13:52:31 -0800669 struct lpfc_sli_ct_request *CTreq;
James Smart51ef4c22007-08-02 11:10:31 -0400670 struct lpfc_nodelist *ndlp;
James Smarta0f2d3e2017-02-12 13:52:31 -0800671 int rc, type;
dea31012005-04-17 16:05:31 -0500672
James Smart51ef4c22007-08-02 11:10:31 -0400673 /* First save ndlp, before we overwrite it */
674 ndlp = cmdiocb->context_un.ndlp;
675
dea31012005-04-17 16:05:31 -0500676 /* we pass cmdiocb to state machine which needs rspiocb as well */
677 cmdiocb->context_un.rsp_iocb = rspiocb;
James Smarta0f2d3e2017-02-12 13:52:31 -0800678 inp = (struct lpfc_dmabuf *) cmdiocb->context1;
dea31012005-04-17 16:05:31 -0500679 outp = (struct lpfc_dmabuf *) cmdiocb->context2;
James Smart858c9f62007-06-17 19:56:39 -0500680 irsp = &rspiocb->iocb;
681
682 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT,
683 "GID_FT cmpl: status:x%x/x%x rtry:%d",
684 irsp->ulpStatus, irsp->un.ulpWord[4], vport->fc_ns_retry);
dea31012005-04-17 16:05:31 -0500685
James Smart92d7f7b2007-06-17 19:56:38 -0500686 /* Don't bother processing response if vport is being torn down. */
James Smarteada2722008-12-04 22:39:13 -0500687 if (vport->load_flag & FC_UNLOADING) {
688 if (vport->fc_flag & FC_RSCN_MODE)
689 lpfc_els_flush_rscn(vport);
James Smart92d7f7b2007-06-17 19:56:38 -0500690 goto out;
James Smarteada2722008-12-04 22:39:13 -0500691 }
James Smart92d7f7b2007-06-17 19:56:38 -0500692
James Smart58da1ff2008-04-07 10:15:56 -0400693 if (lpfc_els_chk_latt(vport)) {
James Smarte8b62012007-08-02 11:10:09 -0400694 lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
695 "0216 Link event during NS query\n");
James Smarteada2722008-12-04 22:39:13 -0500696 if (vport->fc_flag & FC_RSCN_MODE)
697 lpfc_els_flush_rscn(vport);
James Smart858c9f62007-06-17 19:56:39 -0500698 lpfc_vport_set_state(vport, FC_VPORT_FAILED);
699 goto out;
700 }
James Smart58da1ff2008-04-07 10:15:56 -0400701 if (lpfc_error_lost_link(irsp)) {
702 lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
703 "0226 NS query failed due to link event\n");
James Smarteada2722008-12-04 22:39:13 -0500704 if (vport->fc_flag & FC_RSCN_MODE)
705 lpfc_els_flush_rscn(vport);
James Smart58da1ff2008-04-07 10:15:56 -0400706 goto out;
707 }
James Smart49382502017-11-20 16:00:38 -0800708
709 spin_lock_irq(shost->host_lock);
710 if (vport->fc_flag & FC_RSCN_DEFERRED) {
711 vport->fc_flag &= ~FC_RSCN_DEFERRED;
712 spin_unlock_irq(shost->host_lock);
713
James Smartb04744c2018-04-09 14:24:29 -0700714 /* This is a GID_FT completing so the gidft_inp counter was
715 * incremented before the GID_FT was issued to the wire.
716 */
717 vport->gidft_inp--;
718
James Smart49382502017-11-20 16:00:38 -0800719 /*
720 * Skip processing the NS response
721 * Re-issue the NS cmd
722 */
723 lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
724 "0151 Process Deferred RSCN Data: x%x x%x\n",
725 vport->fc_flag, vport->fc_rscn_id_cnt);
726 lpfc_els_handle_rscn(vport);
727
728 goto out;
729 }
730 spin_unlock_irq(shost->host_lock);
731
James Smart858c9f62007-06-17 19:56:39 -0500732 if (irsp->ulpStatus) {
dea31012005-04-17 16:05:31 -0500733 /* Check for retry */
James Smart2e0fef82007-06-17 19:56:36 -0500734 if (vport->fc_ns_retry < LPFC_MAX_NS_RETRY) {
James Smart58da1ff2008-04-07 10:15:56 -0400735 if (irsp->ulpStatus != IOSTAT_LOCAL_REJECT ||
James Smartedb22f02012-10-31 14:45:21 -0400736 (irsp->un.ulpWord[4] & IOERR_PARAM_MASK) !=
James Smarte3d2b802012-08-14 14:25:43 -0400737 IOERR_NO_RESOURCES)
James Smart858c9f62007-06-17 19:56:39 -0500738 vport->fc_ns_retry++;
James Smart0ff10d42008-01-11 01:52:36 -0500739
James Smarta0f2d3e2017-02-12 13:52:31 -0800740 type = lpfc_get_gidft_type(vport, cmdiocb);
741 if (type == 0)
742 goto out;
743
James Smart58da1ff2008-04-07 10:15:56 -0400744 /* CT command is being retried */
James Smarta0f2d3e2017-02-12 13:52:31 -0800745 vport->gidft_inp--;
James Smart58da1ff2008-04-07 10:15:56 -0400746 rc = lpfc_ns_cmd(vport, SLI_CTNS_GID_FT,
James Smarta0f2d3e2017-02-12 13:52:31 -0800747 vport->fc_ns_retry, type);
James Smart58da1ff2008-04-07 10:15:56 -0400748 if (rc == 0)
749 goto out;
James Smart92d7f7b2007-06-17 19:56:38 -0500750 }
James Smarteada2722008-12-04 22:39:13 -0500751 if (vport->fc_flag & FC_RSCN_MODE)
752 lpfc_els_flush_rscn(vport);
James Smart92d7f7b2007-06-17 19:56:38 -0500753 lpfc_vport_set_state(vport, FC_VPORT_FAILED);
James Smarte8b62012007-08-02 11:10:09 -0400754 lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
755 "0257 GID_FT Query error: 0x%x 0x%x\n",
756 irsp->ulpStatus, vport->fc_ns_retry);
dea31012005-04-17 16:05:31 -0500757 } else {
758 /* Good status, continue checking */
James Smarta0f2d3e2017-02-12 13:52:31 -0800759 CTreq = (struct lpfc_sli_ct_request *) inp->virt;
dea31012005-04-17 16:05:31 -0500760 CTrsp = (struct lpfc_sli_ct_request *) outp->virt;
761 if (CTrsp->CommandResponse.bits.CmdRsp ==
James Smart76b2c342015-04-07 15:07:19 -0400762 cpu_to_be16(SLI_CT_RESPONSE_FS_ACC)) {
James Smarte8b62012007-08-02 11:10:09 -0400763 lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
James Smart96d156f2019-08-14 16:56:46 -0700764 "0208 NameServer Rsp Data: x%x x%x "
765 "sz x%x\n",
James Smarta0f2d3e2017-02-12 13:52:31 -0800766 vport->fc_flag,
James Smart96d156f2019-08-14 16:56:46 -0700767 CTreq->un.gid.Fc4Type,
768 irsp->un.genreq64.bdl.bdeSize);
James Smarta0f2d3e2017-02-12 13:52:31 -0800769
770 lpfc_ns_rsp(vport,
771 outp,
772 CTreq->un.gid.Fc4Type,
dea31012005-04-17 16:05:31 -0500773 (uint32_t) (irsp->un.genreq64.bdl.bdeSize));
774 } else if (CTrsp->CommandResponse.bits.CmdRsp ==
775 be16_to_cpu(SLI_CT_RESPONSE_FS_RJT)) {
776 /* NameServer Rsp Error */
James Smarta58cbd52007-08-02 11:09:43 -0400777 if ((CTrsp->ReasonCode == SLI_CT_UNABLE_TO_PERFORM_REQ)
778 && (CTrsp->Explanation == SLI_CT_NO_FC4_TYPES)) {
James Smarte8b62012007-08-02 11:10:09 -0400779 lpfc_printf_vlog(vport, KERN_INFO,
780 LOG_DISCOVERY,
781 "0269 No NameServer Entries "
James Smarta58cbd52007-08-02 11:09:43 -0400782 "Data: x%x x%x x%x x%x\n",
James Smarta58cbd52007-08-02 11:09:43 -0400783 CTrsp->CommandResponse.bits.CmdRsp,
784 (uint32_t) CTrsp->ReasonCode,
785 (uint32_t) CTrsp->Explanation,
786 vport->fc_flag);
787
788 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT,
789 "GID_FT no entry cmd:x%x rsn:x%x exp:x%x",
790 (uint32_t)CTrsp->CommandResponse.bits.CmdRsp,
791 (uint32_t) CTrsp->ReasonCode,
792 (uint32_t) CTrsp->Explanation);
James Smarte8b62012007-08-02 11:10:09 -0400793 } else {
794 lpfc_printf_vlog(vport, KERN_INFO,
795 LOG_DISCOVERY,
796 "0240 NameServer Rsp Error "
dea31012005-04-17 16:05:31 -0500797 "Data: x%x x%x x%x x%x\n",
dea31012005-04-17 16:05:31 -0500798 CTrsp->CommandResponse.bits.CmdRsp,
799 (uint32_t) CTrsp->ReasonCode,
800 (uint32_t) CTrsp->Explanation,
James Smart2e0fef82007-06-17 19:56:36 -0500801 vport->fc_flag);
James Smart858c9f62007-06-17 19:56:39 -0500802
James Smarta58cbd52007-08-02 11:09:43 -0400803 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT,
James Smart858c9f62007-06-17 19:56:39 -0500804 "GID_FT rsp err1 cmd:x%x rsn:x%x exp:x%x",
805 (uint32_t)CTrsp->CommandResponse.bits.CmdRsp,
806 (uint32_t) CTrsp->ReasonCode,
807 (uint32_t) CTrsp->Explanation);
James Smarta58cbd52007-08-02 11:09:43 -0400808 }
809
James Smart858c9f62007-06-17 19:56:39 -0500810
dea31012005-04-17 16:05:31 -0500811 } else {
812 /* NameServer Rsp Error */
James Smarte8b62012007-08-02 11:10:09 -0400813 lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY,
814 "0241 NameServer Rsp Error "
dea31012005-04-17 16:05:31 -0500815 "Data: x%x x%x x%x x%x\n",
dea31012005-04-17 16:05:31 -0500816 CTrsp->CommandResponse.bits.CmdRsp,
817 (uint32_t) CTrsp->ReasonCode,
818 (uint32_t) CTrsp->Explanation,
James Smart2e0fef82007-06-17 19:56:36 -0500819 vport->fc_flag);
James Smart858c9f62007-06-17 19:56:39 -0500820
821 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT,
822 "GID_FT rsp err2 cmd:x%x rsn:x%x exp:x%x",
823 (uint32_t)CTrsp->CommandResponse.bits.CmdRsp,
824 (uint32_t) CTrsp->ReasonCode,
825 (uint32_t) CTrsp->Explanation);
dea31012005-04-17 16:05:31 -0500826 }
James Smarta0f2d3e2017-02-12 13:52:31 -0800827 vport->gidft_inp--;
dea31012005-04-17 16:05:31 -0500828 }
James Smart96d156f2019-08-14 16:56:46 -0700829
830 lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
831 "4216 GID_FT cmpl inp %d disc %d\n",
832 vport->gidft_inp, vport->num_disc_nodes);
833
dea31012005-04-17 16:05:31 -0500834 /* Link up / RSCN discovery */
James Smarta0f2d3e2017-02-12 13:52:31 -0800835 if ((vport->num_disc_nodes == 0) &&
836 (vport->gidft_inp == 0)) {
James Smart92d7f7b2007-06-17 19:56:38 -0500837 /*
838 * The driver has cycled through all Nports in the RSCN payload.
839 * Complete the handling by cleaning up and marking the
840 * current driver state.
841 */
842 if (vport->port_state >= LPFC_DISC_AUTH) {
843 if (vport->fc_flag & FC_RSCN_MODE) {
844 lpfc_els_flush_rscn(vport);
845 spin_lock_irq(shost->host_lock);
846 vport->fc_flag |= FC_RSCN_MODE; /* RSCN still */
847 spin_unlock_irq(shost->host_lock);
848 }
849 else
850 lpfc_els_flush_rscn(vport);
851 }
852
853 lpfc_disc_start(vport);
854 }
dea31012005-04-17 16:05:31 -0500855out:
James Smart51ef4c22007-08-02 11:10:31 -0400856 cmdiocb->context_un.ndlp = ndlp; /* Now restore ndlp for free */
James Smart858c9f62007-06-17 19:56:39 -0500857 lpfc_ct_free_iocb(phba, cmdiocb);
dea31012005-04-17 16:05:31 -0500858 return;
859}
860
James Smart311464e2007-08-02 11:10:37 -0400861static void
James Smart7ea92eb2018-10-23 13:41:10 -0700862lpfc_cmpl_ct_cmd_gid_pt(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
863 struct lpfc_iocbq *rspiocb)
864{
865 struct lpfc_vport *vport = cmdiocb->vport;
866 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
867 IOCB_t *irsp;
868 struct lpfc_dmabuf *outp;
869 struct lpfc_dmabuf *inp;
870 struct lpfc_sli_ct_request *CTrsp;
871 struct lpfc_sli_ct_request *CTreq;
872 struct lpfc_nodelist *ndlp;
873 int rc;
874
875 /* First save ndlp, before we overwrite it */
876 ndlp = cmdiocb->context_un.ndlp;
877
878 /* we pass cmdiocb to state machine which needs rspiocb as well */
879 cmdiocb->context_un.rsp_iocb = rspiocb;
880 inp = (struct lpfc_dmabuf *)cmdiocb->context1;
881 outp = (struct lpfc_dmabuf *)cmdiocb->context2;
882 irsp = &rspiocb->iocb;
883
884 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT,
885 "GID_PT cmpl: status:x%x/x%x rtry:%d",
886 irsp->ulpStatus, irsp->un.ulpWord[4],
887 vport->fc_ns_retry);
888
889 /* Don't bother processing response if vport is being torn down. */
890 if (vport->load_flag & FC_UNLOADING) {
891 if (vport->fc_flag & FC_RSCN_MODE)
892 lpfc_els_flush_rscn(vport);
893 goto out;
894 }
895
896 if (lpfc_els_chk_latt(vport)) {
897 lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
898 "4108 Link event during NS query\n");
899 if (vport->fc_flag & FC_RSCN_MODE)
900 lpfc_els_flush_rscn(vport);
901 lpfc_vport_set_state(vport, FC_VPORT_FAILED);
902 goto out;
903 }
904 if (lpfc_error_lost_link(irsp)) {
905 lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
James Smartc835c082019-03-12 16:30:30 -0700906 "4166 NS query failed due to link event\n");
James Smart7ea92eb2018-10-23 13:41:10 -0700907 if (vport->fc_flag & FC_RSCN_MODE)
908 lpfc_els_flush_rscn(vport);
909 goto out;
910 }
911
912 spin_lock_irq(shost->host_lock);
913 if (vport->fc_flag & FC_RSCN_DEFERRED) {
914 vport->fc_flag &= ~FC_RSCN_DEFERRED;
915 spin_unlock_irq(shost->host_lock);
916
917 /* This is a GID_PT completing so the gidft_inp counter was
918 * incremented before the GID_PT was issued to the wire.
919 */
920 vport->gidft_inp--;
921
922 /*
923 * Skip processing the NS response
924 * Re-issue the NS cmd
925 */
926 lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
James Smartc835c082019-03-12 16:30:30 -0700927 "4167 Process Deferred RSCN Data: x%x x%x\n",
James Smart7ea92eb2018-10-23 13:41:10 -0700928 vport->fc_flag, vport->fc_rscn_id_cnt);
929 lpfc_els_handle_rscn(vport);
930
931 goto out;
932 }
933 spin_unlock_irq(shost->host_lock);
934
935 if (irsp->ulpStatus) {
936 /* Check for retry */
937 if (vport->fc_ns_retry < LPFC_MAX_NS_RETRY) {
938 if (irsp->ulpStatus != IOSTAT_LOCAL_REJECT ||
939 (irsp->un.ulpWord[4] & IOERR_PARAM_MASK) !=
940 IOERR_NO_RESOURCES)
941 vport->fc_ns_retry++;
942
943 /* CT command is being retried */
944 vport->gidft_inp--;
945 rc = lpfc_ns_cmd(vport, SLI_CTNS_GID_PT,
946 vport->fc_ns_retry, GID_PT_N_PORT);
947 if (rc == 0)
948 goto out;
949 }
950 if (vport->fc_flag & FC_RSCN_MODE)
951 lpfc_els_flush_rscn(vport);
952 lpfc_vport_set_state(vport, FC_VPORT_FAILED);
953 lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
954 "4103 GID_FT Query error: 0x%x 0x%x\n",
955 irsp->ulpStatus, vport->fc_ns_retry);
956 } else {
957 /* Good status, continue checking */
958 CTreq = (struct lpfc_sli_ct_request *)inp->virt;
959 CTrsp = (struct lpfc_sli_ct_request *)outp->virt;
960 if (CTrsp->CommandResponse.bits.CmdRsp ==
961 cpu_to_be16(SLI_CT_RESPONSE_FS_ACC)) {
962 lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
963 "4105 NameServer Rsp Data: x%x x%x\n",
964 vport->fc_flag,
965 CTreq->un.gid.Fc4Type);
966
967 lpfc_ns_rsp(vport,
968 outp,
969 CTreq->un.gid.Fc4Type,
970 (uint32_t)(irsp->un.genreq64.bdl.bdeSize));
971 } else if (CTrsp->CommandResponse.bits.CmdRsp ==
972 be16_to_cpu(SLI_CT_RESPONSE_FS_RJT)) {
973 /* NameServer Rsp Error */
974 if ((CTrsp->ReasonCode == SLI_CT_UNABLE_TO_PERFORM_REQ)
975 && (CTrsp->Explanation == SLI_CT_NO_FC4_TYPES)) {
976 lpfc_printf_vlog(
977 vport, KERN_INFO, LOG_DISCOVERY,
978 "4106 No NameServer Entries "
979 "Data: x%x x%x x%x x%x\n",
980 CTrsp->CommandResponse.bits.CmdRsp,
981 (uint32_t)CTrsp->ReasonCode,
982 (uint32_t)CTrsp->Explanation,
983 vport->fc_flag);
984
985 lpfc_debugfs_disc_trc(
986 vport, LPFC_DISC_TRC_CT,
987 "GID_PT no entry cmd:x%x rsn:x%x exp:x%x",
988 (uint32_t)CTrsp->CommandResponse.bits.CmdRsp,
989 (uint32_t)CTrsp->ReasonCode,
990 (uint32_t)CTrsp->Explanation);
991 } else {
992 lpfc_printf_vlog(
993 vport, KERN_INFO, LOG_DISCOVERY,
994 "4107 NameServer Rsp Error "
995 "Data: x%x x%x x%x x%x\n",
996 CTrsp->CommandResponse.bits.CmdRsp,
997 (uint32_t)CTrsp->ReasonCode,
998 (uint32_t)CTrsp->Explanation,
999 vport->fc_flag);
1000
1001 lpfc_debugfs_disc_trc(
1002 vport, LPFC_DISC_TRC_CT,
1003 "GID_PT rsp err1 cmd:x%x rsn:x%x exp:x%x",
1004 (uint32_t)CTrsp->CommandResponse.bits.CmdRsp,
1005 (uint32_t)CTrsp->ReasonCode,
1006 (uint32_t)CTrsp->Explanation);
1007 }
1008 } else {
1009 /* NameServer Rsp Error */
1010 lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY,
1011 "4109 NameServer Rsp Error "
1012 "Data: x%x x%x x%x x%x\n",
1013 CTrsp->CommandResponse.bits.CmdRsp,
1014 (uint32_t)CTrsp->ReasonCode,
1015 (uint32_t)CTrsp->Explanation,
1016 vport->fc_flag);
1017
1018 lpfc_debugfs_disc_trc(
1019 vport, LPFC_DISC_TRC_CT,
1020 "GID_PT rsp err2 cmd:x%x rsn:x%x exp:x%x",
1021 (uint32_t)CTrsp->CommandResponse.bits.CmdRsp,
1022 (uint32_t)CTrsp->ReasonCode,
1023 (uint32_t)CTrsp->Explanation);
1024 }
1025 vport->gidft_inp--;
1026 }
1027 /* Link up / RSCN discovery */
1028 if ((vport->num_disc_nodes == 0) &&
1029 (vport->gidft_inp == 0)) {
1030 /*
1031 * The driver has cycled through all Nports in the RSCN payload.
1032 * Complete the handling by cleaning up and marking the
1033 * current driver state.
1034 */
1035 if (vport->port_state >= LPFC_DISC_AUTH) {
1036 if (vport->fc_flag & FC_RSCN_MODE) {
1037 lpfc_els_flush_rscn(vport);
1038 spin_lock_irq(shost->host_lock);
1039 vport->fc_flag |= FC_RSCN_MODE; /* RSCN still */
1040 spin_unlock_irq(shost->host_lock);
1041 } else {
1042 lpfc_els_flush_rscn(vport);
1043 }
1044 }
1045
1046 lpfc_disc_start(vport);
1047 }
1048out:
1049 cmdiocb->context_un.ndlp = ndlp; /* Now restore ndlp for free */
1050 lpfc_ct_free_iocb(phba, cmdiocb);
1051}
1052
1053static void
James Smart92d7f7b2007-06-17 19:56:38 -05001054lpfc_cmpl_ct_cmd_gff_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
1055 struct lpfc_iocbq *rspiocb)
1056{
1057 struct lpfc_vport *vport = cmdiocb->vport;
1058 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
1059 IOCB_t *irsp = &rspiocb->iocb;
James Smart92d7f7b2007-06-17 19:56:38 -05001060 struct lpfc_dmabuf *inp = (struct lpfc_dmabuf *) cmdiocb->context1;
1061 struct lpfc_dmabuf *outp = (struct lpfc_dmabuf *) cmdiocb->context2;
1062 struct lpfc_sli_ct_request *CTrsp;
James Smart0ff10d42008-01-11 01:52:36 -05001063 int did, rc, retry;
James Smart92d7f7b2007-06-17 19:56:38 -05001064 uint8_t fbits;
1065 struct lpfc_nodelist *ndlp;
1066
1067 did = ((struct lpfc_sli_ct_request *) inp->virt)->un.gff.PortId;
1068 did = be32_to_cpu(did);
1069
James Smart858c9f62007-06-17 19:56:39 -05001070 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT,
1071 "GFF_ID cmpl: status:x%x/x%x did:x%x",
1072 irsp->ulpStatus, irsp->un.ulpWord[4], did);
1073
James Smart92d7f7b2007-06-17 19:56:38 -05001074 if (irsp->ulpStatus == IOSTAT_SUCCESS) {
1075 /* Good status, continue checking */
1076 CTrsp = (struct lpfc_sli_ct_request *) outp->virt;
1077 fbits = CTrsp->un.gff_acc.fbits[FCP_TYPE_FEATURE_OFFSET];
1078
James Smart72ca6b22018-12-13 15:17:56 -08001079 lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
1080 "6431 Process GFF_ID rsp for %08x "
1081 "fbits %02x %s %s\n",
1082 did, fbits,
1083 (fbits & FC4_FEATURE_INIT) ? "Initiator" : " ",
1084 (fbits & FC4_FEATURE_TARGET) ? "Target" : " ");
1085
James Smart92d7f7b2007-06-17 19:56:38 -05001086 if (CTrsp->CommandResponse.bits.CmdRsp ==
1087 be16_to_cpu(SLI_CT_RESPONSE_FS_ACC)) {
1088 if ((fbits & FC4_FEATURE_INIT) &&
1089 !(fbits & FC4_FEATURE_TARGET)) {
James Smarte8b62012007-08-02 11:10:09 -04001090 lpfc_printf_vlog(vport, KERN_INFO,
1091 LOG_DISCOVERY,
1092 "0270 Skip x%x GFF "
1093 "NameServer Rsp Data: (init) "
1094 "x%x x%x\n", did, fbits,
1095 vport->fc_rscn_id_cnt);
James Smart92d7f7b2007-06-17 19:56:38 -05001096 goto out;
1097 }
1098 }
1099 }
James Smart858c9f62007-06-17 19:56:39 -05001100 else {
James Smart0ff10d42008-01-11 01:52:36 -05001101 /* Check for retry */
1102 if (cmdiocb->retry < LPFC_MAX_NS_RETRY) {
1103 retry = 1;
1104 if (irsp->ulpStatus == IOSTAT_LOCAL_REJECT) {
James Smarte3d2b802012-08-14 14:25:43 -04001105 switch ((irsp->un.ulpWord[4] &
1106 IOERR_PARAM_MASK)) {
1107
James Smart0ff10d42008-01-11 01:52:36 -05001108 case IOERR_NO_RESOURCES:
1109 /* We don't increment the retry
1110 * count for this case.
1111 */
1112 break;
1113 case IOERR_LINK_DOWN:
1114 case IOERR_SLI_ABORTED:
1115 case IOERR_SLI_DOWN:
1116 retry = 0;
1117 break;
1118 default:
1119 cmdiocb->retry++;
1120 }
1121 }
1122 else
1123 cmdiocb->retry++;
1124
1125 if (retry) {
1126 /* CT command is being retried */
1127 rc = lpfc_ns_cmd(vport, SLI_CTNS_GFF_ID,
1128 cmdiocb->retry, did);
1129 if (rc == 0) {
1130 /* success */
1131 lpfc_ct_free_iocb(phba, cmdiocb);
1132 return;
1133 }
1134 }
1135 }
James Smarte8b62012007-08-02 11:10:09 -04001136 lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY,
1137 "0267 NameServer GFF Rsp "
1138 "x%x Error (%d %d) Data: x%x x%x\n",
1139 did, irsp->ulpStatus, irsp->un.ulpWord[4],
James Smart7f5f3d02008-02-08 18:50:14 -05001140 vport->fc_flag, vport->fc_rscn_id_cnt);
James Smart858c9f62007-06-17 19:56:39 -05001141 }
1142
James Smart92d7f7b2007-06-17 19:56:38 -05001143 /* This is a target port, unregistered port, or the GFF_ID failed */
1144 ndlp = lpfc_setup_disc_node(vport, did);
James Smart58da1ff2008-04-07 10:15:56 -04001145 if (ndlp && NLP_CHK_NODE_ACT(ndlp)) {
James Smarte8b62012007-08-02 11:10:09 -04001146 lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
1147 "0242 Process x%x GFF "
1148 "NameServer Rsp Data: x%x x%x x%x\n",
1149 did, ndlp->nlp_flag, vport->fc_flag,
1150 vport->fc_rscn_id_cnt);
James Smart92d7f7b2007-06-17 19:56:38 -05001151 } else {
James Smarte8b62012007-08-02 11:10:09 -04001152 lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
1153 "0243 Skip x%x GFF "
1154 "NameServer Rsp Data: x%x x%x\n", did,
1155 vport->fc_flag, vport->fc_rscn_id_cnt);
James Smart92d7f7b2007-06-17 19:56:38 -05001156 }
1157out:
1158 /* Link up / RSCN discovery */
1159 if (vport->num_disc_nodes)
1160 vport->num_disc_nodes--;
1161 if (vport->num_disc_nodes == 0) {
1162 /*
1163 * The driver has cycled through all Nports in the RSCN payload.
1164 * Complete the handling by cleaning up and marking the
1165 * current driver state.
1166 */
1167 if (vport->port_state >= LPFC_DISC_AUTH) {
1168 if (vport->fc_flag & FC_RSCN_MODE) {
1169 lpfc_els_flush_rscn(vport);
1170 spin_lock_irq(shost->host_lock);
1171 vport->fc_flag |= FC_RSCN_MODE; /* RSCN still */
1172 spin_unlock_irq(shost->host_lock);
1173 }
1174 else
1175 lpfc_els_flush_rscn(vport);
1176 }
1177 lpfc_disc_start(vport);
1178 }
James Smart858c9f62007-06-17 19:56:39 -05001179 lpfc_ct_free_iocb(phba, cmdiocb);
James Smart92d7f7b2007-06-17 19:56:38 -05001180 return;
1181}
1182
James Smarta0f2d3e2017-02-12 13:52:31 -08001183static void
1184lpfc_cmpl_ct_cmd_gft_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
1185 struct lpfc_iocbq *rspiocb)
1186{
1187 struct lpfc_vport *vport = cmdiocb->vport;
1188 IOCB_t *irsp = &rspiocb->iocb;
1189 struct lpfc_dmabuf *inp = (struct lpfc_dmabuf *)cmdiocb->context1;
1190 struct lpfc_dmabuf *outp = (struct lpfc_dmabuf *)cmdiocb->context2;
1191 struct lpfc_sli_ct_request *CTrsp;
1192 int did;
1193 struct lpfc_nodelist *ndlp;
1194 uint32_t fc4_data_0, fc4_data_1;
1195
1196 did = ((struct lpfc_sli_ct_request *)inp->virt)->un.gft.PortId;
1197 did = be32_to_cpu(did);
1198
James Smartbd2cdd52017-02-12 13:52:33 -08001199 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT,
1200 "GFT_ID cmpl: status:x%x/x%x did:x%x",
1201 irsp->ulpStatus, irsp->un.ulpWord[4], did);
1202
James Smarta0f2d3e2017-02-12 13:52:31 -08001203 if (irsp->ulpStatus == IOSTAT_SUCCESS) {
1204 /* Good status, continue checking */
1205 CTrsp = (struct lpfc_sli_ct_request *)outp->virt;
1206 fc4_data_0 = be32_to_cpu(CTrsp->un.gft_acc.fc4_types[0]);
1207 fc4_data_1 = be32_to_cpu(CTrsp->un.gft_acc.fc4_types[1]);
James Smart72ca6b22018-12-13 15:17:56 -08001208
Dick Kennedyffb70cd2017-08-23 16:55:34 -07001209 lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
James Smart72ca6b22018-12-13 15:17:56 -08001210 "6432 Process GFT_ID rsp for %08x "
1211 "Data %08x %08x %s %s\n",
1212 did, fc4_data_0, fc4_data_1,
1213 (fc4_data_0 & LPFC_FC4_TYPE_BITMASK) ?
1214 "FCP" : " ",
1215 (fc4_data_1 & LPFC_FC4_TYPE_BITMASK) ?
1216 "NVME" : " ");
James Smarta0f2d3e2017-02-12 13:52:31 -08001217
1218 ndlp = lpfc_findnode_did(vport, did);
1219 if (ndlp) {
1220 /* The bitmask value for FCP and NVME FCP types is
1221 * the same because they are 32 bits distant from
1222 * each other in word0 and word0.
1223 */
1224 if (fc4_data_0 & LPFC_FC4_TYPE_BITMASK)
1225 ndlp->nlp_fc4_type |= NLP_FC4_FCP;
1226 if (fc4_data_1 & LPFC_FC4_TYPE_BITMASK)
1227 ndlp->nlp_fc4_type |= NLP_FC4_NVME;
Dick Kennedyffb70cd2017-08-23 16:55:34 -07001228 lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
James Smarta0f2d3e2017-02-12 13:52:31 -08001229 "3064 Setting ndlp %p, DID x%06x with "
James Smart57178b92019-08-14 16:56:37 -07001230 "FC4 x%08x, Data: x%08x x%08x %d\n",
James Smarta0f2d3e2017-02-12 13:52:31 -08001231 ndlp, did, ndlp->nlp_fc4_type,
James Smart57178b92019-08-14 16:56:37 -07001232 FC_TYPE_FCP, FC_TYPE_NVME,
1233 ndlp->nlp_state);
Gustavo A. R. Silvae6ef6a72017-05-23 10:09:28 -05001234
James Smart7f20c1c2019-08-14 16:56:38 -07001235 if (ndlp->nlp_state == NLP_STE_REG_LOGIN_ISSUE &&
1236 ndlp->nlp_fc4_type) {
James Smart57178b92019-08-14 16:56:37 -07001237 ndlp->nlp_prev_state = NLP_STE_REG_LOGIN_ISSUE;
1238
1239 lpfc_nlp_set_state(vport, ndlp,
1240 NLP_STE_PRLI_ISSUE);
1241 lpfc_issue_els_prli(vport, ndlp, 0);
James Smart7f20c1c2019-08-14 16:56:38 -07001242 } else if (!ndlp->nlp_fc4_type) {
1243 /* If fc4 type is still unknown, then LOGO */
1244 lpfc_printf_vlog(vport, KERN_INFO,
1245 LOG_DISCOVERY,
1246 "6443 Sending LOGO ndlp x%px,"
1247 "DID x%06x with fc4_type: "
1248 "x%08x, state: %d\n",
1249 ndlp, did, ndlp->nlp_fc4_type,
1250 ndlp->nlp_state);
1251 lpfc_issue_els_logo(vport, ndlp, 0);
1252 ndlp->nlp_prev_state = NLP_STE_REG_LOGIN_ISSUE;
1253 lpfc_nlp_set_state(vport, ndlp,
1254 NLP_STE_NPR_NODE);
James Smart57178b92019-08-14 16:56:37 -07001255 }
James Smarta0f2d3e2017-02-12 13:52:31 -08001256 }
James Smarta0f2d3e2017-02-12 13:52:31 -08001257 } else
1258 lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY,
1259 "3065 GFT_ID failed x%08x\n", irsp->ulpStatus);
1260
1261 lpfc_ct_free_iocb(phba, cmdiocb);
1262}
James Smart92d7f7b2007-06-17 19:56:38 -05001263
dea31012005-04-17 16:05:31 -05001264static void
James Smart7ee5d432007-10-27 13:37:17 -04001265lpfc_cmpl_ct(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
1266 struct lpfc_iocbq *rspiocb)
dea31012005-04-17 16:05:31 -05001267{
James Smart92d7f7b2007-06-17 19:56:38 -05001268 struct lpfc_vport *vport = cmdiocb->vport;
dea31012005-04-17 16:05:31 -05001269 struct lpfc_dmabuf *inp;
1270 struct lpfc_dmabuf *outp;
1271 IOCB_t *irsp;
1272 struct lpfc_sli_ct_request *CTrsp;
James Smart51ef4c22007-08-02 11:10:31 -04001273 struct lpfc_nodelist *ndlp;
James Smart92d7f7b2007-06-17 19:56:38 -05001274 int cmdcode, rc;
1275 uint8_t retry;
James Smart858c9f62007-06-17 19:56:39 -05001276 uint32_t latt;
dea31012005-04-17 16:05:31 -05001277
James Smart51ef4c22007-08-02 11:10:31 -04001278 /* First save ndlp, before we overwrite it */
1279 ndlp = cmdiocb->context_un.ndlp;
1280
dea31012005-04-17 16:05:31 -05001281 /* we pass cmdiocb to state machine which needs rspiocb as well */
1282 cmdiocb->context_un.rsp_iocb = rspiocb;
1283
1284 inp = (struct lpfc_dmabuf *) cmdiocb->context1;
1285 outp = (struct lpfc_dmabuf *) cmdiocb->context2;
dea31012005-04-17 16:05:31 -05001286 irsp = &rspiocb->iocb;
1287
James Smart92d7f7b2007-06-17 19:56:38 -05001288 cmdcode = be16_to_cpu(((struct lpfc_sli_ct_request *) inp->virt)->
1289 CommandResponse.bits.CmdRsp);
dea31012005-04-17 16:05:31 -05001290 CTrsp = (struct lpfc_sli_ct_request *) outp->virt;
1291
James Smart858c9f62007-06-17 19:56:39 -05001292 latt = lpfc_els_chk_latt(vport);
1293
1294 /* RFT request completes status <ulpStatus> CmdRsp <CmdRsp> */
James Smarte8b62012007-08-02 11:10:09 -04001295 lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
James Smart7ee5d432007-10-27 13:37:17 -04001296 "0209 CT Request completes, latt %d, "
James Smarte8b62012007-08-02 11:10:09 -04001297 "ulpStatus x%x CmdRsp x%x, Context x%x, Tag x%x\n",
1298 latt, irsp->ulpStatus,
1299 CTrsp->CommandResponse.bits.CmdRsp,
1300 cmdiocb->iocb.ulpContext, cmdiocb->iocb.ulpIoTag);
dea31012005-04-17 16:05:31 -05001301
James Smart858c9f62007-06-17 19:56:39 -05001302 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT,
1303 "CT cmd cmpl: status:x%x/x%x cmd:x%x",
1304 irsp->ulpStatus, irsp->un.ulpWord[4], cmdcode);
1305
James Smart92d7f7b2007-06-17 19:56:38 -05001306 if (irsp->ulpStatus) {
James Smarte8b62012007-08-02 11:10:09 -04001307 lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY,
James Smart6e155202013-07-15 18:35:21 -04001308 "0268 NS cmd x%x Error (x%x x%x)\n",
James Smarte8b62012007-08-02 11:10:09 -04001309 cmdcode, irsp->ulpStatus, irsp->un.ulpWord[4]);
James Smart858c9f62007-06-17 19:56:39 -05001310
James Smart92d7f7b2007-06-17 19:56:38 -05001311 if ((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) &&
James Smarte3d2b802012-08-14 14:25:43 -04001312 (((irsp->un.ulpWord[4] & IOERR_PARAM_MASK) ==
1313 IOERR_SLI_DOWN) ||
1314 ((irsp->un.ulpWord[4] & IOERR_PARAM_MASK) ==
1315 IOERR_SLI_ABORTED)))
James Smart92d7f7b2007-06-17 19:56:38 -05001316 goto out;
1317
1318 retry = cmdiocb->retry;
1319 if (retry >= LPFC_MAX_NS_RETRY)
1320 goto out;
1321
1322 retry++;
James Smarte8b62012007-08-02 11:10:09 -04001323 lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
James Smartd7c255b2008-08-24 21:50:00 -04001324 "0250 Retrying NS cmd %x\n", cmdcode);
James Smart92d7f7b2007-06-17 19:56:38 -05001325 rc = lpfc_ns_cmd(vport, cmdcode, retry, 0);
1326 if (rc == 0)
1327 goto out;
1328 }
1329
1330out:
James Smart51ef4c22007-08-02 11:10:31 -04001331 cmdiocb->context_un.ndlp = ndlp; /* Now restore ndlp for free */
James Smart858c9f62007-06-17 19:56:39 -05001332 lpfc_ct_free_iocb(phba, cmdiocb);
dea31012005-04-17 16:05:31 -05001333 return;
1334}
1335
1336static void
James Smart7ee5d432007-10-27 13:37:17 -04001337lpfc_cmpl_ct_cmd_rft_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
1338 struct lpfc_iocbq *rspiocb)
1339{
1340 IOCB_t *irsp = &rspiocb->iocb;
1341 struct lpfc_vport *vport = cmdiocb->vport;
1342
James Smart98c9ea52007-10-27 13:37:33 -04001343 if (irsp->ulpStatus == IOSTAT_SUCCESS) {
1344 struct lpfc_dmabuf *outp;
1345 struct lpfc_sli_ct_request *CTrsp;
1346
1347 outp = (struct lpfc_dmabuf *) cmdiocb->context2;
1348 CTrsp = (struct lpfc_sli_ct_request *) outp->virt;
1349 if (CTrsp->CommandResponse.bits.CmdRsp ==
1350 be16_to_cpu(SLI_CT_RESPONSE_FS_ACC))
1351 vport->ct_flags |= FC_CT_RFT_ID;
1352 }
James Smart7ee5d432007-10-27 13:37:17 -04001353 lpfc_cmpl_ct(phba, cmdiocb, rspiocb);
1354 return;
1355}
1356
1357static void
James Smart2e0fef82007-06-17 19:56:36 -05001358lpfc_cmpl_ct_cmd_rnn_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
1359 struct lpfc_iocbq *rspiocb)
dea31012005-04-17 16:05:31 -05001360{
James Smart7ee5d432007-10-27 13:37:17 -04001361 IOCB_t *irsp = &rspiocb->iocb;
1362 struct lpfc_vport *vport = cmdiocb->vport;
1363
James Smart98c9ea52007-10-27 13:37:33 -04001364 if (irsp->ulpStatus == IOSTAT_SUCCESS) {
1365 struct lpfc_dmabuf *outp;
1366 struct lpfc_sli_ct_request *CTrsp;
1367
1368 outp = (struct lpfc_dmabuf *) cmdiocb->context2;
1369 CTrsp = (struct lpfc_sli_ct_request *) outp->virt;
1370 if (CTrsp->CommandResponse.bits.CmdRsp ==
1371 be16_to_cpu(SLI_CT_RESPONSE_FS_ACC))
1372 vport->ct_flags |= FC_CT_RNN_ID;
1373 }
James Smart7ee5d432007-10-27 13:37:17 -04001374 lpfc_cmpl_ct(phba, cmdiocb, rspiocb);
dea31012005-04-17 16:05:31 -05001375 return;
1376}
1377
1378static void
James Smart92d7f7b2007-06-17 19:56:38 -05001379lpfc_cmpl_ct_cmd_rspn_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
1380 struct lpfc_iocbq *rspiocb)
1381{
James Smart7ee5d432007-10-27 13:37:17 -04001382 IOCB_t *irsp = &rspiocb->iocb;
1383 struct lpfc_vport *vport = cmdiocb->vport;
1384
James Smart98c9ea52007-10-27 13:37:33 -04001385 if (irsp->ulpStatus == IOSTAT_SUCCESS) {
1386 struct lpfc_dmabuf *outp;
1387 struct lpfc_sli_ct_request *CTrsp;
1388
1389 outp = (struct lpfc_dmabuf *) cmdiocb->context2;
1390 CTrsp = (struct lpfc_sli_ct_request *) outp->virt;
1391 if (CTrsp->CommandResponse.bits.CmdRsp ==
1392 be16_to_cpu(SLI_CT_RESPONSE_FS_ACC))
1393 vport->ct_flags |= FC_CT_RSPN_ID;
1394 }
James Smart7ee5d432007-10-27 13:37:17 -04001395 lpfc_cmpl_ct(phba, cmdiocb, rspiocb);
James Smart92d7f7b2007-06-17 19:56:38 -05001396 return;
1397}
1398
1399static void
James Smart2e0fef82007-06-17 19:56:36 -05001400lpfc_cmpl_ct_cmd_rsnn_nn(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
1401 struct lpfc_iocbq *rspiocb)
dea31012005-04-17 16:05:31 -05001402{
James Smart7ee5d432007-10-27 13:37:17 -04001403 IOCB_t *irsp = &rspiocb->iocb;
1404 struct lpfc_vport *vport = cmdiocb->vport;
1405
James Smart98c9ea52007-10-27 13:37:33 -04001406 if (irsp->ulpStatus == IOSTAT_SUCCESS) {
1407 struct lpfc_dmabuf *outp;
1408 struct lpfc_sli_ct_request *CTrsp;
1409
1410 outp = (struct lpfc_dmabuf *) cmdiocb->context2;
1411 CTrsp = (struct lpfc_sli_ct_request *) outp->virt;
1412 if (CTrsp->CommandResponse.bits.CmdRsp ==
1413 be16_to_cpu(SLI_CT_RESPONSE_FS_ACC))
1414 vport->ct_flags |= FC_CT_RSNN_NN;
1415 }
James Smart7ee5d432007-10-27 13:37:17 -04001416 lpfc_cmpl_ct(phba, cmdiocb, rspiocb);
1417 return;
1418}
1419
1420static void
1421lpfc_cmpl_ct_cmd_da_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
1422 struct lpfc_iocbq *rspiocb)
1423{
1424 struct lpfc_vport *vport = cmdiocb->vport;
1425
1426 /* even if it fails we will act as though it succeeded. */
1427 vport->ct_flags = 0;
1428 lpfc_cmpl_ct(phba, cmdiocb, rspiocb);
dea31012005-04-17 16:05:31 -05001429 return;
1430}
1431
James Smart2fb9bd82006-12-02 13:33:57 -05001432static void
James Smart92d7f7b2007-06-17 19:56:38 -05001433lpfc_cmpl_ct_cmd_rff_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
1434 struct lpfc_iocbq *rspiocb)
James Smart2fb9bd82006-12-02 13:33:57 -05001435{
James Smart92d7f7b2007-06-17 19:56:38 -05001436 IOCB_t *irsp = &rspiocb->iocb;
1437 struct lpfc_vport *vport = cmdiocb->vport;
1438
James Smart98c9ea52007-10-27 13:37:33 -04001439 if (irsp->ulpStatus == IOSTAT_SUCCESS) {
1440 struct lpfc_dmabuf *outp;
1441 struct lpfc_sli_ct_request *CTrsp;
1442
1443 outp = (struct lpfc_dmabuf *) cmdiocb->context2;
1444 CTrsp = (struct lpfc_sli_ct_request *) outp->virt;
1445 if (CTrsp->CommandResponse.bits.CmdRsp ==
1446 be16_to_cpu(SLI_CT_RESPONSE_FS_ACC))
1447 vport->ct_flags |= FC_CT_RFF_ID;
1448 }
James Smart7ee5d432007-10-27 13:37:17 -04001449 lpfc_cmpl_ct(phba, cmdiocb, rspiocb);
James Smart2fb9bd82006-12-02 13:33:57 -05001450 return;
1451}
1452
James Smarta0f2d3e2017-02-12 13:52:31 -08001453/*
1454 * Although the symbolic port name is thought to be an integer
1455 * as of January 18, 2016, leave it as a string until more of
1456 * the record state becomes defined.
1457 */
James Smart495a7142008-06-14 22:52:59 -04001458int
James Smart92d7f7b2007-06-17 19:56:38 -05001459lpfc_vport_symbolic_port_name(struct lpfc_vport *vport, char *symbol,
1460 size_t size)
1461{
1462 int n;
James Smart92d7f7b2007-06-17 19:56:38 -05001463
James Smarta0f2d3e2017-02-12 13:52:31 -08001464 /*
1465 * Use the lpfc board number as the Symbolic Port
1466 * Name object. NPIV is not in play so this integer
1467 * value is sufficient and unique per FC-ID.
1468 */
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07001469 n = scnprintf(symbol, size, "%d", vport->phba->brd_no);
James Smart92d7f7b2007-06-17 19:56:38 -05001470 return n;
1471}
1472
James Smarta0f2d3e2017-02-12 13:52:31 -08001473
James Smart92d7f7b2007-06-17 19:56:38 -05001474int
1475lpfc_vport_symbolic_node_name(struct lpfc_vport *vport, char *symbol,
1476 size_t size)
dea31012005-04-17 16:05:31 -05001477{
James Smart6b5151f2012-01-18 16:24:06 -05001478 char fwrev[FW_REV_STR_SIZE];
James Smart92d7f7b2007-06-17 19:56:38 -05001479 int n;
dea31012005-04-17 16:05:31 -05001480
James Smart92d7f7b2007-06-17 19:56:38 -05001481 lpfc_decode_firmware_rev(vport->phba, fwrev, 0);
dea31012005-04-17 16:05:31 -05001482
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07001483 n = scnprintf(symbol, size, "Emulex %s", vport->phba->ModelName);
James Smartf0bf5f92015-04-07 15:07:18 -04001484 if (size < n)
1485 return n;
James Smarta0f2d3e2017-02-12 13:52:31 -08001486
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07001487 n += scnprintf(symbol + n, size - n, " FV%s", fwrev);
James Smartf0bf5f92015-04-07 15:07:18 -04001488 if (size < n)
1489 return n;
James Smartf0bf5f92015-04-07 15:07:18 -04001490
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07001491 n += scnprintf(symbol + n, size - n, " DV%s.",
James Smarta0f2d3e2017-02-12 13:52:31 -08001492 lpfc_release_version);
James Smartf0bf5f92015-04-07 15:07:18 -04001493 if (size < n)
1494 return n;
James Smarta0f2d3e2017-02-12 13:52:31 -08001495
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07001496 n += scnprintf(symbol + n, size - n, " HN:%s.",
James Smarta0f2d3e2017-02-12 13:52:31 -08001497 init_utsname()->nodename);
1498 if (size < n)
1499 return n;
James Smartf0bf5f92015-04-07 15:07:18 -04001500
1501 /* Note :- OS name is "Linux" */
Silvio Cesaree7f7b6f2019-03-21 09:44:32 -07001502 n += scnprintf(symbol + n, size - n, " OS:%s",
James Smarta0f2d3e2017-02-12 13:52:31 -08001503 init_utsname()->sysname);
James Smart92d7f7b2007-06-17 19:56:38 -05001504 return n;
dea31012005-04-17 16:05:31 -05001505}
1506
James Smart76b2c342015-04-07 15:07:19 -04001507static uint32_t
1508lpfc_find_map_node(struct lpfc_vport *vport)
1509{
1510 struct lpfc_nodelist *ndlp, *next_ndlp;
1511 struct Scsi_Host *shost;
1512 uint32_t cnt = 0;
1513
1514 shost = lpfc_shost_from_vport(vport);
1515 spin_lock_irq(shost->host_lock);
1516 list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) {
1517 if (ndlp->nlp_type & NLP_FABRIC)
1518 continue;
1519 if ((ndlp->nlp_state == NLP_STE_MAPPED_NODE) ||
1520 (ndlp->nlp_state == NLP_STE_UNMAPPED_NODE))
1521 cnt++;
1522 }
1523 spin_unlock_irq(shost->host_lock);
1524 return cnt;
1525}
1526
dea31012005-04-17 16:05:31 -05001527/*
James Smarta0f2d3e2017-02-12 13:52:31 -08001528 * This routine will return the FC4 Type associated with the CT
1529 * GID_FT command.
1530 */
1531int
1532lpfc_get_gidft_type(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb)
1533{
1534 struct lpfc_sli_ct_request *CtReq;
1535 struct lpfc_dmabuf *mp;
1536 uint32_t type;
1537
1538 mp = cmdiocb->context1;
1539 if (mp == NULL)
1540 return 0;
1541 CtReq = (struct lpfc_sli_ct_request *)mp->virt;
1542 type = (uint32_t)CtReq->un.gid.Fc4Type;
1543 if ((type != SLI_CTPT_FCP) && (type != SLI_CTPT_NVME))
1544 return 0;
1545 return type;
1546}
1547
1548/*
dea31012005-04-17 16:05:31 -05001549 * lpfc_ns_cmd
1550 * Description:
1551 * Issue Cmd to NameServer
1552 * SLI_CTNS_GID_FT
1553 * LI_CTNS_RFT_ID
1554 */
1555int
James Smart92d7f7b2007-06-17 19:56:38 -05001556lpfc_ns_cmd(struct lpfc_vport *vport, int cmdcode,
1557 uint8_t retry, uint32_t context)
dea31012005-04-17 16:05:31 -05001558{
James Smart92d7f7b2007-06-17 19:56:38 -05001559 struct lpfc_nodelist * ndlp;
James Smart2e0fef82007-06-17 19:56:36 -05001560 struct lpfc_hba *phba = vport->phba;
dea31012005-04-17 16:05:31 -05001561 struct lpfc_dmabuf *mp, *bmp;
1562 struct lpfc_sli_ct_request *CtReq;
1563 struct ulp_bde64 *bpl;
1564 void (*cmpl) (struct lpfc_hba *, struct lpfc_iocbq *,
1565 struct lpfc_iocbq *) = NULL;
James Smart72ca6b22018-12-13 15:17:56 -08001566 uint32_t *ptr;
dea31012005-04-17 16:05:31 -05001567 uint32_t rsp_size = 1024;
James Smart92d7f7b2007-06-17 19:56:38 -05001568 size_t size;
James Smart858c9f62007-06-17 19:56:39 -05001569 int rc = 0;
James Smart92d7f7b2007-06-17 19:56:38 -05001570
1571 ndlp = lpfc_findnode_did(vport, NameServer_DID);
James Smarte47c9092008-02-08 18:49:26 -05001572 if (!ndlp || !NLP_CHK_NODE_ACT(ndlp)
1573 || ndlp->nlp_state != NLP_STE_UNMAPPED_NODE) {
James Smart858c9f62007-06-17 19:56:39 -05001574 rc=1;
1575 goto ns_cmd_exit;
1576 }
dea31012005-04-17 16:05:31 -05001577
1578 /* fill in BDEs for command */
1579 /* Allocate buffer for command payload */
James Smart4258e982015-12-16 18:11:58 -05001580 mp = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL);
James Smart858c9f62007-06-17 19:56:39 -05001581 if (!mp) {
1582 rc=2;
dea31012005-04-17 16:05:31 -05001583 goto ns_cmd_exit;
James Smart858c9f62007-06-17 19:56:39 -05001584 }
dea31012005-04-17 16:05:31 -05001585
1586 INIT_LIST_HEAD(&mp->list);
1587 mp->virt = lpfc_mbuf_alloc(phba, MEM_PRI, &(mp->phys));
James Smart858c9f62007-06-17 19:56:39 -05001588 if (!mp->virt) {
1589 rc=3;
dea31012005-04-17 16:05:31 -05001590 goto ns_cmd_free_mp;
James Smart858c9f62007-06-17 19:56:39 -05001591 }
dea31012005-04-17 16:05:31 -05001592
1593 /* Allocate buffer for Buffer ptr list */
James Smart4258e982015-12-16 18:11:58 -05001594 bmp = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL);
James Smart858c9f62007-06-17 19:56:39 -05001595 if (!bmp) {
1596 rc=4;
dea31012005-04-17 16:05:31 -05001597 goto ns_cmd_free_mpvirt;
James Smart858c9f62007-06-17 19:56:39 -05001598 }
dea31012005-04-17 16:05:31 -05001599
1600 INIT_LIST_HEAD(&bmp->list);
1601 bmp->virt = lpfc_mbuf_alloc(phba, MEM_PRI, &(bmp->phys));
James Smart858c9f62007-06-17 19:56:39 -05001602 if (!bmp->virt) {
1603 rc=5;
dea31012005-04-17 16:05:31 -05001604 goto ns_cmd_free_bmp;
James Smart858c9f62007-06-17 19:56:39 -05001605 }
dea31012005-04-17 16:05:31 -05001606
1607 /* NameServer Req */
James Smarte8b62012007-08-02 11:10:09 -04001608 lpfc_printf_vlog(vport, KERN_INFO ,LOG_DISCOVERY,
James Smarta0f2d3e2017-02-12 13:52:31 -08001609 "0236 NameServer Req Data: x%x x%x x%x x%x\n",
1610 cmdcode, vport->fc_flag, vport->fc_rscn_id_cnt,
1611 context);
dea31012005-04-17 16:05:31 -05001612
1613 bpl = (struct ulp_bde64 *) bmp->virt;
1614 memset(bpl, 0, sizeof(struct ulp_bde64));
James Smart92d7f7b2007-06-17 19:56:38 -05001615 bpl->addrHigh = le32_to_cpu(putPaddrHigh(mp->phys) );
1616 bpl->addrLow = le32_to_cpu(putPaddrLow(mp->phys) );
dea31012005-04-17 16:05:31 -05001617 bpl->tus.f.bdeFlags = 0;
1618 if (cmdcode == SLI_CTNS_GID_FT)
1619 bpl->tus.f.bdeSize = GID_REQUEST_SZ;
James Smart7ea92eb2018-10-23 13:41:10 -07001620 else if (cmdcode == SLI_CTNS_GID_PT)
1621 bpl->tus.f.bdeSize = GID_REQUEST_SZ;
James Smart92d7f7b2007-06-17 19:56:38 -05001622 else if (cmdcode == SLI_CTNS_GFF_ID)
1623 bpl->tus.f.bdeSize = GFF_REQUEST_SZ;
James Smarta0f2d3e2017-02-12 13:52:31 -08001624 else if (cmdcode == SLI_CTNS_GFT_ID)
1625 bpl->tus.f.bdeSize = GFT_REQUEST_SZ;
dea31012005-04-17 16:05:31 -05001626 else if (cmdcode == SLI_CTNS_RFT_ID)
1627 bpl->tus.f.bdeSize = RFT_REQUEST_SZ;
1628 else if (cmdcode == SLI_CTNS_RNN_ID)
1629 bpl->tus.f.bdeSize = RNN_REQUEST_SZ;
James Smart92d7f7b2007-06-17 19:56:38 -05001630 else if (cmdcode == SLI_CTNS_RSPN_ID)
1631 bpl->tus.f.bdeSize = RSPN_REQUEST_SZ;
dea31012005-04-17 16:05:31 -05001632 else if (cmdcode == SLI_CTNS_RSNN_NN)
1633 bpl->tus.f.bdeSize = RSNN_REQUEST_SZ;
James Smart7ee5d432007-10-27 13:37:17 -04001634 else if (cmdcode == SLI_CTNS_DA_ID)
1635 bpl->tus.f.bdeSize = DA_ID_REQUEST_SZ;
James Smart2fb9bd82006-12-02 13:33:57 -05001636 else if (cmdcode == SLI_CTNS_RFF_ID)
1637 bpl->tus.f.bdeSize = RFF_REQUEST_SZ;
dea31012005-04-17 16:05:31 -05001638 else
1639 bpl->tus.f.bdeSize = 0;
1640 bpl->tus.w = le32_to_cpu(bpl->tus.w);
1641
1642 CtReq = (struct lpfc_sli_ct_request *) mp->virt;
James Smart4258e982015-12-16 18:11:58 -05001643 memset(CtReq, 0, sizeof(struct lpfc_sli_ct_request));
dea31012005-04-17 16:05:31 -05001644 CtReq->RevisionId.bits.Revision = SLI_CT_REVISION;
1645 CtReq->RevisionId.bits.InId = 0;
1646 CtReq->FsType = SLI_CT_DIRECTORY_SERVICE;
1647 CtReq->FsSubType = SLI_CT_DIRECTORY_NAME_SERVER;
1648 CtReq->CommandResponse.bits.Size = 0;
1649 switch (cmdcode) {
1650 case SLI_CTNS_GID_FT:
1651 CtReq->CommandResponse.bits.CmdRsp =
James Smart76b2c342015-04-07 15:07:19 -04001652 cpu_to_be16(SLI_CTNS_GID_FT);
James Smarta0f2d3e2017-02-12 13:52:31 -08001653 CtReq->un.gid.Fc4Type = context;
1654
James Smart92d7f7b2007-06-17 19:56:38 -05001655 if (vport->port_state < LPFC_NS_QRY)
James Smart2e0fef82007-06-17 19:56:36 -05001656 vport->port_state = LPFC_NS_QRY;
1657 lpfc_set_disctmo(vport);
dea31012005-04-17 16:05:31 -05001658 cmpl = lpfc_cmpl_ct_cmd_gid_ft;
1659 rsp_size = FC_MAX_NS_RSP;
1660 break;
1661
James Smart7ea92eb2018-10-23 13:41:10 -07001662 case SLI_CTNS_GID_PT:
1663 CtReq->CommandResponse.bits.CmdRsp =
1664 cpu_to_be16(SLI_CTNS_GID_PT);
1665 CtReq->un.gid.PortType = context;
1666
1667 if (vport->port_state < LPFC_NS_QRY)
1668 vport->port_state = LPFC_NS_QRY;
1669 lpfc_set_disctmo(vport);
1670 cmpl = lpfc_cmpl_ct_cmd_gid_pt;
1671 rsp_size = FC_MAX_NS_RSP;
1672 break;
1673
James Smart92d7f7b2007-06-17 19:56:38 -05001674 case SLI_CTNS_GFF_ID:
1675 CtReq->CommandResponse.bits.CmdRsp =
James Smart76b2c342015-04-07 15:07:19 -04001676 cpu_to_be16(SLI_CTNS_GFF_ID);
James Smart09372822008-01-11 01:52:54 -05001677 CtReq->un.gff.PortId = cpu_to_be32(context);
James Smart92d7f7b2007-06-17 19:56:38 -05001678 cmpl = lpfc_cmpl_ct_cmd_gff_id;
1679 break;
1680
James Smarta0f2d3e2017-02-12 13:52:31 -08001681 case SLI_CTNS_GFT_ID:
1682 CtReq->CommandResponse.bits.CmdRsp =
1683 cpu_to_be16(SLI_CTNS_GFT_ID);
1684 CtReq->un.gft.PortId = cpu_to_be32(context);
1685 cmpl = lpfc_cmpl_ct_cmd_gft_id;
1686 break;
1687
dea31012005-04-17 16:05:31 -05001688 case SLI_CTNS_RFT_ID:
James Smart7ee5d432007-10-27 13:37:17 -04001689 vport->ct_flags &= ~FC_CT_RFT_ID;
dea31012005-04-17 16:05:31 -05001690 CtReq->CommandResponse.bits.CmdRsp =
James Smart76b2c342015-04-07 15:07:19 -04001691 cpu_to_be16(SLI_CTNS_RFT_ID);
James Smart09372822008-01-11 01:52:54 -05001692 CtReq->un.rft.PortId = cpu_to_be32(vport->fc_myDID);
James Smarta0f2d3e2017-02-12 13:52:31 -08001693
1694 /* Register FC4 FCP type if enabled. */
James Smartf6e84792019-01-28 11:14:38 -08001695 if (vport->cfg_enable_fc4_type == LPFC_ENABLE_BOTH ||
1696 vport->cfg_enable_fc4_type == LPFC_ENABLE_FCP)
James Smarta0f2d3e2017-02-12 13:52:31 -08001697 CtReq->un.rft.fcpReg = 1;
1698
1699 /* Register NVME type if enabled. Defined LE and swapped.
1700 * rsvd[0] is used as word1 because of the hard-coded
1701 * word0 usage in the ct_request data structure.
1702 */
James Smartf6e84792019-01-28 11:14:38 -08001703 if (vport->cfg_enable_fc4_type == LPFC_ENABLE_BOTH ||
1704 vport->cfg_enable_fc4_type == LPFC_ENABLE_NVME)
James Smart72ca6b22018-12-13 15:17:56 -08001705 CtReq->un.rft.rsvd[0] =
1706 cpu_to_be32(LPFC_FC4_TYPE_BITMASK);
James Smarta0f2d3e2017-02-12 13:52:31 -08001707
James Smart72ca6b22018-12-13 15:17:56 -08001708 ptr = (uint32_t *)CtReq;
1709 lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
1710 "6433 Issue RFT (%s %s): %08x %08x %08x %08x "
1711 "%08x %08x %08x %08x\n",
1712 CtReq->un.rft.fcpReg ? "FCP" : " ",
1713 CtReq->un.rft.rsvd[0] ? "NVME" : " ",
1714 *ptr, *(ptr + 1), *(ptr + 2), *(ptr + 3),
1715 *(ptr + 4), *(ptr + 5),
1716 *(ptr + 6), *(ptr + 7));
dea31012005-04-17 16:05:31 -05001717 cmpl = lpfc_cmpl_ct_cmd_rft_id;
1718 break;
1719
1720 case SLI_CTNS_RNN_ID:
James Smart7ee5d432007-10-27 13:37:17 -04001721 vport->ct_flags &= ~FC_CT_RNN_ID;
dea31012005-04-17 16:05:31 -05001722 CtReq->CommandResponse.bits.CmdRsp =
James Smart76b2c342015-04-07 15:07:19 -04001723 cpu_to_be16(SLI_CTNS_RNN_ID);
James Smart09372822008-01-11 01:52:54 -05001724 CtReq->un.rnn.PortId = cpu_to_be32(vport->fc_myDID);
James Smart2e0fef82007-06-17 19:56:36 -05001725 memcpy(CtReq->un.rnn.wwnn, &vport->fc_nodename,
James Smart4258e982015-12-16 18:11:58 -05001726 sizeof(struct lpfc_name));
dea31012005-04-17 16:05:31 -05001727 cmpl = lpfc_cmpl_ct_cmd_rnn_id;
1728 break;
1729
James Smart92d7f7b2007-06-17 19:56:38 -05001730 case SLI_CTNS_RSPN_ID:
James Smart7ee5d432007-10-27 13:37:17 -04001731 vport->ct_flags &= ~FC_CT_RSPN_ID;
James Smart92d7f7b2007-06-17 19:56:38 -05001732 CtReq->CommandResponse.bits.CmdRsp =
James Smart76b2c342015-04-07 15:07:19 -04001733 cpu_to_be16(SLI_CTNS_RSPN_ID);
James Smart09372822008-01-11 01:52:54 -05001734 CtReq->un.rspn.PortId = cpu_to_be32(vport->fc_myDID);
James Smart92d7f7b2007-06-17 19:56:38 -05001735 size = sizeof(CtReq->un.rspn.symbname);
1736 CtReq->un.rspn.len =
1737 lpfc_vport_symbolic_port_name(vport,
1738 CtReq->un.rspn.symbname, size);
1739 cmpl = lpfc_cmpl_ct_cmd_rspn_id;
1740 break;
dea31012005-04-17 16:05:31 -05001741 case SLI_CTNS_RSNN_NN:
James Smart7ee5d432007-10-27 13:37:17 -04001742 vport->ct_flags &= ~FC_CT_RSNN_NN;
dea31012005-04-17 16:05:31 -05001743 CtReq->CommandResponse.bits.CmdRsp =
James Smart76b2c342015-04-07 15:07:19 -04001744 cpu_to_be16(SLI_CTNS_RSNN_NN);
James Smart2e0fef82007-06-17 19:56:36 -05001745 memcpy(CtReq->un.rsnn.wwnn, &vport->fc_nodename,
James Smart4258e982015-12-16 18:11:58 -05001746 sizeof(struct lpfc_name));
James Smart92d7f7b2007-06-17 19:56:38 -05001747 size = sizeof(CtReq->un.rsnn.symbname);
1748 CtReq->un.rsnn.len =
1749 lpfc_vport_symbolic_node_name(vport,
1750 CtReq->un.rsnn.symbname, size);
dea31012005-04-17 16:05:31 -05001751 cmpl = lpfc_cmpl_ct_cmd_rsnn_nn;
1752 break;
James Smart7ee5d432007-10-27 13:37:17 -04001753 case SLI_CTNS_DA_ID:
1754 /* Implement DA_ID Nameserver request */
1755 CtReq->CommandResponse.bits.CmdRsp =
James Smart76b2c342015-04-07 15:07:19 -04001756 cpu_to_be16(SLI_CTNS_DA_ID);
James Smart09372822008-01-11 01:52:54 -05001757 CtReq->un.da_id.port_id = cpu_to_be32(vport->fc_myDID);
James Smart7ee5d432007-10-27 13:37:17 -04001758 cmpl = lpfc_cmpl_ct_cmd_da_id;
1759 break;
James Smart92d7f7b2007-06-17 19:56:38 -05001760 case SLI_CTNS_RFF_ID:
James Smart7ee5d432007-10-27 13:37:17 -04001761 vport->ct_flags &= ~FC_CT_RFF_ID;
James Smart92d7f7b2007-06-17 19:56:38 -05001762 CtReq->CommandResponse.bits.CmdRsp =
James Smart76b2c342015-04-07 15:07:19 -04001763 cpu_to_be16(SLI_CTNS_RFF_ID);
Joe Perchesa419aef2009-08-18 11:18:35 -07001764 CtReq->un.rff.PortId = cpu_to_be32(vport->fc_myDID);
James Smart92d7f7b2007-06-17 19:56:38 -05001765 CtReq->un.rff.fbits = FC4_FEATURE_INIT;
James Smarta0f2d3e2017-02-12 13:52:31 -08001766
1767 /* The driver always supports FC_TYPE_FCP. However, the
1768 * caller can specify NVME (type x28) as well. But only
1769 * these that FC4 type is supported.
1770 */
James Smartf6e84792019-01-28 11:14:38 -08001771 if (((vport->cfg_enable_fc4_type == LPFC_ENABLE_BOTH) ||
1772 (vport->cfg_enable_fc4_type == LPFC_ENABLE_NVME)) &&
James Smarta0f2d3e2017-02-12 13:52:31 -08001773 (context == FC_TYPE_NVME)) {
James Smart8c258642017-02-12 13:52:36 -08001774 if ((vport == phba->pport) && phba->nvmet_support) {
1775 CtReq->un.rff.fbits = (FC4_FEATURE_TARGET |
1776 FC4_FEATURE_NVME_DISC);
James Smartd613b6a2017-02-12 13:52:37 -08001777 lpfc_nvmet_update_targetport(phba);
James Smart8c258642017-02-12 13:52:36 -08001778 } else {
1779 lpfc_nvme_update_localport(vport);
1780 }
James Smarta0f2d3e2017-02-12 13:52:31 -08001781 CtReq->un.rff.type_code = context;
1782
James Smartf6e84792019-01-28 11:14:38 -08001783 } else if (((vport->cfg_enable_fc4_type == LPFC_ENABLE_BOTH) ||
1784 (vport->cfg_enable_fc4_type == LPFC_ENABLE_FCP)) &&
James Smarta0f2d3e2017-02-12 13:52:31 -08001785 (context == FC_TYPE_FCP))
1786 CtReq->un.rff.type_code = context;
1787
1788 else
1789 goto ns_cmd_free_bmpvirt;
1790
James Smart72ca6b22018-12-13 15:17:56 -08001791 ptr = (uint32_t *)CtReq;
1792 lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
1793 "6434 Issue RFF (%s): %08x %08x %08x %08x "
1794 "%08x %08x %08x %08x\n",
1795 (context == FC_TYPE_NVME) ? "NVME" : "FCP",
1796 *ptr, *(ptr + 1), *(ptr + 2), *(ptr + 3),
1797 *(ptr + 4), *(ptr + 5),
1798 *(ptr + 6), *(ptr + 7));
James Smart92d7f7b2007-06-17 19:56:38 -05001799 cmpl = lpfc_cmpl_ct_cmd_rff_id;
1800 break;
dea31012005-04-17 16:05:31 -05001801 }
James Smarte47c9092008-02-08 18:49:26 -05001802 /* The lpfc_ct_cmd/lpfc_get_req shall increment ndlp reference count
1803 * to hold ndlp reference for the corresponding callback function.
1804 */
James Smart858c9f62007-06-17 19:56:39 -05001805 if (!lpfc_ct_cmd(vport, mp, bmp, ndlp, cmpl, rsp_size, retry)) {
dea31012005-04-17 16:05:31 -05001806 /* On success, The cmpl function will free the buffers */
James Smart858c9f62007-06-17 19:56:39 -05001807 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT,
1808 "Issue CT cmd: cmd:x%x did:x%x",
1809 cmdcode, ndlp->nlp_DID, 0);
dea31012005-04-17 16:05:31 -05001810 return 0;
James Smart858c9f62007-06-17 19:56:39 -05001811 }
James Smart858c9f62007-06-17 19:56:39 -05001812 rc=6;
James Smarte47c9092008-02-08 18:49:26 -05001813
1814 /* Decrement ndlp reference count to release ndlp reference held
1815 * for the failed command's callback function.
1816 */
James Smart51ef4c22007-08-02 11:10:31 -04001817 lpfc_nlp_put(ndlp);
James Smarte47c9092008-02-08 18:49:26 -05001818
James Smarta0f2d3e2017-02-12 13:52:31 -08001819ns_cmd_free_bmpvirt:
dea31012005-04-17 16:05:31 -05001820 lpfc_mbuf_free(phba, bmp->virt, bmp->phys);
1821ns_cmd_free_bmp:
1822 kfree(bmp);
1823ns_cmd_free_mpvirt:
1824 lpfc_mbuf_free(phba, mp->virt, mp->phys);
1825ns_cmd_free_mp:
1826 kfree(mp);
1827ns_cmd_exit:
James Smarte8b62012007-08-02 11:10:09 -04001828 lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY,
1829 "0266 Issue NameServer Req x%x err %d Data: x%x x%x\n",
1830 cmdcode, rc, vport->fc_flag, vport->fc_rscn_id_cnt);
dea31012005-04-17 16:05:31 -05001831 return 1;
1832}
1833
James Smart4258e982015-12-16 18:11:58 -05001834/**
1835 * lpfc_cmpl_ct_disc_fdmi - Handle a discovery FDMI completion
1836 * @phba: Pointer to HBA context object.
1837 * @cmdiocb: Pointer to the command IOCBQ.
1838 * @rspiocb: Pointer to the response IOCBQ.
1839 *
1840 * This function to handle the completion of a driver initiated FDMI
1841 * CT command issued during discovery.
1842 */
dea31012005-04-17 16:05:31 -05001843static void
James Smart4258e982015-12-16 18:11:58 -05001844lpfc_cmpl_ct_disc_fdmi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
1845 struct lpfc_iocbq *rspiocb)
dea31012005-04-17 16:05:31 -05001846{
James Smart4258e982015-12-16 18:11:58 -05001847 struct lpfc_vport *vport = cmdiocb->vport;
dea31012005-04-17 16:05:31 -05001848 struct lpfc_dmabuf *inp = cmdiocb->context1;
1849 struct lpfc_dmabuf *outp = cmdiocb->context2;
dea31012005-04-17 16:05:31 -05001850 struct lpfc_sli_ct_request *CTcmd = inp->virt;
James Smart4258e982015-12-16 18:11:58 -05001851 struct lpfc_sli_ct_request *CTrsp = outp->virt;
dea31012005-04-17 16:05:31 -05001852 uint16_t fdmi_cmd = CTcmd->CommandResponse.bits.CmdRsp;
1853 uint16_t fdmi_rsp = CTrsp->CommandResponse.bits.CmdRsp;
James Smart858c9f62007-06-17 19:56:39 -05001854 IOCB_t *irsp = &rspiocb->iocb;
James Smart4258e982015-12-16 18:11:58 -05001855 struct lpfc_nodelist *ndlp;
1856 uint32_t latt, cmd, err;
James Smart858c9f62007-06-17 19:56:39 -05001857
1858 latt = lpfc_els_chk_latt(vport);
James Smart858c9f62007-06-17 19:56:39 -05001859 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT,
1860 "FDMI cmpl: status:x%x/x%x latt:%d",
1861 irsp->ulpStatus, irsp->un.ulpWord[4], latt);
1862
1863 if (latt || irsp->ulpStatus) {
James Smart4258e982015-12-16 18:11:58 -05001864
1865 /* Look for a retryable error */
1866 if (irsp->ulpStatus == IOSTAT_LOCAL_REJECT) {
1867 switch ((irsp->un.ulpWord[4] & IOERR_PARAM_MASK)) {
1868 case IOERR_SLI_ABORTED:
1869 case IOERR_ABORT_IN_PROGRESS:
1870 case IOERR_SEQUENCE_TIMEOUT:
1871 case IOERR_ILLEGAL_FRAME:
1872 case IOERR_NO_RESOURCES:
1873 case IOERR_ILLEGAL_COMMAND:
1874 cmdiocb->retry++;
1875 if (cmdiocb->retry >= LPFC_FDMI_MAX_RETRY)
1876 break;
1877
1878 /* Retry the same FDMI command */
1879 err = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING,
1880 cmdiocb, 0);
1881 if (err == IOCB_ERROR)
1882 break;
1883 return;
1884 default:
1885 break;
1886 }
1887 }
1888
James Smarte8b62012007-08-02 11:10:09 -04001889 lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
1890 "0229 FDMI cmd %04x failed, latt = %d "
1891 "ulpStatus: x%x, rid x%x\n",
1892 be16_to_cpu(fdmi_cmd), latt, irsp->ulpStatus,
1893 irsp->un.ulpWord[4]);
James Smart858c9f62007-06-17 19:56:39 -05001894 }
James Smart76b2c342015-04-07 15:07:19 -04001895 lpfc_ct_free_iocb(phba, cmdiocb);
James Smart76b2c342015-04-07 15:07:19 -04001896
1897 ndlp = lpfc_findnode_did(vport, FDMI_DID);
1898 if (!ndlp || !NLP_CHK_NODE_ACT(ndlp))
1899 return;
1900
James Smart4258e982015-12-16 18:11:58 -05001901 /* Check for a CT LS_RJT response */
1902 cmd = be16_to_cpu(fdmi_cmd);
1903 if (fdmi_rsp == cpu_to_be16(SLI_CT_RESPONSE_FS_RJT)) {
1904 /* FDMI rsp failed */
1905 lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
1906 "0220 FDMI cmd failed FS_RJT Data: x%x", cmd);
1907
1908 /* Should we fallback to FDMI-2 / FDMI-1 ? */
1909 switch (cmd) {
1910 case SLI_MGMT_RHBA:
1911 if (vport->fdmi_hba_mask == LPFC_FDMI2_HBA_ATTR) {
1912 /* Fallback to FDMI-1 */
1913 vport->fdmi_hba_mask = LPFC_FDMI1_HBA_ATTR;
1914 vport->fdmi_port_mask = LPFC_FDMI1_PORT_ATTR;
1915 /* Start over */
1916 lpfc_fdmi_cmd(vport, ndlp, SLI_MGMT_DHBA, 0);
1917 }
1918 return;
1919
1920 case SLI_MGMT_RPRT:
1921 if (vport->fdmi_port_mask == LPFC_FDMI2_PORT_ATTR) {
1922 /* Fallback to FDMI-1 */
1923 vport->fdmi_port_mask = LPFC_FDMI1_PORT_ATTR;
1924 /* Start over */
1925 lpfc_fdmi_cmd(vport, ndlp, cmd, 0);
1926 }
1927 if (vport->fdmi_port_mask == LPFC_FDMI2_SMART_ATTR) {
1928 vport->fdmi_port_mask = LPFC_FDMI2_PORT_ATTR;
1929 /* Retry the same command */
1930 lpfc_fdmi_cmd(vport, ndlp, cmd, 0);
1931 }
1932 return;
1933
1934 case SLI_MGMT_RPA:
1935 if (vport->fdmi_port_mask == LPFC_FDMI2_PORT_ATTR) {
1936 /* Fallback to FDMI-1 */
1937 vport->fdmi_hba_mask = LPFC_FDMI1_HBA_ATTR;
1938 vport->fdmi_port_mask = LPFC_FDMI1_PORT_ATTR;
1939 /* Start over */
1940 lpfc_fdmi_cmd(vport, ndlp, SLI_MGMT_DHBA, 0);
1941 }
1942 if (vport->fdmi_port_mask == LPFC_FDMI2_SMART_ATTR) {
1943 vport->fdmi_port_mask = LPFC_FDMI2_PORT_ATTR;
1944 /* Retry the same command */
1945 lpfc_fdmi_cmd(vport, ndlp, cmd, 0);
1946 }
1947 return;
1948 }
1949 }
1950
James Smart76b2c342015-04-07 15:07:19 -04001951 /*
James Smart4258e982015-12-16 18:11:58 -05001952 * On success, need to cycle thru FDMI registration for discovery
1953 * DHBA -> DPRT -> RHBA -> RPA (physical port)
1954 * DPRT -> RPRT (vports)
James Smart76b2c342015-04-07 15:07:19 -04001955 */
James Smart4258e982015-12-16 18:11:58 -05001956 switch (cmd) {
dea31012005-04-17 16:05:31 -05001957 case SLI_MGMT_RHBA:
James Smart4258e982015-12-16 18:11:58 -05001958 lpfc_fdmi_cmd(vport, ndlp, SLI_MGMT_RPA, 0);
dea31012005-04-17 16:05:31 -05001959 break;
1960
dea31012005-04-17 16:05:31 -05001961 case SLI_MGMT_DHBA:
James Smart4258e982015-12-16 18:11:58 -05001962 lpfc_fdmi_cmd(vport, ndlp, SLI_MGMT_DPRT, 0);
dea31012005-04-17 16:05:31 -05001963 break;
1964
1965 case SLI_MGMT_DPRT:
James Smart4258e982015-12-16 18:11:58 -05001966 if (vport->port_type == LPFC_PHYSICAL_PORT)
1967 lpfc_fdmi_cmd(vport, ndlp, SLI_MGMT_RHBA, 0);
1968 else
1969 lpfc_fdmi_cmd(vport, ndlp, SLI_MGMT_RPRT, 0);
dea31012005-04-17 16:05:31 -05001970 break;
1971 }
James Smart4258e982015-12-16 18:11:58 -05001972 return;
dea31012005-04-17 16:05:31 -05001973}
James Smart2e0fef82007-06-17 19:56:36 -05001974
James Smart76b2c342015-04-07 15:07:19 -04001975
James Smart4258e982015-12-16 18:11:58 -05001976/**
1977 * lpfc_fdmi_num_disc_check - Check how many mapped NPorts we are connected to
1978 * @vport: pointer to a host virtual N_Port data structure.
1979 *
1980 * Called from hbeat timeout routine to check if the number of discovered
1981 * ports has changed. If so, re-register thar port Attribute.
1982 */
1983void
1984lpfc_fdmi_num_disc_check(struct lpfc_vport *vport)
1985{
1986 struct lpfc_hba *phba = vport->phba;
1987 struct lpfc_nodelist *ndlp;
1988 uint16_t cnt;
1989
1990 if (!lpfc_is_link_up(phba))
1991 return;
1992
James Smarta03a4212016-07-06 12:36:12 -07001993 /* Must be connected to a Fabric */
1994 if (!(vport->fc_flag & FC_FABRIC))
1995 return;
1996
James Smart4258e982015-12-16 18:11:58 -05001997 if (!(vport->fdmi_port_mask & LPFC_FDMI_PORT_ATTR_num_disc))
1998 return;
1999
2000 cnt = lpfc_find_map_node(vport);
2001 if (cnt == vport->fdmi_num_disc)
2002 return;
2003
2004 ndlp = lpfc_findnode_did(vport, FDMI_DID);
2005 if (!ndlp || !NLP_CHK_NODE_ACT(ndlp))
2006 return;
2007
2008 if (vport->port_type == LPFC_PHYSICAL_PORT) {
2009 lpfc_fdmi_cmd(vport, ndlp, SLI_MGMT_RPA,
2010 LPFC_FDMI_PORT_ATTR_num_disc);
2011 } else {
2012 lpfc_fdmi_cmd(vport, ndlp, SLI_MGMT_RPRT,
2013 LPFC_FDMI_PORT_ATTR_num_disc);
2014 }
2015}
2016
2017/* Routines for all individual HBA attributes */
Baoyou Xiebd4b3e52016-09-25 13:44:55 +08002018static int
James Smart4258e982015-12-16 18:11:58 -05002019lpfc_fdmi_hba_attr_wwnn(struct lpfc_vport *vport, struct lpfc_fdmi_attr_def *ad)
2020{
2021 struct lpfc_fdmi_attr_entry *ae;
2022 uint32_t size;
2023
2024 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
2025 memset(ae, 0, sizeof(struct lpfc_name));
2026
2027 memcpy(&ae->un.AttrWWN, &vport->fc_sparam.nodeName,
2028 sizeof(struct lpfc_name));
2029 size = FOURBYTES + sizeof(struct lpfc_name);
2030 ad->AttrLen = cpu_to_be16(size);
2031 ad->AttrType = cpu_to_be16(RHBA_NODENAME);
2032 return size;
2033}
Baoyou Xiebd4b3e52016-09-25 13:44:55 +08002034static int
James Smart4258e982015-12-16 18:11:58 -05002035lpfc_fdmi_hba_attr_manufacturer(struct lpfc_vport *vport,
2036 struct lpfc_fdmi_attr_def *ad)
2037{
2038 struct lpfc_fdmi_attr_entry *ae;
2039 uint32_t len, size;
2040
2041 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
2042 memset(ae, 0, 256);
2043
James Smartd67f9352019-03-12 16:30:20 -07002044 /* This string MUST be consistent with other FC platforms
2045 * supported by Broadcom.
2046 */
James Smart4258e982015-12-16 18:11:58 -05002047 strncpy(ae->un.AttrString,
James Smartd67f9352019-03-12 16:30:20 -07002048 "Emulex Corporation",
James Smart4258e982015-12-16 18:11:58 -05002049 sizeof(ae->un.AttrString));
2050 len = strnlen(ae->un.AttrString,
2051 sizeof(ae->un.AttrString));
2052 len += (len & 3) ? (4 - (len & 3)) : 4;
2053 size = FOURBYTES + len;
2054 ad->AttrLen = cpu_to_be16(size);
2055 ad->AttrType = cpu_to_be16(RHBA_MANUFACTURER);
2056 return size;
2057}
2058
Baoyou Xiebd4b3e52016-09-25 13:44:55 +08002059static int
James Smart4258e982015-12-16 18:11:58 -05002060lpfc_fdmi_hba_attr_sn(struct lpfc_vport *vport, struct lpfc_fdmi_attr_def *ad)
2061{
2062 struct lpfc_hba *phba = vport->phba;
2063 struct lpfc_fdmi_attr_entry *ae;
2064 uint32_t len, size;
2065
2066 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
2067 memset(ae, 0, 256);
2068
2069 strncpy(ae->un.AttrString, phba->SerialNumber,
2070 sizeof(ae->un.AttrString));
2071 len = strnlen(ae->un.AttrString,
2072 sizeof(ae->un.AttrString));
2073 len += (len & 3) ? (4 - (len & 3)) : 4;
2074 size = FOURBYTES + len;
2075 ad->AttrLen = cpu_to_be16(size);
2076 ad->AttrType = cpu_to_be16(RHBA_SERIAL_NUMBER);
2077 return size;
2078}
2079
Baoyou Xiebd4b3e52016-09-25 13:44:55 +08002080static int
James Smart4258e982015-12-16 18:11:58 -05002081lpfc_fdmi_hba_attr_model(struct lpfc_vport *vport,
2082 struct lpfc_fdmi_attr_def *ad)
2083{
2084 struct lpfc_hba *phba = vport->phba;
2085 struct lpfc_fdmi_attr_entry *ae;
2086 uint32_t len, size;
2087
2088 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
2089 memset(ae, 0, 256);
2090
2091 strncpy(ae->un.AttrString, phba->ModelName,
2092 sizeof(ae->un.AttrString));
2093 len = strnlen(ae->un.AttrString, sizeof(ae->un.AttrString));
2094 len += (len & 3) ? (4 - (len & 3)) : 4;
2095 size = FOURBYTES + len;
2096 ad->AttrLen = cpu_to_be16(size);
2097 ad->AttrType = cpu_to_be16(RHBA_MODEL);
2098 return size;
2099}
2100
Baoyou Xiebd4b3e52016-09-25 13:44:55 +08002101static int
James Smart4258e982015-12-16 18:11:58 -05002102lpfc_fdmi_hba_attr_description(struct lpfc_vport *vport,
2103 struct lpfc_fdmi_attr_def *ad)
2104{
2105 struct lpfc_hba *phba = vport->phba;
2106 struct lpfc_fdmi_attr_entry *ae;
2107 uint32_t len, size;
2108
2109 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
2110 memset(ae, 0, 256);
2111
2112 strncpy(ae->un.AttrString, phba->ModelDesc,
2113 sizeof(ae->un.AttrString));
2114 len = strnlen(ae->un.AttrString,
2115 sizeof(ae->un.AttrString));
2116 len += (len & 3) ? (4 - (len & 3)) : 4;
2117 size = FOURBYTES + len;
2118 ad->AttrLen = cpu_to_be16(size);
2119 ad->AttrType = cpu_to_be16(RHBA_MODEL_DESCRIPTION);
2120 return size;
2121}
2122
Baoyou Xiebd4b3e52016-09-25 13:44:55 +08002123static int
James Smart4258e982015-12-16 18:11:58 -05002124lpfc_fdmi_hba_attr_hdw_ver(struct lpfc_vport *vport,
2125 struct lpfc_fdmi_attr_def *ad)
2126{
2127 struct lpfc_hba *phba = vport->phba;
2128 lpfc_vpd_t *vp = &phba->vpd;
2129 struct lpfc_fdmi_attr_entry *ae;
2130 uint32_t i, j, incr, size;
2131
2132 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
2133 memset(ae, 0, 256);
2134
2135 /* Convert JEDEC ID to ascii for hardware version */
2136 incr = vp->rev.biuRev;
2137 for (i = 0; i < 8; i++) {
2138 j = (incr & 0xf);
2139 if (j <= 9)
2140 ae->un.AttrString[7 - i] =
2141 (char)((uint8_t) 0x30 +
2142 (uint8_t) j);
2143 else
2144 ae->un.AttrString[7 - i] =
2145 (char)((uint8_t) 0x61 +
2146 (uint8_t) (j - 10));
2147 incr = (incr >> 4);
2148 }
2149 size = FOURBYTES + 8;
2150 ad->AttrLen = cpu_to_be16(size);
2151 ad->AttrType = cpu_to_be16(RHBA_HARDWARE_VERSION);
2152 return size;
2153}
2154
Baoyou Xiebd4b3e52016-09-25 13:44:55 +08002155static int
James Smart4258e982015-12-16 18:11:58 -05002156lpfc_fdmi_hba_attr_drvr_ver(struct lpfc_vport *vport,
2157 struct lpfc_fdmi_attr_def *ad)
2158{
2159 struct lpfc_fdmi_attr_entry *ae;
2160 uint32_t len, size;
2161
2162 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
2163 memset(ae, 0, 256);
2164
2165 strncpy(ae->un.AttrString, lpfc_release_version,
2166 sizeof(ae->un.AttrString));
2167 len = strnlen(ae->un.AttrString,
2168 sizeof(ae->un.AttrString));
2169 len += (len & 3) ? (4 - (len & 3)) : 4;
2170 size = FOURBYTES + len;
2171 ad->AttrLen = cpu_to_be16(size);
2172 ad->AttrType = cpu_to_be16(RHBA_DRIVER_VERSION);
2173 return size;
2174}
2175
Baoyou Xiebd4b3e52016-09-25 13:44:55 +08002176static int
James Smart4258e982015-12-16 18:11:58 -05002177lpfc_fdmi_hba_attr_rom_ver(struct lpfc_vport *vport,
2178 struct lpfc_fdmi_attr_def *ad)
2179{
2180 struct lpfc_hba *phba = vport->phba;
2181 struct lpfc_fdmi_attr_entry *ae;
2182 uint32_t len, size;
2183
2184 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
2185 memset(ae, 0, 256);
2186
2187 if (phba->sli_rev == LPFC_SLI_REV4)
2188 lpfc_decode_firmware_rev(phba, ae->un.AttrString, 1);
2189 else
2190 strncpy(ae->un.AttrString, phba->OptionROMVersion,
2191 sizeof(ae->un.AttrString));
2192 len = strnlen(ae->un.AttrString,
2193 sizeof(ae->un.AttrString));
2194 len += (len & 3) ? (4 - (len & 3)) : 4;
2195 size = FOURBYTES + len;
2196 ad->AttrLen = cpu_to_be16(size);
2197 ad->AttrType = cpu_to_be16(RHBA_OPTION_ROM_VERSION);
2198 return size;
2199}
2200
Baoyou Xiebd4b3e52016-09-25 13:44:55 +08002201static int
James Smart4258e982015-12-16 18:11:58 -05002202lpfc_fdmi_hba_attr_fmw_ver(struct lpfc_vport *vport,
2203 struct lpfc_fdmi_attr_def *ad)
2204{
2205 struct lpfc_hba *phba = vport->phba;
2206 struct lpfc_fdmi_attr_entry *ae;
2207 uint32_t len, size;
2208
2209 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
2210 memset(ae, 0, 256);
2211
2212 lpfc_decode_firmware_rev(phba, ae->un.AttrString, 1);
2213 len = strnlen(ae->un.AttrString,
2214 sizeof(ae->un.AttrString));
2215 len += (len & 3) ? (4 - (len & 3)) : 4;
2216 size = FOURBYTES + len;
2217 ad->AttrLen = cpu_to_be16(size);
2218 ad->AttrType = cpu_to_be16(RHBA_FIRMWARE_VERSION);
2219 return size;
2220}
2221
Baoyou Xiebd4b3e52016-09-25 13:44:55 +08002222static int
James Smart4258e982015-12-16 18:11:58 -05002223lpfc_fdmi_hba_attr_os_ver(struct lpfc_vport *vport,
2224 struct lpfc_fdmi_attr_def *ad)
2225{
2226 struct lpfc_fdmi_attr_entry *ae;
2227 uint32_t len, size;
2228
2229 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
2230 memset(ae, 0, 256);
2231
2232 snprintf(ae->un.AttrString, sizeof(ae->un.AttrString), "%s %s %s",
2233 init_utsname()->sysname,
2234 init_utsname()->release,
2235 init_utsname()->version);
2236
2237 len = strnlen(ae->un.AttrString, sizeof(ae->un.AttrString));
2238 len += (len & 3) ? (4 - (len & 3)) : 4;
2239 size = FOURBYTES + len;
2240 ad->AttrLen = cpu_to_be16(size);
2241 ad->AttrType = cpu_to_be16(RHBA_OS_NAME_VERSION);
2242 return size;
2243}
2244
Baoyou Xiebd4b3e52016-09-25 13:44:55 +08002245static int
James Smart4258e982015-12-16 18:11:58 -05002246lpfc_fdmi_hba_attr_ct_len(struct lpfc_vport *vport,
2247 struct lpfc_fdmi_attr_def *ad)
2248{
2249 struct lpfc_fdmi_attr_entry *ae;
2250 uint32_t size;
2251
2252 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
2253
2254 ae->un.AttrInt = cpu_to_be32(LPFC_MAX_CT_SIZE);
2255 size = FOURBYTES + sizeof(uint32_t);
2256 ad->AttrLen = cpu_to_be16(size);
2257 ad->AttrType = cpu_to_be16(RHBA_MAX_CT_PAYLOAD_LEN);
2258 return size;
2259}
2260
Baoyou Xiebd4b3e52016-09-25 13:44:55 +08002261static int
James Smart4258e982015-12-16 18:11:58 -05002262lpfc_fdmi_hba_attr_symbolic_name(struct lpfc_vport *vport,
2263 struct lpfc_fdmi_attr_def *ad)
2264{
2265 struct lpfc_fdmi_attr_entry *ae;
2266 uint32_t len, size;
2267
2268 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
2269 memset(ae, 0, 256);
2270
2271 len = lpfc_vport_symbolic_node_name(vport,
2272 ae->un.AttrString, 256);
2273 len += (len & 3) ? (4 - (len & 3)) : 4;
2274 size = FOURBYTES + len;
2275 ad->AttrLen = cpu_to_be16(size);
2276 ad->AttrType = cpu_to_be16(RHBA_SYM_NODENAME);
2277 return size;
2278}
2279
Baoyou Xiebd4b3e52016-09-25 13:44:55 +08002280static int
James Smart4258e982015-12-16 18:11:58 -05002281lpfc_fdmi_hba_attr_vendor_info(struct lpfc_vport *vport,
2282 struct lpfc_fdmi_attr_def *ad)
2283{
2284 struct lpfc_fdmi_attr_entry *ae;
2285 uint32_t size;
2286
2287 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
2288
2289 /* Nothing is defined for this currently */
2290 ae->un.AttrInt = cpu_to_be32(0);
2291 size = FOURBYTES + sizeof(uint32_t);
2292 ad->AttrLen = cpu_to_be16(size);
2293 ad->AttrType = cpu_to_be16(RHBA_VENDOR_INFO);
2294 return size;
2295}
2296
Baoyou Xiebd4b3e52016-09-25 13:44:55 +08002297static int
James Smart4258e982015-12-16 18:11:58 -05002298lpfc_fdmi_hba_attr_num_ports(struct lpfc_vport *vport,
2299 struct lpfc_fdmi_attr_def *ad)
2300{
2301 struct lpfc_fdmi_attr_entry *ae;
2302 uint32_t size;
2303
2304 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
2305
2306 /* Each driver instance corresponds to a single port */
2307 ae->un.AttrInt = cpu_to_be32(1);
2308 size = FOURBYTES + sizeof(uint32_t);
2309 ad->AttrLen = cpu_to_be16(size);
2310 ad->AttrType = cpu_to_be16(RHBA_NUM_PORTS);
2311 return size;
2312}
2313
Baoyou Xiebd4b3e52016-09-25 13:44:55 +08002314static int
James Smart4258e982015-12-16 18:11:58 -05002315lpfc_fdmi_hba_attr_fabric_wwnn(struct lpfc_vport *vport,
2316 struct lpfc_fdmi_attr_def *ad)
2317{
2318 struct lpfc_fdmi_attr_entry *ae;
2319 uint32_t size;
2320
2321 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
2322 memset(ae, 0, sizeof(struct lpfc_name));
2323
2324 memcpy(&ae->un.AttrWWN, &vport->fabric_nodename,
2325 sizeof(struct lpfc_name));
2326 size = FOURBYTES + sizeof(struct lpfc_name);
2327 ad->AttrLen = cpu_to_be16(size);
2328 ad->AttrType = cpu_to_be16(RHBA_FABRIC_WWNN);
2329 return size;
2330}
2331
Baoyou Xiebd4b3e52016-09-25 13:44:55 +08002332static int
James Smart4258e982015-12-16 18:11:58 -05002333lpfc_fdmi_hba_attr_bios_ver(struct lpfc_vport *vport,
2334 struct lpfc_fdmi_attr_def *ad)
2335{
2336 struct lpfc_hba *phba = vport->phba;
2337 struct lpfc_fdmi_attr_entry *ae;
2338 uint32_t len, size;
2339
2340 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
2341 memset(ae, 0, 256);
2342
James Smartb3b4f3e2019-03-12 16:30:23 -07002343 strlcat(ae->un.AttrString, phba->BIOSVersion,
2344 sizeof(ae->un.AttrString));
James Smart4258e982015-12-16 18:11:58 -05002345 len = strnlen(ae->un.AttrString,
2346 sizeof(ae->un.AttrString));
2347 len += (len & 3) ? (4 - (len & 3)) : 4;
2348 size = FOURBYTES + len;
2349 ad->AttrLen = cpu_to_be16(size);
2350 ad->AttrType = cpu_to_be16(RHBA_BIOS_VERSION);
2351 return size;
2352}
2353
Baoyou Xiebd4b3e52016-09-25 13:44:55 +08002354static int
James Smart4258e982015-12-16 18:11:58 -05002355lpfc_fdmi_hba_attr_bios_state(struct lpfc_vport *vport,
2356 struct lpfc_fdmi_attr_def *ad)
2357{
2358 struct lpfc_fdmi_attr_entry *ae;
2359 uint32_t size;
2360
2361 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
2362
2363 /* Driver doesn't have access to this information */
2364 ae->un.AttrInt = cpu_to_be32(0);
2365 size = FOURBYTES + sizeof(uint32_t);
2366 ad->AttrLen = cpu_to_be16(size);
2367 ad->AttrType = cpu_to_be16(RHBA_BIOS_STATE);
2368 return size;
2369}
2370
Baoyou Xiebd4b3e52016-09-25 13:44:55 +08002371static int
James Smart4258e982015-12-16 18:11:58 -05002372lpfc_fdmi_hba_attr_vendor_id(struct lpfc_vport *vport,
2373 struct lpfc_fdmi_attr_def *ad)
2374{
2375 struct lpfc_fdmi_attr_entry *ae;
2376 uint32_t len, size;
2377
2378 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
2379 memset(ae, 0, 256);
2380
2381 strncpy(ae->un.AttrString, "EMULEX",
2382 sizeof(ae->un.AttrString));
2383 len = strnlen(ae->un.AttrString,
2384 sizeof(ae->un.AttrString));
2385 len += (len & 3) ? (4 - (len & 3)) : 4;
2386 size = FOURBYTES + len;
2387 ad->AttrLen = cpu_to_be16(size);
2388 ad->AttrType = cpu_to_be16(RHBA_VENDOR_ID);
2389 return size;
2390}
2391
2392/* Routines for all individual PORT attributes */
Baoyou Xiebd4b3e52016-09-25 13:44:55 +08002393static int
James Smart4258e982015-12-16 18:11:58 -05002394lpfc_fdmi_port_attr_fc4type(struct lpfc_vport *vport,
2395 struct lpfc_fdmi_attr_def *ad)
2396{
James Smart93f647f2019-05-21 17:49:08 -07002397 struct lpfc_hba *phba = vport->phba;
James Smart4258e982015-12-16 18:11:58 -05002398 struct lpfc_fdmi_attr_entry *ae;
2399 uint32_t size;
2400
2401 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
2402 memset(ae, 0, 32);
2403
James Smart32a80c02019-03-12 16:30:21 -07002404 ae->un.AttrTypes[3] = 0x02; /* Type 0x1 - ELS */
2405 ae->un.AttrTypes[2] = 0x01; /* Type 0x8 - FCP */
James Smart32a80c02019-03-12 16:30:21 -07002406 ae->un.AttrTypes[7] = 0x01; /* Type 0x20 - CT */
James Smart93f647f2019-05-21 17:49:08 -07002407
2408 /* Check to see if Firmware supports NVME and on physical port */
2409 if ((phba->sli_rev == LPFC_SLI_REV4) && (vport == phba->pport) &&
2410 phba->sli4_hba.pc_sli4_params.nvme)
2411 ae->un.AttrTypes[6] = 0x01; /* Type 0x28 - NVME */
2412
James Smart4258e982015-12-16 18:11:58 -05002413 size = FOURBYTES + 32;
2414 ad->AttrLen = cpu_to_be16(size);
2415 ad->AttrType = cpu_to_be16(RPRT_SUPPORTED_FC4_TYPES);
2416 return size;
2417}
2418
Baoyou Xiebd4b3e52016-09-25 13:44:55 +08002419static int
James Smart4258e982015-12-16 18:11:58 -05002420lpfc_fdmi_port_attr_support_speed(struct lpfc_vport *vport,
2421 struct lpfc_fdmi_attr_def *ad)
2422{
2423 struct lpfc_hba *phba = vport->phba;
2424 struct lpfc_fdmi_attr_entry *ae;
2425 uint32_t size;
2426
2427 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
2428
2429 ae->un.AttrInt = 0;
James Smarta085e872015-12-16 18:12:02 -05002430 if (!(phba->hba_flag & HBA_FCOE_MODE)) {
James Smart1dc5ec22018-10-23 13:41:11 -07002431 if (phba->lmt & LMT_128Gb)
2432 ae->un.AttrInt |= HBA_PORTSPEED_128GFC;
James Smartfbd8a6b2018-02-22 08:18:45 -08002433 if (phba->lmt & LMT_64Gb)
2434 ae->un.AttrInt |= HBA_PORTSPEED_64GFC;
James Smarta085e872015-12-16 18:12:02 -05002435 if (phba->lmt & LMT_32Gb)
2436 ae->un.AttrInt |= HBA_PORTSPEED_32GFC;
2437 if (phba->lmt & LMT_16Gb)
2438 ae->un.AttrInt |= HBA_PORTSPEED_16GFC;
2439 if (phba->lmt & LMT_10Gb)
2440 ae->un.AttrInt |= HBA_PORTSPEED_10GFC;
2441 if (phba->lmt & LMT_8Gb)
2442 ae->un.AttrInt |= HBA_PORTSPEED_8GFC;
2443 if (phba->lmt & LMT_4Gb)
2444 ae->un.AttrInt |= HBA_PORTSPEED_4GFC;
2445 if (phba->lmt & LMT_2Gb)
2446 ae->un.AttrInt |= HBA_PORTSPEED_2GFC;
2447 if (phba->lmt & LMT_1Gb)
2448 ae->un.AttrInt |= HBA_PORTSPEED_1GFC;
2449 } else {
2450 /* FCoE links support only one speed */
2451 switch (phba->fc_linkspeed) {
2452 case LPFC_ASYNC_LINK_SPEED_10GBPS:
2453 ae->un.AttrInt = HBA_PORTSPEED_10GE;
2454 break;
2455 case LPFC_ASYNC_LINK_SPEED_25GBPS:
2456 ae->un.AttrInt = HBA_PORTSPEED_25GE;
2457 break;
2458 case LPFC_ASYNC_LINK_SPEED_40GBPS:
2459 ae->un.AttrInt = HBA_PORTSPEED_40GE;
2460 break;
2461 case LPFC_ASYNC_LINK_SPEED_100GBPS:
2462 ae->un.AttrInt = HBA_PORTSPEED_100GE;
2463 break;
2464 }
2465 }
James Smart4258e982015-12-16 18:11:58 -05002466 ae->un.AttrInt = cpu_to_be32(ae->un.AttrInt);
2467 size = FOURBYTES + sizeof(uint32_t);
2468 ad->AttrLen = cpu_to_be16(size);
2469 ad->AttrType = cpu_to_be16(RPRT_SUPPORTED_SPEED);
2470 return size;
2471}
2472
Baoyou Xiebd4b3e52016-09-25 13:44:55 +08002473static int
James Smart4258e982015-12-16 18:11:58 -05002474lpfc_fdmi_port_attr_speed(struct lpfc_vport *vport,
2475 struct lpfc_fdmi_attr_def *ad)
2476{
2477 struct lpfc_hba *phba = vport->phba;
2478 struct lpfc_fdmi_attr_entry *ae;
2479 uint32_t size;
2480
2481 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
2482
James Smarta085e872015-12-16 18:12:02 -05002483 if (!(phba->hba_flag & HBA_FCOE_MODE)) {
2484 switch (phba->fc_linkspeed) {
2485 case LPFC_LINK_SPEED_1GHZ:
2486 ae->un.AttrInt = HBA_PORTSPEED_1GFC;
2487 break;
2488 case LPFC_LINK_SPEED_2GHZ:
2489 ae->un.AttrInt = HBA_PORTSPEED_2GFC;
2490 break;
2491 case LPFC_LINK_SPEED_4GHZ:
2492 ae->un.AttrInt = HBA_PORTSPEED_4GFC;
2493 break;
2494 case LPFC_LINK_SPEED_8GHZ:
2495 ae->un.AttrInt = HBA_PORTSPEED_8GFC;
2496 break;
2497 case LPFC_LINK_SPEED_10GHZ:
2498 ae->un.AttrInt = HBA_PORTSPEED_10GFC;
2499 break;
2500 case LPFC_LINK_SPEED_16GHZ:
2501 ae->un.AttrInt = HBA_PORTSPEED_16GFC;
2502 break;
2503 case LPFC_LINK_SPEED_32GHZ:
2504 ae->un.AttrInt = HBA_PORTSPEED_32GFC;
2505 break;
James Smartfbd8a6b2018-02-22 08:18:45 -08002506 case LPFC_LINK_SPEED_64GHZ:
2507 ae->un.AttrInt = HBA_PORTSPEED_64GFC;
2508 break;
James Smart1dc5ec22018-10-23 13:41:11 -07002509 case LPFC_LINK_SPEED_128GHZ:
2510 ae->un.AttrInt = HBA_PORTSPEED_128GFC;
2511 break;
James Smarta085e872015-12-16 18:12:02 -05002512 default:
2513 ae->un.AttrInt = HBA_PORTSPEED_UNKNOWN;
2514 break;
2515 }
2516 } else {
2517 switch (phba->fc_linkspeed) {
2518 case LPFC_ASYNC_LINK_SPEED_10GBPS:
2519 ae->un.AttrInt = HBA_PORTSPEED_10GE;
2520 break;
2521 case LPFC_ASYNC_LINK_SPEED_25GBPS:
2522 ae->un.AttrInt = HBA_PORTSPEED_25GE;
2523 break;
2524 case LPFC_ASYNC_LINK_SPEED_40GBPS:
2525 ae->un.AttrInt = HBA_PORTSPEED_40GE;
2526 break;
2527 case LPFC_ASYNC_LINK_SPEED_100GBPS:
2528 ae->un.AttrInt = HBA_PORTSPEED_100GE;
2529 break;
2530 default:
2531 ae->un.AttrInt = HBA_PORTSPEED_UNKNOWN;
2532 break;
2533 }
James Smart4258e982015-12-16 18:11:58 -05002534 }
James Smarta085e872015-12-16 18:12:02 -05002535
James Smart4258e982015-12-16 18:11:58 -05002536 ae->un.AttrInt = cpu_to_be32(ae->un.AttrInt);
2537 size = FOURBYTES + sizeof(uint32_t);
2538 ad->AttrLen = cpu_to_be16(size);
2539 ad->AttrType = cpu_to_be16(RPRT_PORT_SPEED);
2540 return size;
2541}
2542
Baoyou Xiebd4b3e52016-09-25 13:44:55 +08002543static int
James Smart4258e982015-12-16 18:11:58 -05002544lpfc_fdmi_port_attr_max_frame(struct lpfc_vport *vport,
2545 struct lpfc_fdmi_attr_def *ad)
2546{
2547 struct serv_parm *hsp;
2548 struct lpfc_fdmi_attr_entry *ae;
2549 uint32_t size;
2550
2551 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
2552
2553 hsp = (struct serv_parm *)&vport->fc_sparam;
2554 ae->un.AttrInt = (((uint32_t) hsp->cmn.bbRcvSizeMsb) << 8) |
2555 (uint32_t) hsp->cmn.bbRcvSizeLsb;
2556 ae->un.AttrInt = cpu_to_be32(ae->un.AttrInt);
2557 size = FOURBYTES + sizeof(uint32_t);
2558 ad->AttrLen = cpu_to_be16(size);
2559 ad->AttrType = cpu_to_be16(RPRT_MAX_FRAME_SIZE);
2560 return size;
2561}
2562
Baoyou Xiebd4b3e52016-09-25 13:44:55 +08002563static int
James Smart4258e982015-12-16 18:11:58 -05002564lpfc_fdmi_port_attr_os_devname(struct lpfc_vport *vport,
2565 struct lpfc_fdmi_attr_def *ad)
2566{
2567 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
2568 struct lpfc_fdmi_attr_entry *ae;
2569 uint32_t len, size;
2570
2571 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
2572 memset(ae, 0, 256);
2573
2574 snprintf(ae->un.AttrString, sizeof(ae->un.AttrString),
2575 "/sys/class/scsi_host/host%d", shost->host_no);
2576 len = strnlen((char *)ae->un.AttrString,
2577 sizeof(ae->un.AttrString));
2578 len += (len & 3) ? (4 - (len & 3)) : 4;
2579 size = FOURBYTES + len;
2580 ad->AttrLen = cpu_to_be16(size);
2581 ad->AttrType = cpu_to_be16(RPRT_OS_DEVICE_NAME);
2582 return size;
2583}
2584
Baoyou Xiebd4b3e52016-09-25 13:44:55 +08002585static int
James Smart4258e982015-12-16 18:11:58 -05002586lpfc_fdmi_port_attr_host_name(struct lpfc_vport *vport,
2587 struct lpfc_fdmi_attr_def *ad)
2588{
2589 struct lpfc_fdmi_attr_entry *ae;
2590 uint32_t len, size;
2591
2592 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
2593 memset(ae, 0, 256);
2594
2595 snprintf(ae->un.AttrString, sizeof(ae->un.AttrString), "%s",
2596 init_utsname()->nodename);
2597
2598 len = strnlen(ae->un.AttrString, sizeof(ae->un.AttrString));
2599 len += (len & 3) ? (4 - (len & 3)) : 4;
2600 size = FOURBYTES + len;
2601 ad->AttrLen = cpu_to_be16(size);
2602 ad->AttrType = cpu_to_be16(RPRT_HOST_NAME);
2603 return size;
2604}
2605
Baoyou Xiebd4b3e52016-09-25 13:44:55 +08002606static int
James Smart4258e982015-12-16 18:11:58 -05002607lpfc_fdmi_port_attr_wwnn(struct lpfc_vport *vport,
2608 struct lpfc_fdmi_attr_def *ad)
2609{
2610 struct lpfc_fdmi_attr_entry *ae;
2611 uint32_t size;
2612
2613 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
2614 memset(ae, 0, sizeof(struct lpfc_name));
2615
2616 memcpy(&ae->un.AttrWWN, &vport->fc_sparam.nodeName,
2617 sizeof(struct lpfc_name));
2618 size = FOURBYTES + sizeof(struct lpfc_name);
2619 ad->AttrLen = cpu_to_be16(size);
2620 ad->AttrType = cpu_to_be16(RPRT_NODENAME);
2621 return size;
2622}
2623
Baoyou Xiebd4b3e52016-09-25 13:44:55 +08002624static int
James Smart4258e982015-12-16 18:11:58 -05002625lpfc_fdmi_port_attr_wwpn(struct lpfc_vport *vport,
2626 struct lpfc_fdmi_attr_def *ad)
2627{
2628 struct lpfc_fdmi_attr_entry *ae;
2629 uint32_t size;
2630
2631 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
2632 memset(ae, 0, sizeof(struct lpfc_name));
2633
2634 memcpy(&ae->un.AttrWWN, &vport->fc_sparam.portName,
2635 sizeof(struct lpfc_name));
2636 size = FOURBYTES + sizeof(struct lpfc_name);
2637 ad->AttrLen = cpu_to_be16(size);
2638 ad->AttrType = cpu_to_be16(RPRT_PORTNAME);
2639 return size;
2640}
2641
Baoyou Xiebd4b3e52016-09-25 13:44:55 +08002642static int
James Smart4258e982015-12-16 18:11:58 -05002643lpfc_fdmi_port_attr_symbolic_name(struct lpfc_vport *vport,
2644 struct lpfc_fdmi_attr_def *ad)
2645{
2646 struct lpfc_fdmi_attr_entry *ae;
2647 uint32_t len, size;
2648
2649 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
2650 memset(ae, 0, 256);
2651
2652 len = lpfc_vport_symbolic_port_name(vport, ae->un.AttrString, 256);
2653 len += (len & 3) ? (4 - (len & 3)) : 4;
2654 size = FOURBYTES + len;
2655 ad->AttrLen = cpu_to_be16(size);
2656 ad->AttrType = cpu_to_be16(RPRT_SYM_PORTNAME);
2657 return size;
2658}
2659
Baoyou Xiebd4b3e52016-09-25 13:44:55 +08002660static int
James Smart4258e982015-12-16 18:11:58 -05002661lpfc_fdmi_port_attr_port_type(struct lpfc_vport *vport,
2662 struct lpfc_fdmi_attr_def *ad)
2663{
2664 struct lpfc_hba *phba = vport->phba;
2665 struct lpfc_fdmi_attr_entry *ae;
2666 uint32_t size;
2667
2668 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
2669 if (phba->fc_topology == LPFC_TOPOLOGY_LOOP)
2670 ae->un.AttrInt = cpu_to_be32(LPFC_FDMI_PORTTYPE_NLPORT);
2671 else
2672 ae->un.AttrInt = cpu_to_be32(LPFC_FDMI_PORTTYPE_NPORT);
2673 size = FOURBYTES + sizeof(uint32_t);
2674 ad->AttrLen = cpu_to_be16(size);
2675 ad->AttrType = cpu_to_be16(RPRT_PORT_TYPE);
2676 return size;
2677}
2678
Baoyou Xiebd4b3e52016-09-25 13:44:55 +08002679static int
James Smart4258e982015-12-16 18:11:58 -05002680lpfc_fdmi_port_attr_class(struct lpfc_vport *vport,
2681 struct lpfc_fdmi_attr_def *ad)
2682{
2683 struct lpfc_fdmi_attr_entry *ae;
2684 uint32_t size;
2685
2686 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
2687 ae->un.AttrInt = cpu_to_be32(FC_COS_CLASS2 | FC_COS_CLASS3);
2688 size = FOURBYTES + sizeof(uint32_t);
2689 ad->AttrLen = cpu_to_be16(size);
2690 ad->AttrType = cpu_to_be16(RPRT_SUPPORTED_CLASS);
2691 return size;
2692}
2693
Baoyou Xiebd4b3e52016-09-25 13:44:55 +08002694static int
James Smart4258e982015-12-16 18:11:58 -05002695lpfc_fdmi_port_attr_fabric_wwpn(struct lpfc_vport *vport,
2696 struct lpfc_fdmi_attr_def *ad)
2697{
2698 struct lpfc_fdmi_attr_entry *ae;
2699 uint32_t size;
2700
2701 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
2702 memset(ae, 0, sizeof(struct lpfc_name));
2703
2704 memcpy(&ae->un.AttrWWN, &vport->fabric_portname,
2705 sizeof(struct lpfc_name));
2706 size = FOURBYTES + sizeof(struct lpfc_name);
2707 ad->AttrLen = cpu_to_be16(size);
2708 ad->AttrType = cpu_to_be16(RPRT_FABRICNAME);
2709 return size;
2710}
2711
Baoyou Xiebd4b3e52016-09-25 13:44:55 +08002712static int
James Smart4258e982015-12-16 18:11:58 -05002713lpfc_fdmi_port_attr_active_fc4type(struct lpfc_vport *vport,
2714 struct lpfc_fdmi_attr_def *ad)
2715{
2716 struct lpfc_fdmi_attr_entry *ae;
2717 uint32_t size;
2718
2719 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
2720 memset(ae, 0, 32);
2721
James Smart32a80c02019-03-12 16:30:21 -07002722 ae->un.AttrTypes[3] = 0x02; /* Type 0x1 - ELS */
2723 ae->un.AttrTypes[2] = 0x01; /* Type 0x8 - FCP */
James Smart93f647f2019-05-21 17:49:08 -07002724 ae->un.AttrTypes[7] = 0x01; /* Type 0x20 - CT */
2725
2726 /* Check to see if NVME is configured or not */
James Smart32a80c02019-03-12 16:30:21 -07002727 if (vport->phba->cfg_enable_fc4_type & LPFC_ENABLE_NVME)
2728 ae->un.AttrTypes[6] = 0x1; /* Type 0x28 - NVME */
James Smart93f647f2019-05-21 17:49:08 -07002729
James Smart4258e982015-12-16 18:11:58 -05002730 size = FOURBYTES + 32;
2731 ad->AttrLen = cpu_to_be16(size);
2732 ad->AttrType = cpu_to_be16(RPRT_ACTIVE_FC4_TYPES);
2733 return size;
2734}
2735
Baoyou Xiebd4b3e52016-09-25 13:44:55 +08002736static int
James Smart4258e982015-12-16 18:11:58 -05002737lpfc_fdmi_port_attr_port_state(struct lpfc_vport *vport,
2738 struct lpfc_fdmi_attr_def *ad)
2739{
2740 struct lpfc_fdmi_attr_entry *ae;
2741 uint32_t size;
2742
2743 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
2744 /* Link Up - operational */
2745 ae->un.AttrInt = cpu_to_be32(LPFC_FDMI_PORTSTATE_ONLINE);
2746 size = FOURBYTES + sizeof(uint32_t);
2747 ad->AttrLen = cpu_to_be16(size);
2748 ad->AttrType = cpu_to_be16(RPRT_PORT_STATE);
2749 return size;
2750}
2751
Baoyou Xiebd4b3e52016-09-25 13:44:55 +08002752static int
James Smart4258e982015-12-16 18:11:58 -05002753lpfc_fdmi_port_attr_num_disc(struct lpfc_vport *vport,
2754 struct lpfc_fdmi_attr_def *ad)
2755{
2756 struct lpfc_fdmi_attr_entry *ae;
2757 uint32_t size;
2758
2759 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
2760 vport->fdmi_num_disc = lpfc_find_map_node(vport);
2761 ae->un.AttrInt = cpu_to_be32(vport->fdmi_num_disc);
2762 size = FOURBYTES + sizeof(uint32_t);
2763 ad->AttrLen = cpu_to_be16(size);
2764 ad->AttrType = cpu_to_be16(RPRT_DISC_PORT);
2765 return size;
2766}
2767
Baoyou Xiebd4b3e52016-09-25 13:44:55 +08002768static int
James Smart4258e982015-12-16 18:11:58 -05002769lpfc_fdmi_port_attr_nportid(struct lpfc_vport *vport,
2770 struct lpfc_fdmi_attr_def *ad)
2771{
2772 struct lpfc_fdmi_attr_entry *ae;
2773 uint32_t size;
2774
2775 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
2776 ae->un.AttrInt = cpu_to_be32(vport->fc_myDID);
2777 size = FOURBYTES + sizeof(uint32_t);
2778 ad->AttrLen = cpu_to_be16(size);
2779 ad->AttrType = cpu_to_be16(RPRT_PORT_ID);
2780 return size;
2781}
2782
Baoyou Xiebd4b3e52016-09-25 13:44:55 +08002783static int
James Smart4258e982015-12-16 18:11:58 -05002784lpfc_fdmi_smart_attr_service(struct lpfc_vport *vport,
2785 struct lpfc_fdmi_attr_def *ad)
2786{
2787 struct lpfc_fdmi_attr_entry *ae;
2788 uint32_t len, size;
2789
2790 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
2791 memset(ae, 0, 256);
2792
2793 strncpy(ae->un.AttrString, "Smart SAN Initiator",
2794 sizeof(ae->un.AttrString));
2795 len = strnlen(ae->un.AttrString,
2796 sizeof(ae->un.AttrString));
2797 len += (len & 3) ? (4 - (len & 3)) : 4;
2798 size = FOURBYTES + len;
2799 ad->AttrLen = cpu_to_be16(size);
2800 ad->AttrType = cpu_to_be16(RPRT_SMART_SERVICE);
2801 return size;
2802}
2803
Baoyou Xiebd4b3e52016-09-25 13:44:55 +08002804static int
James Smart4258e982015-12-16 18:11:58 -05002805lpfc_fdmi_smart_attr_guid(struct lpfc_vport *vport,
2806 struct lpfc_fdmi_attr_def *ad)
2807{
2808 struct lpfc_fdmi_attr_entry *ae;
2809 uint32_t size;
2810
2811 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
2812 memset(ae, 0, 256);
2813
2814 memcpy(&ae->un.AttrString, &vport->fc_sparam.nodeName,
2815 sizeof(struct lpfc_name));
2816 memcpy((((uint8_t *)&ae->un.AttrString) +
2817 sizeof(struct lpfc_name)),
2818 &vport->fc_sparam.portName, sizeof(struct lpfc_name));
2819 size = FOURBYTES + (2 * sizeof(struct lpfc_name));
2820 ad->AttrLen = cpu_to_be16(size);
2821 ad->AttrType = cpu_to_be16(RPRT_SMART_GUID);
2822 return size;
2823}
2824
Baoyou Xiebd4b3e52016-09-25 13:44:55 +08002825static int
James Smart4258e982015-12-16 18:11:58 -05002826lpfc_fdmi_smart_attr_version(struct lpfc_vport *vport,
2827 struct lpfc_fdmi_attr_def *ad)
2828{
2829 struct lpfc_fdmi_attr_entry *ae;
2830 uint32_t len, size;
2831
2832 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
2833 memset(ae, 0, 256);
2834
James Smart56204982016-03-31 14:12:32 -07002835 strncpy(ae->un.AttrString, "Smart SAN Version 2.0",
James Smart4258e982015-12-16 18:11:58 -05002836 sizeof(ae->un.AttrString));
2837 len = strnlen(ae->un.AttrString,
2838 sizeof(ae->un.AttrString));
2839 len += (len & 3) ? (4 - (len & 3)) : 4;
2840 size = FOURBYTES + len;
2841 ad->AttrLen = cpu_to_be16(size);
2842 ad->AttrType = cpu_to_be16(RPRT_SMART_VERSION);
2843 return size;
2844}
2845
Baoyou Xiebd4b3e52016-09-25 13:44:55 +08002846static int
James Smart4258e982015-12-16 18:11:58 -05002847lpfc_fdmi_smart_attr_model(struct lpfc_vport *vport,
2848 struct lpfc_fdmi_attr_def *ad)
2849{
2850 struct lpfc_hba *phba = vport->phba;
2851 struct lpfc_fdmi_attr_entry *ae;
2852 uint32_t len, size;
2853
2854 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
2855 memset(ae, 0, 256);
2856
2857 strncpy(ae->un.AttrString, phba->ModelName,
2858 sizeof(ae->un.AttrString));
2859 len = strnlen(ae->un.AttrString, sizeof(ae->un.AttrString));
2860 len += (len & 3) ? (4 - (len & 3)) : 4;
2861 size = FOURBYTES + len;
2862 ad->AttrLen = cpu_to_be16(size);
2863 ad->AttrType = cpu_to_be16(RPRT_SMART_MODEL);
2864 return size;
2865}
2866
Baoyou Xiebd4b3e52016-09-25 13:44:55 +08002867static int
James Smart4258e982015-12-16 18:11:58 -05002868lpfc_fdmi_smart_attr_port_info(struct lpfc_vport *vport,
2869 struct lpfc_fdmi_attr_def *ad)
2870{
2871 struct lpfc_fdmi_attr_entry *ae;
2872 uint32_t size;
2873
2874 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
2875
2876 /* SRIOV (type 3) is not supported */
2877 if (vport->vpi)
2878 ae->un.AttrInt = cpu_to_be32(2); /* NPIV */
2879 else
2880 ae->un.AttrInt = cpu_to_be32(1); /* Physical */
2881 size = FOURBYTES + sizeof(uint32_t);
2882 ad->AttrLen = cpu_to_be16(size);
2883 ad->AttrType = cpu_to_be16(RPRT_SMART_PORT_INFO);
2884 return size;
2885}
2886
Baoyou Xiebd4b3e52016-09-25 13:44:55 +08002887static int
James Smart4258e982015-12-16 18:11:58 -05002888lpfc_fdmi_smart_attr_qos(struct lpfc_vport *vport,
2889 struct lpfc_fdmi_attr_def *ad)
2890{
2891 struct lpfc_fdmi_attr_entry *ae;
2892 uint32_t size;
2893
2894 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
2895 ae->un.AttrInt = cpu_to_be32(0);
2896 size = FOURBYTES + sizeof(uint32_t);
2897 ad->AttrLen = cpu_to_be16(size);
2898 ad->AttrType = cpu_to_be16(RPRT_SMART_QOS);
2899 return size;
2900}
2901
Baoyou Xiebd4b3e52016-09-25 13:44:55 +08002902static int
James Smart4258e982015-12-16 18:11:58 -05002903lpfc_fdmi_smart_attr_security(struct lpfc_vport *vport,
2904 struct lpfc_fdmi_attr_def *ad)
2905{
2906 struct lpfc_fdmi_attr_entry *ae;
2907 uint32_t size;
2908
2909 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
James Smart56204982016-03-31 14:12:32 -07002910 ae->un.AttrInt = cpu_to_be32(1);
James Smart4258e982015-12-16 18:11:58 -05002911 size = FOURBYTES + sizeof(uint32_t);
2912 ad->AttrLen = cpu_to_be16(size);
2913 ad->AttrType = cpu_to_be16(RPRT_SMART_SECURITY);
2914 return size;
2915}
2916
2917/* RHBA attribute jump table */
2918int (*lpfc_fdmi_hba_action[])
2919 (struct lpfc_vport *vport, struct lpfc_fdmi_attr_def *ad) = {
2920 /* Action routine Mask bit Attribute type */
2921 lpfc_fdmi_hba_attr_wwnn, /* bit0 RHBA_NODENAME */
2922 lpfc_fdmi_hba_attr_manufacturer, /* bit1 RHBA_MANUFACTURER */
2923 lpfc_fdmi_hba_attr_sn, /* bit2 RHBA_SERIAL_NUMBER */
2924 lpfc_fdmi_hba_attr_model, /* bit3 RHBA_MODEL */
2925 lpfc_fdmi_hba_attr_description, /* bit4 RHBA_MODEL_DESCRIPTION */
2926 lpfc_fdmi_hba_attr_hdw_ver, /* bit5 RHBA_HARDWARE_VERSION */
2927 lpfc_fdmi_hba_attr_drvr_ver, /* bit6 RHBA_DRIVER_VERSION */
2928 lpfc_fdmi_hba_attr_rom_ver, /* bit7 RHBA_OPTION_ROM_VERSION */
2929 lpfc_fdmi_hba_attr_fmw_ver, /* bit8 RHBA_FIRMWARE_VERSION */
2930 lpfc_fdmi_hba_attr_os_ver, /* bit9 RHBA_OS_NAME_VERSION */
2931 lpfc_fdmi_hba_attr_ct_len, /* bit10 RHBA_MAX_CT_PAYLOAD_LEN */
2932 lpfc_fdmi_hba_attr_symbolic_name, /* bit11 RHBA_SYM_NODENAME */
2933 lpfc_fdmi_hba_attr_vendor_info, /* bit12 RHBA_VENDOR_INFO */
2934 lpfc_fdmi_hba_attr_num_ports, /* bit13 RHBA_NUM_PORTS */
2935 lpfc_fdmi_hba_attr_fabric_wwnn, /* bit14 RHBA_FABRIC_WWNN */
2936 lpfc_fdmi_hba_attr_bios_ver, /* bit15 RHBA_BIOS_VERSION */
2937 lpfc_fdmi_hba_attr_bios_state, /* bit16 RHBA_BIOS_STATE */
2938 lpfc_fdmi_hba_attr_vendor_id, /* bit17 RHBA_VENDOR_ID */
2939};
2940
2941/* RPA / RPRT attribute jump table */
2942int (*lpfc_fdmi_port_action[])
2943 (struct lpfc_vport *vport, struct lpfc_fdmi_attr_def *ad) = {
2944 /* Action routine Mask bit Attribute type */
2945 lpfc_fdmi_port_attr_fc4type, /* bit0 RPRT_SUPPORT_FC4_TYPES */
2946 lpfc_fdmi_port_attr_support_speed, /* bit1 RPRT_SUPPORTED_SPEED */
2947 lpfc_fdmi_port_attr_speed, /* bit2 RPRT_PORT_SPEED */
2948 lpfc_fdmi_port_attr_max_frame, /* bit3 RPRT_MAX_FRAME_SIZE */
2949 lpfc_fdmi_port_attr_os_devname, /* bit4 RPRT_OS_DEVICE_NAME */
2950 lpfc_fdmi_port_attr_host_name, /* bit5 RPRT_HOST_NAME */
2951 lpfc_fdmi_port_attr_wwnn, /* bit6 RPRT_NODENAME */
2952 lpfc_fdmi_port_attr_wwpn, /* bit7 RPRT_PORTNAME */
2953 lpfc_fdmi_port_attr_symbolic_name, /* bit8 RPRT_SYM_PORTNAME */
2954 lpfc_fdmi_port_attr_port_type, /* bit9 RPRT_PORT_TYPE */
2955 lpfc_fdmi_port_attr_class, /* bit10 RPRT_SUPPORTED_CLASS */
2956 lpfc_fdmi_port_attr_fabric_wwpn, /* bit11 RPRT_FABRICNAME */
2957 lpfc_fdmi_port_attr_active_fc4type, /* bit12 RPRT_ACTIVE_FC4_TYPES */
2958 lpfc_fdmi_port_attr_port_state, /* bit13 RPRT_PORT_STATE */
2959 lpfc_fdmi_port_attr_num_disc, /* bit14 RPRT_DISC_PORT */
2960 lpfc_fdmi_port_attr_nportid, /* bit15 RPRT_PORT_ID */
2961 lpfc_fdmi_smart_attr_service, /* bit16 RPRT_SMART_SERVICE */
2962 lpfc_fdmi_smart_attr_guid, /* bit17 RPRT_SMART_GUID */
2963 lpfc_fdmi_smart_attr_version, /* bit18 RPRT_SMART_VERSION */
2964 lpfc_fdmi_smart_attr_model, /* bit19 RPRT_SMART_MODEL */
2965 lpfc_fdmi_smart_attr_port_info, /* bit20 RPRT_SMART_PORT_INFO */
2966 lpfc_fdmi_smart_attr_qos, /* bit21 RPRT_SMART_QOS */
2967 lpfc_fdmi_smart_attr_security, /* bit22 RPRT_SMART_SECURITY */
2968};
2969
2970/**
2971 * lpfc_fdmi_cmd - Build and send a FDMI cmd to the specified NPort
2972 * @vport: pointer to a host virtual N_Port data structure.
2973 * @ndlp: ndlp to send FDMI cmd to (if NULL use FDMI_DID)
2974 * cmdcode: FDMI command to send
2975 * mask: Mask of HBA or PORT Attributes to send
2976 *
2977 * Builds and sends a FDMI command using the CT subsystem.
2978 */
2979int
2980lpfc_fdmi_cmd(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
2981 int cmdcode, uint32_t new_mask)
dea31012005-04-17 16:05:31 -05002982{
James Smart2e0fef82007-06-17 19:56:36 -05002983 struct lpfc_hba *phba = vport->phba;
dea31012005-04-17 16:05:31 -05002984 struct lpfc_dmabuf *mp, *bmp;
2985 struct lpfc_sli_ct_request *CtReq;
2986 struct ulp_bde64 *bpl;
James Smart4258e982015-12-16 18:11:58 -05002987 uint32_t bit_pos;
dea31012005-04-17 16:05:31 -05002988 uint32_t size;
James Smart76b2c342015-04-07 15:07:19 -04002989 uint32_t rsp_size;
James Smart4258e982015-12-16 18:11:58 -05002990 uint32_t mask;
James Smart76b2c342015-04-07 15:07:19 -04002991 struct lpfc_fdmi_reg_hba *rh;
2992 struct lpfc_fdmi_port_entry *pe;
2993 struct lpfc_fdmi_reg_portattr *pab = NULL;
2994 struct lpfc_fdmi_attr_block *ab = NULL;
James Smart4258e982015-12-16 18:11:58 -05002995 int (*func)(struct lpfc_vport *vport, struct lpfc_fdmi_attr_def *ad);
2996 void (*cmpl)(struct lpfc_hba *, struct lpfc_iocbq *,
2997 struct lpfc_iocbq *);
dea31012005-04-17 16:05:31 -05002998
James Smart4258e982015-12-16 18:11:58 -05002999 if (!ndlp || !NLP_CHK_NODE_ACT(ndlp))
3000 return 0;
3001
3002 cmpl = lpfc_cmpl_ct_disc_fdmi; /* called from discovery */
dea31012005-04-17 16:05:31 -05003003
3004 /* fill in BDEs for command */
3005 /* Allocate buffer for command payload */
James Smart76b2c342015-04-07 15:07:19 -04003006 mp = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL);
dea31012005-04-17 16:05:31 -05003007 if (!mp)
3008 goto fdmi_cmd_exit;
3009
3010 mp->virt = lpfc_mbuf_alloc(phba, 0, &(mp->phys));
3011 if (!mp->virt)
3012 goto fdmi_cmd_free_mp;
3013
3014 /* Allocate buffer for Buffer ptr list */
James Smart76b2c342015-04-07 15:07:19 -04003015 bmp = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL);
dea31012005-04-17 16:05:31 -05003016 if (!bmp)
3017 goto fdmi_cmd_free_mpvirt;
3018
3019 bmp->virt = lpfc_mbuf_alloc(phba, 0, &(bmp->phys));
3020 if (!bmp->virt)
3021 goto fdmi_cmd_free_bmp;
3022
3023 INIT_LIST_HEAD(&mp->list);
3024 INIT_LIST_HEAD(&bmp->list);
3025
3026 /* FDMI request */
James Smarte8b62012007-08-02 11:10:09 -04003027 lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
3028 "0218 FDMI Request Data: x%x x%x x%x\n",
3029 vport->fc_flag, vport->port_state, cmdcode);
James Smart76b2c342015-04-07 15:07:19 -04003030 CtReq = (struct lpfc_sli_ct_request *)mp->virt;
dea31012005-04-17 16:05:31 -05003031
James Smart76b2c342015-04-07 15:07:19 -04003032 /* First populate the CT_IU preamble */
dea31012005-04-17 16:05:31 -05003033 memset(CtReq, 0, sizeof(struct lpfc_sli_ct_request));
3034 CtReq->RevisionId.bits.Revision = SLI_CT_REVISION;
3035 CtReq->RevisionId.bits.InId = 0;
3036
3037 CtReq->FsType = SLI_CT_MANAGEMENT_SERVICE;
3038 CtReq->FsSubType = SLI_CT_FDMI_Subtypes;
James Smart76b2c342015-04-07 15:07:19 -04003039
3040 CtReq->CommandResponse.bits.CmdRsp = cpu_to_be16(cmdcode);
3041 rsp_size = LPFC_BPL_SIZE;
dea31012005-04-17 16:05:31 -05003042 size = 0;
3043
James Smart76b2c342015-04-07 15:07:19 -04003044 /* Next fill in the specific FDMI cmd information */
dea31012005-04-17 16:05:31 -05003045 switch (cmdcode) {
James Smart76b2c342015-04-07 15:07:19 -04003046 case SLI_MGMT_RHAT:
dea31012005-04-17 16:05:31 -05003047 case SLI_MGMT_RHBA:
James Smart4258e982015-12-16 18:11:58 -05003048 rh = (struct lpfc_fdmi_reg_hba *)&CtReq->un.PortID;
3049 /* HBA Identifier */
3050 memcpy(&rh->hi.PortName, &phba->pport->fc_sparam.portName,
3051 sizeof(struct lpfc_name));
dea31012005-04-17 16:05:31 -05003052
James Smart4258e982015-12-16 18:11:58 -05003053 if (cmdcode == SLI_MGMT_RHBA) {
3054 /* Registered Port List */
3055 /* One entry (port) per adapter */
3056 rh->rpl.EntryCnt = cpu_to_be32(1);
3057 memcpy(&rh->rpl.pe, &phba->pport->fc_sparam.portName,
James Smart76b2c342015-04-07 15:07:19 -04003058 sizeof(struct lpfc_name));
dea31012005-04-17 16:05:31 -05003059
James Smart4258e982015-12-16 18:11:58 -05003060 /* point to the HBA attribute block */
3061 size = 2 * sizeof(struct lpfc_name) +
3062 FOURBYTES;
3063 } else {
3064 size = sizeof(struct lpfc_name);
dea31012005-04-17 16:05:31 -05003065 }
James Smart4258e982015-12-16 18:11:58 -05003066 ab = (struct lpfc_fdmi_attr_block *)((uint8_t *)rh + size);
3067 ab->EntryCnt = 0;
3068 size += FOURBYTES;
3069 bit_pos = 0;
3070 if (new_mask)
3071 mask = new_mask;
3072 else
3073 mask = vport->fdmi_hba_mask;
3074
3075 /* Mask will dictate what attributes to build in the request */
3076 while (mask) {
3077 if (mask & 0x1) {
3078 func = lpfc_fdmi_hba_action[bit_pos];
3079 size += func(vport,
3080 (struct lpfc_fdmi_attr_def *)
3081 ((uint8_t *)rh + size));
3082 ab->EntryCnt++;
3083 if ((size + 256) >
3084 (LPFC_BPL_SIZE - LPFC_CT_PREAMBLE))
3085 goto hba_out;
3086 }
3087 mask = mask >> 1;
3088 bit_pos++;
3089 }
3090hba_out:
3091 ab->EntryCnt = cpu_to_be32(ab->EntryCnt);
3092 /* Total size */
3093 size = GID_REQUEST_SZ - 4 + size;
dea31012005-04-17 16:05:31 -05003094 break;
3095
James Smart76b2c342015-04-07 15:07:19 -04003096 case SLI_MGMT_RPRT:
dea31012005-04-17 16:05:31 -05003097 case SLI_MGMT_RPA:
James Smart4258e982015-12-16 18:11:58 -05003098 pab = (struct lpfc_fdmi_reg_portattr *)&CtReq->un.PortID;
3099 if (cmdcode == SLI_MGMT_RPRT) {
3100 rh = (struct lpfc_fdmi_reg_hba *)pab;
3101 /* HBA Identifier */
3102 memcpy(&rh->hi.PortName,
3103 &phba->pport->fc_sparam.portName,
James Smart76b2c342015-04-07 15:07:19 -04003104 sizeof(struct lpfc_name));
James Smart4258e982015-12-16 18:11:58 -05003105 pab = (struct lpfc_fdmi_reg_portattr *)
3106 ((uint8_t *)pab + sizeof(struct lpfc_name));
dea31012005-04-17 16:05:31 -05003107 }
James Smart4258e982015-12-16 18:11:58 -05003108
3109 memcpy((uint8_t *)&pab->PortName,
3110 (uint8_t *)&vport->fc_sparam.portName,
3111 sizeof(struct lpfc_name));
3112 size += sizeof(struct lpfc_name) + FOURBYTES;
3113 pab->ab.EntryCnt = 0;
3114 bit_pos = 0;
3115 if (new_mask)
3116 mask = new_mask;
3117 else
3118 mask = vport->fdmi_port_mask;
3119
3120 /* Mask will dictate what attributes to build in the request */
3121 while (mask) {
3122 if (mask & 0x1) {
3123 func = lpfc_fdmi_port_action[bit_pos];
3124 size += func(vport,
3125 (struct lpfc_fdmi_attr_def *)
3126 ((uint8_t *)pab + size));
3127 pab->ab.EntryCnt++;
3128 if ((size + 256) >
3129 (LPFC_BPL_SIZE - LPFC_CT_PREAMBLE))
3130 goto port_out;
3131 }
3132 mask = mask >> 1;
3133 bit_pos++;
3134 }
3135port_out:
3136 pab->ab.EntryCnt = cpu_to_be32(pab->ab.EntryCnt);
3137 /* Total size */
3138 if (cmdcode == SLI_MGMT_RPRT)
3139 size += sizeof(struct lpfc_name);
3140 size = GID_REQUEST_SZ - 4 + size;
dea31012005-04-17 16:05:31 -05003141 break;
3142
James Smart76b2c342015-04-07 15:07:19 -04003143 case SLI_MGMT_GHAT:
3144 case SLI_MGMT_GRPL:
3145 rsp_size = FC_MAX_NS_RSP;
Bart Van Asschecd05c152019-03-28 11:06:18 -07003146 /* fall through */
dea31012005-04-17 16:05:31 -05003147 case SLI_MGMT_DHBA:
James Smart76b2c342015-04-07 15:07:19 -04003148 case SLI_MGMT_DHAT:
3149 pe = (struct lpfc_fdmi_port_entry *)&CtReq->un.PortID;
3150 memcpy((uint8_t *)&pe->PortName,
3151 (uint8_t *)&vport->fc_sparam.portName,
3152 sizeof(struct lpfc_name));
3153 size = GID_REQUEST_SZ - 4 + sizeof(struct lpfc_name);
dea31012005-04-17 16:05:31 -05003154 break;
3155
James Smart76b2c342015-04-07 15:07:19 -04003156 case SLI_MGMT_GPAT:
3157 case SLI_MGMT_GPAS:
3158 rsp_size = FC_MAX_NS_RSP;
Bart Van Asschecd05c152019-03-28 11:06:18 -07003159 /* fall through */
dea31012005-04-17 16:05:31 -05003160 case SLI_MGMT_DPRT:
James Smart76b2c342015-04-07 15:07:19 -04003161 case SLI_MGMT_DPA:
3162 pe = (struct lpfc_fdmi_port_entry *)&CtReq->un.PortID;
3163 memcpy((uint8_t *)&pe->PortName,
3164 (uint8_t *)&vport->fc_sparam.portName,
3165 sizeof(struct lpfc_name));
3166 size = GID_REQUEST_SZ - 4 + sizeof(struct lpfc_name);
dea31012005-04-17 16:05:31 -05003167 break;
James Smart76b2c342015-04-07 15:07:19 -04003168 case SLI_MGMT_GRHL:
3169 size = GID_REQUEST_SZ - 4;
3170 break;
3171 default:
3172 lpfc_printf_vlog(vport, KERN_WARNING, LOG_DISCOVERY,
3173 "0298 FDMI cmdcode x%x not supported\n",
3174 cmdcode);
3175 goto fdmi_cmd_free_bmpvirt;
dea31012005-04-17 16:05:31 -05003176 }
James Smart76b2c342015-04-07 15:07:19 -04003177 CtReq->CommandResponse.bits.Size = cpu_to_be16(rsp_size);
dea31012005-04-17 16:05:31 -05003178
James Smart76b2c342015-04-07 15:07:19 -04003179 bpl = (struct ulp_bde64 *)bmp->virt;
3180 bpl->addrHigh = le32_to_cpu(putPaddrHigh(mp->phys));
3181 bpl->addrLow = le32_to_cpu(putPaddrLow(mp->phys));
dea31012005-04-17 16:05:31 -05003182 bpl->tus.f.bdeFlags = 0;
3183 bpl->tus.f.bdeSize = size;
dea31012005-04-17 16:05:31 -05003184
James Smart76b2c342015-04-07 15:07:19 -04003185 /*
3186 * The lpfc_ct_cmd/lpfc_get_req shall increment ndlp reference count
James Smarte47c9092008-02-08 18:49:26 -05003187 * to hold ndlp reference for the corresponding callback function.
3188 */
James Smart76b2c342015-04-07 15:07:19 -04003189 if (!lpfc_ct_cmd(vport, mp, bmp, ndlp, cmpl, rsp_size, 0))
dea31012005-04-17 16:05:31 -05003190 return 0;
3191
James Smart76b2c342015-04-07 15:07:19 -04003192 /*
3193 * Decrement ndlp reference count to release ndlp reference held
James Smarte47c9092008-02-08 18:49:26 -05003194 * for the failed command's callback function.
3195 */
James Smart51ef4c22007-08-02 11:10:31 -04003196 lpfc_nlp_put(ndlp);
James Smarte47c9092008-02-08 18:49:26 -05003197
James Smart76b2c342015-04-07 15:07:19 -04003198fdmi_cmd_free_bmpvirt:
dea31012005-04-17 16:05:31 -05003199 lpfc_mbuf_free(phba, bmp->virt, bmp->phys);
3200fdmi_cmd_free_bmp:
3201 kfree(bmp);
3202fdmi_cmd_free_mpvirt:
3203 lpfc_mbuf_free(phba, mp->virt, mp->phys);
3204fdmi_cmd_free_mp:
3205 kfree(mp);
3206fdmi_cmd_exit:
3207 /* Issue FDMI request failed */
James Smarte8b62012007-08-02 11:10:09 -04003208 lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
3209 "0244 Issue FDMI request failed Data: x%x\n",
3210 cmdcode);
dea31012005-04-17 16:05:31 -05003211 return 1;
3212}
3213
James Smart92494142011-02-16 12:39:44 -05003214/**
3215 * lpfc_delayed_disc_tmo - Timeout handler for delayed discovery timer.
3216 * @ptr - Context object of the timer.
3217 *
3218 * This function set the WORKER_DELAYED_DISC_TMO flag and wake up
3219 * the worker thread.
3220 **/
3221void
Kees Cookf22eb4d2017-09-06 20:24:26 -07003222lpfc_delayed_disc_tmo(struct timer_list *t)
James Smart92494142011-02-16 12:39:44 -05003223{
Kees Cookf22eb4d2017-09-06 20:24:26 -07003224 struct lpfc_vport *vport = from_timer(vport, t, delayed_disc_tmo);
James Smart92494142011-02-16 12:39:44 -05003225 struct lpfc_hba *phba = vport->phba;
3226 uint32_t tmo_posted;
3227 unsigned long iflag;
3228
3229 spin_lock_irqsave(&vport->work_port_lock, iflag);
3230 tmo_posted = vport->work_port_events & WORKER_DELAYED_DISC_TMO;
3231 if (!tmo_posted)
3232 vport->work_port_events |= WORKER_DELAYED_DISC_TMO;
3233 spin_unlock_irqrestore(&vport->work_port_lock, iflag);
3234
3235 if (!tmo_posted)
3236 lpfc_worker_wake_up(phba);
3237 return;
3238}
3239
3240/**
3241 * lpfc_delayed_disc_timeout_handler - Function called by worker thread to
3242 * handle delayed discovery.
3243 * @vport: pointer to a host virtual N_Port data structure.
3244 *
3245 * This function start nport discovery of the vport.
3246 **/
3247void
3248lpfc_delayed_disc_timeout_handler(struct lpfc_vport *vport)
3249{
3250 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
3251
3252 spin_lock_irq(shost->host_lock);
3253 if (!(vport->fc_flag & FC_DISC_DELAYED)) {
3254 spin_unlock_irq(shost->host_lock);
3255 return;
3256 }
3257 vport->fc_flag &= ~FC_DISC_DELAYED;
3258 spin_unlock_irq(shost->host_lock);
3259
3260 lpfc_do_scr_ns_plogi(vport->phba, vport);
3261}
3262
dea31012005-04-17 16:05:31 -05003263void
James Smart2e0fef82007-06-17 19:56:36 -05003264lpfc_decode_firmware_rev(struct lpfc_hba *phba, char *fwrevision, int flag)
dea31012005-04-17 16:05:31 -05003265{
3266 struct lpfc_sli *psli = &phba->sli;
3267 lpfc_vpd_t *vp = &phba->vpd;
3268 uint32_t b1, b2, b3, b4, i, rev;
3269 char c;
3270 uint32_t *ptr, str[4];
3271 uint8_t *fwname;
3272
James Smartf1126682009-06-10 17:22:44 -04003273 if (phba->sli_rev == LPFC_SLI_REV4)
James Smart6b5151f2012-01-18 16:24:06 -05003274 snprintf(fwrevision, FW_REV_STR_SIZE, "%s", vp->rev.opFwName);
James Smartf1126682009-06-10 17:22:44 -04003275 else if (vp->rev.rBit) {
James Smartf4b4c682009-05-22 14:53:12 -04003276 if (psli->sli_flag & LPFC_SLI_ACTIVE)
dea31012005-04-17 16:05:31 -05003277 rev = vp->rev.sli2FwRev;
3278 else
3279 rev = vp->rev.sli1FwRev;
3280
3281 b1 = (rev & 0x0000f000) >> 12;
3282 b2 = (rev & 0x00000f00) >> 8;
3283 b3 = (rev & 0x000000c0) >> 6;
3284 b4 = (rev & 0x00000030) >> 4;
3285
3286 switch (b4) {
3287 case 0:
3288 c = 'N';
3289 break;
3290 case 1:
3291 c = 'A';
3292 break;
3293 case 2:
3294 c = 'B';
3295 break;
James Smart73d91e52011-10-10 21:32:10 -04003296 case 3:
3297 c = 'X';
3298 break;
dea31012005-04-17 16:05:31 -05003299 default:
3300 c = 0;
3301 break;
3302 }
3303 b4 = (rev & 0x0000000f);
3304
James Smartf4b4c682009-05-22 14:53:12 -04003305 if (psli->sli_flag & LPFC_SLI_ACTIVE)
dea31012005-04-17 16:05:31 -05003306 fwname = vp->rev.sli2FwName;
3307 else
3308 fwname = vp->rev.sli1FwName;
3309
3310 for (i = 0; i < 16; i++)
3311 if (fwname[i] == 0x20)
3312 fwname[i] = 0;
3313
3314 ptr = (uint32_t*)fwname;
3315
3316 for (i = 0; i < 3; i++)
3317 str[i] = be32_to_cpu(*ptr++);
3318
3319 if (c == 0) {
3320 if (flag)
3321 sprintf(fwrevision, "%d.%d%d (%s)",
3322 b1, b2, b3, (char *)str);
3323 else
3324 sprintf(fwrevision, "%d.%d%d", b1,
3325 b2, b3);
3326 } else {
3327 if (flag)
3328 sprintf(fwrevision, "%d.%d%d%c%d (%s)",
3329 b1, b2, b3, c,
3330 b4, (char *)str);
3331 else
3332 sprintf(fwrevision, "%d.%d%d%c%d",
3333 b1, b2, b3, c, b4);
3334 }
3335 } else {
3336 rev = vp->rev.smFwRev;
3337
3338 b1 = (rev & 0xff000000) >> 24;
3339 b2 = (rev & 0x00f00000) >> 20;
3340 b3 = (rev & 0x000f0000) >> 16;
3341 c = (rev & 0x0000ff00) >> 8;
3342 b4 = (rev & 0x000000ff);
3343
Roel Kluind44a6d22010-01-17 16:15:57 +01003344 sprintf(fwrevision, "%d.%d%d%c%d", b1, b2, b3, c, b4);
dea31012005-04-17 16:05:31 -05003345 }
3346 return;
3347}