blob: 79e261d2a0c879bcd7627f6416d103a75a1876e1 [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 Smartf25e8e72015-04-07 15:07:28 -04004 * Copyright (C) 2004-2015 Emulex. All rights reserved. *
James.Smart@Emulex.Comc44ce172005-06-25 10:34:39 -04005 * EMULEX and SLI are trademarks of Emulex. *
dea31012005-04-17 16:05:31 -05006 * www.emulex.com *
7 * *
8 * This program is free software; you can redistribute it and/or *
James.Smart@Emulex.Comc44ce172005-06-25 10:34:39 -04009 * modify it under the terms of version 2 of the GNU General *
10 * Public License as published by the Free Software Foundation. *
11 * This program is distributed in the hope that it will be useful. *
12 * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND *
13 * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, *
14 * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE *
15 * DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD *
16 * TO BE LEGALLY INVALID. See the GNU General Public License for *
17 * more details, a copy of which can be found in the file COPYING *
18 * included with this package. *
dea31012005-04-17 16:05:31 -050019 *******************************************************************/
20
21/*
James Smart09372822008-01-11 01:52:54 -050022 * Fibre Channel SCSI LAN Device Driver CT support: FC Generic Services FC-GS
dea31012005-04-17 16:05:31 -050023 */
24
25#include <linux/blkdev.h>
26#include <linux/pci.h>
27#include <linux/interrupt.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090028#include <linux/slab.h>
dea31012005-04-17 16:05:31 -050029#include <linux/utsname.h>
30
James.Smart@Emulex.Com91886522005-08-10 15:03:09 -040031#include <scsi/scsi.h>
dea31012005-04-17 16:05:31 -050032#include <scsi/scsi_device.h>
33#include <scsi/scsi_host.h>
James.Smart@Emulex.Comf888ba32005-08-10 15:03:01 -040034#include <scsi/scsi_transport_fc.h>
James Smart6a9c52c2009-10-02 15:16:51 -040035#include <scsi/fc/fc_fs.h>
dea31012005-04-17 16:05:31 -050036
James Smartda0436e2009-05-22 14:51:39 -040037#include "lpfc_hw4.h"
dea31012005-04-17 16:05:31 -050038#include "lpfc_hw.h"
39#include "lpfc_sli.h"
James Smartda0436e2009-05-22 14:51:39 -040040#include "lpfc_sli4.h"
James Smartea2151b2008-09-07 11:52:10 -040041#include "lpfc_nl.h"
dea31012005-04-17 16:05:31 -050042#include "lpfc_disc.h"
43#include "lpfc_scsi.h"
44#include "lpfc.h"
45#include "lpfc_logmsg.h"
46#include "lpfc_crtn.h"
47#include "lpfc_version.h"
James Smart92d7f7b2007-06-17 19:56:38 -050048#include "lpfc_vport.h"
James Smart858c9f62007-06-17 19:56:39 -050049#include "lpfc_debugfs.h"
dea31012005-04-17 16:05:31 -050050
James Smarta085e872015-12-16 18:12:02 -050051/* FDMI Port Speed definitions - FC-GS-7 */
52#define HBA_PORTSPEED_1GFC 0x00000001 /* 1G FC */
53#define HBA_PORTSPEED_2GFC 0x00000002 /* 2G FC */
54#define HBA_PORTSPEED_4GFC 0x00000008 /* 4G FC */
55#define HBA_PORTSPEED_10GFC 0x00000004 /* 10G FC */
56#define HBA_PORTSPEED_8GFC 0x00000010 /* 8G FC */
57#define HBA_PORTSPEED_16GFC 0x00000020 /* 16G FC */
58#define HBA_PORTSPEED_32GFC 0x00000040 /* 32G FC */
59#define HBA_PORTSPEED_20GFC 0x00000080 /* 20G FC */
60#define HBA_PORTSPEED_40GFC 0x00000100 /* 40G FC */
61#define HBA_PORTSPEED_128GFC 0x00000200 /* 128G FC */
62#define HBA_PORTSPEED_64GFC 0x00000400 /* 64G FC */
63#define HBA_PORTSPEED_256GFC 0x00000800 /* 256G FC */
64#define HBA_PORTSPEED_UNKNOWN 0x00008000 /* Unknown */
65#define HBA_PORTSPEED_10GE 0x00010000 /* 10G E */
66#define HBA_PORTSPEED_40GE 0x00020000 /* 40G E */
67#define HBA_PORTSPEED_100GE 0x00040000 /* 100G E */
68#define HBA_PORTSPEED_25GE 0x00080000 /* 25G E */
69#define HBA_PORTSPEED_50GE 0x00100000 /* 50G E */
70#define HBA_PORTSPEED_400GE 0x00200000 /* 400G E */
dea31012005-04-17 16:05:31 -050071
72#define FOURBYTES 4
73
74
75static char *lpfc_release_version = LPFC_DRIVER_VERSION;
76
James Smarted957682007-06-17 19:56:37 -050077static void
78lpfc_ct_ignore_hbq_buffer(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq,
James Smart92d7f7b2007-06-17 19:56:38 -050079 struct lpfc_dmabuf *mp, uint32_t size)
James Smarted957682007-06-17 19:56:37 -050080{
James Smarted957682007-06-17 19:56:37 -050081 if (!mp) {
James Smart9c2face2008-01-11 01:53:18 -050082 lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
James Smart97eab632008-04-07 10:16:05 -040083 "0146 Ignoring unsolicited CT No HBQ "
James Smart9c2face2008-01-11 01:53:18 -050084 "status = x%x\n",
85 piocbq->iocb.ulpStatus);
James Smarted957682007-06-17 19:56:37 -050086 }
James Smart9c2face2008-01-11 01:53:18 -050087 lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
88 "0145 Ignoring unsolicted CT HBQ Size:%d "
89 "status = x%x\n",
90 size, piocbq->iocb.ulpStatus);
91}
92
93static void
94lpfc_ct_unsol_buffer(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq,
95 struct lpfc_dmabuf *mp, uint32_t size)
96{
97 lpfc_ct_ignore_hbq_buffer(phba, piocbq, mp, size);
James Smarted957682007-06-17 19:56:37 -050098}
99
dea31012005-04-17 16:05:31 -0500100void
James Smart2e0fef82007-06-17 19:56:36 -0500101lpfc_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
102 struct lpfc_iocbq *piocbq)
dea31012005-04-17 16:05:31 -0500103{
James Smarted957682007-06-17 19:56:37 -0500104 struct lpfc_dmabuf *mp = NULL;
dea31012005-04-17 16:05:31 -0500105 IOCB_t *icmd = &piocbq->iocb;
James Smarted957682007-06-17 19:56:37 -0500106 int i;
107 struct lpfc_iocbq *iocbq;
108 dma_addr_t paddr;
109 uint32_t size;
James Smart9c2face2008-01-11 01:53:18 -0500110 struct list_head head;
111 struct lpfc_dmabuf *bdeBuf;
James Smart92d7f7b2007-06-17 19:56:38 -0500112
James Smart4fede782010-01-26 23:08:55 -0500113 if (lpfc_bsg_ct_unsol_event(phba, pring, piocbq) == 0)
114 return;
James Smartf1c3b0f2009-07-19 10:01:32 -0400115
James Smart92d7f7b2007-06-17 19:56:38 -0500116 if (unlikely(icmd->ulpStatus == IOSTAT_NEED_BUFFER)) {
117 lpfc_sli_hbqbuf_add_hbqs(phba, LPFC_ELS_HBQ);
118 } else if ((icmd->ulpStatus == IOSTAT_LOCAL_REJECT) &&
James Smarte3d2b802012-08-14 14:25:43 -0400119 ((icmd->un.ulpWord[4] & IOERR_PARAM_MASK) ==
120 IOERR_RCV_BUFFER_WAITING)) {
dea31012005-04-17 16:05:31 -0500121 /* Not enough posted buffers; Try posting more buffers */
122 phba->fc_stat.NoRcvBuf++;
James Smart92d7f7b2007-06-17 19:56:38 -0500123 if (!(phba->sli3_options & LPFC_SLI3_HBQ_ENABLED))
James Smart495a7142008-06-14 22:52:59 -0400124 lpfc_post_buffer(phba, pring, 2);
dea31012005-04-17 16:05:31 -0500125 return;
126 }
127
128 /* If there are no BDEs associated with this IOCB,
129 * there is nothing to do.
130 */
131 if (icmd->ulpBdeCount == 0)
132 return;
133
James Smarted957682007-06-17 19:56:37 -0500134 if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) {
James Smart9c2face2008-01-11 01:53:18 -0500135 INIT_LIST_HEAD(&head);
136 list_add_tail(&head, &piocbq->list);
137 list_for_each_entry(iocbq, &head, list) {
James Smarted957682007-06-17 19:56:37 -0500138 icmd = &iocbq->iocb;
James Smart9c2face2008-01-11 01:53:18 -0500139 if (icmd->ulpBdeCount == 0)
James Smarted957682007-06-17 19:56:37 -0500140 continue;
James Smart9c2face2008-01-11 01:53:18 -0500141 bdeBuf = iocbq->context2;
142 iocbq->context2 = NULL;
James Smarted957682007-06-17 19:56:37 -0500143 size = icmd->un.cont64[0].tus.f.bdeSize;
James Smart9c2face2008-01-11 01:53:18 -0500144 lpfc_ct_unsol_buffer(phba, piocbq, bdeBuf, size);
145 lpfc_in_buf_free(phba, bdeBuf);
James Smarted957682007-06-17 19:56:37 -0500146 if (icmd->ulpBdeCount == 2) {
James Smart9c2face2008-01-11 01:53:18 -0500147 bdeBuf = iocbq->context3;
148 iocbq->context3 = NULL;
149 size = icmd->unsli3.rcvsli3.bde2.tus.f.bdeSize;
150 lpfc_ct_unsol_buffer(phba, piocbq, bdeBuf,
151 size);
152 lpfc_in_buf_free(phba, bdeBuf);
James Smarted957682007-06-17 19:56:37 -0500153 }
dea31012005-04-17 16:05:31 -0500154 }
James Smart9c2face2008-01-11 01:53:18 -0500155 list_del(&head);
James Smarted957682007-06-17 19:56:37 -0500156 } else {
James Smartd7c255b2008-08-24 21:50:00 -0400157 INIT_LIST_HEAD(&head);
158 list_add_tail(&head, &piocbq->list);
159 list_for_each_entry(iocbq, &head, list) {
James Smarted957682007-06-17 19:56:37 -0500160 icmd = &iocbq->iocb;
James Smart9c2face2008-01-11 01:53:18 -0500161 if (icmd->ulpBdeCount == 0)
James Smartd7c255b2008-08-24 21:50:00 -0400162 lpfc_ct_unsol_buffer(phba, iocbq, NULL, 0);
James Smarted957682007-06-17 19:56:37 -0500163 for (i = 0; i < icmd->ulpBdeCount; i++) {
164 paddr = getPaddr(icmd->un.cont64[i].addrHigh,
165 icmd->un.cont64[i].addrLow);
166 mp = lpfc_sli_ringpostbuf_get(phba, pring,
167 paddr);
168 size = icmd->un.cont64[i].tus.f.bdeSize;
James Smartd7c255b2008-08-24 21:50:00 -0400169 lpfc_ct_unsol_buffer(phba, iocbq, mp, size);
James Smart92d7f7b2007-06-17 19:56:38 -0500170 lpfc_in_buf_free(phba, mp);
James Smarted957682007-06-17 19:56:37 -0500171 }
James Smart495a7142008-06-14 22:52:59 -0400172 lpfc_post_buffer(phba, pring, i);
dea31012005-04-17 16:05:31 -0500173 }
James Smartd7c255b2008-08-24 21:50:00 -0400174 list_del(&head);
dea31012005-04-17 16:05:31 -0500175 }
dea31012005-04-17 16:05:31 -0500176}
177
James Smart6669f9b2009-10-02 15:16:45 -0400178/**
James Smart6dd9e312013-01-03 15:43:37 -0500179 * lpfc_ct_handle_unsol_abort - ct upper level protocol abort handler
James Smart6669f9b2009-10-02 15:16:45 -0400180 * @phba: Pointer to HBA context object.
James Smart6dd9e312013-01-03 15:43:37 -0500181 * @dmabuf: pointer to a dmabuf that describes the FC sequence
James Smart6669f9b2009-10-02 15:16:45 -0400182 *
James Smart6dd9e312013-01-03 15:43:37 -0500183 * This function serves as the upper level protocol abort handler for CT
184 * protocol.
185 *
186 * Return 1 if abort has been handled, 0 otherwise.
James Smart6669f9b2009-10-02 15:16:45 -0400187 **/
James Smart6dd9e312013-01-03 15:43:37 -0500188int
189lpfc_ct_handle_unsol_abort(struct lpfc_hba *phba, struct hbq_dmabuf *dmabuf)
James Smart6669f9b2009-10-02 15:16:45 -0400190{
James Smart6dd9e312013-01-03 15:43:37 -0500191 int handled;
James Smart6669f9b2009-10-02 15:16:45 -0400192
James Smart6dd9e312013-01-03 15:43:37 -0500193 /* CT upper level goes through BSG */
194 handled = lpfc_bsg_ct_unsol_abort(phba, dmabuf);
James Smart6669f9b2009-10-02 15:16:45 -0400195
James Smart6dd9e312013-01-03 15:43:37 -0500196 return handled;
James Smart6669f9b2009-10-02 15:16:45 -0400197}
198
dea31012005-04-17 16:05:31 -0500199static void
James Smart2e0fef82007-06-17 19:56:36 -0500200lpfc_free_ct_rsp(struct lpfc_hba *phba, struct lpfc_dmabuf *mlist)
dea31012005-04-17 16:05:31 -0500201{
202 struct lpfc_dmabuf *mlast, *next_mlast;
203
204 list_for_each_entry_safe(mlast, next_mlast, &mlist->list, list) {
205 lpfc_mbuf_free(phba, mlast->virt, mlast->phys);
206 list_del(&mlast->list);
207 kfree(mlast);
208 }
209 lpfc_mbuf_free(phba, mlist->virt, mlist->phys);
210 kfree(mlist);
211 return;
212}
213
214static struct lpfc_dmabuf *
James Smart2e0fef82007-06-17 19:56:36 -0500215lpfc_alloc_ct_rsp(struct lpfc_hba *phba, int cmdcode, struct ulp_bde64 *bpl,
dea31012005-04-17 16:05:31 -0500216 uint32_t size, int *entries)
217{
218 struct lpfc_dmabuf *mlist = NULL;
219 struct lpfc_dmabuf *mp;
220 int cnt, i = 0;
221
James Smart09372822008-01-11 01:52:54 -0500222 /* We get chunks of FCELSSIZE */
dea31012005-04-17 16:05:31 -0500223 cnt = size > FCELSSIZE ? FCELSSIZE: size;
224
225 while (size) {
226 /* Allocate buffer for rsp payload */
227 mp = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL);
228 if (!mp) {
229 if (mlist)
230 lpfc_free_ct_rsp(phba, mlist);
231 return NULL;
232 }
233
234 INIT_LIST_HEAD(&mp->list);
235
James Smart92d7f7b2007-06-17 19:56:38 -0500236 if (cmdcode == be16_to_cpu(SLI_CTNS_GID_FT) ||
237 cmdcode == be16_to_cpu(SLI_CTNS_GFF_ID))
dea31012005-04-17 16:05:31 -0500238 mp->virt = lpfc_mbuf_alloc(phba, MEM_PRI, &(mp->phys));
239 else
240 mp->virt = lpfc_mbuf_alloc(phba, 0, &(mp->phys));
241
242 if (!mp->virt) {
243 kfree(mp);
Eric Sesterhenn0b3a82d2006-10-10 14:41:43 -0700244 if (mlist)
245 lpfc_free_ct_rsp(phba, mlist);
dea31012005-04-17 16:05:31 -0500246 return NULL;
247 }
248
249 /* Queue it to a linked list */
250 if (!mlist)
251 mlist = mp;
252 else
253 list_add_tail(&mp->list, &mlist->list);
254
James Smart34b02dc2008-08-24 21:49:55 -0400255 bpl->tus.f.bdeFlags = BUFF_TYPE_BDE_64I;
dea31012005-04-17 16:05:31 -0500256 /* build buffer ptr list for IOCB */
James Smart92d7f7b2007-06-17 19:56:38 -0500257 bpl->addrLow = le32_to_cpu(putPaddrLow(mp->phys) );
258 bpl->addrHigh = le32_to_cpu(putPaddrHigh(mp->phys) );
dea31012005-04-17 16:05:31 -0500259 bpl->tus.f.bdeSize = (uint16_t) cnt;
260 bpl->tus.w = le32_to_cpu(bpl->tus.w);
261 bpl++;
262
263 i++;
264 size -= cnt;
265 }
266
267 *entries = i;
268 return mlist;
269}
270
James Smart858c9f62007-06-17 19:56:39 -0500271int
272lpfc_ct_free_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *ctiocb)
273{
274 struct lpfc_dmabuf *buf_ptr;
275
James Smart51ef4c22007-08-02 11:10:31 -0400276 if (ctiocb->context_un.ndlp) {
277 lpfc_nlp_put(ctiocb->context_un.ndlp);
278 ctiocb->context_un.ndlp = NULL;
279 }
James Smart858c9f62007-06-17 19:56:39 -0500280 if (ctiocb->context1) {
281 buf_ptr = (struct lpfc_dmabuf *) ctiocb->context1;
282 lpfc_mbuf_free(phba, buf_ptr->virt, buf_ptr->phys);
283 kfree(buf_ptr);
284 ctiocb->context1 = NULL;
285 }
286 if (ctiocb->context2) {
287 lpfc_free_ct_rsp(phba, (struct lpfc_dmabuf *) ctiocb->context2);
288 ctiocb->context2 = NULL;
289 }
290
291 if (ctiocb->context3) {
292 buf_ptr = (struct lpfc_dmabuf *) ctiocb->context3;
293 lpfc_mbuf_free(phba, buf_ptr->virt, buf_ptr->phys);
294 kfree(buf_ptr);
Felipe Pena1109c942013-10-15 21:29:50 -0300295 ctiocb->context3 = NULL;
James Smart858c9f62007-06-17 19:56:39 -0500296 }
297 lpfc_sli_release_iocbq(phba, ctiocb);
298 return 0;
299}
300
James Smart4258e982015-12-16 18:11:58 -0500301/**
302 * lpfc_gen_req - Build and issue a GEN_REQUEST command to the SLI Layer
303 * @vport: pointer to a host virtual N_Port data structure.
304 * @bmp: Pointer to BPL for SLI command
305 * @inp: Pointer to data buffer for response data.
306 * @outp: Pointer to data buffer that hold the CT command.
307 * @cmpl: completion routine to call when command completes
308 * @ndlp: Destination NPort nodelist entry
309 *
310 * This function as the final part for issuing a CT command.
311 */
dea31012005-04-17 16:05:31 -0500312static int
James Smart2e0fef82007-06-17 19:56:36 -0500313lpfc_gen_req(struct lpfc_vport *vport, struct lpfc_dmabuf *bmp,
dea31012005-04-17 16:05:31 -0500314 struct lpfc_dmabuf *inp, struct lpfc_dmabuf *outp,
315 void (*cmpl) (struct lpfc_hba *, struct lpfc_iocbq *,
316 struct lpfc_iocbq *),
317 struct lpfc_nodelist *ndlp, uint32_t usr_flg, uint32_t num_entry,
James Smart92d7f7b2007-06-17 19:56:38 -0500318 uint32_t tmo, uint8_t retry)
dea31012005-04-17 16:05:31 -0500319{
James Smart2e0fef82007-06-17 19:56:36 -0500320 struct lpfc_hba *phba = vport->phba;
dea31012005-04-17 16:05:31 -0500321 IOCB_t *icmd;
James.Smart@Emulex.Com0bd4ca22005-10-28 20:30:02 -0400322 struct lpfc_iocbq *geniocb;
James Smart92d7f7b2007-06-17 19:56:38 -0500323 int rc;
dea31012005-04-17 16:05:31 -0500324
325 /* Allocate buffer for command iocb */
James.Smart@Emulex.Com0bd4ca22005-10-28 20:30:02 -0400326 geniocb = lpfc_sli_get_iocbq(phba);
dea31012005-04-17 16:05:31 -0500327
328 if (geniocb == NULL)
329 return 1;
dea31012005-04-17 16:05:31 -0500330
331 icmd = &geniocb->iocb;
332 icmd->un.genreq64.bdl.ulpIoTag32 = 0;
333 icmd->un.genreq64.bdl.addrHigh = putPaddrHigh(bmp->phys);
334 icmd->un.genreq64.bdl.addrLow = putPaddrLow(bmp->phys);
James Smart34b02dc2008-08-24 21:49:55 -0400335 icmd->un.genreq64.bdl.bdeFlags = BUFF_TYPE_BLP_64;
James Smart4258e982015-12-16 18:11:58 -0500336 icmd->un.genreq64.bdl.bdeSize = (num_entry * sizeof(struct ulp_bde64));
dea31012005-04-17 16:05:31 -0500337
338 if (usr_flg)
339 geniocb->context3 = NULL;
340 else
341 geniocb->context3 = (uint8_t *) bmp;
342
343 /* Save for completion so we can release these resources */
344 geniocb->context1 = (uint8_t *) inp;
345 geniocb->context2 = (uint8_t *) outp;
James Smarte47c9092008-02-08 18:49:26 -0500346 geniocb->context_un.ndlp = lpfc_nlp_get(ndlp);
dea31012005-04-17 16:05:31 -0500347
348 /* Fill in payload, bp points to frame payload */
349 icmd->ulpCommand = CMD_GEN_REQUEST64_CR;
350
351 /* Fill in rest of iocb */
352 icmd->un.genreq64.w5.hcsw.Fctl = (SI | LA);
353 icmd->un.genreq64.w5.hcsw.Dfctl = 0;
James Smart6a9c52c2009-10-02 15:16:51 -0400354 icmd->un.genreq64.w5.hcsw.Rctl = FC_RCTL_DD_UNSOL_CTL;
355 icmd->un.genreq64.w5.hcsw.Type = FC_TYPE_CT;
dea31012005-04-17 16:05:31 -0500356
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500357 if (!tmo) {
358 /* FC spec states we need 3 * ratov for CT requests */
359 tmo = (3 * phba->fc_ratov);
360 }
dea31012005-04-17 16:05:31 -0500361 icmd->ulpTimeout = tmo;
362 icmd->ulpBdeCount = 1;
363 icmd->ulpLe = 1;
364 icmd->ulpClass = CLASS3;
365 icmd->ulpContext = ndlp->nlp_rpi;
James Smart6d368e52011-05-24 11:44:12 -0400366 if (phba->sli_rev == LPFC_SLI_REV4)
367 icmd->ulpContext = phba->sli4_hba.rpi_ids[ndlp->nlp_rpi];
dea31012005-04-17 16:05:31 -0500368
James Smart92d7f7b2007-06-17 19:56:38 -0500369 if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) {
370 /* For GEN_REQUEST64_CR, use the RPI */
371 icmd->ulpCt_h = 0;
372 icmd->ulpCt_l = 0;
373 }
374
dea31012005-04-17 16:05:31 -0500375 /* Issue GEN REQ IOCB for NPORT <did> */
James Smarte8b62012007-08-02 11:10:09 -0400376 lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
377 "0119 Issue GEN REQ IOCB to NPORT x%x "
378 "Data: x%x x%x\n",
379 ndlp->nlp_DID, icmd->ulpIoTag,
380 vport->port_state);
dea31012005-04-17 16:05:31 -0500381 geniocb->iocb_cmpl = cmpl;
382 geniocb->drvrTimeout = icmd->ulpTimeout + LPFC_DRVR_TIMEOUT;
James Smart2e0fef82007-06-17 19:56:36 -0500383 geniocb->vport = vport;
James Smart92d7f7b2007-06-17 19:56:38 -0500384 geniocb->retry = retry;
James Smart3772a992009-05-22 14:50:54 -0400385 rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, geniocb, 0);
James Smart92d7f7b2007-06-17 19:56:38 -0500386
387 if (rc == IOCB_ERROR) {
James Bottomley604a3e32005-10-29 10:28:33 -0500388 lpfc_sli_release_iocbq(phba, geniocb);
dea31012005-04-17 16:05:31 -0500389 return 1;
390 }
dea31012005-04-17 16:05:31 -0500391
392 return 0;
393}
394
James Smart4258e982015-12-16 18:11:58 -0500395/**
396 * lpfc_ct_cmd - Build and issue a CT command
397 * @vport: pointer to a host virtual N_Port data structure.
398 * @inmp: Pointer to data buffer for response data.
399 * @bmp: Pointer to BPL for SLI command
400 * @ndlp: Destination NPort nodelist entry
401 * @cmpl: completion routine to call when command completes
402 *
403 * This function is called for issuing a CT command.
404 */
dea31012005-04-17 16:05:31 -0500405static int
James Smart2e0fef82007-06-17 19:56:36 -0500406lpfc_ct_cmd(struct lpfc_vport *vport, struct lpfc_dmabuf *inmp,
dea31012005-04-17 16:05:31 -0500407 struct lpfc_dmabuf *bmp, struct lpfc_nodelist *ndlp,
408 void (*cmpl) (struct lpfc_hba *, struct lpfc_iocbq *,
409 struct lpfc_iocbq *),
James Smart92d7f7b2007-06-17 19:56:38 -0500410 uint32_t rsp_size, uint8_t retry)
dea31012005-04-17 16:05:31 -0500411{
James Smart2e0fef82007-06-17 19:56:36 -0500412 struct lpfc_hba *phba = vport->phba;
dea31012005-04-17 16:05:31 -0500413 struct ulp_bde64 *bpl = (struct ulp_bde64 *) bmp->virt;
414 struct lpfc_dmabuf *outmp;
415 int cnt = 0, status;
416 int cmdcode = ((struct lpfc_sli_ct_request *) inmp->virt)->
417 CommandResponse.bits.CmdRsp;
418
419 bpl++; /* Skip past ct request */
420
421 /* Put buffer(s) for ct rsp in bpl */
422 outmp = lpfc_alloc_ct_rsp(phba, cmdcode, bpl, rsp_size, &cnt);
423 if (!outmp)
424 return -ENOMEM;
James Smart6a9c52c2009-10-02 15:16:51 -0400425 /*
426 * Form the CT IOCB. The total number of BDEs in this IOCB
427 * is the single command plus response count from
428 * lpfc_alloc_ct_rsp.
429 */
430 cnt += 1;
James Smart2e0fef82007-06-17 19:56:36 -0500431 status = lpfc_gen_req(vport, bmp, inmp, outmp, cmpl, ndlp, 0,
James Smart6a9c52c2009-10-02 15:16:51 -0400432 cnt, 0, retry);
dea31012005-04-17 16:05:31 -0500433 if (status) {
434 lpfc_free_ct_rsp(phba, outmp);
435 return -ENOMEM;
436 }
437 return 0;
438}
439
James Smart549e55c2007-08-02 11:09:51 -0400440struct lpfc_vport *
James Smart92d7f7b2007-06-17 19:56:38 -0500441lpfc_find_vport_by_did(struct lpfc_hba *phba, uint32_t did) {
James Smart92d7f7b2007-06-17 19:56:38 -0500442 struct lpfc_vport *vport_curr;
James Smart549e55c2007-08-02 11:09:51 -0400443 unsigned long flags;
James Smart92d7f7b2007-06-17 19:56:38 -0500444
James Smart549e55c2007-08-02 11:09:51 -0400445 spin_lock_irqsave(&phba->hbalock, flags);
James Smart92d7f7b2007-06-17 19:56:38 -0500446 list_for_each_entry(vport_curr, &phba->port_list, listentry) {
James Smart549e55c2007-08-02 11:09:51 -0400447 if ((vport_curr->fc_myDID) && (vport_curr->fc_myDID == did)) {
448 spin_unlock_irqrestore(&phba->hbalock, flags);
James Smart92d7f7b2007-06-17 19:56:38 -0500449 return vport_curr;
James Smart549e55c2007-08-02 11:09:51 -0400450 }
James Smart92d7f7b2007-06-17 19:56:38 -0500451 }
James Smart549e55c2007-08-02 11:09:51 -0400452 spin_unlock_irqrestore(&phba->hbalock, flags);
James Smart92d7f7b2007-06-17 19:56:38 -0500453 return NULL;
454}
455
dea31012005-04-17 16:05:31 -0500456static int
James Smart2e0fef82007-06-17 19:56:36 -0500457lpfc_ns_rsp(struct lpfc_vport *vport, struct lpfc_dmabuf *mp, uint32_t Size)
dea31012005-04-17 16:05:31 -0500458{
James Smart2e0fef82007-06-17 19:56:36 -0500459 struct lpfc_hba *phba = vport->phba;
dea31012005-04-17 16:05:31 -0500460 struct lpfc_sli_ct_request *Response =
461 (struct lpfc_sli_ct_request *) mp->virt;
462 struct lpfc_nodelist *ndlp = NULL;
463 struct lpfc_dmabuf *mlast, *next_mp;
464 uint32_t *ctptr = (uint32_t *) & Response->un.gid.PortType;
James Smart2e0fef82007-06-17 19:56:36 -0500465 uint32_t Did, CTentry;
dea31012005-04-17 16:05:31 -0500466 int Cnt;
467 struct list_head head;
468
James Smart2e0fef82007-06-17 19:56:36 -0500469 lpfc_set_disctmo(vport);
James Smart92d7f7b2007-06-17 19:56:38 -0500470 vport->num_disc_nodes = 0;
James Smart0ff10d42008-01-11 01:52:36 -0500471 vport->fc_ns_retry = 0;
dea31012005-04-17 16:05:31 -0500472
dea31012005-04-17 16:05:31 -0500473
474 list_add_tail(&head, &mp->list);
475 list_for_each_entry_safe(mp, next_mp, &head, list) {
476 mlast = mp;
477
James Smart7054a602007-04-25 09:52:34 -0400478 Cnt = Size > FCELSSIZE ? FCELSSIZE : Size;
479
dea31012005-04-17 16:05:31 -0500480 Size -= Cnt;
481
James Smart1dcb58e2007-04-25 09:51:30 -0400482 if (!ctptr) {
dea31012005-04-17 16:05:31 -0500483 ctptr = (uint32_t *) mlast->virt;
James Smart1dcb58e2007-04-25 09:51:30 -0400484 } else
dea31012005-04-17 16:05:31 -0500485 Cnt -= 16; /* subtract length of CT header */
486
487 /* Loop through entire NameServer list of DIDs */
James Smart4258e982015-12-16 18:11:58 -0500488 while (Cnt >= sizeof(uint32_t)) {
dea31012005-04-17 16:05:31 -0500489 /* Get next DID from NameServer List */
490 CTentry = *ctptr++;
491 Did = ((be32_to_cpu(CTentry)) & Mask_DID);
James Smart92d7f7b2007-06-17 19:56:38 -0500492
dea31012005-04-17 16:05:31 -0500493 ndlp = NULL;
James Smart92d7f7b2007-06-17 19:56:38 -0500494
495 /*
496 * Check for rscn processing or not
497 * To conserve rpi's, filter out addresses for other
498 * vports on the same physical HBAs.
499 */
500 if ((Did != vport->fc_myDID) &&
501 ((lpfc_find_vport_by_did(phba, Did) == NULL) ||
James Smart3de2a652007-08-02 11:09:59 -0400502 vport->cfg_peer_port_login)) {
James Smart92d7f7b2007-06-17 19:56:38 -0500503 if ((vport->port_type != LPFC_NPIV_PORT) ||
James Smart98c9ea52007-10-27 13:37:33 -0400504 (!(vport->ct_flags & FC_CT_RFF_ID)) ||
James Smart3de2a652007-08-02 11:09:59 -0400505 (!vport->cfg_restrict_login)) {
James Smart92d7f7b2007-06-17 19:56:38 -0500506 ndlp = lpfc_setup_disc_node(vport, Did);
James Smart58da1ff2008-04-07 10:15:56 -0400507 if (ndlp && NLP_CHK_NODE_ACT(ndlp)) {
James Smart858c9f62007-06-17 19:56:39 -0500508 lpfc_debugfs_disc_trc(vport,
509 LPFC_DISC_TRC_CT,
510 "Parse GID_FTrsp: "
511 "did:x%x flg:x%x x%x",
512 Did, ndlp->nlp_flag,
513 vport->fc_flag);
514
James Smarte8b62012007-08-02 11:10:09 -0400515 lpfc_printf_vlog(vport,
516 KERN_INFO,
James Smart92d7f7b2007-06-17 19:56:38 -0500517 LOG_DISCOVERY,
James Smarte8b62012007-08-02 11:10:09 -0400518 "0238 Process "
James Smart92d7f7b2007-06-17 19:56:38 -0500519 "x%x NameServer Rsp"
520 "Data: x%x x%x x%x\n",
James Smarte8b62012007-08-02 11:10:09 -0400521 Did, ndlp->nlp_flag,
James Smart92d7f7b2007-06-17 19:56:38 -0500522 vport->fc_flag,
523 vport->fc_rscn_id_cnt);
524 } else {
James Smart858c9f62007-06-17 19:56:39 -0500525 lpfc_debugfs_disc_trc(vport,
526 LPFC_DISC_TRC_CT,
527 "Skip1 GID_FTrsp: "
528 "did:x%x flg:x%x cnt:%d",
529 Did, vport->fc_flag,
530 vport->fc_rscn_id_cnt);
531
James Smarte8b62012007-08-02 11:10:09 -0400532 lpfc_printf_vlog(vport,
533 KERN_INFO,
James Smart92d7f7b2007-06-17 19:56:38 -0500534 LOG_DISCOVERY,
James Smarte8b62012007-08-02 11:10:09 -0400535 "0239 Skip x%x "
James Smart92d7f7b2007-06-17 19:56:38 -0500536 "NameServer Rsp Data: "
537 "x%x x%x\n",
James Smarte8b62012007-08-02 11:10:09 -0400538 Did, vport->fc_flag,
James Smart92d7f7b2007-06-17 19:56:38 -0500539 vport->fc_rscn_id_cnt);
540 }
541
542 } else {
543 if (!(vport->fc_flag & FC_RSCN_MODE) ||
544 (lpfc_rscn_payload_check(vport, Did))) {
James Smart858c9f62007-06-17 19:56:39 -0500545 lpfc_debugfs_disc_trc(vport,
546 LPFC_DISC_TRC_CT,
547 "Query GID_FTrsp: "
548 "did:x%x flg:x%x cnt:%d",
549 Did, vport->fc_flag,
550 vport->fc_rscn_id_cnt);
551
James Smart0ff10d42008-01-11 01:52:36 -0500552 /* This NPortID was previously
553 * a FCP target, * Don't even
554 * bother to send GFF_ID.
555 */
556 ndlp = lpfc_findnode_did(vport,
557 Did);
James Smarte47c9092008-02-08 18:49:26 -0500558 if (ndlp &&
559 NLP_CHK_NODE_ACT(ndlp)
560 && (ndlp->nlp_type &
561 NLP_FCP_TARGET))
James Smart0ff10d42008-01-11 01:52:36 -0500562 lpfc_setup_disc_node
563 (vport, Did);
564 else if (lpfc_ns_cmd(vport,
James Smart92d7f7b2007-06-17 19:56:38 -0500565 SLI_CTNS_GFF_ID,
566 0, Did) == 0)
567 vport->num_disc_nodes++;
James Smart6a9c52c2009-10-02 15:16:51 -0400568 else
569 lpfc_setup_disc_node
570 (vport, Did);
James Smart92d7f7b2007-06-17 19:56:38 -0500571 }
572 else {
James Smart858c9f62007-06-17 19:56:39 -0500573 lpfc_debugfs_disc_trc(vport,
574 LPFC_DISC_TRC_CT,
575 "Skip2 GID_FTrsp: "
576 "did:x%x flg:x%x cnt:%d",
577 Did, vport->fc_flag,
578 vport->fc_rscn_id_cnt);
579
James Smarte8b62012007-08-02 11:10:09 -0400580 lpfc_printf_vlog(vport,
581 KERN_INFO,
James Smart92d7f7b2007-06-17 19:56:38 -0500582 LOG_DISCOVERY,
James Smarte8b62012007-08-02 11:10:09 -0400583 "0245 Skip x%x "
James Smart92d7f7b2007-06-17 19:56:38 -0500584 "NameServer Rsp Data: "
585 "x%x x%x\n",
James Smarte8b62012007-08-02 11:10:09 -0400586 Did, vport->fc_flag,
James Smart92d7f7b2007-06-17 19:56:38 -0500587 vport->fc_rscn_id_cnt);
588 }
589 }
dea31012005-04-17 16:05:31 -0500590 }
James Smart76b2c342015-04-07 15:07:19 -0400591 if (CTentry & (cpu_to_be32(SLI_CT_LAST_ENTRY)))
dea31012005-04-17 16:05:31 -0500592 goto nsout1;
James Smart4258e982015-12-16 18:11:58 -0500593 Cnt -= sizeof(uint32_t);
dea31012005-04-17 16:05:31 -0500594 }
595 ctptr = NULL;
596
597 }
598
599nsout1:
600 list_del(&head);
dea31012005-04-17 16:05:31 -0500601 return 0;
602}
603
dea31012005-04-17 16:05:31 -0500604static void
James Smart2e0fef82007-06-17 19:56:36 -0500605lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
606 struct lpfc_iocbq *rspiocb)
dea31012005-04-17 16:05:31 -0500607{
James Smart2e0fef82007-06-17 19:56:36 -0500608 struct lpfc_vport *vport = cmdiocb->vport;
James Smart92d7f7b2007-06-17 19:56:38 -0500609 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
dea31012005-04-17 16:05:31 -0500610 IOCB_t *irsp;
dea31012005-04-17 16:05:31 -0500611 struct lpfc_dmabuf *outp;
dea31012005-04-17 16:05:31 -0500612 struct lpfc_sli_ct_request *CTrsp;
James Smart51ef4c22007-08-02 11:10:31 -0400613 struct lpfc_nodelist *ndlp;
James Smart58da1ff2008-04-07 10:15:56 -0400614 int rc;
dea31012005-04-17 16:05:31 -0500615
James Smart51ef4c22007-08-02 11:10:31 -0400616 /* First save ndlp, before we overwrite it */
617 ndlp = cmdiocb->context_un.ndlp;
618
dea31012005-04-17 16:05:31 -0500619 /* we pass cmdiocb to state machine which needs rspiocb as well */
620 cmdiocb->context_un.rsp_iocb = rspiocb;
621
dea31012005-04-17 16:05:31 -0500622 outp = (struct lpfc_dmabuf *) cmdiocb->context2;
James Smart858c9f62007-06-17 19:56:39 -0500623 irsp = &rspiocb->iocb;
624
625 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT,
626 "GID_FT cmpl: status:x%x/x%x rtry:%d",
627 irsp->ulpStatus, irsp->un.ulpWord[4], vport->fc_ns_retry);
dea31012005-04-17 16:05:31 -0500628
James Smart92d7f7b2007-06-17 19:56:38 -0500629 /* Don't bother processing response if vport is being torn down. */
James Smarteada2722008-12-04 22:39:13 -0500630 if (vport->load_flag & FC_UNLOADING) {
631 if (vport->fc_flag & FC_RSCN_MODE)
632 lpfc_els_flush_rscn(vport);
James Smart92d7f7b2007-06-17 19:56:38 -0500633 goto out;
James Smarteada2722008-12-04 22:39:13 -0500634 }
James Smart92d7f7b2007-06-17 19:56:38 -0500635
James Smart58da1ff2008-04-07 10:15:56 -0400636 if (lpfc_els_chk_latt(vport)) {
James Smarte8b62012007-08-02 11:10:09 -0400637 lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
638 "0216 Link event during NS query\n");
James Smarteada2722008-12-04 22:39:13 -0500639 if (vport->fc_flag & FC_RSCN_MODE)
640 lpfc_els_flush_rscn(vport);
James Smart858c9f62007-06-17 19:56:39 -0500641 lpfc_vport_set_state(vport, FC_VPORT_FAILED);
642 goto out;
643 }
James Smart58da1ff2008-04-07 10:15:56 -0400644 if (lpfc_error_lost_link(irsp)) {
645 lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
646 "0226 NS query failed due to link event\n");
James Smarteada2722008-12-04 22:39:13 -0500647 if (vport->fc_flag & FC_RSCN_MODE)
648 lpfc_els_flush_rscn(vport);
James Smart58da1ff2008-04-07 10:15:56 -0400649 goto out;
650 }
James Smart858c9f62007-06-17 19:56:39 -0500651 if (irsp->ulpStatus) {
dea31012005-04-17 16:05:31 -0500652 /* Check for retry */
James Smart2e0fef82007-06-17 19:56:36 -0500653 if (vport->fc_ns_retry < LPFC_MAX_NS_RETRY) {
James Smart58da1ff2008-04-07 10:15:56 -0400654 if (irsp->ulpStatus != IOSTAT_LOCAL_REJECT ||
James Smartedb22f02012-10-31 14:45:21 -0400655 (irsp->un.ulpWord[4] & IOERR_PARAM_MASK) !=
James Smarte3d2b802012-08-14 14:25:43 -0400656 IOERR_NO_RESOURCES)
James Smart858c9f62007-06-17 19:56:39 -0500657 vport->fc_ns_retry++;
James Smart0ff10d42008-01-11 01:52:36 -0500658
James Smart58da1ff2008-04-07 10:15:56 -0400659 /* CT command is being retried */
660 rc = lpfc_ns_cmd(vport, SLI_CTNS_GID_FT,
James Smart92d7f7b2007-06-17 19:56:38 -0500661 vport->fc_ns_retry, 0);
James Smart58da1ff2008-04-07 10:15:56 -0400662 if (rc == 0)
663 goto out;
James Smart92d7f7b2007-06-17 19:56:38 -0500664 }
James Smarteada2722008-12-04 22:39:13 -0500665 if (vport->fc_flag & FC_RSCN_MODE)
666 lpfc_els_flush_rscn(vport);
James Smart92d7f7b2007-06-17 19:56:38 -0500667 lpfc_vport_set_state(vport, FC_VPORT_FAILED);
James Smarte8b62012007-08-02 11:10:09 -0400668 lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
669 "0257 GID_FT Query error: 0x%x 0x%x\n",
670 irsp->ulpStatus, vport->fc_ns_retry);
dea31012005-04-17 16:05:31 -0500671 } else {
672 /* Good status, continue checking */
673 CTrsp = (struct lpfc_sli_ct_request *) outp->virt;
674 if (CTrsp->CommandResponse.bits.CmdRsp ==
James Smart76b2c342015-04-07 15:07:19 -0400675 cpu_to_be16(SLI_CT_RESPONSE_FS_ACC)) {
James Smarte8b62012007-08-02 11:10:09 -0400676 lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
677 "0208 NameServer Rsp Data: x%x\n",
678 vport->fc_flag);
James Smart2e0fef82007-06-17 19:56:36 -0500679 lpfc_ns_rsp(vport, outp,
dea31012005-04-17 16:05:31 -0500680 (uint32_t) (irsp->un.genreq64.bdl.bdeSize));
681 } else if (CTrsp->CommandResponse.bits.CmdRsp ==
682 be16_to_cpu(SLI_CT_RESPONSE_FS_RJT)) {
683 /* NameServer Rsp Error */
James Smarta58cbd52007-08-02 11:09:43 -0400684 if ((CTrsp->ReasonCode == SLI_CT_UNABLE_TO_PERFORM_REQ)
685 && (CTrsp->Explanation == SLI_CT_NO_FC4_TYPES)) {
James Smarte8b62012007-08-02 11:10:09 -0400686 lpfc_printf_vlog(vport, KERN_INFO,
687 LOG_DISCOVERY,
688 "0269 No NameServer Entries "
James Smarta58cbd52007-08-02 11:09:43 -0400689 "Data: x%x x%x x%x x%x\n",
James Smarta58cbd52007-08-02 11:09:43 -0400690 CTrsp->CommandResponse.bits.CmdRsp,
691 (uint32_t) CTrsp->ReasonCode,
692 (uint32_t) CTrsp->Explanation,
693 vport->fc_flag);
694
695 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT,
696 "GID_FT no entry cmd:x%x rsn:x%x exp:x%x",
697 (uint32_t)CTrsp->CommandResponse.bits.CmdRsp,
698 (uint32_t) CTrsp->ReasonCode,
699 (uint32_t) CTrsp->Explanation);
James Smarte8b62012007-08-02 11:10:09 -0400700 } else {
701 lpfc_printf_vlog(vport, KERN_INFO,
702 LOG_DISCOVERY,
703 "0240 NameServer Rsp Error "
dea31012005-04-17 16:05:31 -0500704 "Data: x%x x%x x%x x%x\n",
dea31012005-04-17 16:05:31 -0500705 CTrsp->CommandResponse.bits.CmdRsp,
706 (uint32_t) CTrsp->ReasonCode,
707 (uint32_t) CTrsp->Explanation,
James Smart2e0fef82007-06-17 19:56:36 -0500708 vport->fc_flag);
James Smart858c9f62007-06-17 19:56:39 -0500709
James Smarta58cbd52007-08-02 11:09:43 -0400710 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT,
James Smart858c9f62007-06-17 19:56:39 -0500711 "GID_FT rsp err1 cmd:x%x rsn:x%x exp:x%x",
712 (uint32_t)CTrsp->CommandResponse.bits.CmdRsp,
713 (uint32_t) CTrsp->ReasonCode,
714 (uint32_t) CTrsp->Explanation);
James Smarta58cbd52007-08-02 11:09:43 -0400715 }
716
James Smart858c9f62007-06-17 19:56:39 -0500717
dea31012005-04-17 16:05:31 -0500718 } else {
719 /* NameServer Rsp Error */
James Smarte8b62012007-08-02 11:10:09 -0400720 lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY,
721 "0241 NameServer Rsp Error "
dea31012005-04-17 16:05:31 -0500722 "Data: x%x x%x x%x x%x\n",
dea31012005-04-17 16:05:31 -0500723 CTrsp->CommandResponse.bits.CmdRsp,
724 (uint32_t) CTrsp->ReasonCode,
725 (uint32_t) CTrsp->Explanation,
James Smart2e0fef82007-06-17 19:56:36 -0500726 vport->fc_flag);
James Smart858c9f62007-06-17 19:56:39 -0500727
728 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT,
729 "GID_FT rsp err2 cmd:x%x rsn:x%x exp:x%x",
730 (uint32_t)CTrsp->CommandResponse.bits.CmdRsp,
731 (uint32_t) CTrsp->ReasonCode,
732 (uint32_t) CTrsp->Explanation);
dea31012005-04-17 16:05:31 -0500733 }
734 }
735 /* Link up / RSCN discovery */
James Smart92d7f7b2007-06-17 19:56:38 -0500736 if (vport->num_disc_nodes == 0) {
737 /*
738 * The driver has cycled through all Nports in the RSCN payload.
739 * Complete the handling by cleaning up and marking the
740 * current driver state.
741 */
742 if (vport->port_state >= LPFC_DISC_AUTH) {
743 if (vport->fc_flag & FC_RSCN_MODE) {
744 lpfc_els_flush_rscn(vport);
745 spin_lock_irq(shost->host_lock);
746 vport->fc_flag |= FC_RSCN_MODE; /* RSCN still */
747 spin_unlock_irq(shost->host_lock);
748 }
749 else
750 lpfc_els_flush_rscn(vport);
751 }
752
753 lpfc_disc_start(vport);
754 }
dea31012005-04-17 16:05:31 -0500755out:
James Smart51ef4c22007-08-02 11:10:31 -0400756 cmdiocb->context_un.ndlp = ndlp; /* Now restore ndlp for free */
James Smart858c9f62007-06-17 19:56:39 -0500757 lpfc_ct_free_iocb(phba, cmdiocb);
dea31012005-04-17 16:05:31 -0500758 return;
759}
760
James Smart311464e2007-08-02 11:10:37 -0400761static void
James Smart92d7f7b2007-06-17 19:56:38 -0500762lpfc_cmpl_ct_cmd_gff_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
763 struct lpfc_iocbq *rspiocb)
764{
765 struct lpfc_vport *vport = cmdiocb->vport;
766 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
767 IOCB_t *irsp = &rspiocb->iocb;
James Smart92d7f7b2007-06-17 19:56:38 -0500768 struct lpfc_dmabuf *inp = (struct lpfc_dmabuf *) cmdiocb->context1;
769 struct lpfc_dmabuf *outp = (struct lpfc_dmabuf *) cmdiocb->context2;
770 struct lpfc_sli_ct_request *CTrsp;
James Smart0ff10d42008-01-11 01:52:36 -0500771 int did, rc, retry;
James Smart92d7f7b2007-06-17 19:56:38 -0500772 uint8_t fbits;
773 struct lpfc_nodelist *ndlp;
774
775 did = ((struct lpfc_sli_ct_request *) inp->virt)->un.gff.PortId;
776 did = be32_to_cpu(did);
777
James Smart858c9f62007-06-17 19:56:39 -0500778 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT,
779 "GFF_ID cmpl: status:x%x/x%x did:x%x",
780 irsp->ulpStatus, irsp->un.ulpWord[4], did);
781
James Smart92d7f7b2007-06-17 19:56:38 -0500782 if (irsp->ulpStatus == IOSTAT_SUCCESS) {
783 /* Good status, continue checking */
784 CTrsp = (struct lpfc_sli_ct_request *) outp->virt;
785 fbits = CTrsp->un.gff_acc.fbits[FCP_TYPE_FEATURE_OFFSET];
786
787 if (CTrsp->CommandResponse.bits.CmdRsp ==
788 be16_to_cpu(SLI_CT_RESPONSE_FS_ACC)) {
789 if ((fbits & FC4_FEATURE_INIT) &&
790 !(fbits & FC4_FEATURE_TARGET)) {
James Smarte8b62012007-08-02 11:10:09 -0400791 lpfc_printf_vlog(vport, KERN_INFO,
792 LOG_DISCOVERY,
793 "0270 Skip x%x GFF "
794 "NameServer Rsp Data: (init) "
795 "x%x x%x\n", did, fbits,
796 vport->fc_rscn_id_cnt);
James Smart92d7f7b2007-06-17 19:56:38 -0500797 goto out;
798 }
799 }
800 }
James Smart858c9f62007-06-17 19:56:39 -0500801 else {
James Smart0ff10d42008-01-11 01:52:36 -0500802 /* Check for retry */
803 if (cmdiocb->retry < LPFC_MAX_NS_RETRY) {
804 retry = 1;
805 if (irsp->ulpStatus == IOSTAT_LOCAL_REJECT) {
James Smarte3d2b802012-08-14 14:25:43 -0400806 switch ((irsp->un.ulpWord[4] &
807 IOERR_PARAM_MASK)) {
808
James Smart0ff10d42008-01-11 01:52:36 -0500809 case IOERR_NO_RESOURCES:
810 /* We don't increment the retry
811 * count for this case.
812 */
813 break;
814 case IOERR_LINK_DOWN:
815 case IOERR_SLI_ABORTED:
816 case IOERR_SLI_DOWN:
817 retry = 0;
818 break;
819 default:
820 cmdiocb->retry++;
821 }
822 }
823 else
824 cmdiocb->retry++;
825
826 if (retry) {
827 /* CT command is being retried */
828 rc = lpfc_ns_cmd(vport, SLI_CTNS_GFF_ID,
829 cmdiocb->retry, did);
830 if (rc == 0) {
831 /* success */
832 lpfc_ct_free_iocb(phba, cmdiocb);
833 return;
834 }
835 }
836 }
James Smarte8b62012007-08-02 11:10:09 -0400837 lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY,
838 "0267 NameServer GFF Rsp "
839 "x%x Error (%d %d) Data: x%x x%x\n",
840 did, irsp->ulpStatus, irsp->un.ulpWord[4],
James Smart7f5f3d02008-02-08 18:50:14 -0500841 vport->fc_flag, vport->fc_rscn_id_cnt);
James Smart858c9f62007-06-17 19:56:39 -0500842 }
843
James Smart92d7f7b2007-06-17 19:56:38 -0500844 /* This is a target port, unregistered port, or the GFF_ID failed */
845 ndlp = lpfc_setup_disc_node(vport, did);
James Smart58da1ff2008-04-07 10:15:56 -0400846 if (ndlp && NLP_CHK_NODE_ACT(ndlp)) {
James Smarte8b62012007-08-02 11:10:09 -0400847 lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
848 "0242 Process x%x GFF "
849 "NameServer Rsp Data: x%x x%x x%x\n",
850 did, ndlp->nlp_flag, vport->fc_flag,
851 vport->fc_rscn_id_cnt);
James Smart92d7f7b2007-06-17 19:56:38 -0500852 } else {
James Smarte8b62012007-08-02 11:10:09 -0400853 lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
854 "0243 Skip x%x GFF "
855 "NameServer Rsp Data: x%x x%x\n", did,
856 vport->fc_flag, vport->fc_rscn_id_cnt);
James Smart92d7f7b2007-06-17 19:56:38 -0500857 }
858out:
859 /* Link up / RSCN discovery */
860 if (vport->num_disc_nodes)
861 vport->num_disc_nodes--;
862 if (vport->num_disc_nodes == 0) {
863 /*
864 * The driver has cycled through all Nports in the RSCN payload.
865 * Complete the handling by cleaning up and marking the
866 * current driver state.
867 */
868 if (vport->port_state >= LPFC_DISC_AUTH) {
869 if (vport->fc_flag & FC_RSCN_MODE) {
870 lpfc_els_flush_rscn(vport);
871 spin_lock_irq(shost->host_lock);
872 vport->fc_flag |= FC_RSCN_MODE; /* RSCN still */
873 spin_unlock_irq(shost->host_lock);
874 }
875 else
876 lpfc_els_flush_rscn(vport);
877 }
878 lpfc_disc_start(vport);
879 }
James Smart858c9f62007-06-17 19:56:39 -0500880 lpfc_ct_free_iocb(phba, cmdiocb);
James Smart92d7f7b2007-06-17 19:56:38 -0500881 return;
882}
883
884
dea31012005-04-17 16:05:31 -0500885static void
James Smart7ee5d432007-10-27 13:37:17 -0400886lpfc_cmpl_ct(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
887 struct lpfc_iocbq *rspiocb)
dea31012005-04-17 16:05:31 -0500888{
James Smart92d7f7b2007-06-17 19:56:38 -0500889 struct lpfc_vport *vport = cmdiocb->vport;
dea31012005-04-17 16:05:31 -0500890 struct lpfc_dmabuf *inp;
891 struct lpfc_dmabuf *outp;
892 IOCB_t *irsp;
893 struct lpfc_sli_ct_request *CTrsp;
James Smart51ef4c22007-08-02 11:10:31 -0400894 struct lpfc_nodelist *ndlp;
James Smart92d7f7b2007-06-17 19:56:38 -0500895 int cmdcode, rc;
896 uint8_t retry;
James Smart858c9f62007-06-17 19:56:39 -0500897 uint32_t latt;
dea31012005-04-17 16:05:31 -0500898
James Smart51ef4c22007-08-02 11:10:31 -0400899 /* First save ndlp, before we overwrite it */
900 ndlp = cmdiocb->context_un.ndlp;
901
dea31012005-04-17 16:05:31 -0500902 /* we pass cmdiocb to state machine which needs rspiocb as well */
903 cmdiocb->context_un.rsp_iocb = rspiocb;
904
905 inp = (struct lpfc_dmabuf *) cmdiocb->context1;
906 outp = (struct lpfc_dmabuf *) cmdiocb->context2;
dea31012005-04-17 16:05:31 -0500907 irsp = &rspiocb->iocb;
908
James Smart92d7f7b2007-06-17 19:56:38 -0500909 cmdcode = be16_to_cpu(((struct lpfc_sli_ct_request *) inp->virt)->
910 CommandResponse.bits.CmdRsp);
dea31012005-04-17 16:05:31 -0500911 CTrsp = (struct lpfc_sli_ct_request *) outp->virt;
912
James Smart858c9f62007-06-17 19:56:39 -0500913 latt = lpfc_els_chk_latt(vport);
914
915 /* RFT request completes status <ulpStatus> CmdRsp <CmdRsp> */
James Smarte8b62012007-08-02 11:10:09 -0400916 lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
James Smart7ee5d432007-10-27 13:37:17 -0400917 "0209 CT Request completes, latt %d, "
James Smarte8b62012007-08-02 11:10:09 -0400918 "ulpStatus x%x CmdRsp x%x, Context x%x, Tag x%x\n",
919 latt, irsp->ulpStatus,
920 CTrsp->CommandResponse.bits.CmdRsp,
921 cmdiocb->iocb.ulpContext, cmdiocb->iocb.ulpIoTag);
dea31012005-04-17 16:05:31 -0500922
James Smart858c9f62007-06-17 19:56:39 -0500923 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT,
924 "CT cmd cmpl: status:x%x/x%x cmd:x%x",
925 irsp->ulpStatus, irsp->un.ulpWord[4], cmdcode);
926
James Smart92d7f7b2007-06-17 19:56:38 -0500927 if (irsp->ulpStatus) {
James Smarte8b62012007-08-02 11:10:09 -0400928 lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY,
James Smart6e155202013-07-15 18:35:21 -0400929 "0268 NS cmd x%x Error (x%x x%x)\n",
James Smarte8b62012007-08-02 11:10:09 -0400930 cmdcode, irsp->ulpStatus, irsp->un.ulpWord[4]);
James Smart858c9f62007-06-17 19:56:39 -0500931
James Smart92d7f7b2007-06-17 19:56:38 -0500932 if ((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) &&
James Smarte3d2b802012-08-14 14:25:43 -0400933 (((irsp->un.ulpWord[4] & IOERR_PARAM_MASK) ==
934 IOERR_SLI_DOWN) ||
935 ((irsp->un.ulpWord[4] & IOERR_PARAM_MASK) ==
936 IOERR_SLI_ABORTED)))
James Smart92d7f7b2007-06-17 19:56:38 -0500937 goto out;
938
939 retry = cmdiocb->retry;
940 if (retry >= LPFC_MAX_NS_RETRY)
941 goto out;
942
943 retry++;
James Smarte8b62012007-08-02 11:10:09 -0400944 lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
James Smartd7c255b2008-08-24 21:50:00 -0400945 "0250 Retrying NS cmd %x\n", cmdcode);
James Smart92d7f7b2007-06-17 19:56:38 -0500946 rc = lpfc_ns_cmd(vport, cmdcode, retry, 0);
947 if (rc == 0)
948 goto out;
949 }
950
951out:
James Smart51ef4c22007-08-02 11:10:31 -0400952 cmdiocb->context_un.ndlp = ndlp; /* Now restore ndlp for free */
James Smart858c9f62007-06-17 19:56:39 -0500953 lpfc_ct_free_iocb(phba, cmdiocb);
dea31012005-04-17 16:05:31 -0500954 return;
955}
956
957static void
James Smart7ee5d432007-10-27 13:37:17 -0400958lpfc_cmpl_ct_cmd_rft_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
959 struct lpfc_iocbq *rspiocb)
960{
961 IOCB_t *irsp = &rspiocb->iocb;
962 struct lpfc_vport *vport = cmdiocb->vport;
963
James Smart98c9ea52007-10-27 13:37:33 -0400964 if (irsp->ulpStatus == IOSTAT_SUCCESS) {
965 struct lpfc_dmabuf *outp;
966 struct lpfc_sli_ct_request *CTrsp;
967
968 outp = (struct lpfc_dmabuf *) cmdiocb->context2;
969 CTrsp = (struct lpfc_sli_ct_request *) outp->virt;
970 if (CTrsp->CommandResponse.bits.CmdRsp ==
971 be16_to_cpu(SLI_CT_RESPONSE_FS_ACC))
972 vport->ct_flags |= FC_CT_RFT_ID;
973 }
James Smart7ee5d432007-10-27 13:37:17 -0400974 lpfc_cmpl_ct(phba, cmdiocb, rspiocb);
975 return;
976}
977
978static void
James Smart2e0fef82007-06-17 19:56:36 -0500979lpfc_cmpl_ct_cmd_rnn_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
980 struct lpfc_iocbq *rspiocb)
dea31012005-04-17 16:05:31 -0500981{
James Smart7ee5d432007-10-27 13:37:17 -0400982 IOCB_t *irsp = &rspiocb->iocb;
983 struct lpfc_vport *vport = cmdiocb->vport;
984
James Smart98c9ea52007-10-27 13:37:33 -0400985 if (irsp->ulpStatus == IOSTAT_SUCCESS) {
986 struct lpfc_dmabuf *outp;
987 struct lpfc_sli_ct_request *CTrsp;
988
989 outp = (struct lpfc_dmabuf *) cmdiocb->context2;
990 CTrsp = (struct lpfc_sli_ct_request *) outp->virt;
991 if (CTrsp->CommandResponse.bits.CmdRsp ==
992 be16_to_cpu(SLI_CT_RESPONSE_FS_ACC))
993 vport->ct_flags |= FC_CT_RNN_ID;
994 }
James Smart7ee5d432007-10-27 13:37:17 -0400995 lpfc_cmpl_ct(phba, cmdiocb, rspiocb);
dea31012005-04-17 16:05:31 -0500996 return;
997}
998
999static void
James Smart92d7f7b2007-06-17 19:56:38 -05001000lpfc_cmpl_ct_cmd_rspn_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
1001 struct lpfc_iocbq *rspiocb)
1002{
James Smart7ee5d432007-10-27 13:37:17 -04001003 IOCB_t *irsp = &rspiocb->iocb;
1004 struct lpfc_vport *vport = cmdiocb->vport;
1005
James Smart98c9ea52007-10-27 13:37:33 -04001006 if (irsp->ulpStatus == IOSTAT_SUCCESS) {
1007 struct lpfc_dmabuf *outp;
1008 struct lpfc_sli_ct_request *CTrsp;
1009
1010 outp = (struct lpfc_dmabuf *) cmdiocb->context2;
1011 CTrsp = (struct lpfc_sli_ct_request *) outp->virt;
1012 if (CTrsp->CommandResponse.bits.CmdRsp ==
1013 be16_to_cpu(SLI_CT_RESPONSE_FS_ACC))
1014 vport->ct_flags |= FC_CT_RSPN_ID;
1015 }
James Smart7ee5d432007-10-27 13:37:17 -04001016 lpfc_cmpl_ct(phba, cmdiocb, rspiocb);
James Smart92d7f7b2007-06-17 19:56:38 -05001017 return;
1018}
1019
1020static void
James Smart2e0fef82007-06-17 19:56:36 -05001021lpfc_cmpl_ct_cmd_rsnn_nn(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
1022 struct lpfc_iocbq *rspiocb)
dea31012005-04-17 16:05:31 -05001023{
James Smart7ee5d432007-10-27 13:37:17 -04001024 IOCB_t *irsp = &rspiocb->iocb;
1025 struct lpfc_vport *vport = cmdiocb->vport;
1026
James Smart98c9ea52007-10-27 13:37:33 -04001027 if (irsp->ulpStatus == IOSTAT_SUCCESS) {
1028 struct lpfc_dmabuf *outp;
1029 struct lpfc_sli_ct_request *CTrsp;
1030
1031 outp = (struct lpfc_dmabuf *) cmdiocb->context2;
1032 CTrsp = (struct lpfc_sli_ct_request *) outp->virt;
1033 if (CTrsp->CommandResponse.bits.CmdRsp ==
1034 be16_to_cpu(SLI_CT_RESPONSE_FS_ACC))
1035 vport->ct_flags |= FC_CT_RSNN_NN;
1036 }
James Smart7ee5d432007-10-27 13:37:17 -04001037 lpfc_cmpl_ct(phba, cmdiocb, rspiocb);
1038 return;
1039}
1040
1041static void
1042lpfc_cmpl_ct_cmd_da_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
1043 struct lpfc_iocbq *rspiocb)
1044{
1045 struct lpfc_vport *vport = cmdiocb->vport;
1046
1047 /* even if it fails we will act as though it succeeded. */
1048 vport->ct_flags = 0;
1049 lpfc_cmpl_ct(phba, cmdiocb, rspiocb);
dea31012005-04-17 16:05:31 -05001050 return;
1051}
1052
James Smart2fb9bd82006-12-02 13:33:57 -05001053static void
James Smart92d7f7b2007-06-17 19:56:38 -05001054lpfc_cmpl_ct_cmd_rff_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
1055 struct lpfc_iocbq *rspiocb)
James Smart2fb9bd82006-12-02 13:33:57 -05001056{
James Smart92d7f7b2007-06-17 19:56:38 -05001057 IOCB_t *irsp = &rspiocb->iocb;
1058 struct lpfc_vport *vport = cmdiocb->vport;
1059
James Smart98c9ea52007-10-27 13:37:33 -04001060 if (irsp->ulpStatus == IOSTAT_SUCCESS) {
1061 struct lpfc_dmabuf *outp;
1062 struct lpfc_sli_ct_request *CTrsp;
1063
1064 outp = (struct lpfc_dmabuf *) cmdiocb->context2;
1065 CTrsp = (struct lpfc_sli_ct_request *) outp->virt;
1066 if (CTrsp->CommandResponse.bits.CmdRsp ==
1067 be16_to_cpu(SLI_CT_RESPONSE_FS_ACC))
1068 vport->ct_flags |= FC_CT_RFF_ID;
1069 }
James Smart7ee5d432007-10-27 13:37:17 -04001070 lpfc_cmpl_ct(phba, cmdiocb, rspiocb);
James Smart2fb9bd82006-12-02 13:33:57 -05001071 return;
1072}
1073
James Smart495a7142008-06-14 22:52:59 -04001074int
James Smart92d7f7b2007-06-17 19:56:38 -05001075lpfc_vport_symbolic_port_name(struct lpfc_vport *vport, char *symbol,
1076 size_t size)
1077{
1078 int n;
1079 uint8_t *wwn = vport->phba->wwpn;
1080
1081 n = snprintf(symbol, size,
1082 "Emulex PPN-%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
1083 wwn[0], wwn[1], wwn[2], wwn[3],
1084 wwn[4], wwn[5], wwn[6], wwn[7]);
1085
1086 if (vport->port_type == LPFC_PHYSICAL_PORT)
1087 return n;
1088
1089 if (n < size)
1090 n += snprintf(symbol + n, size - n, " VPort-%d", vport->vpi);
1091
James Smarteada2722008-12-04 22:39:13 -05001092 if (n < size &&
1093 strlen(vport->fc_vport->symbolic_name))
1094 n += snprintf(symbol + n, size - n, " VName-%s",
1095 vport->fc_vport->symbolic_name);
James Smart92d7f7b2007-06-17 19:56:38 -05001096 return n;
1097}
1098
1099int
1100lpfc_vport_symbolic_node_name(struct lpfc_vport *vport, char *symbol,
1101 size_t size)
dea31012005-04-17 16:05:31 -05001102{
James Smart6b5151f2012-01-18 16:24:06 -05001103 char fwrev[FW_REV_STR_SIZE];
James Smart92d7f7b2007-06-17 19:56:38 -05001104 int n;
dea31012005-04-17 16:05:31 -05001105
James Smart92d7f7b2007-06-17 19:56:38 -05001106 lpfc_decode_firmware_rev(vport->phba, fwrev, 0);
dea31012005-04-17 16:05:31 -05001107
James Smartf0bf5f92015-04-07 15:07:18 -04001108 n = snprintf(symbol, size, "Emulex %s", vport->phba->ModelName);
1109
1110 if (size < n)
1111 return n;
1112 n += snprintf(symbol + n, size - n, " FV%s", fwrev);
1113
1114 if (size < n)
1115 return n;
1116 n += snprintf(symbol + n, size - n, " DV%s", lpfc_release_version);
1117
1118 if (size < n)
1119 return n;
1120 n += snprintf(symbol + n, size - n, " HN:%s", init_utsname()->nodename);
1121
1122 /* Note :- OS name is "Linux" */
1123 if (size < n)
1124 return n;
1125 n += snprintf(symbol + n, size - n, " OS:%s", init_utsname()->sysname);
1126
James Smart92d7f7b2007-06-17 19:56:38 -05001127 return n;
dea31012005-04-17 16:05:31 -05001128}
1129
James Smart76b2c342015-04-07 15:07:19 -04001130static uint32_t
1131lpfc_find_map_node(struct lpfc_vport *vport)
1132{
1133 struct lpfc_nodelist *ndlp, *next_ndlp;
1134 struct Scsi_Host *shost;
1135 uint32_t cnt = 0;
1136
1137 shost = lpfc_shost_from_vport(vport);
1138 spin_lock_irq(shost->host_lock);
1139 list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) {
1140 if (ndlp->nlp_type & NLP_FABRIC)
1141 continue;
1142 if ((ndlp->nlp_state == NLP_STE_MAPPED_NODE) ||
1143 (ndlp->nlp_state == NLP_STE_UNMAPPED_NODE))
1144 cnt++;
1145 }
1146 spin_unlock_irq(shost->host_lock);
1147 return cnt;
1148}
1149
dea31012005-04-17 16:05:31 -05001150/*
1151 * lpfc_ns_cmd
1152 * Description:
1153 * Issue Cmd to NameServer
1154 * SLI_CTNS_GID_FT
1155 * LI_CTNS_RFT_ID
1156 */
1157int
James Smart92d7f7b2007-06-17 19:56:38 -05001158lpfc_ns_cmd(struct lpfc_vport *vport, int cmdcode,
1159 uint8_t retry, uint32_t context)
dea31012005-04-17 16:05:31 -05001160{
James Smart92d7f7b2007-06-17 19:56:38 -05001161 struct lpfc_nodelist * ndlp;
James Smart2e0fef82007-06-17 19:56:36 -05001162 struct lpfc_hba *phba = vport->phba;
dea31012005-04-17 16:05:31 -05001163 struct lpfc_dmabuf *mp, *bmp;
1164 struct lpfc_sli_ct_request *CtReq;
1165 struct ulp_bde64 *bpl;
1166 void (*cmpl) (struct lpfc_hba *, struct lpfc_iocbq *,
1167 struct lpfc_iocbq *) = NULL;
1168 uint32_t rsp_size = 1024;
James Smart92d7f7b2007-06-17 19:56:38 -05001169 size_t size;
James Smart858c9f62007-06-17 19:56:39 -05001170 int rc = 0;
James Smart92d7f7b2007-06-17 19:56:38 -05001171
1172 ndlp = lpfc_findnode_did(vport, NameServer_DID);
James Smarte47c9092008-02-08 18:49:26 -05001173 if (!ndlp || !NLP_CHK_NODE_ACT(ndlp)
1174 || ndlp->nlp_state != NLP_STE_UNMAPPED_NODE) {
James Smart858c9f62007-06-17 19:56:39 -05001175 rc=1;
1176 goto ns_cmd_exit;
1177 }
dea31012005-04-17 16:05:31 -05001178
1179 /* fill in BDEs for command */
1180 /* Allocate buffer for command payload */
James Smart4258e982015-12-16 18:11:58 -05001181 mp = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL);
James Smart858c9f62007-06-17 19:56:39 -05001182 if (!mp) {
1183 rc=2;
dea31012005-04-17 16:05:31 -05001184 goto ns_cmd_exit;
James Smart858c9f62007-06-17 19:56:39 -05001185 }
dea31012005-04-17 16:05:31 -05001186
1187 INIT_LIST_HEAD(&mp->list);
1188 mp->virt = lpfc_mbuf_alloc(phba, MEM_PRI, &(mp->phys));
James Smart858c9f62007-06-17 19:56:39 -05001189 if (!mp->virt) {
1190 rc=3;
dea31012005-04-17 16:05:31 -05001191 goto ns_cmd_free_mp;
James Smart858c9f62007-06-17 19:56:39 -05001192 }
dea31012005-04-17 16:05:31 -05001193
1194 /* Allocate buffer for Buffer ptr list */
James Smart4258e982015-12-16 18:11:58 -05001195 bmp = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL);
James Smart858c9f62007-06-17 19:56:39 -05001196 if (!bmp) {
1197 rc=4;
dea31012005-04-17 16:05:31 -05001198 goto ns_cmd_free_mpvirt;
James Smart858c9f62007-06-17 19:56:39 -05001199 }
dea31012005-04-17 16:05:31 -05001200
1201 INIT_LIST_HEAD(&bmp->list);
1202 bmp->virt = lpfc_mbuf_alloc(phba, MEM_PRI, &(bmp->phys));
James Smart858c9f62007-06-17 19:56:39 -05001203 if (!bmp->virt) {
1204 rc=5;
dea31012005-04-17 16:05:31 -05001205 goto ns_cmd_free_bmp;
James Smart858c9f62007-06-17 19:56:39 -05001206 }
dea31012005-04-17 16:05:31 -05001207
1208 /* NameServer Req */
James Smarte8b62012007-08-02 11:10:09 -04001209 lpfc_printf_vlog(vport, KERN_INFO ,LOG_DISCOVERY,
1210 "0236 NameServer Req Data: x%x x%x x%x\n",
1211 cmdcode, vport->fc_flag, vport->fc_rscn_id_cnt);
dea31012005-04-17 16:05:31 -05001212
1213 bpl = (struct ulp_bde64 *) bmp->virt;
1214 memset(bpl, 0, sizeof(struct ulp_bde64));
James Smart92d7f7b2007-06-17 19:56:38 -05001215 bpl->addrHigh = le32_to_cpu(putPaddrHigh(mp->phys) );
1216 bpl->addrLow = le32_to_cpu(putPaddrLow(mp->phys) );
dea31012005-04-17 16:05:31 -05001217 bpl->tus.f.bdeFlags = 0;
1218 if (cmdcode == SLI_CTNS_GID_FT)
1219 bpl->tus.f.bdeSize = GID_REQUEST_SZ;
James Smart92d7f7b2007-06-17 19:56:38 -05001220 else if (cmdcode == SLI_CTNS_GFF_ID)
1221 bpl->tus.f.bdeSize = GFF_REQUEST_SZ;
dea31012005-04-17 16:05:31 -05001222 else if (cmdcode == SLI_CTNS_RFT_ID)
1223 bpl->tus.f.bdeSize = RFT_REQUEST_SZ;
1224 else if (cmdcode == SLI_CTNS_RNN_ID)
1225 bpl->tus.f.bdeSize = RNN_REQUEST_SZ;
James Smart92d7f7b2007-06-17 19:56:38 -05001226 else if (cmdcode == SLI_CTNS_RSPN_ID)
1227 bpl->tus.f.bdeSize = RSPN_REQUEST_SZ;
dea31012005-04-17 16:05:31 -05001228 else if (cmdcode == SLI_CTNS_RSNN_NN)
1229 bpl->tus.f.bdeSize = RSNN_REQUEST_SZ;
James Smart7ee5d432007-10-27 13:37:17 -04001230 else if (cmdcode == SLI_CTNS_DA_ID)
1231 bpl->tus.f.bdeSize = DA_ID_REQUEST_SZ;
James Smart2fb9bd82006-12-02 13:33:57 -05001232 else if (cmdcode == SLI_CTNS_RFF_ID)
1233 bpl->tus.f.bdeSize = RFF_REQUEST_SZ;
dea31012005-04-17 16:05:31 -05001234 else
1235 bpl->tus.f.bdeSize = 0;
1236 bpl->tus.w = le32_to_cpu(bpl->tus.w);
1237
1238 CtReq = (struct lpfc_sli_ct_request *) mp->virt;
James Smart4258e982015-12-16 18:11:58 -05001239 memset(CtReq, 0, sizeof(struct lpfc_sli_ct_request));
dea31012005-04-17 16:05:31 -05001240 CtReq->RevisionId.bits.Revision = SLI_CT_REVISION;
1241 CtReq->RevisionId.bits.InId = 0;
1242 CtReq->FsType = SLI_CT_DIRECTORY_SERVICE;
1243 CtReq->FsSubType = SLI_CT_DIRECTORY_NAME_SERVER;
1244 CtReq->CommandResponse.bits.Size = 0;
1245 switch (cmdcode) {
1246 case SLI_CTNS_GID_FT:
1247 CtReq->CommandResponse.bits.CmdRsp =
James Smart76b2c342015-04-07 15:07:19 -04001248 cpu_to_be16(SLI_CTNS_GID_FT);
dea31012005-04-17 16:05:31 -05001249 CtReq->un.gid.Fc4Type = SLI_CTPT_FCP;
James Smart92d7f7b2007-06-17 19:56:38 -05001250 if (vport->port_state < LPFC_NS_QRY)
James Smart2e0fef82007-06-17 19:56:36 -05001251 vport->port_state = LPFC_NS_QRY;
1252 lpfc_set_disctmo(vport);
dea31012005-04-17 16:05:31 -05001253 cmpl = lpfc_cmpl_ct_cmd_gid_ft;
1254 rsp_size = FC_MAX_NS_RSP;
1255 break;
1256
James Smart92d7f7b2007-06-17 19:56:38 -05001257 case SLI_CTNS_GFF_ID:
1258 CtReq->CommandResponse.bits.CmdRsp =
James Smart76b2c342015-04-07 15:07:19 -04001259 cpu_to_be16(SLI_CTNS_GFF_ID);
James Smart09372822008-01-11 01:52:54 -05001260 CtReq->un.gff.PortId = cpu_to_be32(context);
James Smart92d7f7b2007-06-17 19:56:38 -05001261 cmpl = lpfc_cmpl_ct_cmd_gff_id;
1262 break;
1263
dea31012005-04-17 16:05:31 -05001264 case SLI_CTNS_RFT_ID:
James Smart7ee5d432007-10-27 13:37:17 -04001265 vport->ct_flags &= ~FC_CT_RFT_ID;
dea31012005-04-17 16:05:31 -05001266 CtReq->CommandResponse.bits.CmdRsp =
James Smart76b2c342015-04-07 15:07:19 -04001267 cpu_to_be16(SLI_CTNS_RFT_ID);
James Smart09372822008-01-11 01:52:54 -05001268 CtReq->un.rft.PortId = cpu_to_be32(vport->fc_myDID);
dea31012005-04-17 16:05:31 -05001269 CtReq->un.rft.fcpReg = 1;
1270 cmpl = lpfc_cmpl_ct_cmd_rft_id;
1271 break;
1272
1273 case SLI_CTNS_RNN_ID:
James Smart7ee5d432007-10-27 13:37:17 -04001274 vport->ct_flags &= ~FC_CT_RNN_ID;
dea31012005-04-17 16:05:31 -05001275 CtReq->CommandResponse.bits.CmdRsp =
James Smart76b2c342015-04-07 15:07:19 -04001276 cpu_to_be16(SLI_CTNS_RNN_ID);
James Smart09372822008-01-11 01:52:54 -05001277 CtReq->un.rnn.PortId = cpu_to_be32(vport->fc_myDID);
James Smart2e0fef82007-06-17 19:56:36 -05001278 memcpy(CtReq->un.rnn.wwnn, &vport->fc_nodename,
James Smart4258e982015-12-16 18:11:58 -05001279 sizeof(struct lpfc_name));
dea31012005-04-17 16:05:31 -05001280 cmpl = lpfc_cmpl_ct_cmd_rnn_id;
1281 break;
1282
James Smart92d7f7b2007-06-17 19:56:38 -05001283 case SLI_CTNS_RSPN_ID:
James Smart7ee5d432007-10-27 13:37:17 -04001284 vport->ct_flags &= ~FC_CT_RSPN_ID;
James Smart92d7f7b2007-06-17 19:56:38 -05001285 CtReq->CommandResponse.bits.CmdRsp =
James Smart76b2c342015-04-07 15:07:19 -04001286 cpu_to_be16(SLI_CTNS_RSPN_ID);
James Smart09372822008-01-11 01:52:54 -05001287 CtReq->un.rspn.PortId = cpu_to_be32(vport->fc_myDID);
James Smart92d7f7b2007-06-17 19:56:38 -05001288 size = sizeof(CtReq->un.rspn.symbname);
1289 CtReq->un.rspn.len =
1290 lpfc_vport_symbolic_port_name(vport,
1291 CtReq->un.rspn.symbname, size);
1292 cmpl = lpfc_cmpl_ct_cmd_rspn_id;
1293 break;
dea31012005-04-17 16:05:31 -05001294 case SLI_CTNS_RSNN_NN:
James Smart7ee5d432007-10-27 13:37:17 -04001295 vport->ct_flags &= ~FC_CT_RSNN_NN;
dea31012005-04-17 16:05:31 -05001296 CtReq->CommandResponse.bits.CmdRsp =
James Smart76b2c342015-04-07 15:07:19 -04001297 cpu_to_be16(SLI_CTNS_RSNN_NN);
James Smart2e0fef82007-06-17 19:56:36 -05001298 memcpy(CtReq->un.rsnn.wwnn, &vport->fc_nodename,
James Smart4258e982015-12-16 18:11:58 -05001299 sizeof(struct lpfc_name));
James Smart92d7f7b2007-06-17 19:56:38 -05001300 size = sizeof(CtReq->un.rsnn.symbname);
1301 CtReq->un.rsnn.len =
1302 lpfc_vport_symbolic_node_name(vport,
1303 CtReq->un.rsnn.symbname, size);
dea31012005-04-17 16:05:31 -05001304 cmpl = lpfc_cmpl_ct_cmd_rsnn_nn;
1305 break;
James Smart7ee5d432007-10-27 13:37:17 -04001306 case SLI_CTNS_DA_ID:
1307 /* Implement DA_ID Nameserver request */
1308 CtReq->CommandResponse.bits.CmdRsp =
James Smart76b2c342015-04-07 15:07:19 -04001309 cpu_to_be16(SLI_CTNS_DA_ID);
James Smart09372822008-01-11 01:52:54 -05001310 CtReq->un.da_id.port_id = cpu_to_be32(vport->fc_myDID);
James Smart7ee5d432007-10-27 13:37:17 -04001311 cmpl = lpfc_cmpl_ct_cmd_da_id;
1312 break;
James Smart92d7f7b2007-06-17 19:56:38 -05001313 case SLI_CTNS_RFF_ID:
James Smart7ee5d432007-10-27 13:37:17 -04001314 vport->ct_flags &= ~FC_CT_RFF_ID;
James Smart92d7f7b2007-06-17 19:56:38 -05001315 CtReq->CommandResponse.bits.CmdRsp =
James Smart76b2c342015-04-07 15:07:19 -04001316 cpu_to_be16(SLI_CTNS_RFF_ID);
Joe Perchesa419aef2009-08-18 11:18:35 -07001317 CtReq->un.rff.PortId = cpu_to_be32(vport->fc_myDID);
James Smart92d7f7b2007-06-17 19:56:38 -05001318 CtReq->un.rff.fbits = FC4_FEATURE_INIT;
James Smart6a9c52c2009-10-02 15:16:51 -04001319 CtReq->un.rff.type_code = FC_TYPE_FCP;
James Smart92d7f7b2007-06-17 19:56:38 -05001320 cmpl = lpfc_cmpl_ct_cmd_rff_id;
1321 break;
dea31012005-04-17 16:05:31 -05001322 }
James Smarte47c9092008-02-08 18:49:26 -05001323 /* The lpfc_ct_cmd/lpfc_get_req shall increment ndlp reference count
1324 * to hold ndlp reference for the corresponding callback function.
1325 */
James Smart858c9f62007-06-17 19:56:39 -05001326 if (!lpfc_ct_cmd(vport, mp, bmp, ndlp, cmpl, rsp_size, retry)) {
dea31012005-04-17 16:05:31 -05001327 /* On success, The cmpl function will free the buffers */
James Smart858c9f62007-06-17 19:56:39 -05001328 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT,
1329 "Issue CT cmd: cmd:x%x did:x%x",
1330 cmdcode, ndlp->nlp_DID, 0);
dea31012005-04-17 16:05:31 -05001331 return 0;
James Smart858c9f62007-06-17 19:56:39 -05001332 }
James Smart858c9f62007-06-17 19:56:39 -05001333 rc=6;
James Smarte47c9092008-02-08 18:49:26 -05001334
1335 /* Decrement ndlp reference count to release ndlp reference held
1336 * for the failed command's callback function.
1337 */
James Smart51ef4c22007-08-02 11:10:31 -04001338 lpfc_nlp_put(ndlp);
James Smarte47c9092008-02-08 18:49:26 -05001339
dea31012005-04-17 16:05:31 -05001340 lpfc_mbuf_free(phba, bmp->virt, bmp->phys);
1341ns_cmd_free_bmp:
1342 kfree(bmp);
1343ns_cmd_free_mpvirt:
1344 lpfc_mbuf_free(phba, mp->virt, mp->phys);
1345ns_cmd_free_mp:
1346 kfree(mp);
1347ns_cmd_exit:
James Smarte8b62012007-08-02 11:10:09 -04001348 lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY,
1349 "0266 Issue NameServer Req x%x err %d Data: x%x x%x\n",
1350 cmdcode, rc, vport->fc_flag, vport->fc_rscn_id_cnt);
dea31012005-04-17 16:05:31 -05001351 return 1;
1352}
1353
James Smart4258e982015-12-16 18:11:58 -05001354/**
1355 * lpfc_cmpl_ct_disc_fdmi - Handle a discovery FDMI completion
1356 * @phba: Pointer to HBA context object.
1357 * @cmdiocb: Pointer to the command IOCBQ.
1358 * @rspiocb: Pointer to the response IOCBQ.
1359 *
1360 * This function to handle the completion of a driver initiated FDMI
1361 * CT command issued during discovery.
1362 */
dea31012005-04-17 16:05:31 -05001363static void
James Smart4258e982015-12-16 18:11:58 -05001364lpfc_cmpl_ct_disc_fdmi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
1365 struct lpfc_iocbq *rspiocb)
dea31012005-04-17 16:05:31 -05001366{
James Smart4258e982015-12-16 18:11:58 -05001367 struct lpfc_vport *vport = cmdiocb->vport;
dea31012005-04-17 16:05:31 -05001368 struct lpfc_dmabuf *inp = cmdiocb->context1;
1369 struct lpfc_dmabuf *outp = cmdiocb->context2;
dea31012005-04-17 16:05:31 -05001370 struct lpfc_sli_ct_request *CTcmd = inp->virt;
James Smart4258e982015-12-16 18:11:58 -05001371 struct lpfc_sli_ct_request *CTrsp = outp->virt;
dea31012005-04-17 16:05:31 -05001372 uint16_t fdmi_cmd = CTcmd->CommandResponse.bits.CmdRsp;
1373 uint16_t fdmi_rsp = CTrsp->CommandResponse.bits.CmdRsp;
James Smart858c9f62007-06-17 19:56:39 -05001374 IOCB_t *irsp = &rspiocb->iocb;
James Smart4258e982015-12-16 18:11:58 -05001375 struct lpfc_nodelist *ndlp;
1376 uint32_t latt, cmd, err;
James Smart858c9f62007-06-17 19:56:39 -05001377
1378 latt = lpfc_els_chk_latt(vport);
James Smart858c9f62007-06-17 19:56:39 -05001379 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT,
1380 "FDMI cmpl: status:x%x/x%x latt:%d",
1381 irsp->ulpStatus, irsp->un.ulpWord[4], latt);
1382
1383 if (latt || irsp->ulpStatus) {
James Smart4258e982015-12-16 18:11:58 -05001384
1385 /* Look for a retryable error */
1386 if (irsp->ulpStatus == IOSTAT_LOCAL_REJECT) {
1387 switch ((irsp->un.ulpWord[4] & IOERR_PARAM_MASK)) {
1388 case IOERR_SLI_ABORTED:
1389 case IOERR_ABORT_IN_PROGRESS:
1390 case IOERR_SEQUENCE_TIMEOUT:
1391 case IOERR_ILLEGAL_FRAME:
1392 case IOERR_NO_RESOURCES:
1393 case IOERR_ILLEGAL_COMMAND:
1394 cmdiocb->retry++;
1395 if (cmdiocb->retry >= LPFC_FDMI_MAX_RETRY)
1396 break;
1397
1398 /* Retry the same FDMI command */
1399 err = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING,
1400 cmdiocb, 0);
1401 if (err == IOCB_ERROR)
1402 break;
1403 return;
1404 default:
1405 break;
1406 }
1407 }
1408
James Smarte8b62012007-08-02 11:10:09 -04001409 lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
1410 "0229 FDMI cmd %04x failed, latt = %d "
1411 "ulpStatus: x%x, rid x%x\n",
1412 be16_to_cpu(fdmi_cmd), latt, irsp->ulpStatus,
1413 irsp->un.ulpWord[4]);
James Smart858c9f62007-06-17 19:56:39 -05001414 }
James Smart76b2c342015-04-07 15:07:19 -04001415 lpfc_ct_free_iocb(phba, cmdiocb);
James Smart76b2c342015-04-07 15:07:19 -04001416
1417 ndlp = lpfc_findnode_did(vport, FDMI_DID);
1418 if (!ndlp || !NLP_CHK_NODE_ACT(ndlp))
1419 return;
1420
James Smart4258e982015-12-16 18:11:58 -05001421 /* Check for a CT LS_RJT response */
1422 cmd = be16_to_cpu(fdmi_cmd);
1423 if (fdmi_rsp == cpu_to_be16(SLI_CT_RESPONSE_FS_RJT)) {
1424 /* FDMI rsp failed */
1425 lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
1426 "0220 FDMI cmd failed FS_RJT Data: x%x", cmd);
1427
1428 /* Should we fallback to FDMI-2 / FDMI-1 ? */
1429 switch (cmd) {
1430 case SLI_MGMT_RHBA:
1431 if (vport->fdmi_hba_mask == LPFC_FDMI2_HBA_ATTR) {
1432 /* Fallback to FDMI-1 */
1433 vport->fdmi_hba_mask = LPFC_FDMI1_HBA_ATTR;
1434 vport->fdmi_port_mask = LPFC_FDMI1_PORT_ATTR;
1435 /* Start over */
1436 lpfc_fdmi_cmd(vport, ndlp, SLI_MGMT_DHBA, 0);
1437 }
1438 return;
1439
1440 case SLI_MGMT_RPRT:
1441 if (vport->fdmi_port_mask == LPFC_FDMI2_PORT_ATTR) {
1442 /* Fallback to FDMI-1 */
1443 vport->fdmi_port_mask = LPFC_FDMI1_PORT_ATTR;
1444 /* Start over */
1445 lpfc_fdmi_cmd(vport, ndlp, cmd, 0);
1446 }
1447 if (vport->fdmi_port_mask == LPFC_FDMI2_SMART_ATTR) {
1448 vport->fdmi_port_mask = LPFC_FDMI2_PORT_ATTR;
1449 /* Retry the same command */
1450 lpfc_fdmi_cmd(vport, ndlp, cmd, 0);
1451 }
1452 return;
1453
1454 case SLI_MGMT_RPA:
1455 if (vport->fdmi_port_mask == LPFC_FDMI2_PORT_ATTR) {
1456 /* Fallback to FDMI-1 */
1457 vport->fdmi_hba_mask = LPFC_FDMI1_HBA_ATTR;
1458 vport->fdmi_port_mask = LPFC_FDMI1_PORT_ATTR;
1459 /* Start over */
1460 lpfc_fdmi_cmd(vport, ndlp, SLI_MGMT_DHBA, 0);
1461 }
1462 if (vport->fdmi_port_mask == LPFC_FDMI2_SMART_ATTR) {
1463 vport->fdmi_port_mask = LPFC_FDMI2_PORT_ATTR;
1464 /* Retry the same command */
1465 lpfc_fdmi_cmd(vport, ndlp, cmd, 0);
1466 }
1467 return;
1468 }
1469 }
1470
James Smart76b2c342015-04-07 15:07:19 -04001471 /*
James Smart4258e982015-12-16 18:11:58 -05001472 * On success, need to cycle thru FDMI registration for discovery
1473 * DHBA -> DPRT -> RHBA -> RPA (physical port)
1474 * DPRT -> RPRT (vports)
James Smart76b2c342015-04-07 15:07:19 -04001475 */
James Smart4258e982015-12-16 18:11:58 -05001476 switch (cmd) {
dea31012005-04-17 16:05:31 -05001477 case SLI_MGMT_RHBA:
James Smart4258e982015-12-16 18:11:58 -05001478 lpfc_fdmi_cmd(vport, ndlp, SLI_MGMT_RPA, 0);
dea31012005-04-17 16:05:31 -05001479 break;
1480
dea31012005-04-17 16:05:31 -05001481 case SLI_MGMT_DHBA:
James Smart4258e982015-12-16 18:11:58 -05001482 lpfc_fdmi_cmd(vport, ndlp, SLI_MGMT_DPRT, 0);
dea31012005-04-17 16:05:31 -05001483 break;
1484
1485 case SLI_MGMT_DPRT:
James Smart4258e982015-12-16 18:11:58 -05001486 if (vport->port_type == LPFC_PHYSICAL_PORT)
1487 lpfc_fdmi_cmd(vport, ndlp, SLI_MGMT_RHBA, 0);
1488 else
1489 lpfc_fdmi_cmd(vport, ndlp, SLI_MGMT_RPRT, 0);
dea31012005-04-17 16:05:31 -05001490 break;
1491 }
James Smart4258e982015-12-16 18:11:58 -05001492 return;
dea31012005-04-17 16:05:31 -05001493}
James Smart2e0fef82007-06-17 19:56:36 -05001494
James Smart76b2c342015-04-07 15:07:19 -04001495
James Smart4258e982015-12-16 18:11:58 -05001496/**
1497 * lpfc_fdmi_num_disc_check - Check how many mapped NPorts we are connected to
1498 * @vport: pointer to a host virtual N_Port data structure.
1499 *
1500 * Called from hbeat timeout routine to check if the number of discovered
1501 * ports has changed. If so, re-register thar port Attribute.
1502 */
1503void
1504lpfc_fdmi_num_disc_check(struct lpfc_vport *vport)
1505{
1506 struct lpfc_hba *phba = vport->phba;
1507 struct lpfc_nodelist *ndlp;
1508 uint16_t cnt;
1509
1510 if (!lpfc_is_link_up(phba))
1511 return;
1512
1513 if (!(vport->fdmi_port_mask & LPFC_FDMI_PORT_ATTR_num_disc))
1514 return;
1515
1516 cnt = lpfc_find_map_node(vport);
1517 if (cnt == vport->fdmi_num_disc)
1518 return;
1519
1520 ndlp = lpfc_findnode_did(vport, FDMI_DID);
1521 if (!ndlp || !NLP_CHK_NODE_ACT(ndlp))
1522 return;
1523
1524 if (vport->port_type == LPFC_PHYSICAL_PORT) {
1525 lpfc_fdmi_cmd(vport, ndlp, SLI_MGMT_RPA,
1526 LPFC_FDMI_PORT_ATTR_num_disc);
1527 } else {
1528 lpfc_fdmi_cmd(vport, ndlp, SLI_MGMT_RPRT,
1529 LPFC_FDMI_PORT_ATTR_num_disc);
1530 }
1531}
1532
1533/* Routines for all individual HBA attributes */
dea31012005-04-17 16:05:31 -05001534int
James Smart4258e982015-12-16 18:11:58 -05001535lpfc_fdmi_hba_attr_wwnn(struct lpfc_vport *vport, struct lpfc_fdmi_attr_def *ad)
1536{
1537 struct lpfc_fdmi_attr_entry *ae;
1538 uint32_t size;
1539
1540 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
1541 memset(ae, 0, sizeof(struct lpfc_name));
1542
1543 memcpy(&ae->un.AttrWWN, &vport->fc_sparam.nodeName,
1544 sizeof(struct lpfc_name));
1545 size = FOURBYTES + sizeof(struct lpfc_name);
1546 ad->AttrLen = cpu_to_be16(size);
1547 ad->AttrType = cpu_to_be16(RHBA_NODENAME);
1548 return size;
1549}
1550int
1551lpfc_fdmi_hba_attr_manufacturer(struct lpfc_vport *vport,
1552 struct lpfc_fdmi_attr_def *ad)
1553{
1554 struct lpfc_fdmi_attr_entry *ae;
1555 uint32_t len, size;
1556
1557 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
1558 memset(ae, 0, 256);
1559
1560 strncpy(ae->un.AttrString,
1561 "Emulex Corporation",
1562 sizeof(ae->un.AttrString));
1563 len = strnlen(ae->un.AttrString,
1564 sizeof(ae->un.AttrString));
1565 len += (len & 3) ? (4 - (len & 3)) : 4;
1566 size = FOURBYTES + len;
1567 ad->AttrLen = cpu_to_be16(size);
1568 ad->AttrType = cpu_to_be16(RHBA_MANUFACTURER);
1569 return size;
1570}
1571
1572int
1573lpfc_fdmi_hba_attr_sn(struct lpfc_vport *vport, struct lpfc_fdmi_attr_def *ad)
1574{
1575 struct lpfc_hba *phba = vport->phba;
1576 struct lpfc_fdmi_attr_entry *ae;
1577 uint32_t len, size;
1578
1579 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
1580 memset(ae, 0, 256);
1581
1582 strncpy(ae->un.AttrString, phba->SerialNumber,
1583 sizeof(ae->un.AttrString));
1584 len = strnlen(ae->un.AttrString,
1585 sizeof(ae->un.AttrString));
1586 len += (len & 3) ? (4 - (len & 3)) : 4;
1587 size = FOURBYTES + len;
1588 ad->AttrLen = cpu_to_be16(size);
1589 ad->AttrType = cpu_to_be16(RHBA_SERIAL_NUMBER);
1590 return size;
1591}
1592
1593int
1594lpfc_fdmi_hba_attr_model(struct lpfc_vport *vport,
1595 struct lpfc_fdmi_attr_def *ad)
1596{
1597 struct lpfc_hba *phba = vport->phba;
1598 struct lpfc_fdmi_attr_entry *ae;
1599 uint32_t len, size;
1600
1601 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
1602 memset(ae, 0, 256);
1603
1604 strncpy(ae->un.AttrString, phba->ModelName,
1605 sizeof(ae->un.AttrString));
1606 len = strnlen(ae->un.AttrString, sizeof(ae->un.AttrString));
1607 len += (len & 3) ? (4 - (len & 3)) : 4;
1608 size = FOURBYTES + len;
1609 ad->AttrLen = cpu_to_be16(size);
1610 ad->AttrType = cpu_to_be16(RHBA_MODEL);
1611 return size;
1612}
1613
1614int
1615lpfc_fdmi_hba_attr_description(struct lpfc_vport *vport,
1616 struct lpfc_fdmi_attr_def *ad)
1617{
1618 struct lpfc_hba *phba = vport->phba;
1619 struct lpfc_fdmi_attr_entry *ae;
1620 uint32_t len, size;
1621
1622 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
1623 memset(ae, 0, 256);
1624
1625 strncpy(ae->un.AttrString, phba->ModelDesc,
1626 sizeof(ae->un.AttrString));
1627 len = strnlen(ae->un.AttrString,
1628 sizeof(ae->un.AttrString));
1629 len += (len & 3) ? (4 - (len & 3)) : 4;
1630 size = FOURBYTES + len;
1631 ad->AttrLen = cpu_to_be16(size);
1632 ad->AttrType = cpu_to_be16(RHBA_MODEL_DESCRIPTION);
1633 return size;
1634}
1635
1636int
1637lpfc_fdmi_hba_attr_hdw_ver(struct lpfc_vport *vport,
1638 struct lpfc_fdmi_attr_def *ad)
1639{
1640 struct lpfc_hba *phba = vport->phba;
1641 lpfc_vpd_t *vp = &phba->vpd;
1642 struct lpfc_fdmi_attr_entry *ae;
1643 uint32_t i, j, incr, size;
1644
1645 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
1646 memset(ae, 0, 256);
1647
1648 /* Convert JEDEC ID to ascii for hardware version */
1649 incr = vp->rev.biuRev;
1650 for (i = 0; i < 8; i++) {
1651 j = (incr & 0xf);
1652 if (j <= 9)
1653 ae->un.AttrString[7 - i] =
1654 (char)((uint8_t) 0x30 +
1655 (uint8_t) j);
1656 else
1657 ae->un.AttrString[7 - i] =
1658 (char)((uint8_t) 0x61 +
1659 (uint8_t) (j - 10));
1660 incr = (incr >> 4);
1661 }
1662 size = FOURBYTES + 8;
1663 ad->AttrLen = cpu_to_be16(size);
1664 ad->AttrType = cpu_to_be16(RHBA_HARDWARE_VERSION);
1665 return size;
1666}
1667
1668int
1669lpfc_fdmi_hba_attr_drvr_ver(struct lpfc_vport *vport,
1670 struct lpfc_fdmi_attr_def *ad)
1671{
1672 struct lpfc_fdmi_attr_entry *ae;
1673 uint32_t len, size;
1674
1675 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
1676 memset(ae, 0, 256);
1677
1678 strncpy(ae->un.AttrString, lpfc_release_version,
1679 sizeof(ae->un.AttrString));
1680 len = strnlen(ae->un.AttrString,
1681 sizeof(ae->un.AttrString));
1682 len += (len & 3) ? (4 - (len & 3)) : 4;
1683 size = FOURBYTES + len;
1684 ad->AttrLen = cpu_to_be16(size);
1685 ad->AttrType = cpu_to_be16(RHBA_DRIVER_VERSION);
1686 return size;
1687}
1688
1689int
1690lpfc_fdmi_hba_attr_rom_ver(struct lpfc_vport *vport,
1691 struct lpfc_fdmi_attr_def *ad)
1692{
1693 struct lpfc_hba *phba = vport->phba;
1694 struct lpfc_fdmi_attr_entry *ae;
1695 uint32_t len, size;
1696
1697 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
1698 memset(ae, 0, 256);
1699
1700 if (phba->sli_rev == LPFC_SLI_REV4)
1701 lpfc_decode_firmware_rev(phba, ae->un.AttrString, 1);
1702 else
1703 strncpy(ae->un.AttrString, phba->OptionROMVersion,
1704 sizeof(ae->un.AttrString));
1705 len = strnlen(ae->un.AttrString,
1706 sizeof(ae->un.AttrString));
1707 len += (len & 3) ? (4 - (len & 3)) : 4;
1708 size = FOURBYTES + len;
1709 ad->AttrLen = cpu_to_be16(size);
1710 ad->AttrType = cpu_to_be16(RHBA_OPTION_ROM_VERSION);
1711 return size;
1712}
1713
1714int
1715lpfc_fdmi_hba_attr_fmw_ver(struct lpfc_vport *vport,
1716 struct lpfc_fdmi_attr_def *ad)
1717{
1718 struct lpfc_hba *phba = vport->phba;
1719 struct lpfc_fdmi_attr_entry *ae;
1720 uint32_t len, size;
1721
1722 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
1723 memset(ae, 0, 256);
1724
1725 lpfc_decode_firmware_rev(phba, ae->un.AttrString, 1);
1726 len = strnlen(ae->un.AttrString,
1727 sizeof(ae->un.AttrString));
1728 len += (len & 3) ? (4 - (len & 3)) : 4;
1729 size = FOURBYTES + len;
1730 ad->AttrLen = cpu_to_be16(size);
1731 ad->AttrType = cpu_to_be16(RHBA_FIRMWARE_VERSION);
1732 return size;
1733}
1734
1735int
1736lpfc_fdmi_hba_attr_os_ver(struct lpfc_vport *vport,
1737 struct lpfc_fdmi_attr_def *ad)
1738{
1739 struct lpfc_fdmi_attr_entry *ae;
1740 uint32_t len, size;
1741
1742 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
1743 memset(ae, 0, 256);
1744
1745 snprintf(ae->un.AttrString, sizeof(ae->un.AttrString), "%s %s %s",
1746 init_utsname()->sysname,
1747 init_utsname()->release,
1748 init_utsname()->version);
1749
1750 len = strnlen(ae->un.AttrString, sizeof(ae->un.AttrString));
1751 len += (len & 3) ? (4 - (len & 3)) : 4;
1752 size = FOURBYTES + len;
1753 ad->AttrLen = cpu_to_be16(size);
1754 ad->AttrType = cpu_to_be16(RHBA_OS_NAME_VERSION);
1755 return size;
1756}
1757
1758int
1759lpfc_fdmi_hba_attr_ct_len(struct lpfc_vport *vport,
1760 struct lpfc_fdmi_attr_def *ad)
1761{
1762 struct lpfc_fdmi_attr_entry *ae;
1763 uint32_t size;
1764
1765 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
1766
1767 ae->un.AttrInt = cpu_to_be32(LPFC_MAX_CT_SIZE);
1768 size = FOURBYTES + sizeof(uint32_t);
1769 ad->AttrLen = cpu_to_be16(size);
1770 ad->AttrType = cpu_to_be16(RHBA_MAX_CT_PAYLOAD_LEN);
1771 return size;
1772}
1773
1774int
1775lpfc_fdmi_hba_attr_symbolic_name(struct lpfc_vport *vport,
1776 struct lpfc_fdmi_attr_def *ad)
1777{
1778 struct lpfc_fdmi_attr_entry *ae;
1779 uint32_t len, size;
1780
1781 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
1782 memset(ae, 0, 256);
1783
1784 len = lpfc_vport_symbolic_node_name(vport,
1785 ae->un.AttrString, 256);
1786 len += (len & 3) ? (4 - (len & 3)) : 4;
1787 size = FOURBYTES + len;
1788 ad->AttrLen = cpu_to_be16(size);
1789 ad->AttrType = cpu_to_be16(RHBA_SYM_NODENAME);
1790 return size;
1791}
1792
1793int
1794lpfc_fdmi_hba_attr_vendor_info(struct lpfc_vport *vport,
1795 struct lpfc_fdmi_attr_def *ad)
1796{
1797 struct lpfc_fdmi_attr_entry *ae;
1798 uint32_t size;
1799
1800 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
1801
1802 /* Nothing is defined for this currently */
1803 ae->un.AttrInt = cpu_to_be32(0);
1804 size = FOURBYTES + sizeof(uint32_t);
1805 ad->AttrLen = cpu_to_be16(size);
1806 ad->AttrType = cpu_to_be16(RHBA_VENDOR_INFO);
1807 return size;
1808}
1809
1810int
1811lpfc_fdmi_hba_attr_num_ports(struct lpfc_vport *vport,
1812 struct lpfc_fdmi_attr_def *ad)
1813{
1814 struct lpfc_fdmi_attr_entry *ae;
1815 uint32_t size;
1816
1817 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
1818
1819 /* Each driver instance corresponds to a single port */
1820 ae->un.AttrInt = cpu_to_be32(1);
1821 size = FOURBYTES + sizeof(uint32_t);
1822 ad->AttrLen = cpu_to_be16(size);
1823 ad->AttrType = cpu_to_be16(RHBA_NUM_PORTS);
1824 return size;
1825}
1826
1827int
1828lpfc_fdmi_hba_attr_fabric_wwnn(struct lpfc_vport *vport,
1829 struct lpfc_fdmi_attr_def *ad)
1830{
1831 struct lpfc_fdmi_attr_entry *ae;
1832 uint32_t size;
1833
1834 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
1835 memset(ae, 0, sizeof(struct lpfc_name));
1836
1837 memcpy(&ae->un.AttrWWN, &vport->fabric_nodename,
1838 sizeof(struct lpfc_name));
1839 size = FOURBYTES + sizeof(struct lpfc_name);
1840 ad->AttrLen = cpu_to_be16(size);
1841 ad->AttrType = cpu_to_be16(RHBA_FABRIC_WWNN);
1842 return size;
1843}
1844
1845int
1846lpfc_fdmi_hba_attr_bios_ver(struct lpfc_vport *vport,
1847 struct lpfc_fdmi_attr_def *ad)
1848{
1849 struct lpfc_hba *phba = vport->phba;
1850 struct lpfc_fdmi_attr_entry *ae;
1851 uint32_t len, size;
1852
1853 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
1854 memset(ae, 0, 256);
1855
1856 lpfc_decode_firmware_rev(phba, ae->un.AttrString, 1);
1857 len = strnlen(ae->un.AttrString,
1858 sizeof(ae->un.AttrString));
1859 len += (len & 3) ? (4 - (len & 3)) : 4;
1860 size = FOURBYTES + len;
1861 ad->AttrLen = cpu_to_be16(size);
1862 ad->AttrType = cpu_to_be16(RHBA_BIOS_VERSION);
1863 return size;
1864}
1865
1866int
1867lpfc_fdmi_hba_attr_bios_state(struct lpfc_vport *vport,
1868 struct lpfc_fdmi_attr_def *ad)
1869{
1870 struct lpfc_fdmi_attr_entry *ae;
1871 uint32_t size;
1872
1873 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
1874
1875 /* Driver doesn't have access to this information */
1876 ae->un.AttrInt = cpu_to_be32(0);
1877 size = FOURBYTES + sizeof(uint32_t);
1878 ad->AttrLen = cpu_to_be16(size);
1879 ad->AttrType = cpu_to_be16(RHBA_BIOS_STATE);
1880 return size;
1881}
1882
1883int
1884lpfc_fdmi_hba_attr_vendor_id(struct lpfc_vport *vport,
1885 struct lpfc_fdmi_attr_def *ad)
1886{
1887 struct lpfc_fdmi_attr_entry *ae;
1888 uint32_t len, size;
1889
1890 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
1891 memset(ae, 0, 256);
1892
1893 strncpy(ae->un.AttrString, "EMULEX",
1894 sizeof(ae->un.AttrString));
1895 len = strnlen(ae->un.AttrString,
1896 sizeof(ae->un.AttrString));
1897 len += (len & 3) ? (4 - (len & 3)) : 4;
1898 size = FOURBYTES + len;
1899 ad->AttrLen = cpu_to_be16(size);
1900 ad->AttrType = cpu_to_be16(RHBA_VENDOR_ID);
1901 return size;
1902}
1903
1904/* Routines for all individual PORT attributes */
1905int
1906lpfc_fdmi_port_attr_fc4type(struct lpfc_vport *vport,
1907 struct lpfc_fdmi_attr_def *ad)
1908{
1909 struct lpfc_fdmi_attr_entry *ae;
1910 uint32_t size;
1911
1912 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
1913 memset(ae, 0, 32);
1914
1915 ae->un.AttrTypes[3] = 0x02; /* Type 1 - ELS */
1916 ae->un.AttrTypes[2] = 0x01; /* Type 8 - FCP */
1917 ae->un.AttrTypes[7] = 0x01; /* Type 32 - CT */
1918 size = FOURBYTES + 32;
1919 ad->AttrLen = cpu_to_be16(size);
1920 ad->AttrType = cpu_to_be16(RPRT_SUPPORTED_FC4_TYPES);
1921 return size;
1922}
1923
1924int
1925lpfc_fdmi_port_attr_support_speed(struct lpfc_vport *vport,
1926 struct lpfc_fdmi_attr_def *ad)
1927{
1928 struct lpfc_hba *phba = vport->phba;
1929 struct lpfc_fdmi_attr_entry *ae;
1930 uint32_t size;
1931
1932 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
1933
1934 ae->un.AttrInt = 0;
James Smarta085e872015-12-16 18:12:02 -05001935 if (!(phba->hba_flag & HBA_FCOE_MODE)) {
1936 if (phba->lmt & LMT_32Gb)
1937 ae->un.AttrInt |= HBA_PORTSPEED_32GFC;
1938 if (phba->lmt & LMT_16Gb)
1939 ae->un.AttrInt |= HBA_PORTSPEED_16GFC;
1940 if (phba->lmt & LMT_10Gb)
1941 ae->un.AttrInt |= HBA_PORTSPEED_10GFC;
1942 if (phba->lmt & LMT_8Gb)
1943 ae->un.AttrInt |= HBA_PORTSPEED_8GFC;
1944 if (phba->lmt & LMT_4Gb)
1945 ae->un.AttrInt |= HBA_PORTSPEED_4GFC;
1946 if (phba->lmt & LMT_2Gb)
1947 ae->un.AttrInt |= HBA_PORTSPEED_2GFC;
1948 if (phba->lmt & LMT_1Gb)
1949 ae->un.AttrInt |= HBA_PORTSPEED_1GFC;
1950 } else {
1951 /* FCoE links support only one speed */
1952 switch (phba->fc_linkspeed) {
1953 case LPFC_ASYNC_LINK_SPEED_10GBPS:
1954 ae->un.AttrInt = HBA_PORTSPEED_10GE;
1955 break;
1956 case LPFC_ASYNC_LINK_SPEED_25GBPS:
1957 ae->un.AttrInt = HBA_PORTSPEED_25GE;
1958 break;
1959 case LPFC_ASYNC_LINK_SPEED_40GBPS:
1960 ae->un.AttrInt = HBA_PORTSPEED_40GE;
1961 break;
1962 case LPFC_ASYNC_LINK_SPEED_100GBPS:
1963 ae->un.AttrInt = HBA_PORTSPEED_100GE;
1964 break;
1965 }
1966 }
James Smart4258e982015-12-16 18:11:58 -05001967 ae->un.AttrInt = cpu_to_be32(ae->un.AttrInt);
1968 size = FOURBYTES + sizeof(uint32_t);
1969 ad->AttrLen = cpu_to_be16(size);
1970 ad->AttrType = cpu_to_be16(RPRT_SUPPORTED_SPEED);
1971 return size;
1972}
1973
1974int
1975lpfc_fdmi_port_attr_speed(struct lpfc_vport *vport,
1976 struct lpfc_fdmi_attr_def *ad)
1977{
1978 struct lpfc_hba *phba = vport->phba;
1979 struct lpfc_fdmi_attr_entry *ae;
1980 uint32_t size;
1981
1982 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
1983
James Smarta085e872015-12-16 18:12:02 -05001984 if (!(phba->hba_flag & HBA_FCOE_MODE)) {
1985 switch (phba->fc_linkspeed) {
1986 case LPFC_LINK_SPEED_1GHZ:
1987 ae->un.AttrInt = HBA_PORTSPEED_1GFC;
1988 break;
1989 case LPFC_LINK_SPEED_2GHZ:
1990 ae->un.AttrInt = HBA_PORTSPEED_2GFC;
1991 break;
1992 case LPFC_LINK_SPEED_4GHZ:
1993 ae->un.AttrInt = HBA_PORTSPEED_4GFC;
1994 break;
1995 case LPFC_LINK_SPEED_8GHZ:
1996 ae->un.AttrInt = HBA_PORTSPEED_8GFC;
1997 break;
1998 case LPFC_LINK_SPEED_10GHZ:
1999 ae->un.AttrInt = HBA_PORTSPEED_10GFC;
2000 break;
2001 case LPFC_LINK_SPEED_16GHZ:
2002 ae->un.AttrInt = HBA_PORTSPEED_16GFC;
2003 break;
2004 case LPFC_LINK_SPEED_32GHZ:
2005 ae->un.AttrInt = HBA_PORTSPEED_32GFC;
2006 break;
2007 default:
2008 ae->un.AttrInt = HBA_PORTSPEED_UNKNOWN;
2009 break;
2010 }
2011 } else {
2012 switch (phba->fc_linkspeed) {
2013 case LPFC_ASYNC_LINK_SPEED_10GBPS:
2014 ae->un.AttrInt = HBA_PORTSPEED_10GE;
2015 break;
2016 case LPFC_ASYNC_LINK_SPEED_25GBPS:
2017 ae->un.AttrInt = HBA_PORTSPEED_25GE;
2018 break;
2019 case LPFC_ASYNC_LINK_SPEED_40GBPS:
2020 ae->un.AttrInt = HBA_PORTSPEED_40GE;
2021 break;
2022 case LPFC_ASYNC_LINK_SPEED_100GBPS:
2023 ae->un.AttrInt = HBA_PORTSPEED_100GE;
2024 break;
2025 default:
2026 ae->un.AttrInt = HBA_PORTSPEED_UNKNOWN;
2027 break;
2028 }
James Smart4258e982015-12-16 18:11:58 -05002029 }
James Smarta085e872015-12-16 18:12:02 -05002030
James Smart4258e982015-12-16 18:11:58 -05002031 ae->un.AttrInt = cpu_to_be32(ae->un.AttrInt);
2032 size = FOURBYTES + sizeof(uint32_t);
2033 ad->AttrLen = cpu_to_be16(size);
2034 ad->AttrType = cpu_to_be16(RPRT_PORT_SPEED);
2035 return size;
2036}
2037
2038int
2039lpfc_fdmi_port_attr_max_frame(struct lpfc_vport *vport,
2040 struct lpfc_fdmi_attr_def *ad)
2041{
2042 struct serv_parm *hsp;
2043 struct lpfc_fdmi_attr_entry *ae;
2044 uint32_t size;
2045
2046 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
2047
2048 hsp = (struct serv_parm *)&vport->fc_sparam;
2049 ae->un.AttrInt = (((uint32_t) hsp->cmn.bbRcvSizeMsb) << 8) |
2050 (uint32_t) hsp->cmn.bbRcvSizeLsb;
2051 ae->un.AttrInt = cpu_to_be32(ae->un.AttrInt);
2052 size = FOURBYTES + sizeof(uint32_t);
2053 ad->AttrLen = cpu_to_be16(size);
2054 ad->AttrType = cpu_to_be16(RPRT_MAX_FRAME_SIZE);
2055 return size;
2056}
2057
2058int
2059lpfc_fdmi_port_attr_os_devname(struct lpfc_vport *vport,
2060 struct lpfc_fdmi_attr_def *ad)
2061{
2062 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
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 snprintf(ae->un.AttrString, sizeof(ae->un.AttrString),
2070 "/sys/class/scsi_host/host%d", shost->host_no);
2071 len = strnlen((char *)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(RPRT_OS_DEVICE_NAME);
2077 return size;
2078}
2079
2080int
2081lpfc_fdmi_port_attr_host_name(struct lpfc_vport *vport,
2082 struct lpfc_fdmi_attr_def *ad)
2083{
2084 struct lpfc_fdmi_attr_entry *ae;
2085 uint32_t len, size;
2086
2087 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
2088 memset(ae, 0, 256);
2089
2090 snprintf(ae->un.AttrString, sizeof(ae->un.AttrString), "%s",
2091 init_utsname()->nodename);
2092
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(RPRT_HOST_NAME);
2098 return size;
2099}
2100
2101int
2102lpfc_fdmi_port_attr_wwnn(struct lpfc_vport *vport,
2103 struct lpfc_fdmi_attr_def *ad)
2104{
2105 struct lpfc_fdmi_attr_entry *ae;
2106 uint32_t size;
2107
2108 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
2109 memset(ae, 0, sizeof(struct lpfc_name));
2110
2111 memcpy(&ae->un.AttrWWN, &vport->fc_sparam.nodeName,
2112 sizeof(struct lpfc_name));
2113 size = FOURBYTES + sizeof(struct lpfc_name);
2114 ad->AttrLen = cpu_to_be16(size);
2115 ad->AttrType = cpu_to_be16(RPRT_NODENAME);
2116 return size;
2117}
2118
2119int
2120lpfc_fdmi_port_attr_wwpn(struct lpfc_vport *vport,
2121 struct lpfc_fdmi_attr_def *ad)
2122{
2123 struct lpfc_fdmi_attr_entry *ae;
2124 uint32_t size;
2125
2126 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
2127 memset(ae, 0, sizeof(struct lpfc_name));
2128
2129 memcpy(&ae->un.AttrWWN, &vport->fc_sparam.portName,
2130 sizeof(struct lpfc_name));
2131 size = FOURBYTES + sizeof(struct lpfc_name);
2132 ad->AttrLen = cpu_to_be16(size);
2133 ad->AttrType = cpu_to_be16(RPRT_PORTNAME);
2134 return size;
2135}
2136
2137int
2138lpfc_fdmi_port_attr_symbolic_name(struct lpfc_vport *vport,
2139 struct lpfc_fdmi_attr_def *ad)
2140{
2141 struct lpfc_fdmi_attr_entry *ae;
2142 uint32_t len, size;
2143
2144 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
2145 memset(ae, 0, 256);
2146
2147 len = lpfc_vport_symbolic_port_name(vport, ae->un.AttrString, 256);
2148 len += (len & 3) ? (4 - (len & 3)) : 4;
2149 size = FOURBYTES + len;
2150 ad->AttrLen = cpu_to_be16(size);
2151 ad->AttrType = cpu_to_be16(RPRT_SYM_PORTNAME);
2152 return size;
2153}
2154
2155int
2156lpfc_fdmi_port_attr_port_type(struct lpfc_vport *vport,
2157 struct lpfc_fdmi_attr_def *ad)
2158{
2159 struct lpfc_hba *phba = vport->phba;
2160 struct lpfc_fdmi_attr_entry *ae;
2161 uint32_t size;
2162
2163 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
2164 if (phba->fc_topology == LPFC_TOPOLOGY_LOOP)
2165 ae->un.AttrInt = cpu_to_be32(LPFC_FDMI_PORTTYPE_NLPORT);
2166 else
2167 ae->un.AttrInt = cpu_to_be32(LPFC_FDMI_PORTTYPE_NPORT);
2168 size = FOURBYTES + sizeof(uint32_t);
2169 ad->AttrLen = cpu_to_be16(size);
2170 ad->AttrType = cpu_to_be16(RPRT_PORT_TYPE);
2171 return size;
2172}
2173
2174int
2175lpfc_fdmi_port_attr_class(struct lpfc_vport *vport,
2176 struct lpfc_fdmi_attr_def *ad)
2177{
2178 struct lpfc_fdmi_attr_entry *ae;
2179 uint32_t size;
2180
2181 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
2182 ae->un.AttrInt = cpu_to_be32(FC_COS_CLASS2 | FC_COS_CLASS3);
2183 size = FOURBYTES + sizeof(uint32_t);
2184 ad->AttrLen = cpu_to_be16(size);
2185 ad->AttrType = cpu_to_be16(RPRT_SUPPORTED_CLASS);
2186 return size;
2187}
2188
2189int
2190lpfc_fdmi_port_attr_fabric_wwpn(struct lpfc_vport *vport,
2191 struct lpfc_fdmi_attr_def *ad)
2192{
2193 struct lpfc_fdmi_attr_entry *ae;
2194 uint32_t size;
2195
2196 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
2197 memset(ae, 0, sizeof(struct lpfc_name));
2198
2199 memcpy(&ae->un.AttrWWN, &vport->fabric_portname,
2200 sizeof(struct lpfc_name));
2201 size = FOURBYTES + sizeof(struct lpfc_name);
2202 ad->AttrLen = cpu_to_be16(size);
2203 ad->AttrType = cpu_to_be16(RPRT_FABRICNAME);
2204 return size;
2205}
2206
2207int
2208lpfc_fdmi_port_attr_active_fc4type(struct lpfc_vport *vport,
2209 struct lpfc_fdmi_attr_def *ad)
2210{
2211 struct lpfc_fdmi_attr_entry *ae;
2212 uint32_t size;
2213
2214 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
2215 memset(ae, 0, 32);
2216
2217 ae->un.AttrTypes[3] = 0x02; /* Type 1 - ELS */
2218 ae->un.AttrTypes[2] = 0x01; /* Type 8 - FCP */
2219 ae->un.AttrTypes[7] = 0x01; /* Type 32 - CT */
2220 size = FOURBYTES + 32;
2221 ad->AttrLen = cpu_to_be16(size);
2222 ad->AttrType = cpu_to_be16(RPRT_ACTIVE_FC4_TYPES);
2223 return size;
2224}
2225
2226int
2227lpfc_fdmi_port_attr_port_state(struct lpfc_vport *vport,
2228 struct lpfc_fdmi_attr_def *ad)
2229{
2230 struct lpfc_fdmi_attr_entry *ae;
2231 uint32_t size;
2232
2233 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
2234 /* Link Up - operational */
2235 ae->un.AttrInt = cpu_to_be32(LPFC_FDMI_PORTSTATE_ONLINE);
2236 size = FOURBYTES + sizeof(uint32_t);
2237 ad->AttrLen = cpu_to_be16(size);
2238 ad->AttrType = cpu_to_be16(RPRT_PORT_STATE);
2239 return size;
2240}
2241
2242int
2243lpfc_fdmi_port_attr_num_disc(struct lpfc_vport *vport,
2244 struct lpfc_fdmi_attr_def *ad)
2245{
2246 struct lpfc_fdmi_attr_entry *ae;
2247 uint32_t size;
2248
2249 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
2250 vport->fdmi_num_disc = lpfc_find_map_node(vport);
2251 ae->un.AttrInt = cpu_to_be32(vport->fdmi_num_disc);
2252 size = FOURBYTES + sizeof(uint32_t);
2253 ad->AttrLen = cpu_to_be16(size);
2254 ad->AttrType = cpu_to_be16(RPRT_DISC_PORT);
2255 return size;
2256}
2257
2258int
2259lpfc_fdmi_port_attr_nportid(struct lpfc_vport *vport,
2260 struct lpfc_fdmi_attr_def *ad)
2261{
2262 struct lpfc_fdmi_attr_entry *ae;
2263 uint32_t size;
2264
2265 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
2266 ae->un.AttrInt = cpu_to_be32(vport->fc_myDID);
2267 size = FOURBYTES + sizeof(uint32_t);
2268 ad->AttrLen = cpu_to_be16(size);
2269 ad->AttrType = cpu_to_be16(RPRT_PORT_ID);
2270 return size;
2271}
2272
2273int
2274lpfc_fdmi_smart_attr_service(struct lpfc_vport *vport,
2275 struct lpfc_fdmi_attr_def *ad)
2276{
2277 struct lpfc_fdmi_attr_entry *ae;
2278 uint32_t len, size;
2279
2280 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
2281 memset(ae, 0, 256);
2282
2283 strncpy(ae->un.AttrString, "Smart SAN Initiator",
2284 sizeof(ae->un.AttrString));
2285 len = strnlen(ae->un.AttrString,
2286 sizeof(ae->un.AttrString));
2287 len += (len & 3) ? (4 - (len & 3)) : 4;
2288 size = FOURBYTES + len;
2289 ad->AttrLen = cpu_to_be16(size);
2290 ad->AttrType = cpu_to_be16(RPRT_SMART_SERVICE);
2291 return size;
2292}
2293
2294int
2295lpfc_fdmi_smart_attr_guid(struct lpfc_vport *vport,
2296 struct lpfc_fdmi_attr_def *ad)
2297{
2298 struct lpfc_fdmi_attr_entry *ae;
2299 uint32_t size;
2300
2301 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
2302 memset(ae, 0, 256);
2303
2304 memcpy(&ae->un.AttrString, &vport->fc_sparam.nodeName,
2305 sizeof(struct lpfc_name));
2306 memcpy((((uint8_t *)&ae->un.AttrString) +
2307 sizeof(struct lpfc_name)),
2308 &vport->fc_sparam.portName, sizeof(struct lpfc_name));
2309 size = FOURBYTES + (2 * sizeof(struct lpfc_name));
2310 ad->AttrLen = cpu_to_be16(size);
2311 ad->AttrType = cpu_to_be16(RPRT_SMART_GUID);
2312 return size;
2313}
2314
2315int
2316lpfc_fdmi_smart_attr_version(struct lpfc_vport *vport,
2317 struct lpfc_fdmi_attr_def *ad)
2318{
2319 struct lpfc_fdmi_attr_entry *ae;
2320 uint32_t len, size;
2321
2322 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
2323 memset(ae, 0, 256);
2324
2325 strncpy(ae->un.AttrString, "Smart SAN Version 1.0",
2326 sizeof(ae->un.AttrString));
2327 len = strnlen(ae->un.AttrString,
2328 sizeof(ae->un.AttrString));
2329 len += (len & 3) ? (4 - (len & 3)) : 4;
2330 size = FOURBYTES + len;
2331 ad->AttrLen = cpu_to_be16(size);
2332 ad->AttrType = cpu_to_be16(RPRT_SMART_VERSION);
2333 return size;
2334}
2335
2336int
2337lpfc_fdmi_smart_attr_model(struct lpfc_vport *vport,
2338 struct lpfc_fdmi_attr_def *ad)
2339{
2340 struct lpfc_hba *phba = vport->phba;
2341 struct lpfc_fdmi_attr_entry *ae;
2342 uint32_t len, size;
2343
2344 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
2345 memset(ae, 0, 256);
2346
2347 strncpy(ae->un.AttrString, phba->ModelName,
2348 sizeof(ae->un.AttrString));
2349 len = strnlen(ae->un.AttrString, sizeof(ae->un.AttrString));
2350 len += (len & 3) ? (4 - (len & 3)) : 4;
2351 size = FOURBYTES + len;
2352 ad->AttrLen = cpu_to_be16(size);
2353 ad->AttrType = cpu_to_be16(RPRT_SMART_MODEL);
2354 return size;
2355}
2356
2357int
2358lpfc_fdmi_smart_attr_port_info(struct lpfc_vport *vport,
2359 struct lpfc_fdmi_attr_def *ad)
2360{
2361 struct lpfc_fdmi_attr_entry *ae;
2362 uint32_t size;
2363
2364 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
2365
2366 /* SRIOV (type 3) is not supported */
2367 if (vport->vpi)
2368 ae->un.AttrInt = cpu_to_be32(2); /* NPIV */
2369 else
2370 ae->un.AttrInt = cpu_to_be32(1); /* Physical */
2371 size = FOURBYTES + sizeof(uint32_t);
2372 ad->AttrLen = cpu_to_be16(size);
2373 ad->AttrType = cpu_to_be16(RPRT_SMART_PORT_INFO);
2374 return size;
2375}
2376
2377int
2378lpfc_fdmi_smart_attr_qos(struct lpfc_vport *vport,
2379 struct lpfc_fdmi_attr_def *ad)
2380{
2381 struct lpfc_fdmi_attr_entry *ae;
2382 uint32_t size;
2383
2384 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
2385 ae->un.AttrInt = cpu_to_be32(0);
2386 size = FOURBYTES + sizeof(uint32_t);
2387 ad->AttrLen = cpu_to_be16(size);
2388 ad->AttrType = cpu_to_be16(RPRT_SMART_QOS);
2389 return size;
2390}
2391
2392int
2393lpfc_fdmi_smart_attr_security(struct lpfc_vport *vport,
2394 struct lpfc_fdmi_attr_def *ad)
2395{
2396 struct lpfc_fdmi_attr_entry *ae;
2397 uint32_t size;
2398
2399 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
2400 ae->un.AttrInt = cpu_to_be32(0);
2401 size = FOURBYTES + sizeof(uint32_t);
2402 ad->AttrLen = cpu_to_be16(size);
2403 ad->AttrType = cpu_to_be16(RPRT_SMART_SECURITY);
2404 return size;
2405}
2406
2407/* RHBA attribute jump table */
2408int (*lpfc_fdmi_hba_action[])
2409 (struct lpfc_vport *vport, struct lpfc_fdmi_attr_def *ad) = {
2410 /* Action routine Mask bit Attribute type */
2411 lpfc_fdmi_hba_attr_wwnn, /* bit0 RHBA_NODENAME */
2412 lpfc_fdmi_hba_attr_manufacturer, /* bit1 RHBA_MANUFACTURER */
2413 lpfc_fdmi_hba_attr_sn, /* bit2 RHBA_SERIAL_NUMBER */
2414 lpfc_fdmi_hba_attr_model, /* bit3 RHBA_MODEL */
2415 lpfc_fdmi_hba_attr_description, /* bit4 RHBA_MODEL_DESCRIPTION */
2416 lpfc_fdmi_hba_attr_hdw_ver, /* bit5 RHBA_HARDWARE_VERSION */
2417 lpfc_fdmi_hba_attr_drvr_ver, /* bit6 RHBA_DRIVER_VERSION */
2418 lpfc_fdmi_hba_attr_rom_ver, /* bit7 RHBA_OPTION_ROM_VERSION */
2419 lpfc_fdmi_hba_attr_fmw_ver, /* bit8 RHBA_FIRMWARE_VERSION */
2420 lpfc_fdmi_hba_attr_os_ver, /* bit9 RHBA_OS_NAME_VERSION */
2421 lpfc_fdmi_hba_attr_ct_len, /* bit10 RHBA_MAX_CT_PAYLOAD_LEN */
2422 lpfc_fdmi_hba_attr_symbolic_name, /* bit11 RHBA_SYM_NODENAME */
2423 lpfc_fdmi_hba_attr_vendor_info, /* bit12 RHBA_VENDOR_INFO */
2424 lpfc_fdmi_hba_attr_num_ports, /* bit13 RHBA_NUM_PORTS */
2425 lpfc_fdmi_hba_attr_fabric_wwnn, /* bit14 RHBA_FABRIC_WWNN */
2426 lpfc_fdmi_hba_attr_bios_ver, /* bit15 RHBA_BIOS_VERSION */
2427 lpfc_fdmi_hba_attr_bios_state, /* bit16 RHBA_BIOS_STATE */
2428 lpfc_fdmi_hba_attr_vendor_id, /* bit17 RHBA_VENDOR_ID */
2429};
2430
2431/* RPA / RPRT attribute jump table */
2432int (*lpfc_fdmi_port_action[])
2433 (struct lpfc_vport *vport, struct lpfc_fdmi_attr_def *ad) = {
2434 /* Action routine Mask bit Attribute type */
2435 lpfc_fdmi_port_attr_fc4type, /* bit0 RPRT_SUPPORT_FC4_TYPES */
2436 lpfc_fdmi_port_attr_support_speed, /* bit1 RPRT_SUPPORTED_SPEED */
2437 lpfc_fdmi_port_attr_speed, /* bit2 RPRT_PORT_SPEED */
2438 lpfc_fdmi_port_attr_max_frame, /* bit3 RPRT_MAX_FRAME_SIZE */
2439 lpfc_fdmi_port_attr_os_devname, /* bit4 RPRT_OS_DEVICE_NAME */
2440 lpfc_fdmi_port_attr_host_name, /* bit5 RPRT_HOST_NAME */
2441 lpfc_fdmi_port_attr_wwnn, /* bit6 RPRT_NODENAME */
2442 lpfc_fdmi_port_attr_wwpn, /* bit7 RPRT_PORTNAME */
2443 lpfc_fdmi_port_attr_symbolic_name, /* bit8 RPRT_SYM_PORTNAME */
2444 lpfc_fdmi_port_attr_port_type, /* bit9 RPRT_PORT_TYPE */
2445 lpfc_fdmi_port_attr_class, /* bit10 RPRT_SUPPORTED_CLASS */
2446 lpfc_fdmi_port_attr_fabric_wwpn, /* bit11 RPRT_FABRICNAME */
2447 lpfc_fdmi_port_attr_active_fc4type, /* bit12 RPRT_ACTIVE_FC4_TYPES */
2448 lpfc_fdmi_port_attr_port_state, /* bit13 RPRT_PORT_STATE */
2449 lpfc_fdmi_port_attr_num_disc, /* bit14 RPRT_DISC_PORT */
2450 lpfc_fdmi_port_attr_nportid, /* bit15 RPRT_PORT_ID */
2451 lpfc_fdmi_smart_attr_service, /* bit16 RPRT_SMART_SERVICE */
2452 lpfc_fdmi_smart_attr_guid, /* bit17 RPRT_SMART_GUID */
2453 lpfc_fdmi_smart_attr_version, /* bit18 RPRT_SMART_VERSION */
2454 lpfc_fdmi_smart_attr_model, /* bit19 RPRT_SMART_MODEL */
2455 lpfc_fdmi_smart_attr_port_info, /* bit20 RPRT_SMART_PORT_INFO */
2456 lpfc_fdmi_smart_attr_qos, /* bit21 RPRT_SMART_QOS */
2457 lpfc_fdmi_smart_attr_security, /* bit22 RPRT_SMART_SECURITY */
2458};
2459
2460/**
2461 * lpfc_fdmi_cmd - Build and send a FDMI cmd to the specified NPort
2462 * @vport: pointer to a host virtual N_Port data structure.
2463 * @ndlp: ndlp to send FDMI cmd to (if NULL use FDMI_DID)
2464 * cmdcode: FDMI command to send
2465 * mask: Mask of HBA or PORT Attributes to send
2466 *
2467 * Builds and sends a FDMI command using the CT subsystem.
2468 */
2469int
2470lpfc_fdmi_cmd(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
2471 int cmdcode, uint32_t new_mask)
dea31012005-04-17 16:05:31 -05002472{
James Smart2e0fef82007-06-17 19:56:36 -05002473 struct lpfc_hba *phba = vport->phba;
dea31012005-04-17 16:05:31 -05002474 struct lpfc_dmabuf *mp, *bmp;
2475 struct lpfc_sli_ct_request *CtReq;
2476 struct ulp_bde64 *bpl;
James Smart4258e982015-12-16 18:11:58 -05002477 uint32_t bit_pos;
dea31012005-04-17 16:05:31 -05002478 uint32_t size;
James Smart76b2c342015-04-07 15:07:19 -04002479 uint32_t rsp_size;
James Smart4258e982015-12-16 18:11:58 -05002480 uint32_t mask;
James Smart76b2c342015-04-07 15:07:19 -04002481 struct lpfc_fdmi_reg_hba *rh;
2482 struct lpfc_fdmi_port_entry *pe;
2483 struct lpfc_fdmi_reg_portattr *pab = NULL;
2484 struct lpfc_fdmi_attr_block *ab = NULL;
James Smart4258e982015-12-16 18:11:58 -05002485 int (*func)(struct lpfc_vport *vport, struct lpfc_fdmi_attr_def *ad);
2486 void (*cmpl)(struct lpfc_hba *, struct lpfc_iocbq *,
2487 struct lpfc_iocbq *);
dea31012005-04-17 16:05:31 -05002488
James Smart4258e982015-12-16 18:11:58 -05002489 if (!ndlp || !NLP_CHK_NODE_ACT(ndlp))
2490 return 0;
2491
2492 cmpl = lpfc_cmpl_ct_disc_fdmi; /* called from discovery */
dea31012005-04-17 16:05:31 -05002493
2494 /* fill in BDEs for command */
2495 /* Allocate buffer for command payload */
James Smart76b2c342015-04-07 15:07:19 -04002496 mp = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL);
dea31012005-04-17 16:05:31 -05002497 if (!mp)
2498 goto fdmi_cmd_exit;
2499
2500 mp->virt = lpfc_mbuf_alloc(phba, 0, &(mp->phys));
2501 if (!mp->virt)
2502 goto fdmi_cmd_free_mp;
2503
2504 /* Allocate buffer for Buffer ptr list */
James Smart76b2c342015-04-07 15:07:19 -04002505 bmp = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL);
dea31012005-04-17 16:05:31 -05002506 if (!bmp)
2507 goto fdmi_cmd_free_mpvirt;
2508
2509 bmp->virt = lpfc_mbuf_alloc(phba, 0, &(bmp->phys));
2510 if (!bmp->virt)
2511 goto fdmi_cmd_free_bmp;
2512
2513 INIT_LIST_HEAD(&mp->list);
2514 INIT_LIST_HEAD(&bmp->list);
2515
2516 /* FDMI request */
James Smarte8b62012007-08-02 11:10:09 -04002517 lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
2518 "0218 FDMI Request Data: x%x x%x x%x\n",
2519 vport->fc_flag, vport->port_state, cmdcode);
James Smart76b2c342015-04-07 15:07:19 -04002520 CtReq = (struct lpfc_sli_ct_request *)mp->virt;
dea31012005-04-17 16:05:31 -05002521
James Smart76b2c342015-04-07 15:07:19 -04002522 /* First populate the CT_IU preamble */
dea31012005-04-17 16:05:31 -05002523 memset(CtReq, 0, sizeof(struct lpfc_sli_ct_request));
2524 CtReq->RevisionId.bits.Revision = SLI_CT_REVISION;
2525 CtReq->RevisionId.bits.InId = 0;
2526
2527 CtReq->FsType = SLI_CT_MANAGEMENT_SERVICE;
2528 CtReq->FsSubType = SLI_CT_FDMI_Subtypes;
James Smart76b2c342015-04-07 15:07:19 -04002529
2530 CtReq->CommandResponse.bits.CmdRsp = cpu_to_be16(cmdcode);
2531 rsp_size = LPFC_BPL_SIZE;
dea31012005-04-17 16:05:31 -05002532 size = 0;
2533
James Smart76b2c342015-04-07 15:07:19 -04002534 /* Next fill in the specific FDMI cmd information */
dea31012005-04-17 16:05:31 -05002535 switch (cmdcode) {
James Smart76b2c342015-04-07 15:07:19 -04002536 case SLI_MGMT_RHAT:
dea31012005-04-17 16:05:31 -05002537 case SLI_MGMT_RHBA:
James Smart4258e982015-12-16 18:11:58 -05002538 rh = (struct lpfc_fdmi_reg_hba *)&CtReq->un.PortID;
2539 /* HBA Identifier */
2540 memcpy(&rh->hi.PortName, &phba->pport->fc_sparam.portName,
2541 sizeof(struct lpfc_name));
dea31012005-04-17 16:05:31 -05002542
James Smart4258e982015-12-16 18:11:58 -05002543 if (cmdcode == SLI_MGMT_RHBA) {
2544 /* Registered Port List */
2545 /* One entry (port) per adapter */
2546 rh->rpl.EntryCnt = cpu_to_be32(1);
2547 memcpy(&rh->rpl.pe, &phba->pport->fc_sparam.portName,
James Smart76b2c342015-04-07 15:07:19 -04002548 sizeof(struct lpfc_name));
dea31012005-04-17 16:05:31 -05002549
James Smart4258e982015-12-16 18:11:58 -05002550 /* point to the HBA attribute block */
2551 size = 2 * sizeof(struct lpfc_name) +
2552 FOURBYTES;
2553 } else {
2554 size = sizeof(struct lpfc_name);
dea31012005-04-17 16:05:31 -05002555 }
James Smart4258e982015-12-16 18:11:58 -05002556 ab = (struct lpfc_fdmi_attr_block *)((uint8_t *)rh + size);
2557 ab->EntryCnt = 0;
2558 size += FOURBYTES;
2559 bit_pos = 0;
2560 if (new_mask)
2561 mask = new_mask;
2562 else
2563 mask = vport->fdmi_hba_mask;
2564
2565 /* Mask will dictate what attributes to build in the request */
2566 while (mask) {
2567 if (mask & 0x1) {
2568 func = lpfc_fdmi_hba_action[bit_pos];
2569 size += func(vport,
2570 (struct lpfc_fdmi_attr_def *)
2571 ((uint8_t *)rh + size));
2572 ab->EntryCnt++;
2573 if ((size + 256) >
2574 (LPFC_BPL_SIZE - LPFC_CT_PREAMBLE))
2575 goto hba_out;
2576 }
2577 mask = mask >> 1;
2578 bit_pos++;
2579 }
2580hba_out:
2581 ab->EntryCnt = cpu_to_be32(ab->EntryCnt);
2582 /* Total size */
2583 size = GID_REQUEST_SZ - 4 + size;
dea31012005-04-17 16:05:31 -05002584 break;
2585
James Smart76b2c342015-04-07 15:07:19 -04002586 case SLI_MGMT_RPRT:
dea31012005-04-17 16:05:31 -05002587 case SLI_MGMT_RPA:
James Smart4258e982015-12-16 18:11:58 -05002588 pab = (struct lpfc_fdmi_reg_portattr *)&CtReq->un.PortID;
2589 if (cmdcode == SLI_MGMT_RPRT) {
2590 rh = (struct lpfc_fdmi_reg_hba *)pab;
2591 /* HBA Identifier */
2592 memcpy(&rh->hi.PortName,
2593 &phba->pport->fc_sparam.portName,
James Smart76b2c342015-04-07 15:07:19 -04002594 sizeof(struct lpfc_name));
James Smart4258e982015-12-16 18:11:58 -05002595 pab = (struct lpfc_fdmi_reg_portattr *)
2596 ((uint8_t *)pab + sizeof(struct lpfc_name));
dea31012005-04-17 16:05:31 -05002597 }
James Smart4258e982015-12-16 18:11:58 -05002598
2599 memcpy((uint8_t *)&pab->PortName,
2600 (uint8_t *)&vport->fc_sparam.portName,
2601 sizeof(struct lpfc_name));
2602 size += sizeof(struct lpfc_name) + FOURBYTES;
2603 pab->ab.EntryCnt = 0;
2604 bit_pos = 0;
2605 if (new_mask)
2606 mask = new_mask;
2607 else
2608 mask = vport->fdmi_port_mask;
2609
2610 /* Mask will dictate what attributes to build in the request */
2611 while (mask) {
2612 if (mask & 0x1) {
2613 func = lpfc_fdmi_port_action[bit_pos];
2614 size += func(vport,
2615 (struct lpfc_fdmi_attr_def *)
2616 ((uint8_t *)pab + size));
2617 pab->ab.EntryCnt++;
2618 if ((size + 256) >
2619 (LPFC_BPL_SIZE - LPFC_CT_PREAMBLE))
2620 goto port_out;
2621 }
2622 mask = mask >> 1;
2623 bit_pos++;
2624 }
2625port_out:
2626 pab->ab.EntryCnt = cpu_to_be32(pab->ab.EntryCnt);
2627 /* Total size */
2628 if (cmdcode == SLI_MGMT_RPRT)
2629 size += sizeof(struct lpfc_name);
2630 size = GID_REQUEST_SZ - 4 + size;
dea31012005-04-17 16:05:31 -05002631 break;
2632
James Smart76b2c342015-04-07 15:07:19 -04002633 case SLI_MGMT_GHAT:
2634 case SLI_MGMT_GRPL:
2635 rsp_size = FC_MAX_NS_RSP;
dea31012005-04-17 16:05:31 -05002636 case SLI_MGMT_DHBA:
James Smart76b2c342015-04-07 15:07:19 -04002637 case SLI_MGMT_DHAT:
2638 pe = (struct lpfc_fdmi_port_entry *)&CtReq->un.PortID;
2639 memcpy((uint8_t *)&pe->PortName,
2640 (uint8_t *)&vport->fc_sparam.portName,
2641 sizeof(struct lpfc_name));
2642 size = GID_REQUEST_SZ - 4 + sizeof(struct lpfc_name);
dea31012005-04-17 16:05:31 -05002643 break;
2644
James Smart76b2c342015-04-07 15:07:19 -04002645 case SLI_MGMT_GPAT:
2646 case SLI_MGMT_GPAS:
2647 rsp_size = FC_MAX_NS_RSP;
dea31012005-04-17 16:05:31 -05002648 case SLI_MGMT_DPRT:
James Smart76b2c342015-04-07 15:07:19 -04002649 case SLI_MGMT_DPA:
2650 pe = (struct lpfc_fdmi_port_entry *)&CtReq->un.PortID;
2651 memcpy((uint8_t *)&pe->PortName,
2652 (uint8_t *)&vport->fc_sparam.portName,
2653 sizeof(struct lpfc_name));
2654 size = GID_REQUEST_SZ - 4 + sizeof(struct lpfc_name);
dea31012005-04-17 16:05:31 -05002655 break;
James Smart76b2c342015-04-07 15:07:19 -04002656 case SLI_MGMT_GRHL:
2657 size = GID_REQUEST_SZ - 4;
2658 break;
2659 default:
2660 lpfc_printf_vlog(vport, KERN_WARNING, LOG_DISCOVERY,
2661 "0298 FDMI cmdcode x%x not supported\n",
2662 cmdcode);
2663 goto fdmi_cmd_free_bmpvirt;
dea31012005-04-17 16:05:31 -05002664 }
James Smart76b2c342015-04-07 15:07:19 -04002665 CtReq->CommandResponse.bits.Size = cpu_to_be16(rsp_size);
dea31012005-04-17 16:05:31 -05002666
James Smart76b2c342015-04-07 15:07:19 -04002667 bpl = (struct ulp_bde64 *)bmp->virt;
2668 bpl->addrHigh = le32_to_cpu(putPaddrHigh(mp->phys));
2669 bpl->addrLow = le32_to_cpu(putPaddrLow(mp->phys));
dea31012005-04-17 16:05:31 -05002670 bpl->tus.f.bdeFlags = 0;
2671 bpl->tus.f.bdeSize = size;
dea31012005-04-17 16:05:31 -05002672
James Smart76b2c342015-04-07 15:07:19 -04002673 /*
2674 * The lpfc_ct_cmd/lpfc_get_req shall increment ndlp reference count
James Smarte47c9092008-02-08 18:49:26 -05002675 * to hold ndlp reference for the corresponding callback function.
2676 */
James Smart76b2c342015-04-07 15:07:19 -04002677 if (!lpfc_ct_cmd(vport, mp, bmp, ndlp, cmpl, rsp_size, 0))
dea31012005-04-17 16:05:31 -05002678 return 0;
2679
James Smart76b2c342015-04-07 15:07:19 -04002680 /*
2681 * Decrement ndlp reference count to release ndlp reference held
James Smarte47c9092008-02-08 18:49:26 -05002682 * for the failed command's callback function.
2683 */
James Smart51ef4c22007-08-02 11:10:31 -04002684 lpfc_nlp_put(ndlp);
James Smarte47c9092008-02-08 18:49:26 -05002685
James Smart76b2c342015-04-07 15:07:19 -04002686fdmi_cmd_free_bmpvirt:
dea31012005-04-17 16:05:31 -05002687 lpfc_mbuf_free(phba, bmp->virt, bmp->phys);
2688fdmi_cmd_free_bmp:
2689 kfree(bmp);
2690fdmi_cmd_free_mpvirt:
2691 lpfc_mbuf_free(phba, mp->virt, mp->phys);
2692fdmi_cmd_free_mp:
2693 kfree(mp);
2694fdmi_cmd_exit:
2695 /* Issue FDMI request failed */
James Smarte8b62012007-08-02 11:10:09 -04002696 lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
2697 "0244 Issue FDMI request failed Data: x%x\n",
2698 cmdcode);
dea31012005-04-17 16:05:31 -05002699 return 1;
2700}
2701
James Smart92494142011-02-16 12:39:44 -05002702/**
2703 * lpfc_delayed_disc_tmo - Timeout handler for delayed discovery timer.
2704 * @ptr - Context object of the timer.
2705 *
2706 * This function set the WORKER_DELAYED_DISC_TMO flag and wake up
2707 * the worker thread.
2708 **/
2709void
2710lpfc_delayed_disc_tmo(unsigned long ptr)
2711{
2712 struct lpfc_vport *vport = (struct lpfc_vport *)ptr;
2713 struct lpfc_hba *phba = vport->phba;
2714 uint32_t tmo_posted;
2715 unsigned long iflag;
2716
2717 spin_lock_irqsave(&vport->work_port_lock, iflag);
2718 tmo_posted = vport->work_port_events & WORKER_DELAYED_DISC_TMO;
2719 if (!tmo_posted)
2720 vport->work_port_events |= WORKER_DELAYED_DISC_TMO;
2721 spin_unlock_irqrestore(&vport->work_port_lock, iflag);
2722
2723 if (!tmo_posted)
2724 lpfc_worker_wake_up(phba);
2725 return;
2726}
2727
2728/**
2729 * lpfc_delayed_disc_timeout_handler - Function called by worker thread to
2730 * handle delayed discovery.
2731 * @vport: pointer to a host virtual N_Port data structure.
2732 *
2733 * This function start nport discovery of the vport.
2734 **/
2735void
2736lpfc_delayed_disc_timeout_handler(struct lpfc_vport *vport)
2737{
2738 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
2739
2740 spin_lock_irq(shost->host_lock);
2741 if (!(vport->fc_flag & FC_DISC_DELAYED)) {
2742 spin_unlock_irq(shost->host_lock);
2743 return;
2744 }
2745 vport->fc_flag &= ~FC_DISC_DELAYED;
2746 spin_unlock_irq(shost->host_lock);
2747
2748 lpfc_do_scr_ns_plogi(vport->phba, vport);
2749}
2750
dea31012005-04-17 16:05:31 -05002751void
James Smart2e0fef82007-06-17 19:56:36 -05002752lpfc_decode_firmware_rev(struct lpfc_hba *phba, char *fwrevision, int flag)
dea31012005-04-17 16:05:31 -05002753{
2754 struct lpfc_sli *psli = &phba->sli;
2755 lpfc_vpd_t *vp = &phba->vpd;
2756 uint32_t b1, b2, b3, b4, i, rev;
2757 char c;
2758 uint32_t *ptr, str[4];
2759 uint8_t *fwname;
2760
James Smartf1126682009-06-10 17:22:44 -04002761 if (phba->sli_rev == LPFC_SLI_REV4)
James Smart6b5151f2012-01-18 16:24:06 -05002762 snprintf(fwrevision, FW_REV_STR_SIZE, "%s", vp->rev.opFwName);
James Smartf1126682009-06-10 17:22:44 -04002763 else if (vp->rev.rBit) {
James Smartf4b4c682009-05-22 14:53:12 -04002764 if (psli->sli_flag & LPFC_SLI_ACTIVE)
dea31012005-04-17 16:05:31 -05002765 rev = vp->rev.sli2FwRev;
2766 else
2767 rev = vp->rev.sli1FwRev;
2768
2769 b1 = (rev & 0x0000f000) >> 12;
2770 b2 = (rev & 0x00000f00) >> 8;
2771 b3 = (rev & 0x000000c0) >> 6;
2772 b4 = (rev & 0x00000030) >> 4;
2773
2774 switch (b4) {
2775 case 0:
2776 c = 'N';
2777 break;
2778 case 1:
2779 c = 'A';
2780 break;
2781 case 2:
2782 c = 'B';
2783 break;
James Smart73d91e52011-10-10 21:32:10 -04002784 case 3:
2785 c = 'X';
2786 break;
dea31012005-04-17 16:05:31 -05002787 default:
2788 c = 0;
2789 break;
2790 }
2791 b4 = (rev & 0x0000000f);
2792
James Smartf4b4c682009-05-22 14:53:12 -04002793 if (psli->sli_flag & LPFC_SLI_ACTIVE)
dea31012005-04-17 16:05:31 -05002794 fwname = vp->rev.sli2FwName;
2795 else
2796 fwname = vp->rev.sli1FwName;
2797
2798 for (i = 0; i < 16; i++)
2799 if (fwname[i] == 0x20)
2800 fwname[i] = 0;
2801
2802 ptr = (uint32_t*)fwname;
2803
2804 for (i = 0; i < 3; i++)
2805 str[i] = be32_to_cpu(*ptr++);
2806
2807 if (c == 0) {
2808 if (flag)
2809 sprintf(fwrevision, "%d.%d%d (%s)",
2810 b1, b2, b3, (char *)str);
2811 else
2812 sprintf(fwrevision, "%d.%d%d", b1,
2813 b2, b3);
2814 } else {
2815 if (flag)
2816 sprintf(fwrevision, "%d.%d%d%c%d (%s)",
2817 b1, b2, b3, c,
2818 b4, (char *)str);
2819 else
2820 sprintf(fwrevision, "%d.%d%d%c%d",
2821 b1, b2, b3, c, b4);
2822 }
2823 } else {
2824 rev = vp->rev.smFwRev;
2825
2826 b1 = (rev & 0xff000000) >> 24;
2827 b2 = (rev & 0x00f00000) >> 20;
2828 b3 = (rev & 0x000f0000) >> 16;
2829 c = (rev & 0x0000ff00) >> 8;
2830 b4 = (rev & 0x000000ff);
2831
Roel Kluind44a6d22010-01-17 16:15:57 +01002832 sprintf(fwrevision, "%d.%d%d%c%d", b1, b2, b3, c, b4);
dea31012005-04-17 16:05:31 -05002833 }
2834 return;
2835}