blob: ac6e087f6857c60f375d9b8609cd20b1bbf42dc9 [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 Smart76a95d72010-11-20 23:11:48 -050051/* FDMI Port Speed definitions */
52#define HBA_PORTSPEED_1GBIT 0x0001 /* 1 GBit/sec */
53#define HBA_PORTSPEED_2GBIT 0x0002 /* 2 GBit/sec */
54#define HBA_PORTSPEED_4GBIT 0x0008 /* 4 GBit/sec */
55#define HBA_PORTSPEED_10GBIT 0x0004 /* 10 GBit/sec */
56#define HBA_PORTSPEED_8GBIT 0x0010 /* 8 GBit/sec */
57#define HBA_PORTSPEED_16GBIT 0x0020 /* 16 GBit/sec */
James Smartd38dd522015-08-31 16:48:17 -040058#define HBA_PORTSPEED_32GBIT 0x0040 /* 32 GBit/sec */
James Smart76a95d72010-11-20 23:11:48 -050059#define HBA_PORTSPEED_UNKNOWN 0x0800 /* Unknown */
dea31012005-04-17 16:05:31 -050060
61#define FOURBYTES 4
62
63
64static char *lpfc_release_version = LPFC_DRIVER_VERSION;
65
James Smarted957682007-06-17 19:56:37 -050066static void
67lpfc_ct_ignore_hbq_buffer(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq,
James Smart92d7f7b2007-06-17 19:56:38 -050068 struct lpfc_dmabuf *mp, uint32_t size)
James Smarted957682007-06-17 19:56:37 -050069{
James Smarted957682007-06-17 19:56:37 -050070 if (!mp) {
James Smart9c2face2008-01-11 01:53:18 -050071 lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
James Smart97eab632008-04-07 10:16:05 -040072 "0146 Ignoring unsolicited CT No HBQ "
James Smart9c2face2008-01-11 01:53:18 -050073 "status = x%x\n",
74 piocbq->iocb.ulpStatus);
James Smarted957682007-06-17 19:56:37 -050075 }
James Smart9c2face2008-01-11 01:53:18 -050076 lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
77 "0145 Ignoring unsolicted CT HBQ Size:%d "
78 "status = x%x\n",
79 size, piocbq->iocb.ulpStatus);
80}
81
82static void
83lpfc_ct_unsol_buffer(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq,
84 struct lpfc_dmabuf *mp, uint32_t size)
85{
86 lpfc_ct_ignore_hbq_buffer(phba, piocbq, mp, size);
James Smarted957682007-06-17 19:56:37 -050087}
88
dea31012005-04-17 16:05:31 -050089void
James Smart2e0fef82007-06-17 19:56:36 -050090lpfc_ct_unsol_event(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
91 struct lpfc_iocbq *piocbq)
dea31012005-04-17 16:05:31 -050092{
James Smarted957682007-06-17 19:56:37 -050093 struct lpfc_dmabuf *mp = NULL;
dea31012005-04-17 16:05:31 -050094 IOCB_t *icmd = &piocbq->iocb;
James Smarted957682007-06-17 19:56:37 -050095 int i;
96 struct lpfc_iocbq *iocbq;
97 dma_addr_t paddr;
98 uint32_t size;
James Smart9c2face2008-01-11 01:53:18 -050099 struct list_head head;
100 struct lpfc_dmabuf *bdeBuf;
James Smart92d7f7b2007-06-17 19:56:38 -0500101
James Smart4fede782010-01-26 23:08:55 -0500102 if (lpfc_bsg_ct_unsol_event(phba, pring, piocbq) == 0)
103 return;
James Smartf1c3b0f2009-07-19 10:01:32 -0400104
James Smart92d7f7b2007-06-17 19:56:38 -0500105 if (unlikely(icmd->ulpStatus == IOSTAT_NEED_BUFFER)) {
106 lpfc_sli_hbqbuf_add_hbqs(phba, LPFC_ELS_HBQ);
107 } else if ((icmd->ulpStatus == IOSTAT_LOCAL_REJECT) &&
James Smarte3d2b802012-08-14 14:25:43 -0400108 ((icmd->un.ulpWord[4] & IOERR_PARAM_MASK) ==
109 IOERR_RCV_BUFFER_WAITING)) {
dea31012005-04-17 16:05:31 -0500110 /* Not enough posted buffers; Try posting more buffers */
111 phba->fc_stat.NoRcvBuf++;
James Smart92d7f7b2007-06-17 19:56:38 -0500112 if (!(phba->sli3_options & LPFC_SLI3_HBQ_ENABLED))
James Smart495a7142008-06-14 22:52:59 -0400113 lpfc_post_buffer(phba, pring, 2);
dea31012005-04-17 16:05:31 -0500114 return;
115 }
116
117 /* If there are no BDEs associated with this IOCB,
118 * there is nothing to do.
119 */
120 if (icmd->ulpBdeCount == 0)
121 return;
122
James Smarted957682007-06-17 19:56:37 -0500123 if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) {
James Smart9c2face2008-01-11 01:53:18 -0500124 INIT_LIST_HEAD(&head);
125 list_add_tail(&head, &piocbq->list);
126 list_for_each_entry(iocbq, &head, list) {
James Smarted957682007-06-17 19:56:37 -0500127 icmd = &iocbq->iocb;
James Smart9c2face2008-01-11 01:53:18 -0500128 if (icmd->ulpBdeCount == 0)
James Smarted957682007-06-17 19:56:37 -0500129 continue;
James Smart9c2face2008-01-11 01:53:18 -0500130 bdeBuf = iocbq->context2;
131 iocbq->context2 = NULL;
James Smarted957682007-06-17 19:56:37 -0500132 size = icmd->un.cont64[0].tus.f.bdeSize;
James Smart9c2face2008-01-11 01:53:18 -0500133 lpfc_ct_unsol_buffer(phba, piocbq, bdeBuf, size);
134 lpfc_in_buf_free(phba, bdeBuf);
James Smarted957682007-06-17 19:56:37 -0500135 if (icmd->ulpBdeCount == 2) {
James Smart9c2face2008-01-11 01:53:18 -0500136 bdeBuf = iocbq->context3;
137 iocbq->context3 = NULL;
138 size = icmd->unsli3.rcvsli3.bde2.tus.f.bdeSize;
139 lpfc_ct_unsol_buffer(phba, piocbq, bdeBuf,
140 size);
141 lpfc_in_buf_free(phba, bdeBuf);
James Smarted957682007-06-17 19:56:37 -0500142 }
dea31012005-04-17 16:05:31 -0500143 }
James Smart9c2face2008-01-11 01:53:18 -0500144 list_del(&head);
James Smarted957682007-06-17 19:56:37 -0500145 } else {
James Smartd7c255b2008-08-24 21:50:00 -0400146 INIT_LIST_HEAD(&head);
147 list_add_tail(&head, &piocbq->list);
148 list_for_each_entry(iocbq, &head, list) {
James Smarted957682007-06-17 19:56:37 -0500149 icmd = &iocbq->iocb;
James Smart9c2face2008-01-11 01:53:18 -0500150 if (icmd->ulpBdeCount == 0)
James Smartd7c255b2008-08-24 21:50:00 -0400151 lpfc_ct_unsol_buffer(phba, iocbq, NULL, 0);
James Smarted957682007-06-17 19:56:37 -0500152 for (i = 0; i < icmd->ulpBdeCount; i++) {
153 paddr = getPaddr(icmd->un.cont64[i].addrHigh,
154 icmd->un.cont64[i].addrLow);
155 mp = lpfc_sli_ringpostbuf_get(phba, pring,
156 paddr);
157 size = icmd->un.cont64[i].tus.f.bdeSize;
James Smartd7c255b2008-08-24 21:50:00 -0400158 lpfc_ct_unsol_buffer(phba, iocbq, mp, size);
James Smart92d7f7b2007-06-17 19:56:38 -0500159 lpfc_in_buf_free(phba, mp);
James Smarted957682007-06-17 19:56:37 -0500160 }
James Smart495a7142008-06-14 22:52:59 -0400161 lpfc_post_buffer(phba, pring, i);
dea31012005-04-17 16:05:31 -0500162 }
James Smartd7c255b2008-08-24 21:50:00 -0400163 list_del(&head);
dea31012005-04-17 16:05:31 -0500164 }
dea31012005-04-17 16:05:31 -0500165}
166
James Smart6669f9b2009-10-02 15:16:45 -0400167/**
James Smart6dd9e312013-01-03 15:43:37 -0500168 * lpfc_ct_handle_unsol_abort - ct upper level protocol abort handler
James Smart6669f9b2009-10-02 15:16:45 -0400169 * @phba: Pointer to HBA context object.
James Smart6dd9e312013-01-03 15:43:37 -0500170 * @dmabuf: pointer to a dmabuf that describes the FC sequence
James Smart6669f9b2009-10-02 15:16:45 -0400171 *
James Smart6dd9e312013-01-03 15:43:37 -0500172 * This function serves as the upper level protocol abort handler for CT
173 * protocol.
174 *
175 * Return 1 if abort has been handled, 0 otherwise.
James Smart6669f9b2009-10-02 15:16:45 -0400176 **/
James Smart6dd9e312013-01-03 15:43:37 -0500177int
178lpfc_ct_handle_unsol_abort(struct lpfc_hba *phba, struct hbq_dmabuf *dmabuf)
James Smart6669f9b2009-10-02 15:16:45 -0400179{
James Smart6dd9e312013-01-03 15:43:37 -0500180 int handled;
James Smart6669f9b2009-10-02 15:16:45 -0400181
James Smart6dd9e312013-01-03 15:43:37 -0500182 /* CT upper level goes through BSG */
183 handled = lpfc_bsg_ct_unsol_abort(phba, dmabuf);
James Smart6669f9b2009-10-02 15:16:45 -0400184
James Smart6dd9e312013-01-03 15:43:37 -0500185 return handled;
James Smart6669f9b2009-10-02 15:16:45 -0400186}
187
dea31012005-04-17 16:05:31 -0500188static void
James Smart2e0fef82007-06-17 19:56:36 -0500189lpfc_free_ct_rsp(struct lpfc_hba *phba, struct lpfc_dmabuf *mlist)
dea31012005-04-17 16:05:31 -0500190{
191 struct lpfc_dmabuf *mlast, *next_mlast;
192
193 list_for_each_entry_safe(mlast, next_mlast, &mlist->list, list) {
194 lpfc_mbuf_free(phba, mlast->virt, mlast->phys);
195 list_del(&mlast->list);
196 kfree(mlast);
197 }
198 lpfc_mbuf_free(phba, mlist->virt, mlist->phys);
199 kfree(mlist);
200 return;
201}
202
203static struct lpfc_dmabuf *
James Smart2e0fef82007-06-17 19:56:36 -0500204lpfc_alloc_ct_rsp(struct lpfc_hba *phba, int cmdcode, struct ulp_bde64 *bpl,
dea31012005-04-17 16:05:31 -0500205 uint32_t size, int *entries)
206{
207 struct lpfc_dmabuf *mlist = NULL;
208 struct lpfc_dmabuf *mp;
209 int cnt, i = 0;
210
James Smart09372822008-01-11 01:52:54 -0500211 /* We get chunks of FCELSSIZE */
dea31012005-04-17 16:05:31 -0500212 cnt = size > FCELSSIZE ? FCELSSIZE: size;
213
214 while (size) {
215 /* Allocate buffer for rsp payload */
216 mp = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL);
217 if (!mp) {
218 if (mlist)
219 lpfc_free_ct_rsp(phba, mlist);
220 return NULL;
221 }
222
223 INIT_LIST_HEAD(&mp->list);
224
James Smart92d7f7b2007-06-17 19:56:38 -0500225 if (cmdcode == be16_to_cpu(SLI_CTNS_GID_FT) ||
226 cmdcode == be16_to_cpu(SLI_CTNS_GFF_ID))
dea31012005-04-17 16:05:31 -0500227 mp->virt = lpfc_mbuf_alloc(phba, MEM_PRI, &(mp->phys));
228 else
229 mp->virt = lpfc_mbuf_alloc(phba, 0, &(mp->phys));
230
231 if (!mp->virt) {
232 kfree(mp);
Eric Sesterhenn0b3a82d2006-10-10 14:41:43 -0700233 if (mlist)
234 lpfc_free_ct_rsp(phba, mlist);
dea31012005-04-17 16:05:31 -0500235 return NULL;
236 }
237
238 /* Queue it to a linked list */
239 if (!mlist)
240 mlist = mp;
241 else
242 list_add_tail(&mp->list, &mlist->list);
243
James Smart34b02dc2008-08-24 21:49:55 -0400244 bpl->tus.f.bdeFlags = BUFF_TYPE_BDE_64I;
dea31012005-04-17 16:05:31 -0500245 /* build buffer ptr list for IOCB */
James Smart92d7f7b2007-06-17 19:56:38 -0500246 bpl->addrLow = le32_to_cpu(putPaddrLow(mp->phys) );
247 bpl->addrHigh = le32_to_cpu(putPaddrHigh(mp->phys) );
dea31012005-04-17 16:05:31 -0500248 bpl->tus.f.bdeSize = (uint16_t) cnt;
249 bpl->tus.w = le32_to_cpu(bpl->tus.w);
250 bpl++;
251
252 i++;
253 size -= cnt;
254 }
255
256 *entries = i;
257 return mlist;
258}
259
James Smart858c9f62007-06-17 19:56:39 -0500260int
261lpfc_ct_free_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *ctiocb)
262{
263 struct lpfc_dmabuf *buf_ptr;
264
James Smart51ef4c22007-08-02 11:10:31 -0400265 if (ctiocb->context_un.ndlp) {
266 lpfc_nlp_put(ctiocb->context_un.ndlp);
267 ctiocb->context_un.ndlp = NULL;
268 }
James Smart858c9f62007-06-17 19:56:39 -0500269 if (ctiocb->context1) {
270 buf_ptr = (struct lpfc_dmabuf *) ctiocb->context1;
271 lpfc_mbuf_free(phba, buf_ptr->virt, buf_ptr->phys);
272 kfree(buf_ptr);
273 ctiocb->context1 = NULL;
274 }
275 if (ctiocb->context2) {
276 lpfc_free_ct_rsp(phba, (struct lpfc_dmabuf *) ctiocb->context2);
277 ctiocb->context2 = NULL;
278 }
279
280 if (ctiocb->context3) {
281 buf_ptr = (struct lpfc_dmabuf *) ctiocb->context3;
282 lpfc_mbuf_free(phba, buf_ptr->virt, buf_ptr->phys);
283 kfree(buf_ptr);
Felipe Pena1109c942013-10-15 21:29:50 -0300284 ctiocb->context3 = NULL;
James Smart858c9f62007-06-17 19:56:39 -0500285 }
286 lpfc_sli_release_iocbq(phba, ctiocb);
287 return 0;
288}
289
James Smart4258e982015-12-16 18:11:58 -0500290/**
291 * lpfc_gen_req - Build and issue a GEN_REQUEST command to the SLI Layer
292 * @vport: pointer to a host virtual N_Port data structure.
293 * @bmp: Pointer to BPL for SLI command
294 * @inp: Pointer to data buffer for response data.
295 * @outp: Pointer to data buffer that hold the CT command.
296 * @cmpl: completion routine to call when command completes
297 * @ndlp: Destination NPort nodelist entry
298 *
299 * This function as the final part for issuing a CT command.
300 */
dea31012005-04-17 16:05:31 -0500301static int
James Smart2e0fef82007-06-17 19:56:36 -0500302lpfc_gen_req(struct lpfc_vport *vport, struct lpfc_dmabuf *bmp,
dea31012005-04-17 16:05:31 -0500303 struct lpfc_dmabuf *inp, struct lpfc_dmabuf *outp,
304 void (*cmpl) (struct lpfc_hba *, struct lpfc_iocbq *,
305 struct lpfc_iocbq *),
306 struct lpfc_nodelist *ndlp, uint32_t usr_flg, uint32_t num_entry,
James Smart92d7f7b2007-06-17 19:56:38 -0500307 uint32_t tmo, uint8_t retry)
dea31012005-04-17 16:05:31 -0500308{
James Smart2e0fef82007-06-17 19:56:36 -0500309 struct lpfc_hba *phba = vport->phba;
dea31012005-04-17 16:05:31 -0500310 IOCB_t *icmd;
James.Smart@Emulex.Com0bd4ca22005-10-28 20:30:02 -0400311 struct lpfc_iocbq *geniocb;
James Smart92d7f7b2007-06-17 19:56:38 -0500312 int rc;
dea31012005-04-17 16:05:31 -0500313
314 /* Allocate buffer for command iocb */
James.Smart@Emulex.Com0bd4ca22005-10-28 20:30:02 -0400315 geniocb = lpfc_sli_get_iocbq(phba);
dea31012005-04-17 16:05:31 -0500316
317 if (geniocb == NULL)
318 return 1;
dea31012005-04-17 16:05:31 -0500319
320 icmd = &geniocb->iocb;
321 icmd->un.genreq64.bdl.ulpIoTag32 = 0;
322 icmd->un.genreq64.bdl.addrHigh = putPaddrHigh(bmp->phys);
323 icmd->un.genreq64.bdl.addrLow = putPaddrLow(bmp->phys);
James Smart34b02dc2008-08-24 21:49:55 -0400324 icmd->un.genreq64.bdl.bdeFlags = BUFF_TYPE_BLP_64;
James Smart4258e982015-12-16 18:11:58 -0500325 icmd->un.genreq64.bdl.bdeSize = (num_entry * sizeof(struct ulp_bde64));
dea31012005-04-17 16:05:31 -0500326
327 if (usr_flg)
328 geniocb->context3 = NULL;
329 else
330 geniocb->context3 = (uint8_t *) bmp;
331
332 /* Save for completion so we can release these resources */
333 geniocb->context1 = (uint8_t *) inp;
334 geniocb->context2 = (uint8_t *) outp;
James Smarte47c9092008-02-08 18:49:26 -0500335 geniocb->context_un.ndlp = lpfc_nlp_get(ndlp);
dea31012005-04-17 16:05:31 -0500336
337 /* Fill in payload, bp points to frame payload */
338 icmd->ulpCommand = CMD_GEN_REQUEST64_CR;
339
340 /* Fill in rest of iocb */
341 icmd->un.genreq64.w5.hcsw.Fctl = (SI | LA);
342 icmd->un.genreq64.w5.hcsw.Dfctl = 0;
James Smart6a9c52c2009-10-02 15:16:51 -0400343 icmd->un.genreq64.w5.hcsw.Rctl = FC_RCTL_DD_UNSOL_CTL;
344 icmd->un.genreq64.w5.hcsw.Type = FC_TYPE_CT;
dea31012005-04-17 16:05:31 -0500345
Jamie Wellnitzc9f87352006-02-28 19:25:23 -0500346 if (!tmo) {
347 /* FC spec states we need 3 * ratov for CT requests */
348 tmo = (3 * phba->fc_ratov);
349 }
dea31012005-04-17 16:05:31 -0500350 icmd->ulpTimeout = tmo;
351 icmd->ulpBdeCount = 1;
352 icmd->ulpLe = 1;
353 icmd->ulpClass = CLASS3;
354 icmd->ulpContext = ndlp->nlp_rpi;
James Smart6d368e52011-05-24 11:44:12 -0400355 if (phba->sli_rev == LPFC_SLI_REV4)
356 icmd->ulpContext = phba->sli4_hba.rpi_ids[ndlp->nlp_rpi];
dea31012005-04-17 16:05:31 -0500357
James Smart92d7f7b2007-06-17 19:56:38 -0500358 if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) {
359 /* For GEN_REQUEST64_CR, use the RPI */
360 icmd->ulpCt_h = 0;
361 icmd->ulpCt_l = 0;
362 }
363
dea31012005-04-17 16:05:31 -0500364 /* Issue GEN REQ IOCB for NPORT <did> */
James Smarte8b62012007-08-02 11:10:09 -0400365 lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
366 "0119 Issue GEN REQ IOCB to NPORT x%x "
367 "Data: x%x x%x\n",
368 ndlp->nlp_DID, icmd->ulpIoTag,
369 vport->port_state);
dea31012005-04-17 16:05:31 -0500370 geniocb->iocb_cmpl = cmpl;
371 geniocb->drvrTimeout = icmd->ulpTimeout + LPFC_DRVR_TIMEOUT;
James Smart2e0fef82007-06-17 19:56:36 -0500372 geniocb->vport = vport;
James Smart92d7f7b2007-06-17 19:56:38 -0500373 geniocb->retry = retry;
James Smart3772a992009-05-22 14:50:54 -0400374 rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, geniocb, 0);
James Smart92d7f7b2007-06-17 19:56:38 -0500375
376 if (rc == IOCB_ERROR) {
James Bottomley604a3e32005-10-29 10:28:33 -0500377 lpfc_sli_release_iocbq(phba, geniocb);
dea31012005-04-17 16:05:31 -0500378 return 1;
379 }
dea31012005-04-17 16:05:31 -0500380
381 return 0;
382}
383
James Smart4258e982015-12-16 18:11:58 -0500384/**
385 * lpfc_ct_cmd - Build and issue a CT command
386 * @vport: pointer to a host virtual N_Port data structure.
387 * @inmp: Pointer to data buffer for response data.
388 * @bmp: Pointer to BPL for SLI command
389 * @ndlp: Destination NPort nodelist entry
390 * @cmpl: completion routine to call when command completes
391 *
392 * This function is called for issuing a CT command.
393 */
dea31012005-04-17 16:05:31 -0500394static int
James Smart2e0fef82007-06-17 19:56:36 -0500395lpfc_ct_cmd(struct lpfc_vport *vport, struct lpfc_dmabuf *inmp,
dea31012005-04-17 16:05:31 -0500396 struct lpfc_dmabuf *bmp, struct lpfc_nodelist *ndlp,
397 void (*cmpl) (struct lpfc_hba *, struct lpfc_iocbq *,
398 struct lpfc_iocbq *),
James Smart92d7f7b2007-06-17 19:56:38 -0500399 uint32_t rsp_size, uint8_t retry)
dea31012005-04-17 16:05:31 -0500400{
James Smart2e0fef82007-06-17 19:56:36 -0500401 struct lpfc_hba *phba = vport->phba;
dea31012005-04-17 16:05:31 -0500402 struct ulp_bde64 *bpl = (struct ulp_bde64 *) bmp->virt;
403 struct lpfc_dmabuf *outmp;
404 int cnt = 0, status;
405 int cmdcode = ((struct lpfc_sli_ct_request *) inmp->virt)->
406 CommandResponse.bits.CmdRsp;
407
408 bpl++; /* Skip past ct request */
409
410 /* Put buffer(s) for ct rsp in bpl */
411 outmp = lpfc_alloc_ct_rsp(phba, cmdcode, bpl, rsp_size, &cnt);
412 if (!outmp)
413 return -ENOMEM;
James Smart6a9c52c2009-10-02 15:16:51 -0400414 /*
415 * Form the CT IOCB. The total number of BDEs in this IOCB
416 * is the single command plus response count from
417 * lpfc_alloc_ct_rsp.
418 */
419 cnt += 1;
James Smart2e0fef82007-06-17 19:56:36 -0500420 status = lpfc_gen_req(vport, bmp, inmp, outmp, cmpl, ndlp, 0,
James Smart6a9c52c2009-10-02 15:16:51 -0400421 cnt, 0, retry);
dea31012005-04-17 16:05:31 -0500422 if (status) {
423 lpfc_free_ct_rsp(phba, outmp);
424 return -ENOMEM;
425 }
426 return 0;
427}
428
James Smart549e55c2007-08-02 11:09:51 -0400429struct lpfc_vport *
James Smart92d7f7b2007-06-17 19:56:38 -0500430lpfc_find_vport_by_did(struct lpfc_hba *phba, uint32_t did) {
James Smart92d7f7b2007-06-17 19:56:38 -0500431 struct lpfc_vport *vport_curr;
James Smart549e55c2007-08-02 11:09:51 -0400432 unsigned long flags;
James Smart92d7f7b2007-06-17 19:56:38 -0500433
James Smart549e55c2007-08-02 11:09:51 -0400434 spin_lock_irqsave(&phba->hbalock, flags);
James Smart92d7f7b2007-06-17 19:56:38 -0500435 list_for_each_entry(vport_curr, &phba->port_list, listentry) {
James Smart549e55c2007-08-02 11:09:51 -0400436 if ((vport_curr->fc_myDID) && (vport_curr->fc_myDID == did)) {
437 spin_unlock_irqrestore(&phba->hbalock, flags);
James Smart92d7f7b2007-06-17 19:56:38 -0500438 return vport_curr;
James Smart549e55c2007-08-02 11:09:51 -0400439 }
James Smart92d7f7b2007-06-17 19:56:38 -0500440 }
James Smart549e55c2007-08-02 11:09:51 -0400441 spin_unlock_irqrestore(&phba->hbalock, flags);
James Smart92d7f7b2007-06-17 19:56:38 -0500442 return NULL;
443}
444
dea31012005-04-17 16:05:31 -0500445static int
James Smart2e0fef82007-06-17 19:56:36 -0500446lpfc_ns_rsp(struct lpfc_vport *vport, struct lpfc_dmabuf *mp, uint32_t Size)
dea31012005-04-17 16:05:31 -0500447{
James Smart2e0fef82007-06-17 19:56:36 -0500448 struct lpfc_hba *phba = vport->phba;
dea31012005-04-17 16:05:31 -0500449 struct lpfc_sli_ct_request *Response =
450 (struct lpfc_sli_ct_request *) mp->virt;
451 struct lpfc_nodelist *ndlp = NULL;
452 struct lpfc_dmabuf *mlast, *next_mp;
453 uint32_t *ctptr = (uint32_t *) & Response->un.gid.PortType;
James Smart2e0fef82007-06-17 19:56:36 -0500454 uint32_t Did, CTentry;
dea31012005-04-17 16:05:31 -0500455 int Cnt;
456 struct list_head head;
457
James Smart2e0fef82007-06-17 19:56:36 -0500458 lpfc_set_disctmo(vport);
James Smart92d7f7b2007-06-17 19:56:38 -0500459 vport->num_disc_nodes = 0;
James Smart0ff10d42008-01-11 01:52:36 -0500460 vport->fc_ns_retry = 0;
dea31012005-04-17 16:05:31 -0500461
dea31012005-04-17 16:05:31 -0500462
463 list_add_tail(&head, &mp->list);
464 list_for_each_entry_safe(mp, next_mp, &head, list) {
465 mlast = mp;
466
James Smart7054a602007-04-25 09:52:34 -0400467 Cnt = Size > FCELSSIZE ? FCELSSIZE : Size;
468
dea31012005-04-17 16:05:31 -0500469 Size -= Cnt;
470
James Smart1dcb58e2007-04-25 09:51:30 -0400471 if (!ctptr) {
dea31012005-04-17 16:05:31 -0500472 ctptr = (uint32_t *) mlast->virt;
James Smart1dcb58e2007-04-25 09:51:30 -0400473 } else
dea31012005-04-17 16:05:31 -0500474 Cnt -= 16; /* subtract length of CT header */
475
476 /* Loop through entire NameServer list of DIDs */
James Smart4258e982015-12-16 18:11:58 -0500477 while (Cnt >= sizeof(uint32_t)) {
dea31012005-04-17 16:05:31 -0500478 /* Get next DID from NameServer List */
479 CTentry = *ctptr++;
480 Did = ((be32_to_cpu(CTentry)) & Mask_DID);
James Smart92d7f7b2007-06-17 19:56:38 -0500481
dea31012005-04-17 16:05:31 -0500482 ndlp = NULL;
James Smart92d7f7b2007-06-17 19:56:38 -0500483
484 /*
485 * Check for rscn processing or not
486 * To conserve rpi's, filter out addresses for other
487 * vports on the same physical HBAs.
488 */
489 if ((Did != vport->fc_myDID) &&
490 ((lpfc_find_vport_by_did(phba, Did) == NULL) ||
James Smart3de2a652007-08-02 11:09:59 -0400491 vport->cfg_peer_port_login)) {
James Smart92d7f7b2007-06-17 19:56:38 -0500492 if ((vport->port_type != LPFC_NPIV_PORT) ||
James Smart98c9ea52007-10-27 13:37:33 -0400493 (!(vport->ct_flags & FC_CT_RFF_ID)) ||
James Smart3de2a652007-08-02 11:09:59 -0400494 (!vport->cfg_restrict_login)) {
James Smart92d7f7b2007-06-17 19:56:38 -0500495 ndlp = lpfc_setup_disc_node(vport, Did);
James Smart58da1ff2008-04-07 10:15:56 -0400496 if (ndlp && NLP_CHK_NODE_ACT(ndlp)) {
James Smart858c9f62007-06-17 19:56:39 -0500497 lpfc_debugfs_disc_trc(vport,
498 LPFC_DISC_TRC_CT,
499 "Parse GID_FTrsp: "
500 "did:x%x flg:x%x x%x",
501 Did, ndlp->nlp_flag,
502 vport->fc_flag);
503
James Smarte8b62012007-08-02 11:10:09 -0400504 lpfc_printf_vlog(vport,
505 KERN_INFO,
James Smart92d7f7b2007-06-17 19:56:38 -0500506 LOG_DISCOVERY,
James Smarte8b62012007-08-02 11:10:09 -0400507 "0238 Process "
James Smart92d7f7b2007-06-17 19:56:38 -0500508 "x%x NameServer Rsp"
509 "Data: x%x x%x x%x\n",
James Smarte8b62012007-08-02 11:10:09 -0400510 Did, ndlp->nlp_flag,
James Smart92d7f7b2007-06-17 19:56:38 -0500511 vport->fc_flag,
512 vport->fc_rscn_id_cnt);
513 } else {
James Smart858c9f62007-06-17 19:56:39 -0500514 lpfc_debugfs_disc_trc(vport,
515 LPFC_DISC_TRC_CT,
516 "Skip1 GID_FTrsp: "
517 "did:x%x flg:x%x cnt:%d",
518 Did, vport->fc_flag,
519 vport->fc_rscn_id_cnt);
520
James Smarte8b62012007-08-02 11:10:09 -0400521 lpfc_printf_vlog(vport,
522 KERN_INFO,
James Smart92d7f7b2007-06-17 19:56:38 -0500523 LOG_DISCOVERY,
James Smarte8b62012007-08-02 11:10:09 -0400524 "0239 Skip x%x "
James Smart92d7f7b2007-06-17 19:56:38 -0500525 "NameServer Rsp Data: "
526 "x%x x%x\n",
James Smarte8b62012007-08-02 11:10:09 -0400527 Did, vport->fc_flag,
James Smart92d7f7b2007-06-17 19:56:38 -0500528 vport->fc_rscn_id_cnt);
529 }
530
531 } else {
532 if (!(vport->fc_flag & FC_RSCN_MODE) ||
533 (lpfc_rscn_payload_check(vport, Did))) {
James Smart858c9f62007-06-17 19:56:39 -0500534 lpfc_debugfs_disc_trc(vport,
535 LPFC_DISC_TRC_CT,
536 "Query GID_FTrsp: "
537 "did:x%x flg:x%x cnt:%d",
538 Did, vport->fc_flag,
539 vport->fc_rscn_id_cnt);
540
James Smart0ff10d42008-01-11 01:52:36 -0500541 /* This NPortID was previously
542 * a FCP target, * Don't even
543 * bother to send GFF_ID.
544 */
545 ndlp = lpfc_findnode_did(vport,
546 Did);
James Smarte47c9092008-02-08 18:49:26 -0500547 if (ndlp &&
548 NLP_CHK_NODE_ACT(ndlp)
549 && (ndlp->nlp_type &
550 NLP_FCP_TARGET))
James Smart0ff10d42008-01-11 01:52:36 -0500551 lpfc_setup_disc_node
552 (vport, Did);
553 else if (lpfc_ns_cmd(vport,
James Smart92d7f7b2007-06-17 19:56:38 -0500554 SLI_CTNS_GFF_ID,
555 0, Did) == 0)
556 vport->num_disc_nodes++;
James Smart6a9c52c2009-10-02 15:16:51 -0400557 else
558 lpfc_setup_disc_node
559 (vport, Did);
James Smart92d7f7b2007-06-17 19:56:38 -0500560 }
561 else {
James Smart858c9f62007-06-17 19:56:39 -0500562 lpfc_debugfs_disc_trc(vport,
563 LPFC_DISC_TRC_CT,
564 "Skip2 GID_FTrsp: "
565 "did:x%x flg:x%x cnt:%d",
566 Did, vport->fc_flag,
567 vport->fc_rscn_id_cnt);
568
James Smarte8b62012007-08-02 11:10:09 -0400569 lpfc_printf_vlog(vport,
570 KERN_INFO,
James Smart92d7f7b2007-06-17 19:56:38 -0500571 LOG_DISCOVERY,
James Smarte8b62012007-08-02 11:10:09 -0400572 "0245 Skip x%x "
James Smart92d7f7b2007-06-17 19:56:38 -0500573 "NameServer Rsp Data: "
574 "x%x x%x\n",
James Smarte8b62012007-08-02 11:10:09 -0400575 Did, vport->fc_flag,
James Smart92d7f7b2007-06-17 19:56:38 -0500576 vport->fc_rscn_id_cnt);
577 }
578 }
dea31012005-04-17 16:05:31 -0500579 }
James Smart76b2c342015-04-07 15:07:19 -0400580 if (CTentry & (cpu_to_be32(SLI_CT_LAST_ENTRY)))
dea31012005-04-17 16:05:31 -0500581 goto nsout1;
James Smart4258e982015-12-16 18:11:58 -0500582 Cnt -= sizeof(uint32_t);
dea31012005-04-17 16:05:31 -0500583 }
584 ctptr = NULL;
585
586 }
587
588nsout1:
589 list_del(&head);
dea31012005-04-17 16:05:31 -0500590 return 0;
591}
592
dea31012005-04-17 16:05:31 -0500593static void
James Smart2e0fef82007-06-17 19:56:36 -0500594lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
595 struct lpfc_iocbq *rspiocb)
dea31012005-04-17 16:05:31 -0500596{
James Smart2e0fef82007-06-17 19:56:36 -0500597 struct lpfc_vport *vport = cmdiocb->vport;
James Smart92d7f7b2007-06-17 19:56:38 -0500598 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
dea31012005-04-17 16:05:31 -0500599 IOCB_t *irsp;
dea31012005-04-17 16:05:31 -0500600 struct lpfc_dmabuf *outp;
dea31012005-04-17 16:05:31 -0500601 struct lpfc_sli_ct_request *CTrsp;
James Smart51ef4c22007-08-02 11:10:31 -0400602 struct lpfc_nodelist *ndlp;
James Smart58da1ff2008-04-07 10:15:56 -0400603 int rc;
dea31012005-04-17 16:05:31 -0500604
James Smart51ef4c22007-08-02 11:10:31 -0400605 /* First save ndlp, before we overwrite it */
606 ndlp = cmdiocb->context_un.ndlp;
607
dea31012005-04-17 16:05:31 -0500608 /* we pass cmdiocb to state machine which needs rspiocb as well */
609 cmdiocb->context_un.rsp_iocb = rspiocb;
610
dea31012005-04-17 16:05:31 -0500611 outp = (struct lpfc_dmabuf *) cmdiocb->context2;
James Smart858c9f62007-06-17 19:56:39 -0500612 irsp = &rspiocb->iocb;
613
614 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT,
615 "GID_FT cmpl: status:x%x/x%x rtry:%d",
616 irsp->ulpStatus, irsp->un.ulpWord[4], vport->fc_ns_retry);
dea31012005-04-17 16:05:31 -0500617
James Smart92d7f7b2007-06-17 19:56:38 -0500618 /* Don't bother processing response if vport is being torn down. */
James Smarteada2722008-12-04 22:39:13 -0500619 if (vport->load_flag & FC_UNLOADING) {
620 if (vport->fc_flag & FC_RSCN_MODE)
621 lpfc_els_flush_rscn(vport);
James Smart92d7f7b2007-06-17 19:56:38 -0500622 goto out;
James Smarteada2722008-12-04 22:39:13 -0500623 }
James Smart92d7f7b2007-06-17 19:56:38 -0500624
James Smart58da1ff2008-04-07 10:15:56 -0400625 if (lpfc_els_chk_latt(vport)) {
James Smarte8b62012007-08-02 11:10:09 -0400626 lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
627 "0216 Link event during NS query\n");
James Smarteada2722008-12-04 22:39:13 -0500628 if (vport->fc_flag & FC_RSCN_MODE)
629 lpfc_els_flush_rscn(vport);
James Smart858c9f62007-06-17 19:56:39 -0500630 lpfc_vport_set_state(vport, FC_VPORT_FAILED);
631 goto out;
632 }
James Smart58da1ff2008-04-07 10:15:56 -0400633 if (lpfc_error_lost_link(irsp)) {
634 lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
635 "0226 NS query failed due to link event\n");
James Smarteada2722008-12-04 22:39:13 -0500636 if (vport->fc_flag & FC_RSCN_MODE)
637 lpfc_els_flush_rscn(vport);
James Smart58da1ff2008-04-07 10:15:56 -0400638 goto out;
639 }
James Smart858c9f62007-06-17 19:56:39 -0500640 if (irsp->ulpStatus) {
dea31012005-04-17 16:05:31 -0500641 /* Check for retry */
James Smart2e0fef82007-06-17 19:56:36 -0500642 if (vport->fc_ns_retry < LPFC_MAX_NS_RETRY) {
James Smart58da1ff2008-04-07 10:15:56 -0400643 if (irsp->ulpStatus != IOSTAT_LOCAL_REJECT ||
James Smartedb22f02012-10-31 14:45:21 -0400644 (irsp->un.ulpWord[4] & IOERR_PARAM_MASK) !=
James Smarte3d2b802012-08-14 14:25:43 -0400645 IOERR_NO_RESOURCES)
James Smart858c9f62007-06-17 19:56:39 -0500646 vport->fc_ns_retry++;
James Smart0ff10d42008-01-11 01:52:36 -0500647
James Smart58da1ff2008-04-07 10:15:56 -0400648 /* CT command is being retried */
649 rc = lpfc_ns_cmd(vport, SLI_CTNS_GID_FT,
James Smart92d7f7b2007-06-17 19:56:38 -0500650 vport->fc_ns_retry, 0);
James Smart58da1ff2008-04-07 10:15:56 -0400651 if (rc == 0)
652 goto out;
James Smart92d7f7b2007-06-17 19:56:38 -0500653 }
James Smarteada2722008-12-04 22:39:13 -0500654 if (vport->fc_flag & FC_RSCN_MODE)
655 lpfc_els_flush_rscn(vport);
James Smart92d7f7b2007-06-17 19:56:38 -0500656 lpfc_vport_set_state(vport, FC_VPORT_FAILED);
James Smarte8b62012007-08-02 11:10:09 -0400657 lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
658 "0257 GID_FT Query error: 0x%x 0x%x\n",
659 irsp->ulpStatus, vport->fc_ns_retry);
dea31012005-04-17 16:05:31 -0500660 } else {
661 /* Good status, continue checking */
662 CTrsp = (struct lpfc_sli_ct_request *) outp->virt;
663 if (CTrsp->CommandResponse.bits.CmdRsp ==
James Smart76b2c342015-04-07 15:07:19 -0400664 cpu_to_be16(SLI_CT_RESPONSE_FS_ACC)) {
James Smarte8b62012007-08-02 11:10:09 -0400665 lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
666 "0208 NameServer Rsp Data: x%x\n",
667 vport->fc_flag);
James Smart2e0fef82007-06-17 19:56:36 -0500668 lpfc_ns_rsp(vport, outp,
dea31012005-04-17 16:05:31 -0500669 (uint32_t) (irsp->un.genreq64.bdl.bdeSize));
670 } else if (CTrsp->CommandResponse.bits.CmdRsp ==
671 be16_to_cpu(SLI_CT_RESPONSE_FS_RJT)) {
672 /* NameServer Rsp Error */
James Smarta58cbd52007-08-02 11:09:43 -0400673 if ((CTrsp->ReasonCode == SLI_CT_UNABLE_TO_PERFORM_REQ)
674 && (CTrsp->Explanation == SLI_CT_NO_FC4_TYPES)) {
James Smarte8b62012007-08-02 11:10:09 -0400675 lpfc_printf_vlog(vport, KERN_INFO,
676 LOG_DISCOVERY,
677 "0269 No NameServer Entries "
James Smarta58cbd52007-08-02 11:09:43 -0400678 "Data: x%x x%x x%x x%x\n",
James Smarta58cbd52007-08-02 11:09:43 -0400679 CTrsp->CommandResponse.bits.CmdRsp,
680 (uint32_t) CTrsp->ReasonCode,
681 (uint32_t) CTrsp->Explanation,
682 vport->fc_flag);
683
684 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT,
685 "GID_FT no entry cmd:x%x rsn:x%x exp:x%x",
686 (uint32_t)CTrsp->CommandResponse.bits.CmdRsp,
687 (uint32_t) CTrsp->ReasonCode,
688 (uint32_t) CTrsp->Explanation);
James Smarte8b62012007-08-02 11:10:09 -0400689 } else {
690 lpfc_printf_vlog(vport, KERN_INFO,
691 LOG_DISCOVERY,
692 "0240 NameServer Rsp Error "
dea31012005-04-17 16:05:31 -0500693 "Data: x%x x%x x%x x%x\n",
dea31012005-04-17 16:05:31 -0500694 CTrsp->CommandResponse.bits.CmdRsp,
695 (uint32_t) CTrsp->ReasonCode,
696 (uint32_t) CTrsp->Explanation,
James Smart2e0fef82007-06-17 19:56:36 -0500697 vport->fc_flag);
James Smart858c9f62007-06-17 19:56:39 -0500698
James Smarta58cbd52007-08-02 11:09:43 -0400699 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT,
James Smart858c9f62007-06-17 19:56:39 -0500700 "GID_FT rsp err1 cmd:x%x rsn:x%x exp:x%x",
701 (uint32_t)CTrsp->CommandResponse.bits.CmdRsp,
702 (uint32_t) CTrsp->ReasonCode,
703 (uint32_t) CTrsp->Explanation);
James Smarta58cbd52007-08-02 11:09:43 -0400704 }
705
James Smart858c9f62007-06-17 19:56:39 -0500706
dea31012005-04-17 16:05:31 -0500707 } else {
708 /* NameServer Rsp Error */
James Smarte8b62012007-08-02 11:10:09 -0400709 lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY,
710 "0241 NameServer Rsp Error "
dea31012005-04-17 16:05:31 -0500711 "Data: x%x x%x x%x x%x\n",
dea31012005-04-17 16:05:31 -0500712 CTrsp->CommandResponse.bits.CmdRsp,
713 (uint32_t) CTrsp->ReasonCode,
714 (uint32_t) CTrsp->Explanation,
James Smart2e0fef82007-06-17 19:56:36 -0500715 vport->fc_flag);
James Smart858c9f62007-06-17 19:56:39 -0500716
717 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT,
718 "GID_FT rsp err2 cmd:x%x rsn:x%x exp:x%x",
719 (uint32_t)CTrsp->CommandResponse.bits.CmdRsp,
720 (uint32_t) CTrsp->ReasonCode,
721 (uint32_t) CTrsp->Explanation);
dea31012005-04-17 16:05:31 -0500722 }
723 }
724 /* Link up / RSCN discovery */
James Smart92d7f7b2007-06-17 19:56:38 -0500725 if (vport->num_disc_nodes == 0) {
726 /*
727 * The driver has cycled through all Nports in the RSCN payload.
728 * Complete the handling by cleaning up and marking the
729 * current driver state.
730 */
731 if (vport->port_state >= LPFC_DISC_AUTH) {
732 if (vport->fc_flag & FC_RSCN_MODE) {
733 lpfc_els_flush_rscn(vport);
734 spin_lock_irq(shost->host_lock);
735 vport->fc_flag |= FC_RSCN_MODE; /* RSCN still */
736 spin_unlock_irq(shost->host_lock);
737 }
738 else
739 lpfc_els_flush_rscn(vport);
740 }
741
742 lpfc_disc_start(vport);
743 }
dea31012005-04-17 16:05:31 -0500744out:
James Smart51ef4c22007-08-02 11:10:31 -0400745 cmdiocb->context_un.ndlp = ndlp; /* Now restore ndlp for free */
James Smart858c9f62007-06-17 19:56:39 -0500746 lpfc_ct_free_iocb(phba, cmdiocb);
dea31012005-04-17 16:05:31 -0500747 return;
748}
749
James Smart311464e2007-08-02 11:10:37 -0400750static void
James Smart92d7f7b2007-06-17 19:56:38 -0500751lpfc_cmpl_ct_cmd_gff_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
752 struct lpfc_iocbq *rspiocb)
753{
754 struct lpfc_vport *vport = cmdiocb->vport;
755 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
756 IOCB_t *irsp = &rspiocb->iocb;
James Smart92d7f7b2007-06-17 19:56:38 -0500757 struct lpfc_dmabuf *inp = (struct lpfc_dmabuf *) cmdiocb->context1;
758 struct lpfc_dmabuf *outp = (struct lpfc_dmabuf *) cmdiocb->context2;
759 struct lpfc_sli_ct_request *CTrsp;
James Smart0ff10d42008-01-11 01:52:36 -0500760 int did, rc, retry;
James Smart92d7f7b2007-06-17 19:56:38 -0500761 uint8_t fbits;
762 struct lpfc_nodelist *ndlp;
763
764 did = ((struct lpfc_sli_ct_request *) inp->virt)->un.gff.PortId;
765 did = be32_to_cpu(did);
766
James Smart858c9f62007-06-17 19:56:39 -0500767 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT,
768 "GFF_ID cmpl: status:x%x/x%x did:x%x",
769 irsp->ulpStatus, irsp->un.ulpWord[4], did);
770
James Smart92d7f7b2007-06-17 19:56:38 -0500771 if (irsp->ulpStatus == IOSTAT_SUCCESS) {
772 /* Good status, continue checking */
773 CTrsp = (struct lpfc_sli_ct_request *) outp->virt;
774 fbits = CTrsp->un.gff_acc.fbits[FCP_TYPE_FEATURE_OFFSET];
775
776 if (CTrsp->CommandResponse.bits.CmdRsp ==
777 be16_to_cpu(SLI_CT_RESPONSE_FS_ACC)) {
778 if ((fbits & FC4_FEATURE_INIT) &&
779 !(fbits & FC4_FEATURE_TARGET)) {
James Smarte8b62012007-08-02 11:10:09 -0400780 lpfc_printf_vlog(vport, KERN_INFO,
781 LOG_DISCOVERY,
782 "0270 Skip x%x GFF "
783 "NameServer Rsp Data: (init) "
784 "x%x x%x\n", did, fbits,
785 vport->fc_rscn_id_cnt);
James Smart92d7f7b2007-06-17 19:56:38 -0500786 goto out;
787 }
788 }
789 }
James Smart858c9f62007-06-17 19:56:39 -0500790 else {
James Smart0ff10d42008-01-11 01:52:36 -0500791 /* Check for retry */
792 if (cmdiocb->retry < LPFC_MAX_NS_RETRY) {
793 retry = 1;
794 if (irsp->ulpStatus == IOSTAT_LOCAL_REJECT) {
James Smarte3d2b802012-08-14 14:25:43 -0400795 switch ((irsp->un.ulpWord[4] &
796 IOERR_PARAM_MASK)) {
797
James Smart0ff10d42008-01-11 01:52:36 -0500798 case IOERR_NO_RESOURCES:
799 /* We don't increment the retry
800 * count for this case.
801 */
802 break;
803 case IOERR_LINK_DOWN:
804 case IOERR_SLI_ABORTED:
805 case IOERR_SLI_DOWN:
806 retry = 0;
807 break;
808 default:
809 cmdiocb->retry++;
810 }
811 }
812 else
813 cmdiocb->retry++;
814
815 if (retry) {
816 /* CT command is being retried */
817 rc = lpfc_ns_cmd(vport, SLI_CTNS_GFF_ID,
818 cmdiocb->retry, did);
819 if (rc == 0) {
820 /* success */
821 lpfc_ct_free_iocb(phba, cmdiocb);
822 return;
823 }
824 }
825 }
James Smarte8b62012007-08-02 11:10:09 -0400826 lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY,
827 "0267 NameServer GFF Rsp "
828 "x%x Error (%d %d) Data: x%x x%x\n",
829 did, irsp->ulpStatus, irsp->un.ulpWord[4],
James Smart7f5f3d02008-02-08 18:50:14 -0500830 vport->fc_flag, vport->fc_rscn_id_cnt);
James Smart858c9f62007-06-17 19:56:39 -0500831 }
832
James Smart92d7f7b2007-06-17 19:56:38 -0500833 /* This is a target port, unregistered port, or the GFF_ID failed */
834 ndlp = lpfc_setup_disc_node(vport, did);
James Smart58da1ff2008-04-07 10:15:56 -0400835 if (ndlp && NLP_CHK_NODE_ACT(ndlp)) {
James Smarte8b62012007-08-02 11:10:09 -0400836 lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
837 "0242 Process x%x GFF "
838 "NameServer Rsp Data: x%x x%x x%x\n",
839 did, ndlp->nlp_flag, vport->fc_flag,
840 vport->fc_rscn_id_cnt);
James Smart92d7f7b2007-06-17 19:56:38 -0500841 } else {
James Smarte8b62012007-08-02 11:10:09 -0400842 lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
843 "0243 Skip x%x GFF "
844 "NameServer Rsp Data: x%x x%x\n", did,
845 vport->fc_flag, vport->fc_rscn_id_cnt);
James Smart92d7f7b2007-06-17 19:56:38 -0500846 }
847out:
848 /* Link up / RSCN discovery */
849 if (vport->num_disc_nodes)
850 vport->num_disc_nodes--;
851 if (vport->num_disc_nodes == 0) {
852 /*
853 * The driver has cycled through all Nports in the RSCN payload.
854 * Complete the handling by cleaning up and marking the
855 * current driver state.
856 */
857 if (vport->port_state >= LPFC_DISC_AUTH) {
858 if (vport->fc_flag & FC_RSCN_MODE) {
859 lpfc_els_flush_rscn(vport);
860 spin_lock_irq(shost->host_lock);
861 vport->fc_flag |= FC_RSCN_MODE; /* RSCN still */
862 spin_unlock_irq(shost->host_lock);
863 }
864 else
865 lpfc_els_flush_rscn(vport);
866 }
867 lpfc_disc_start(vport);
868 }
James Smart858c9f62007-06-17 19:56:39 -0500869 lpfc_ct_free_iocb(phba, cmdiocb);
James Smart92d7f7b2007-06-17 19:56:38 -0500870 return;
871}
872
873
dea31012005-04-17 16:05:31 -0500874static void
James Smart7ee5d432007-10-27 13:37:17 -0400875lpfc_cmpl_ct(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
876 struct lpfc_iocbq *rspiocb)
dea31012005-04-17 16:05:31 -0500877{
James Smart92d7f7b2007-06-17 19:56:38 -0500878 struct lpfc_vport *vport = cmdiocb->vport;
dea31012005-04-17 16:05:31 -0500879 struct lpfc_dmabuf *inp;
880 struct lpfc_dmabuf *outp;
881 IOCB_t *irsp;
882 struct lpfc_sli_ct_request *CTrsp;
James Smart51ef4c22007-08-02 11:10:31 -0400883 struct lpfc_nodelist *ndlp;
James Smart92d7f7b2007-06-17 19:56:38 -0500884 int cmdcode, rc;
885 uint8_t retry;
James Smart858c9f62007-06-17 19:56:39 -0500886 uint32_t latt;
dea31012005-04-17 16:05:31 -0500887
James Smart51ef4c22007-08-02 11:10:31 -0400888 /* First save ndlp, before we overwrite it */
889 ndlp = cmdiocb->context_un.ndlp;
890
dea31012005-04-17 16:05:31 -0500891 /* we pass cmdiocb to state machine which needs rspiocb as well */
892 cmdiocb->context_un.rsp_iocb = rspiocb;
893
894 inp = (struct lpfc_dmabuf *) cmdiocb->context1;
895 outp = (struct lpfc_dmabuf *) cmdiocb->context2;
dea31012005-04-17 16:05:31 -0500896 irsp = &rspiocb->iocb;
897
James Smart92d7f7b2007-06-17 19:56:38 -0500898 cmdcode = be16_to_cpu(((struct lpfc_sli_ct_request *) inp->virt)->
899 CommandResponse.bits.CmdRsp);
dea31012005-04-17 16:05:31 -0500900 CTrsp = (struct lpfc_sli_ct_request *) outp->virt;
901
James Smart858c9f62007-06-17 19:56:39 -0500902 latt = lpfc_els_chk_latt(vport);
903
904 /* RFT request completes status <ulpStatus> CmdRsp <CmdRsp> */
James Smarte8b62012007-08-02 11:10:09 -0400905 lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
James Smart7ee5d432007-10-27 13:37:17 -0400906 "0209 CT Request completes, latt %d, "
James Smarte8b62012007-08-02 11:10:09 -0400907 "ulpStatus x%x CmdRsp x%x, Context x%x, Tag x%x\n",
908 latt, irsp->ulpStatus,
909 CTrsp->CommandResponse.bits.CmdRsp,
910 cmdiocb->iocb.ulpContext, cmdiocb->iocb.ulpIoTag);
dea31012005-04-17 16:05:31 -0500911
James Smart858c9f62007-06-17 19:56:39 -0500912 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT,
913 "CT cmd cmpl: status:x%x/x%x cmd:x%x",
914 irsp->ulpStatus, irsp->un.ulpWord[4], cmdcode);
915
James Smart92d7f7b2007-06-17 19:56:38 -0500916 if (irsp->ulpStatus) {
James Smarte8b62012007-08-02 11:10:09 -0400917 lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY,
James Smart6e155202013-07-15 18:35:21 -0400918 "0268 NS cmd x%x Error (x%x x%x)\n",
James Smarte8b62012007-08-02 11:10:09 -0400919 cmdcode, irsp->ulpStatus, irsp->un.ulpWord[4]);
James Smart858c9f62007-06-17 19:56:39 -0500920
James Smart92d7f7b2007-06-17 19:56:38 -0500921 if ((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) &&
James Smarte3d2b802012-08-14 14:25:43 -0400922 (((irsp->un.ulpWord[4] & IOERR_PARAM_MASK) ==
923 IOERR_SLI_DOWN) ||
924 ((irsp->un.ulpWord[4] & IOERR_PARAM_MASK) ==
925 IOERR_SLI_ABORTED)))
James Smart92d7f7b2007-06-17 19:56:38 -0500926 goto out;
927
928 retry = cmdiocb->retry;
929 if (retry >= LPFC_MAX_NS_RETRY)
930 goto out;
931
932 retry++;
James Smarte8b62012007-08-02 11:10:09 -0400933 lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
James Smartd7c255b2008-08-24 21:50:00 -0400934 "0250 Retrying NS cmd %x\n", cmdcode);
James Smart92d7f7b2007-06-17 19:56:38 -0500935 rc = lpfc_ns_cmd(vport, cmdcode, retry, 0);
936 if (rc == 0)
937 goto out;
938 }
939
940out:
James Smart51ef4c22007-08-02 11:10:31 -0400941 cmdiocb->context_un.ndlp = ndlp; /* Now restore ndlp for free */
James Smart858c9f62007-06-17 19:56:39 -0500942 lpfc_ct_free_iocb(phba, cmdiocb);
dea31012005-04-17 16:05:31 -0500943 return;
944}
945
946static void
James Smart7ee5d432007-10-27 13:37:17 -0400947lpfc_cmpl_ct_cmd_rft_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
948 struct lpfc_iocbq *rspiocb)
949{
950 IOCB_t *irsp = &rspiocb->iocb;
951 struct lpfc_vport *vport = cmdiocb->vport;
952
James Smart98c9ea52007-10-27 13:37:33 -0400953 if (irsp->ulpStatus == IOSTAT_SUCCESS) {
954 struct lpfc_dmabuf *outp;
955 struct lpfc_sli_ct_request *CTrsp;
956
957 outp = (struct lpfc_dmabuf *) cmdiocb->context2;
958 CTrsp = (struct lpfc_sli_ct_request *) outp->virt;
959 if (CTrsp->CommandResponse.bits.CmdRsp ==
960 be16_to_cpu(SLI_CT_RESPONSE_FS_ACC))
961 vport->ct_flags |= FC_CT_RFT_ID;
962 }
James Smart7ee5d432007-10-27 13:37:17 -0400963 lpfc_cmpl_ct(phba, cmdiocb, rspiocb);
964 return;
965}
966
967static void
James Smart2e0fef82007-06-17 19:56:36 -0500968lpfc_cmpl_ct_cmd_rnn_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
969 struct lpfc_iocbq *rspiocb)
dea31012005-04-17 16:05:31 -0500970{
James Smart7ee5d432007-10-27 13:37:17 -0400971 IOCB_t *irsp = &rspiocb->iocb;
972 struct lpfc_vport *vport = cmdiocb->vport;
973
James Smart98c9ea52007-10-27 13:37:33 -0400974 if (irsp->ulpStatus == IOSTAT_SUCCESS) {
975 struct lpfc_dmabuf *outp;
976 struct lpfc_sli_ct_request *CTrsp;
977
978 outp = (struct lpfc_dmabuf *) cmdiocb->context2;
979 CTrsp = (struct lpfc_sli_ct_request *) outp->virt;
980 if (CTrsp->CommandResponse.bits.CmdRsp ==
981 be16_to_cpu(SLI_CT_RESPONSE_FS_ACC))
982 vport->ct_flags |= FC_CT_RNN_ID;
983 }
James Smart7ee5d432007-10-27 13:37:17 -0400984 lpfc_cmpl_ct(phba, cmdiocb, rspiocb);
dea31012005-04-17 16:05:31 -0500985 return;
986}
987
988static void
James Smart92d7f7b2007-06-17 19:56:38 -0500989lpfc_cmpl_ct_cmd_rspn_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
990 struct lpfc_iocbq *rspiocb)
991{
James Smart7ee5d432007-10-27 13:37:17 -0400992 IOCB_t *irsp = &rspiocb->iocb;
993 struct lpfc_vport *vport = cmdiocb->vport;
994
James Smart98c9ea52007-10-27 13:37:33 -0400995 if (irsp->ulpStatus == IOSTAT_SUCCESS) {
996 struct lpfc_dmabuf *outp;
997 struct lpfc_sli_ct_request *CTrsp;
998
999 outp = (struct lpfc_dmabuf *) cmdiocb->context2;
1000 CTrsp = (struct lpfc_sli_ct_request *) outp->virt;
1001 if (CTrsp->CommandResponse.bits.CmdRsp ==
1002 be16_to_cpu(SLI_CT_RESPONSE_FS_ACC))
1003 vport->ct_flags |= FC_CT_RSPN_ID;
1004 }
James Smart7ee5d432007-10-27 13:37:17 -04001005 lpfc_cmpl_ct(phba, cmdiocb, rspiocb);
James Smart92d7f7b2007-06-17 19:56:38 -05001006 return;
1007}
1008
1009static void
James Smart2e0fef82007-06-17 19:56:36 -05001010lpfc_cmpl_ct_cmd_rsnn_nn(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
1011 struct lpfc_iocbq *rspiocb)
dea31012005-04-17 16:05:31 -05001012{
James Smart7ee5d432007-10-27 13:37:17 -04001013 IOCB_t *irsp = &rspiocb->iocb;
1014 struct lpfc_vport *vport = cmdiocb->vport;
1015
James Smart98c9ea52007-10-27 13:37:33 -04001016 if (irsp->ulpStatus == IOSTAT_SUCCESS) {
1017 struct lpfc_dmabuf *outp;
1018 struct lpfc_sli_ct_request *CTrsp;
1019
1020 outp = (struct lpfc_dmabuf *) cmdiocb->context2;
1021 CTrsp = (struct lpfc_sli_ct_request *) outp->virt;
1022 if (CTrsp->CommandResponse.bits.CmdRsp ==
1023 be16_to_cpu(SLI_CT_RESPONSE_FS_ACC))
1024 vport->ct_flags |= FC_CT_RSNN_NN;
1025 }
James Smart7ee5d432007-10-27 13:37:17 -04001026 lpfc_cmpl_ct(phba, cmdiocb, rspiocb);
1027 return;
1028}
1029
1030static void
1031lpfc_cmpl_ct_cmd_da_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
1032 struct lpfc_iocbq *rspiocb)
1033{
1034 struct lpfc_vport *vport = cmdiocb->vport;
1035
1036 /* even if it fails we will act as though it succeeded. */
1037 vport->ct_flags = 0;
1038 lpfc_cmpl_ct(phba, cmdiocb, rspiocb);
dea31012005-04-17 16:05:31 -05001039 return;
1040}
1041
James Smart2fb9bd82006-12-02 13:33:57 -05001042static void
James Smart92d7f7b2007-06-17 19:56:38 -05001043lpfc_cmpl_ct_cmd_rff_id(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
1044 struct lpfc_iocbq *rspiocb)
James Smart2fb9bd82006-12-02 13:33:57 -05001045{
James Smart92d7f7b2007-06-17 19:56:38 -05001046 IOCB_t *irsp = &rspiocb->iocb;
1047 struct lpfc_vport *vport = cmdiocb->vport;
1048
James Smart98c9ea52007-10-27 13:37:33 -04001049 if (irsp->ulpStatus == IOSTAT_SUCCESS) {
1050 struct lpfc_dmabuf *outp;
1051 struct lpfc_sli_ct_request *CTrsp;
1052
1053 outp = (struct lpfc_dmabuf *) cmdiocb->context2;
1054 CTrsp = (struct lpfc_sli_ct_request *) outp->virt;
1055 if (CTrsp->CommandResponse.bits.CmdRsp ==
1056 be16_to_cpu(SLI_CT_RESPONSE_FS_ACC))
1057 vport->ct_flags |= FC_CT_RFF_ID;
1058 }
James Smart7ee5d432007-10-27 13:37:17 -04001059 lpfc_cmpl_ct(phba, cmdiocb, rspiocb);
James Smart2fb9bd82006-12-02 13:33:57 -05001060 return;
1061}
1062
James Smart495a7142008-06-14 22:52:59 -04001063int
James Smart92d7f7b2007-06-17 19:56:38 -05001064lpfc_vport_symbolic_port_name(struct lpfc_vport *vport, char *symbol,
1065 size_t size)
1066{
1067 int n;
1068 uint8_t *wwn = vport->phba->wwpn;
1069
1070 n = snprintf(symbol, size,
1071 "Emulex PPN-%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
1072 wwn[0], wwn[1], wwn[2], wwn[3],
1073 wwn[4], wwn[5], wwn[6], wwn[7]);
1074
1075 if (vport->port_type == LPFC_PHYSICAL_PORT)
1076 return n;
1077
1078 if (n < size)
1079 n += snprintf(symbol + n, size - n, " VPort-%d", vport->vpi);
1080
James Smarteada2722008-12-04 22:39:13 -05001081 if (n < size &&
1082 strlen(vport->fc_vport->symbolic_name))
1083 n += snprintf(symbol + n, size - n, " VName-%s",
1084 vport->fc_vport->symbolic_name);
James Smart92d7f7b2007-06-17 19:56:38 -05001085 return n;
1086}
1087
1088int
1089lpfc_vport_symbolic_node_name(struct lpfc_vport *vport, char *symbol,
1090 size_t size)
dea31012005-04-17 16:05:31 -05001091{
James Smart6b5151f2012-01-18 16:24:06 -05001092 char fwrev[FW_REV_STR_SIZE];
James Smart92d7f7b2007-06-17 19:56:38 -05001093 int n;
dea31012005-04-17 16:05:31 -05001094
James Smart92d7f7b2007-06-17 19:56:38 -05001095 lpfc_decode_firmware_rev(vport->phba, fwrev, 0);
dea31012005-04-17 16:05:31 -05001096
James Smartf0bf5f92015-04-07 15:07:18 -04001097 n = snprintf(symbol, size, "Emulex %s", vport->phba->ModelName);
1098
1099 if (size < n)
1100 return n;
1101 n += snprintf(symbol + n, size - n, " FV%s", fwrev);
1102
1103 if (size < n)
1104 return n;
1105 n += snprintf(symbol + n, size - n, " DV%s", lpfc_release_version);
1106
1107 if (size < n)
1108 return n;
1109 n += snprintf(symbol + n, size - n, " HN:%s", init_utsname()->nodename);
1110
1111 /* Note :- OS name is "Linux" */
1112 if (size < n)
1113 return n;
1114 n += snprintf(symbol + n, size - n, " OS:%s", init_utsname()->sysname);
1115
James Smart92d7f7b2007-06-17 19:56:38 -05001116 return n;
dea31012005-04-17 16:05:31 -05001117}
1118
James Smart76b2c342015-04-07 15:07:19 -04001119static uint32_t
1120lpfc_find_map_node(struct lpfc_vport *vport)
1121{
1122 struct lpfc_nodelist *ndlp, *next_ndlp;
1123 struct Scsi_Host *shost;
1124 uint32_t cnt = 0;
1125
1126 shost = lpfc_shost_from_vport(vport);
1127 spin_lock_irq(shost->host_lock);
1128 list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) {
1129 if (ndlp->nlp_type & NLP_FABRIC)
1130 continue;
1131 if ((ndlp->nlp_state == NLP_STE_MAPPED_NODE) ||
1132 (ndlp->nlp_state == NLP_STE_UNMAPPED_NODE))
1133 cnt++;
1134 }
1135 spin_unlock_irq(shost->host_lock);
1136 return cnt;
1137}
1138
dea31012005-04-17 16:05:31 -05001139/*
1140 * lpfc_ns_cmd
1141 * Description:
1142 * Issue Cmd to NameServer
1143 * SLI_CTNS_GID_FT
1144 * LI_CTNS_RFT_ID
1145 */
1146int
James Smart92d7f7b2007-06-17 19:56:38 -05001147lpfc_ns_cmd(struct lpfc_vport *vport, int cmdcode,
1148 uint8_t retry, uint32_t context)
dea31012005-04-17 16:05:31 -05001149{
James Smart92d7f7b2007-06-17 19:56:38 -05001150 struct lpfc_nodelist * ndlp;
James Smart2e0fef82007-06-17 19:56:36 -05001151 struct lpfc_hba *phba = vport->phba;
dea31012005-04-17 16:05:31 -05001152 struct lpfc_dmabuf *mp, *bmp;
1153 struct lpfc_sli_ct_request *CtReq;
1154 struct ulp_bde64 *bpl;
1155 void (*cmpl) (struct lpfc_hba *, struct lpfc_iocbq *,
1156 struct lpfc_iocbq *) = NULL;
1157 uint32_t rsp_size = 1024;
James Smart92d7f7b2007-06-17 19:56:38 -05001158 size_t size;
James Smart858c9f62007-06-17 19:56:39 -05001159 int rc = 0;
James Smart92d7f7b2007-06-17 19:56:38 -05001160
1161 ndlp = lpfc_findnode_did(vport, NameServer_DID);
James Smarte47c9092008-02-08 18:49:26 -05001162 if (!ndlp || !NLP_CHK_NODE_ACT(ndlp)
1163 || ndlp->nlp_state != NLP_STE_UNMAPPED_NODE) {
James Smart858c9f62007-06-17 19:56:39 -05001164 rc=1;
1165 goto ns_cmd_exit;
1166 }
dea31012005-04-17 16:05:31 -05001167
1168 /* fill in BDEs for command */
1169 /* Allocate buffer for command payload */
James Smart4258e982015-12-16 18:11:58 -05001170 mp = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL);
James Smart858c9f62007-06-17 19:56:39 -05001171 if (!mp) {
1172 rc=2;
dea31012005-04-17 16:05:31 -05001173 goto ns_cmd_exit;
James Smart858c9f62007-06-17 19:56:39 -05001174 }
dea31012005-04-17 16:05:31 -05001175
1176 INIT_LIST_HEAD(&mp->list);
1177 mp->virt = lpfc_mbuf_alloc(phba, MEM_PRI, &(mp->phys));
James Smart858c9f62007-06-17 19:56:39 -05001178 if (!mp->virt) {
1179 rc=3;
dea31012005-04-17 16:05:31 -05001180 goto ns_cmd_free_mp;
James Smart858c9f62007-06-17 19:56:39 -05001181 }
dea31012005-04-17 16:05:31 -05001182
1183 /* Allocate buffer for Buffer ptr list */
James Smart4258e982015-12-16 18:11:58 -05001184 bmp = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL);
James Smart858c9f62007-06-17 19:56:39 -05001185 if (!bmp) {
1186 rc=4;
dea31012005-04-17 16:05:31 -05001187 goto ns_cmd_free_mpvirt;
James Smart858c9f62007-06-17 19:56:39 -05001188 }
dea31012005-04-17 16:05:31 -05001189
1190 INIT_LIST_HEAD(&bmp->list);
1191 bmp->virt = lpfc_mbuf_alloc(phba, MEM_PRI, &(bmp->phys));
James Smart858c9f62007-06-17 19:56:39 -05001192 if (!bmp->virt) {
1193 rc=5;
dea31012005-04-17 16:05:31 -05001194 goto ns_cmd_free_bmp;
James Smart858c9f62007-06-17 19:56:39 -05001195 }
dea31012005-04-17 16:05:31 -05001196
1197 /* NameServer Req */
James Smarte8b62012007-08-02 11:10:09 -04001198 lpfc_printf_vlog(vport, KERN_INFO ,LOG_DISCOVERY,
1199 "0236 NameServer Req Data: x%x x%x x%x\n",
1200 cmdcode, vport->fc_flag, vport->fc_rscn_id_cnt);
dea31012005-04-17 16:05:31 -05001201
1202 bpl = (struct ulp_bde64 *) bmp->virt;
1203 memset(bpl, 0, sizeof(struct ulp_bde64));
James Smart92d7f7b2007-06-17 19:56:38 -05001204 bpl->addrHigh = le32_to_cpu(putPaddrHigh(mp->phys) );
1205 bpl->addrLow = le32_to_cpu(putPaddrLow(mp->phys) );
dea31012005-04-17 16:05:31 -05001206 bpl->tus.f.bdeFlags = 0;
1207 if (cmdcode == SLI_CTNS_GID_FT)
1208 bpl->tus.f.bdeSize = GID_REQUEST_SZ;
James Smart92d7f7b2007-06-17 19:56:38 -05001209 else if (cmdcode == SLI_CTNS_GFF_ID)
1210 bpl->tus.f.bdeSize = GFF_REQUEST_SZ;
dea31012005-04-17 16:05:31 -05001211 else if (cmdcode == SLI_CTNS_RFT_ID)
1212 bpl->tus.f.bdeSize = RFT_REQUEST_SZ;
1213 else if (cmdcode == SLI_CTNS_RNN_ID)
1214 bpl->tus.f.bdeSize = RNN_REQUEST_SZ;
James Smart92d7f7b2007-06-17 19:56:38 -05001215 else if (cmdcode == SLI_CTNS_RSPN_ID)
1216 bpl->tus.f.bdeSize = RSPN_REQUEST_SZ;
dea31012005-04-17 16:05:31 -05001217 else if (cmdcode == SLI_CTNS_RSNN_NN)
1218 bpl->tus.f.bdeSize = RSNN_REQUEST_SZ;
James Smart7ee5d432007-10-27 13:37:17 -04001219 else if (cmdcode == SLI_CTNS_DA_ID)
1220 bpl->tus.f.bdeSize = DA_ID_REQUEST_SZ;
James Smart2fb9bd82006-12-02 13:33:57 -05001221 else if (cmdcode == SLI_CTNS_RFF_ID)
1222 bpl->tus.f.bdeSize = RFF_REQUEST_SZ;
dea31012005-04-17 16:05:31 -05001223 else
1224 bpl->tus.f.bdeSize = 0;
1225 bpl->tus.w = le32_to_cpu(bpl->tus.w);
1226
1227 CtReq = (struct lpfc_sli_ct_request *) mp->virt;
James Smart4258e982015-12-16 18:11:58 -05001228 memset(CtReq, 0, sizeof(struct lpfc_sli_ct_request));
dea31012005-04-17 16:05:31 -05001229 CtReq->RevisionId.bits.Revision = SLI_CT_REVISION;
1230 CtReq->RevisionId.bits.InId = 0;
1231 CtReq->FsType = SLI_CT_DIRECTORY_SERVICE;
1232 CtReq->FsSubType = SLI_CT_DIRECTORY_NAME_SERVER;
1233 CtReq->CommandResponse.bits.Size = 0;
1234 switch (cmdcode) {
1235 case SLI_CTNS_GID_FT:
1236 CtReq->CommandResponse.bits.CmdRsp =
James Smart76b2c342015-04-07 15:07:19 -04001237 cpu_to_be16(SLI_CTNS_GID_FT);
dea31012005-04-17 16:05:31 -05001238 CtReq->un.gid.Fc4Type = SLI_CTPT_FCP;
James Smart92d7f7b2007-06-17 19:56:38 -05001239 if (vport->port_state < LPFC_NS_QRY)
James Smart2e0fef82007-06-17 19:56:36 -05001240 vport->port_state = LPFC_NS_QRY;
1241 lpfc_set_disctmo(vport);
dea31012005-04-17 16:05:31 -05001242 cmpl = lpfc_cmpl_ct_cmd_gid_ft;
1243 rsp_size = FC_MAX_NS_RSP;
1244 break;
1245
James Smart92d7f7b2007-06-17 19:56:38 -05001246 case SLI_CTNS_GFF_ID:
1247 CtReq->CommandResponse.bits.CmdRsp =
James Smart76b2c342015-04-07 15:07:19 -04001248 cpu_to_be16(SLI_CTNS_GFF_ID);
James Smart09372822008-01-11 01:52:54 -05001249 CtReq->un.gff.PortId = cpu_to_be32(context);
James Smart92d7f7b2007-06-17 19:56:38 -05001250 cmpl = lpfc_cmpl_ct_cmd_gff_id;
1251 break;
1252
dea31012005-04-17 16:05:31 -05001253 case SLI_CTNS_RFT_ID:
James Smart7ee5d432007-10-27 13:37:17 -04001254 vport->ct_flags &= ~FC_CT_RFT_ID;
dea31012005-04-17 16:05:31 -05001255 CtReq->CommandResponse.bits.CmdRsp =
James Smart76b2c342015-04-07 15:07:19 -04001256 cpu_to_be16(SLI_CTNS_RFT_ID);
James Smart09372822008-01-11 01:52:54 -05001257 CtReq->un.rft.PortId = cpu_to_be32(vport->fc_myDID);
dea31012005-04-17 16:05:31 -05001258 CtReq->un.rft.fcpReg = 1;
1259 cmpl = lpfc_cmpl_ct_cmd_rft_id;
1260 break;
1261
1262 case SLI_CTNS_RNN_ID:
James Smart7ee5d432007-10-27 13:37:17 -04001263 vport->ct_flags &= ~FC_CT_RNN_ID;
dea31012005-04-17 16:05:31 -05001264 CtReq->CommandResponse.bits.CmdRsp =
James Smart76b2c342015-04-07 15:07:19 -04001265 cpu_to_be16(SLI_CTNS_RNN_ID);
James Smart09372822008-01-11 01:52:54 -05001266 CtReq->un.rnn.PortId = cpu_to_be32(vport->fc_myDID);
James Smart2e0fef82007-06-17 19:56:36 -05001267 memcpy(CtReq->un.rnn.wwnn, &vport->fc_nodename,
James Smart4258e982015-12-16 18:11:58 -05001268 sizeof(struct lpfc_name));
dea31012005-04-17 16:05:31 -05001269 cmpl = lpfc_cmpl_ct_cmd_rnn_id;
1270 break;
1271
James Smart92d7f7b2007-06-17 19:56:38 -05001272 case SLI_CTNS_RSPN_ID:
James Smart7ee5d432007-10-27 13:37:17 -04001273 vport->ct_flags &= ~FC_CT_RSPN_ID;
James Smart92d7f7b2007-06-17 19:56:38 -05001274 CtReq->CommandResponse.bits.CmdRsp =
James Smart76b2c342015-04-07 15:07:19 -04001275 cpu_to_be16(SLI_CTNS_RSPN_ID);
James Smart09372822008-01-11 01:52:54 -05001276 CtReq->un.rspn.PortId = cpu_to_be32(vport->fc_myDID);
James Smart92d7f7b2007-06-17 19:56:38 -05001277 size = sizeof(CtReq->un.rspn.symbname);
1278 CtReq->un.rspn.len =
1279 lpfc_vport_symbolic_port_name(vport,
1280 CtReq->un.rspn.symbname, size);
1281 cmpl = lpfc_cmpl_ct_cmd_rspn_id;
1282 break;
dea31012005-04-17 16:05:31 -05001283 case SLI_CTNS_RSNN_NN:
James Smart7ee5d432007-10-27 13:37:17 -04001284 vport->ct_flags &= ~FC_CT_RSNN_NN;
dea31012005-04-17 16:05:31 -05001285 CtReq->CommandResponse.bits.CmdRsp =
James Smart76b2c342015-04-07 15:07:19 -04001286 cpu_to_be16(SLI_CTNS_RSNN_NN);
James Smart2e0fef82007-06-17 19:56:36 -05001287 memcpy(CtReq->un.rsnn.wwnn, &vport->fc_nodename,
James Smart4258e982015-12-16 18:11:58 -05001288 sizeof(struct lpfc_name));
James Smart92d7f7b2007-06-17 19:56:38 -05001289 size = sizeof(CtReq->un.rsnn.symbname);
1290 CtReq->un.rsnn.len =
1291 lpfc_vport_symbolic_node_name(vport,
1292 CtReq->un.rsnn.symbname, size);
dea31012005-04-17 16:05:31 -05001293 cmpl = lpfc_cmpl_ct_cmd_rsnn_nn;
1294 break;
James Smart7ee5d432007-10-27 13:37:17 -04001295 case SLI_CTNS_DA_ID:
1296 /* Implement DA_ID Nameserver request */
1297 CtReq->CommandResponse.bits.CmdRsp =
James Smart76b2c342015-04-07 15:07:19 -04001298 cpu_to_be16(SLI_CTNS_DA_ID);
James Smart09372822008-01-11 01:52:54 -05001299 CtReq->un.da_id.port_id = cpu_to_be32(vport->fc_myDID);
James Smart7ee5d432007-10-27 13:37:17 -04001300 cmpl = lpfc_cmpl_ct_cmd_da_id;
1301 break;
James Smart92d7f7b2007-06-17 19:56:38 -05001302 case SLI_CTNS_RFF_ID:
James Smart7ee5d432007-10-27 13:37:17 -04001303 vport->ct_flags &= ~FC_CT_RFF_ID;
James Smart92d7f7b2007-06-17 19:56:38 -05001304 CtReq->CommandResponse.bits.CmdRsp =
James Smart76b2c342015-04-07 15:07:19 -04001305 cpu_to_be16(SLI_CTNS_RFF_ID);
Joe Perchesa419aef2009-08-18 11:18:35 -07001306 CtReq->un.rff.PortId = cpu_to_be32(vport->fc_myDID);
James Smart92d7f7b2007-06-17 19:56:38 -05001307 CtReq->un.rff.fbits = FC4_FEATURE_INIT;
James Smart6a9c52c2009-10-02 15:16:51 -04001308 CtReq->un.rff.type_code = FC_TYPE_FCP;
James Smart92d7f7b2007-06-17 19:56:38 -05001309 cmpl = lpfc_cmpl_ct_cmd_rff_id;
1310 break;
dea31012005-04-17 16:05:31 -05001311 }
James Smarte47c9092008-02-08 18:49:26 -05001312 /* The lpfc_ct_cmd/lpfc_get_req shall increment ndlp reference count
1313 * to hold ndlp reference for the corresponding callback function.
1314 */
James Smart858c9f62007-06-17 19:56:39 -05001315 if (!lpfc_ct_cmd(vport, mp, bmp, ndlp, cmpl, rsp_size, retry)) {
dea31012005-04-17 16:05:31 -05001316 /* On success, The cmpl function will free the buffers */
James Smart858c9f62007-06-17 19:56:39 -05001317 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT,
1318 "Issue CT cmd: cmd:x%x did:x%x",
1319 cmdcode, ndlp->nlp_DID, 0);
dea31012005-04-17 16:05:31 -05001320 return 0;
James Smart858c9f62007-06-17 19:56:39 -05001321 }
James Smart858c9f62007-06-17 19:56:39 -05001322 rc=6;
James Smarte47c9092008-02-08 18:49:26 -05001323
1324 /* Decrement ndlp reference count to release ndlp reference held
1325 * for the failed command's callback function.
1326 */
James Smart51ef4c22007-08-02 11:10:31 -04001327 lpfc_nlp_put(ndlp);
James Smarte47c9092008-02-08 18:49:26 -05001328
dea31012005-04-17 16:05:31 -05001329 lpfc_mbuf_free(phba, bmp->virt, bmp->phys);
1330ns_cmd_free_bmp:
1331 kfree(bmp);
1332ns_cmd_free_mpvirt:
1333 lpfc_mbuf_free(phba, mp->virt, mp->phys);
1334ns_cmd_free_mp:
1335 kfree(mp);
1336ns_cmd_exit:
James Smarte8b62012007-08-02 11:10:09 -04001337 lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY,
1338 "0266 Issue NameServer Req x%x err %d Data: x%x x%x\n",
1339 cmdcode, rc, vport->fc_flag, vport->fc_rscn_id_cnt);
dea31012005-04-17 16:05:31 -05001340 return 1;
1341}
1342
James Smart4258e982015-12-16 18:11:58 -05001343/**
1344 * lpfc_cmpl_ct_disc_fdmi - Handle a discovery FDMI completion
1345 * @phba: Pointer to HBA context object.
1346 * @cmdiocb: Pointer to the command IOCBQ.
1347 * @rspiocb: Pointer to the response IOCBQ.
1348 *
1349 * This function to handle the completion of a driver initiated FDMI
1350 * CT command issued during discovery.
1351 */
dea31012005-04-17 16:05:31 -05001352static void
James Smart4258e982015-12-16 18:11:58 -05001353lpfc_cmpl_ct_disc_fdmi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
1354 struct lpfc_iocbq *rspiocb)
dea31012005-04-17 16:05:31 -05001355{
James Smart4258e982015-12-16 18:11:58 -05001356 struct lpfc_vport *vport = cmdiocb->vport;
dea31012005-04-17 16:05:31 -05001357 struct lpfc_dmabuf *inp = cmdiocb->context1;
1358 struct lpfc_dmabuf *outp = cmdiocb->context2;
dea31012005-04-17 16:05:31 -05001359 struct lpfc_sli_ct_request *CTcmd = inp->virt;
James Smart4258e982015-12-16 18:11:58 -05001360 struct lpfc_sli_ct_request *CTrsp = outp->virt;
dea31012005-04-17 16:05:31 -05001361 uint16_t fdmi_cmd = CTcmd->CommandResponse.bits.CmdRsp;
1362 uint16_t fdmi_rsp = CTrsp->CommandResponse.bits.CmdRsp;
James Smart858c9f62007-06-17 19:56:39 -05001363 IOCB_t *irsp = &rspiocb->iocb;
James Smart4258e982015-12-16 18:11:58 -05001364 struct lpfc_nodelist *ndlp;
1365 uint32_t latt, cmd, err;
James Smart858c9f62007-06-17 19:56:39 -05001366
1367 latt = lpfc_els_chk_latt(vport);
James Smart858c9f62007-06-17 19:56:39 -05001368 lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT,
1369 "FDMI cmpl: status:x%x/x%x latt:%d",
1370 irsp->ulpStatus, irsp->un.ulpWord[4], latt);
1371
1372 if (latt || irsp->ulpStatus) {
James Smart4258e982015-12-16 18:11:58 -05001373
1374 /* Look for a retryable error */
1375 if (irsp->ulpStatus == IOSTAT_LOCAL_REJECT) {
1376 switch ((irsp->un.ulpWord[4] & IOERR_PARAM_MASK)) {
1377 case IOERR_SLI_ABORTED:
1378 case IOERR_ABORT_IN_PROGRESS:
1379 case IOERR_SEQUENCE_TIMEOUT:
1380 case IOERR_ILLEGAL_FRAME:
1381 case IOERR_NO_RESOURCES:
1382 case IOERR_ILLEGAL_COMMAND:
1383 cmdiocb->retry++;
1384 if (cmdiocb->retry >= LPFC_FDMI_MAX_RETRY)
1385 break;
1386
1387 /* Retry the same FDMI command */
1388 err = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING,
1389 cmdiocb, 0);
1390 if (err == IOCB_ERROR)
1391 break;
1392 return;
1393 default:
1394 break;
1395 }
1396 }
1397
James Smarte8b62012007-08-02 11:10:09 -04001398 lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
1399 "0229 FDMI cmd %04x failed, latt = %d "
1400 "ulpStatus: x%x, rid x%x\n",
1401 be16_to_cpu(fdmi_cmd), latt, irsp->ulpStatus,
1402 irsp->un.ulpWord[4]);
James Smart858c9f62007-06-17 19:56:39 -05001403 }
James Smart76b2c342015-04-07 15:07:19 -04001404 lpfc_ct_free_iocb(phba, cmdiocb);
James Smart76b2c342015-04-07 15:07:19 -04001405
1406 ndlp = lpfc_findnode_did(vport, FDMI_DID);
1407 if (!ndlp || !NLP_CHK_NODE_ACT(ndlp))
1408 return;
1409
James Smart4258e982015-12-16 18:11:58 -05001410 /* Check for a CT LS_RJT response */
1411 cmd = be16_to_cpu(fdmi_cmd);
1412 if (fdmi_rsp == cpu_to_be16(SLI_CT_RESPONSE_FS_RJT)) {
1413 /* FDMI rsp failed */
1414 lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
1415 "0220 FDMI cmd failed FS_RJT Data: x%x", cmd);
1416
1417 /* Should we fallback to FDMI-2 / FDMI-1 ? */
1418 switch (cmd) {
1419 case SLI_MGMT_RHBA:
1420 if (vport->fdmi_hba_mask == LPFC_FDMI2_HBA_ATTR) {
1421 /* Fallback to FDMI-1 */
1422 vport->fdmi_hba_mask = LPFC_FDMI1_HBA_ATTR;
1423 vport->fdmi_port_mask = LPFC_FDMI1_PORT_ATTR;
1424 /* Start over */
1425 lpfc_fdmi_cmd(vport, ndlp, SLI_MGMT_DHBA, 0);
1426 }
1427 return;
1428
1429 case SLI_MGMT_RPRT:
1430 if (vport->fdmi_port_mask == LPFC_FDMI2_PORT_ATTR) {
1431 /* Fallback to FDMI-1 */
1432 vport->fdmi_port_mask = LPFC_FDMI1_PORT_ATTR;
1433 /* Start over */
1434 lpfc_fdmi_cmd(vport, ndlp, cmd, 0);
1435 }
1436 if (vport->fdmi_port_mask == LPFC_FDMI2_SMART_ATTR) {
1437 vport->fdmi_port_mask = LPFC_FDMI2_PORT_ATTR;
1438 /* Retry the same command */
1439 lpfc_fdmi_cmd(vport, ndlp, cmd, 0);
1440 }
1441 return;
1442
1443 case SLI_MGMT_RPA:
1444 if (vport->fdmi_port_mask == LPFC_FDMI2_PORT_ATTR) {
1445 /* Fallback to FDMI-1 */
1446 vport->fdmi_hba_mask = LPFC_FDMI1_HBA_ATTR;
1447 vport->fdmi_port_mask = LPFC_FDMI1_PORT_ATTR;
1448 /* Start over */
1449 lpfc_fdmi_cmd(vport, ndlp, SLI_MGMT_DHBA, 0);
1450 }
1451 if (vport->fdmi_port_mask == LPFC_FDMI2_SMART_ATTR) {
1452 vport->fdmi_port_mask = LPFC_FDMI2_PORT_ATTR;
1453 /* Retry the same command */
1454 lpfc_fdmi_cmd(vport, ndlp, cmd, 0);
1455 }
1456 return;
1457 }
1458 }
1459
James Smart76b2c342015-04-07 15:07:19 -04001460 /*
James Smart4258e982015-12-16 18:11:58 -05001461 * On success, need to cycle thru FDMI registration for discovery
1462 * DHBA -> DPRT -> RHBA -> RPA (physical port)
1463 * DPRT -> RPRT (vports)
James Smart76b2c342015-04-07 15:07:19 -04001464 */
James Smart4258e982015-12-16 18:11:58 -05001465 switch (cmd) {
dea31012005-04-17 16:05:31 -05001466 case SLI_MGMT_RHBA:
James Smart4258e982015-12-16 18:11:58 -05001467 lpfc_fdmi_cmd(vport, ndlp, SLI_MGMT_RPA, 0);
dea31012005-04-17 16:05:31 -05001468 break;
1469
dea31012005-04-17 16:05:31 -05001470 case SLI_MGMT_DHBA:
James Smart4258e982015-12-16 18:11:58 -05001471 lpfc_fdmi_cmd(vport, ndlp, SLI_MGMT_DPRT, 0);
dea31012005-04-17 16:05:31 -05001472 break;
1473
1474 case SLI_MGMT_DPRT:
James Smart4258e982015-12-16 18:11:58 -05001475 if (vport->port_type == LPFC_PHYSICAL_PORT)
1476 lpfc_fdmi_cmd(vport, ndlp, SLI_MGMT_RHBA, 0);
1477 else
1478 lpfc_fdmi_cmd(vport, ndlp, SLI_MGMT_RPRT, 0);
dea31012005-04-17 16:05:31 -05001479 break;
1480 }
James Smart4258e982015-12-16 18:11:58 -05001481 return;
dea31012005-04-17 16:05:31 -05001482}
James Smart2e0fef82007-06-17 19:56:36 -05001483
James Smart76b2c342015-04-07 15:07:19 -04001484
James Smart4258e982015-12-16 18:11:58 -05001485/**
1486 * lpfc_fdmi_num_disc_check - Check how many mapped NPorts we are connected to
1487 * @vport: pointer to a host virtual N_Port data structure.
1488 *
1489 * Called from hbeat timeout routine to check if the number of discovered
1490 * ports has changed. If so, re-register thar port Attribute.
1491 */
1492void
1493lpfc_fdmi_num_disc_check(struct lpfc_vport *vport)
1494{
1495 struct lpfc_hba *phba = vport->phba;
1496 struct lpfc_nodelist *ndlp;
1497 uint16_t cnt;
1498
1499 if (!lpfc_is_link_up(phba))
1500 return;
1501
1502 if (!(vport->fdmi_port_mask & LPFC_FDMI_PORT_ATTR_num_disc))
1503 return;
1504
1505 cnt = lpfc_find_map_node(vport);
1506 if (cnt == vport->fdmi_num_disc)
1507 return;
1508
1509 ndlp = lpfc_findnode_did(vport, FDMI_DID);
1510 if (!ndlp || !NLP_CHK_NODE_ACT(ndlp))
1511 return;
1512
1513 if (vport->port_type == LPFC_PHYSICAL_PORT) {
1514 lpfc_fdmi_cmd(vport, ndlp, SLI_MGMT_RPA,
1515 LPFC_FDMI_PORT_ATTR_num_disc);
1516 } else {
1517 lpfc_fdmi_cmd(vport, ndlp, SLI_MGMT_RPRT,
1518 LPFC_FDMI_PORT_ATTR_num_disc);
1519 }
1520}
1521
1522/* Routines for all individual HBA attributes */
dea31012005-04-17 16:05:31 -05001523int
James Smart4258e982015-12-16 18:11:58 -05001524lpfc_fdmi_hba_attr_wwnn(struct lpfc_vport *vport, struct lpfc_fdmi_attr_def *ad)
1525{
1526 struct lpfc_fdmi_attr_entry *ae;
1527 uint32_t size;
1528
1529 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
1530 memset(ae, 0, sizeof(struct lpfc_name));
1531
1532 memcpy(&ae->un.AttrWWN, &vport->fc_sparam.nodeName,
1533 sizeof(struct lpfc_name));
1534 size = FOURBYTES + sizeof(struct lpfc_name);
1535 ad->AttrLen = cpu_to_be16(size);
1536 ad->AttrType = cpu_to_be16(RHBA_NODENAME);
1537 return size;
1538}
1539int
1540lpfc_fdmi_hba_attr_manufacturer(struct lpfc_vport *vport,
1541 struct lpfc_fdmi_attr_def *ad)
1542{
1543 struct lpfc_fdmi_attr_entry *ae;
1544 uint32_t len, size;
1545
1546 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
1547 memset(ae, 0, 256);
1548
1549 strncpy(ae->un.AttrString,
1550 "Emulex Corporation",
1551 sizeof(ae->un.AttrString));
1552 len = strnlen(ae->un.AttrString,
1553 sizeof(ae->un.AttrString));
1554 len += (len & 3) ? (4 - (len & 3)) : 4;
1555 size = FOURBYTES + len;
1556 ad->AttrLen = cpu_to_be16(size);
1557 ad->AttrType = cpu_to_be16(RHBA_MANUFACTURER);
1558 return size;
1559}
1560
1561int
1562lpfc_fdmi_hba_attr_sn(struct lpfc_vport *vport, struct lpfc_fdmi_attr_def *ad)
1563{
1564 struct lpfc_hba *phba = vport->phba;
1565 struct lpfc_fdmi_attr_entry *ae;
1566 uint32_t len, size;
1567
1568 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
1569 memset(ae, 0, 256);
1570
1571 strncpy(ae->un.AttrString, phba->SerialNumber,
1572 sizeof(ae->un.AttrString));
1573 len = strnlen(ae->un.AttrString,
1574 sizeof(ae->un.AttrString));
1575 len += (len & 3) ? (4 - (len & 3)) : 4;
1576 size = FOURBYTES + len;
1577 ad->AttrLen = cpu_to_be16(size);
1578 ad->AttrType = cpu_to_be16(RHBA_SERIAL_NUMBER);
1579 return size;
1580}
1581
1582int
1583lpfc_fdmi_hba_attr_model(struct lpfc_vport *vport,
1584 struct lpfc_fdmi_attr_def *ad)
1585{
1586 struct lpfc_hba *phba = vport->phba;
1587 struct lpfc_fdmi_attr_entry *ae;
1588 uint32_t len, size;
1589
1590 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
1591 memset(ae, 0, 256);
1592
1593 strncpy(ae->un.AttrString, phba->ModelName,
1594 sizeof(ae->un.AttrString));
1595 len = strnlen(ae->un.AttrString, sizeof(ae->un.AttrString));
1596 len += (len & 3) ? (4 - (len & 3)) : 4;
1597 size = FOURBYTES + len;
1598 ad->AttrLen = cpu_to_be16(size);
1599 ad->AttrType = cpu_to_be16(RHBA_MODEL);
1600 return size;
1601}
1602
1603int
1604lpfc_fdmi_hba_attr_description(struct lpfc_vport *vport,
1605 struct lpfc_fdmi_attr_def *ad)
1606{
1607 struct lpfc_hba *phba = vport->phba;
1608 struct lpfc_fdmi_attr_entry *ae;
1609 uint32_t len, size;
1610
1611 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
1612 memset(ae, 0, 256);
1613
1614 strncpy(ae->un.AttrString, phba->ModelDesc,
1615 sizeof(ae->un.AttrString));
1616 len = strnlen(ae->un.AttrString,
1617 sizeof(ae->un.AttrString));
1618 len += (len & 3) ? (4 - (len & 3)) : 4;
1619 size = FOURBYTES + len;
1620 ad->AttrLen = cpu_to_be16(size);
1621 ad->AttrType = cpu_to_be16(RHBA_MODEL_DESCRIPTION);
1622 return size;
1623}
1624
1625int
1626lpfc_fdmi_hba_attr_hdw_ver(struct lpfc_vport *vport,
1627 struct lpfc_fdmi_attr_def *ad)
1628{
1629 struct lpfc_hba *phba = vport->phba;
1630 lpfc_vpd_t *vp = &phba->vpd;
1631 struct lpfc_fdmi_attr_entry *ae;
1632 uint32_t i, j, incr, size;
1633
1634 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
1635 memset(ae, 0, 256);
1636
1637 /* Convert JEDEC ID to ascii for hardware version */
1638 incr = vp->rev.biuRev;
1639 for (i = 0; i < 8; i++) {
1640 j = (incr & 0xf);
1641 if (j <= 9)
1642 ae->un.AttrString[7 - i] =
1643 (char)((uint8_t) 0x30 +
1644 (uint8_t) j);
1645 else
1646 ae->un.AttrString[7 - i] =
1647 (char)((uint8_t) 0x61 +
1648 (uint8_t) (j - 10));
1649 incr = (incr >> 4);
1650 }
1651 size = FOURBYTES + 8;
1652 ad->AttrLen = cpu_to_be16(size);
1653 ad->AttrType = cpu_to_be16(RHBA_HARDWARE_VERSION);
1654 return size;
1655}
1656
1657int
1658lpfc_fdmi_hba_attr_drvr_ver(struct lpfc_vport *vport,
1659 struct lpfc_fdmi_attr_def *ad)
1660{
1661 struct lpfc_fdmi_attr_entry *ae;
1662 uint32_t len, size;
1663
1664 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
1665 memset(ae, 0, 256);
1666
1667 strncpy(ae->un.AttrString, lpfc_release_version,
1668 sizeof(ae->un.AttrString));
1669 len = strnlen(ae->un.AttrString,
1670 sizeof(ae->un.AttrString));
1671 len += (len & 3) ? (4 - (len & 3)) : 4;
1672 size = FOURBYTES + len;
1673 ad->AttrLen = cpu_to_be16(size);
1674 ad->AttrType = cpu_to_be16(RHBA_DRIVER_VERSION);
1675 return size;
1676}
1677
1678int
1679lpfc_fdmi_hba_attr_rom_ver(struct lpfc_vport *vport,
1680 struct lpfc_fdmi_attr_def *ad)
1681{
1682 struct lpfc_hba *phba = vport->phba;
1683 struct lpfc_fdmi_attr_entry *ae;
1684 uint32_t len, size;
1685
1686 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
1687 memset(ae, 0, 256);
1688
1689 if (phba->sli_rev == LPFC_SLI_REV4)
1690 lpfc_decode_firmware_rev(phba, ae->un.AttrString, 1);
1691 else
1692 strncpy(ae->un.AttrString, phba->OptionROMVersion,
1693 sizeof(ae->un.AttrString));
1694 len = strnlen(ae->un.AttrString,
1695 sizeof(ae->un.AttrString));
1696 len += (len & 3) ? (4 - (len & 3)) : 4;
1697 size = FOURBYTES + len;
1698 ad->AttrLen = cpu_to_be16(size);
1699 ad->AttrType = cpu_to_be16(RHBA_OPTION_ROM_VERSION);
1700 return size;
1701}
1702
1703int
1704lpfc_fdmi_hba_attr_fmw_ver(struct lpfc_vport *vport,
1705 struct lpfc_fdmi_attr_def *ad)
1706{
1707 struct lpfc_hba *phba = vport->phba;
1708 struct lpfc_fdmi_attr_entry *ae;
1709 uint32_t len, size;
1710
1711 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
1712 memset(ae, 0, 256);
1713
1714 lpfc_decode_firmware_rev(phba, ae->un.AttrString, 1);
1715 len = strnlen(ae->un.AttrString,
1716 sizeof(ae->un.AttrString));
1717 len += (len & 3) ? (4 - (len & 3)) : 4;
1718 size = FOURBYTES + len;
1719 ad->AttrLen = cpu_to_be16(size);
1720 ad->AttrType = cpu_to_be16(RHBA_FIRMWARE_VERSION);
1721 return size;
1722}
1723
1724int
1725lpfc_fdmi_hba_attr_os_ver(struct lpfc_vport *vport,
1726 struct lpfc_fdmi_attr_def *ad)
1727{
1728 struct lpfc_fdmi_attr_entry *ae;
1729 uint32_t len, size;
1730
1731 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
1732 memset(ae, 0, 256);
1733
1734 snprintf(ae->un.AttrString, sizeof(ae->un.AttrString), "%s %s %s",
1735 init_utsname()->sysname,
1736 init_utsname()->release,
1737 init_utsname()->version);
1738
1739 len = strnlen(ae->un.AttrString, sizeof(ae->un.AttrString));
1740 len += (len & 3) ? (4 - (len & 3)) : 4;
1741 size = FOURBYTES + len;
1742 ad->AttrLen = cpu_to_be16(size);
1743 ad->AttrType = cpu_to_be16(RHBA_OS_NAME_VERSION);
1744 return size;
1745}
1746
1747int
1748lpfc_fdmi_hba_attr_ct_len(struct lpfc_vport *vport,
1749 struct lpfc_fdmi_attr_def *ad)
1750{
1751 struct lpfc_fdmi_attr_entry *ae;
1752 uint32_t size;
1753
1754 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
1755
1756 ae->un.AttrInt = cpu_to_be32(LPFC_MAX_CT_SIZE);
1757 size = FOURBYTES + sizeof(uint32_t);
1758 ad->AttrLen = cpu_to_be16(size);
1759 ad->AttrType = cpu_to_be16(RHBA_MAX_CT_PAYLOAD_LEN);
1760 return size;
1761}
1762
1763int
1764lpfc_fdmi_hba_attr_symbolic_name(struct lpfc_vport *vport,
1765 struct lpfc_fdmi_attr_def *ad)
1766{
1767 struct lpfc_fdmi_attr_entry *ae;
1768 uint32_t len, size;
1769
1770 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
1771 memset(ae, 0, 256);
1772
1773 len = lpfc_vport_symbolic_node_name(vport,
1774 ae->un.AttrString, 256);
1775 len += (len & 3) ? (4 - (len & 3)) : 4;
1776 size = FOURBYTES + len;
1777 ad->AttrLen = cpu_to_be16(size);
1778 ad->AttrType = cpu_to_be16(RHBA_SYM_NODENAME);
1779 return size;
1780}
1781
1782int
1783lpfc_fdmi_hba_attr_vendor_info(struct lpfc_vport *vport,
1784 struct lpfc_fdmi_attr_def *ad)
1785{
1786 struct lpfc_fdmi_attr_entry *ae;
1787 uint32_t size;
1788
1789 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
1790
1791 /* Nothing is defined for this currently */
1792 ae->un.AttrInt = cpu_to_be32(0);
1793 size = FOURBYTES + sizeof(uint32_t);
1794 ad->AttrLen = cpu_to_be16(size);
1795 ad->AttrType = cpu_to_be16(RHBA_VENDOR_INFO);
1796 return size;
1797}
1798
1799int
1800lpfc_fdmi_hba_attr_num_ports(struct lpfc_vport *vport,
1801 struct lpfc_fdmi_attr_def *ad)
1802{
1803 struct lpfc_fdmi_attr_entry *ae;
1804 uint32_t size;
1805
1806 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
1807
1808 /* Each driver instance corresponds to a single port */
1809 ae->un.AttrInt = cpu_to_be32(1);
1810 size = FOURBYTES + sizeof(uint32_t);
1811 ad->AttrLen = cpu_to_be16(size);
1812 ad->AttrType = cpu_to_be16(RHBA_NUM_PORTS);
1813 return size;
1814}
1815
1816int
1817lpfc_fdmi_hba_attr_fabric_wwnn(struct lpfc_vport *vport,
1818 struct lpfc_fdmi_attr_def *ad)
1819{
1820 struct lpfc_fdmi_attr_entry *ae;
1821 uint32_t size;
1822
1823 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
1824 memset(ae, 0, sizeof(struct lpfc_name));
1825
1826 memcpy(&ae->un.AttrWWN, &vport->fabric_nodename,
1827 sizeof(struct lpfc_name));
1828 size = FOURBYTES + sizeof(struct lpfc_name);
1829 ad->AttrLen = cpu_to_be16(size);
1830 ad->AttrType = cpu_to_be16(RHBA_FABRIC_WWNN);
1831 return size;
1832}
1833
1834int
1835lpfc_fdmi_hba_attr_bios_ver(struct lpfc_vport *vport,
1836 struct lpfc_fdmi_attr_def *ad)
1837{
1838 struct lpfc_hba *phba = vport->phba;
1839 struct lpfc_fdmi_attr_entry *ae;
1840 uint32_t len, size;
1841
1842 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
1843 memset(ae, 0, 256);
1844
1845 lpfc_decode_firmware_rev(phba, ae->un.AttrString, 1);
1846 len = strnlen(ae->un.AttrString,
1847 sizeof(ae->un.AttrString));
1848 len += (len & 3) ? (4 - (len & 3)) : 4;
1849 size = FOURBYTES + len;
1850 ad->AttrLen = cpu_to_be16(size);
1851 ad->AttrType = cpu_to_be16(RHBA_BIOS_VERSION);
1852 return size;
1853}
1854
1855int
1856lpfc_fdmi_hba_attr_bios_state(struct lpfc_vport *vport,
1857 struct lpfc_fdmi_attr_def *ad)
1858{
1859 struct lpfc_fdmi_attr_entry *ae;
1860 uint32_t size;
1861
1862 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
1863
1864 /* Driver doesn't have access to this information */
1865 ae->un.AttrInt = cpu_to_be32(0);
1866 size = FOURBYTES + sizeof(uint32_t);
1867 ad->AttrLen = cpu_to_be16(size);
1868 ad->AttrType = cpu_to_be16(RHBA_BIOS_STATE);
1869 return size;
1870}
1871
1872int
1873lpfc_fdmi_hba_attr_vendor_id(struct lpfc_vport *vport,
1874 struct lpfc_fdmi_attr_def *ad)
1875{
1876 struct lpfc_fdmi_attr_entry *ae;
1877 uint32_t len, size;
1878
1879 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
1880 memset(ae, 0, 256);
1881
1882 strncpy(ae->un.AttrString, "EMULEX",
1883 sizeof(ae->un.AttrString));
1884 len = strnlen(ae->un.AttrString,
1885 sizeof(ae->un.AttrString));
1886 len += (len & 3) ? (4 - (len & 3)) : 4;
1887 size = FOURBYTES + len;
1888 ad->AttrLen = cpu_to_be16(size);
1889 ad->AttrType = cpu_to_be16(RHBA_VENDOR_ID);
1890 return size;
1891}
1892
1893/* Routines for all individual PORT attributes */
1894int
1895lpfc_fdmi_port_attr_fc4type(struct lpfc_vport *vport,
1896 struct lpfc_fdmi_attr_def *ad)
1897{
1898 struct lpfc_fdmi_attr_entry *ae;
1899 uint32_t size;
1900
1901 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
1902 memset(ae, 0, 32);
1903
1904 ae->un.AttrTypes[3] = 0x02; /* Type 1 - ELS */
1905 ae->un.AttrTypes[2] = 0x01; /* Type 8 - FCP */
1906 ae->un.AttrTypes[7] = 0x01; /* Type 32 - CT */
1907 size = FOURBYTES + 32;
1908 ad->AttrLen = cpu_to_be16(size);
1909 ad->AttrType = cpu_to_be16(RPRT_SUPPORTED_FC4_TYPES);
1910 return size;
1911}
1912
1913int
1914lpfc_fdmi_port_attr_support_speed(struct lpfc_vport *vport,
1915 struct lpfc_fdmi_attr_def *ad)
1916{
1917 struct lpfc_hba *phba = vport->phba;
1918 struct lpfc_fdmi_attr_entry *ae;
1919 uint32_t size;
1920
1921 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
1922
1923 ae->un.AttrInt = 0;
1924 if (phba->lmt & LMT_32Gb)
1925 ae->un.AttrInt |= HBA_PORTSPEED_32GBIT;
1926 if (phba->lmt & LMT_16Gb)
1927 ae->un.AttrInt |= HBA_PORTSPEED_16GBIT;
1928 if (phba->lmt & LMT_10Gb)
1929 ae->un.AttrInt |= HBA_PORTSPEED_10GBIT;
1930 if (phba->lmt & LMT_8Gb)
1931 ae->un.AttrInt |= HBA_PORTSPEED_8GBIT;
1932 if (phba->lmt & LMT_4Gb)
1933 ae->un.AttrInt |= HBA_PORTSPEED_4GBIT;
1934 if (phba->lmt & LMT_2Gb)
1935 ae->un.AttrInt |= HBA_PORTSPEED_2GBIT;
1936 if (phba->lmt & LMT_1Gb)
1937 ae->un.AttrInt |= HBA_PORTSPEED_1GBIT;
1938 ae->un.AttrInt = cpu_to_be32(ae->un.AttrInt);
1939 size = FOURBYTES + sizeof(uint32_t);
1940 ad->AttrLen = cpu_to_be16(size);
1941 ad->AttrType = cpu_to_be16(RPRT_SUPPORTED_SPEED);
1942 return size;
1943}
1944
1945int
1946lpfc_fdmi_port_attr_speed(struct lpfc_vport *vport,
1947 struct lpfc_fdmi_attr_def *ad)
1948{
1949 struct lpfc_hba *phba = vport->phba;
1950 struct lpfc_fdmi_attr_entry *ae;
1951 uint32_t size;
1952
1953 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
1954
1955 switch (phba->fc_linkspeed) {
1956 case LPFC_LINK_SPEED_1GHZ:
1957 ae->un.AttrInt = HBA_PORTSPEED_1GBIT;
1958 break;
1959 case LPFC_LINK_SPEED_2GHZ:
1960 ae->un.AttrInt = HBA_PORTSPEED_2GBIT;
1961 break;
1962 case LPFC_LINK_SPEED_4GHZ:
1963 ae->un.AttrInt = HBA_PORTSPEED_4GBIT;
1964 break;
1965 case LPFC_LINK_SPEED_8GHZ:
1966 ae->un.AttrInt = HBA_PORTSPEED_8GBIT;
1967 break;
1968 case LPFC_LINK_SPEED_10GHZ:
1969 ae->un.AttrInt = HBA_PORTSPEED_10GBIT;
1970 break;
1971 case LPFC_LINK_SPEED_16GHZ:
1972 ae->un.AttrInt = HBA_PORTSPEED_16GBIT;
1973 break;
1974 case LPFC_LINK_SPEED_32GHZ:
1975 ae->un.AttrInt = HBA_PORTSPEED_32GBIT;
1976 break;
1977 default:
1978 ae->un.AttrInt = HBA_PORTSPEED_UNKNOWN;
1979 break;
1980 }
1981 ae->un.AttrInt = cpu_to_be32(ae->un.AttrInt);
1982 size = FOURBYTES + sizeof(uint32_t);
1983 ad->AttrLen = cpu_to_be16(size);
1984 ad->AttrType = cpu_to_be16(RPRT_PORT_SPEED);
1985 return size;
1986}
1987
1988int
1989lpfc_fdmi_port_attr_max_frame(struct lpfc_vport *vport,
1990 struct lpfc_fdmi_attr_def *ad)
1991{
1992 struct serv_parm *hsp;
1993 struct lpfc_fdmi_attr_entry *ae;
1994 uint32_t size;
1995
1996 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
1997
1998 hsp = (struct serv_parm *)&vport->fc_sparam;
1999 ae->un.AttrInt = (((uint32_t) hsp->cmn.bbRcvSizeMsb) << 8) |
2000 (uint32_t) hsp->cmn.bbRcvSizeLsb;
2001 ae->un.AttrInt = cpu_to_be32(ae->un.AttrInt);
2002 size = FOURBYTES + sizeof(uint32_t);
2003 ad->AttrLen = cpu_to_be16(size);
2004 ad->AttrType = cpu_to_be16(RPRT_MAX_FRAME_SIZE);
2005 return size;
2006}
2007
2008int
2009lpfc_fdmi_port_attr_os_devname(struct lpfc_vport *vport,
2010 struct lpfc_fdmi_attr_def *ad)
2011{
2012 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
2013 struct lpfc_fdmi_attr_entry *ae;
2014 uint32_t len, size;
2015
2016 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
2017 memset(ae, 0, 256);
2018
2019 snprintf(ae->un.AttrString, sizeof(ae->un.AttrString),
2020 "/sys/class/scsi_host/host%d", shost->host_no);
2021 len = strnlen((char *)ae->un.AttrString,
2022 sizeof(ae->un.AttrString));
2023 len += (len & 3) ? (4 - (len & 3)) : 4;
2024 size = FOURBYTES + len;
2025 ad->AttrLen = cpu_to_be16(size);
2026 ad->AttrType = cpu_to_be16(RPRT_OS_DEVICE_NAME);
2027 return size;
2028}
2029
2030int
2031lpfc_fdmi_port_attr_host_name(struct lpfc_vport *vport,
2032 struct lpfc_fdmi_attr_def *ad)
2033{
2034 struct lpfc_fdmi_attr_entry *ae;
2035 uint32_t len, size;
2036
2037 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
2038 memset(ae, 0, 256);
2039
2040 snprintf(ae->un.AttrString, sizeof(ae->un.AttrString), "%s",
2041 init_utsname()->nodename);
2042
2043 len = strnlen(ae->un.AttrString, sizeof(ae->un.AttrString));
2044 len += (len & 3) ? (4 - (len & 3)) : 4;
2045 size = FOURBYTES + len;
2046 ad->AttrLen = cpu_to_be16(size);
2047 ad->AttrType = cpu_to_be16(RPRT_HOST_NAME);
2048 return size;
2049}
2050
2051int
2052lpfc_fdmi_port_attr_wwnn(struct lpfc_vport *vport,
2053 struct lpfc_fdmi_attr_def *ad)
2054{
2055 struct lpfc_fdmi_attr_entry *ae;
2056 uint32_t size;
2057
2058 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
2059 memset(ae, 0, sizeof(struct lpfc_name));
2060
2061 memcpy(&ae->un.AttrWWN, &vport->fc_sparam.nodeName,
2062 sizeof(struct lpfc_name));
2063 size = FOURBYTES + sizeof(struct lpfc_name);
2064 ad->AttrLen = cpu_to_be16(size);
2065 ad->AttrType = cpu_to_be16(RPRT_NODENAME);
2066 return size;
2067}
2068
2069int
2070lpfc_fdmi_port_attr_wwpn(struct lpfc_vport *vport,
2071 struct lpfc_fdmi_attr_def *ad)
2072{
2073 struct lpfc_fdmi_attr_entry *ae;
2074 uint32_t size;
2075
2076 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
2077 memset(ae, 0, sizeof(struct lpfc_name));
2078
2079 memcpy(&ae->un.AttrWWN, &vport->fc_sparam.portName,
2080 sizeof(struct lpfc_name));
2081 size = FOURBYTES + sizeof(struct lpfc_name);
2082 ad->AttrLen = cpu_to_be16(size);
2083 ad->AttrType = cpu_to_be16(RPRT_PORTNAME);
2084 return size;
2085}
2086
2087int
2088lpfc_fdmi_port_attr_symbolic_name(struct lpfc_vport *vport,
2089 struct lpfc_fdmi_attr_def *ad)
2090{
2091 struct lpfc_fdmi_attr_entry *ae;
2092 uint32_t len, size;
2093
2094 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
2095 memset(ae, 0, 256);
2096
2097 len = lpfc_vport_symbolic_port_name(vport, ae->un.AttrString, 256);
2098 len += (len & 3) ? (4 - (len & 3)) : 4;
2099 size = FOURBYTES + len;
2100 ad->AttrLen = cpu_to_be16(size);
2101 ad->AttrType = cpu_to_be16(RPRT_SYM_PORTNAME);
2102 return size;
2103}
2104
2105int
2106lpfc_fdmi_port_attr_port_type(struct lpfc_vport *vport,
2107 struct lpfc_fdmi_attr_def *ad)
2108{
2109 struct lpfc_hba *phba = vport->phba;
2110 struct lpfc_fdmi_attr_entry *ae;
2111 uint32_t size;
2112
2113 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
2114 if (phba->fc_topology == LPFC_TOPOLOGY_LOOP)
2115 ae->un.AttrInt = cpu_to_be32(LPFC_FDMI_PORTTYPE_NLPORT);
2116 else
2117 ae->un.AttrInt = cpu_to_be32(LPFC_FDMI_PORTTYPE_NPORT);
2118 size = FOURBYTES + sizeof(uint32_t);
2119 ad->AttrLen = cpu_to_be16(size);
2120 ad->AttrType = cpu_to_be16(RPRT_PORT_TYPE);
2121 return size;
2122}
2123
2124int
2125lpfc_fdmi_port_attr_class(struct lpfc_vport *vport,
2126 struct lpfc_fdmi_attr_def *ad)
2127{
2128 struct lpfc_fdmi_attr_entry *ae;
2129 uint32_t size;
2130
2131 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
2132 ae->un.AttrInt = cpu_to_be32(FC_COS_CLASS2 | FC_COS_CLASS3);
2133 size = FOURBYTES + sizeof(uint32_t);
2134 ad->AttrLen = cpu_to_be16(size);
2135 ad->AttrType = cpu_to_be16(RPRT_SUPPORTED_CLASS);
2136 return size;
2137}
2138
2139int
2140lpfc_fdmi_port_attr_fabric_wwpn(struct lpfc_vport *vport,
2141 struct lpfc_fdmi_attr_def *ad)
2142{
2143 struct lpfc_fdmi_attr_entry *ae;
2144 uint32_t size;
2145
2146 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
2147 memset(ae, 0, sizeof(struct lpfc_name));
2148
2149 memcpy(&ae->un.AttrWWN, &vport->fabric_portname,
2150 sizeof(struct lpfc_name));
2151 size = FOURBYTES + sizeof(struct lpfc_name);
2152 ad->AttrLen = cpu_to_be16(size);
2153 ad->AttrType = cpu_to_be16(RPRT_FABRICNAME);
2154 return size;
2155}
2156
2157int
2158lpfc_fdmi_port_attr_active_fc4type(struct lpfc_vport *vport,
2159 struct lpfc_fdmi_attr_def *ad)
2160{
2161 struct lpfc_fdmi_attr_entry *ae;
2162 uint32_t size;
2163
2164 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
2165 memset(ae, 0, 32);
2166
2167 ae->un.AttrTypes[3] = 0x02; /* Type 1 - ELS */
2168 ae->un.AttrTypes[2] = 0x01; /* Type 8 - FCP */
2169 ae->un.AttrTypes[7] = 0x01; /* Type 32 - CT */
2170 size = FOURBYTES + 32;
2171 ad->AttrLen = cpu_to_be16(size);
2172 ad->AttrType = cpu_to_be16(RPRT_ACTIVE_FC4_TYPES);
2173 return size;
2174}
2175
2176int
2177lpfc_fdmi_port_attr_port_state(struct lpfc_vport *vport,
2178 struct lpfc_fdmi_attr_def *ad)
2179{
2180 struct lpfc_fdmi_attr_entry *ae;
2181 uint32_t size;
2182
2183 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
2184 /* Link Up - operational */
2185 ae->un.AttrInt = cpu_to_be32(LPFC_FDMI_PORTSTATE_ONLINE);
2186 size = FOURBYTES + sizeof(uint32_t);
2187 ad->AttrLen = cpu_to_be16(size);
2188 ad->AttrType = cpu_to_be16(RPRT_PORT_STATE);
2189 return size;
2190}
2191
2192int
2193lpfc_fdmi_port_attr_num_disc(struct lpfc_vport *vport,
2194 struct lpfc_fdmi_attr_def *ad)
2195{
2196 struct lpfc_fdmi_attr_entry *ae;
2197 uint32_t size;
2198
2199 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
2200 vport->fdmi_num_disc = lpfc_find_map_node(vport);
2201 ae->un.AttrInt = cpu_to_be32(vport->fdmi_num_disc);
2202 size = FOURBYTES + sizeof(uint32_t);
2203 ad->AttrLen = cpu_to_be16(size);
2204 ad->AttrType = cpu_to_be16(RPRT_DISC_PORT);
2205 return size;
2206}
2207
2208int
2209lpfc_fdmi_port_attr_nportid(struct lpfc_vport *vport,
2210 struct lpfc_fdmi_attr_def *ad)
2211{
2212 struct lpfc_fdmi_attr_entry *ae;
2213 uint32_t size;
2214
2215 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
2216 ae->un.AttrInt = cpu_to_be32(vport->fc_myDID);
2217 size = FOURBYTES + sizeof(uint32_t);
2218 ad->AttrLen = cpu_to_be16(size);
2219 ad->AttrType = cpu_to_be16(RPRT_PORT_ID);
2220 return size;
2221}
2222
2223int
2224lpfc_fdmi_smart_attr_service(struct lpfc_vport *vport,
2225 struct lpfc_fdmi_attr_def *ad)
2226{
2227 struct lpfc_fdmi_attr_entry *ae;
2228 uint32_t len, size;
2229
2230 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
2231 memset(ae, 0, 256);
2232
2233 strncpy(ae->un.AttrString, "Smart SAN Initiator",
2234 sizeof(ae->un.AttrString));
2235 len = strnlen(ae->un.AttrString,
2236 sizeof(ae->un.AttrString));
2237 len += (len & 3) ? (4 - (len & 3)) : 4;
2238 size = FOURBYTES + len;
2239 ad->AttrLen = cpu_to_be16(size);
2240 ad->AttrType = cpu_to_be16(RPRT_SMART_SERVICE);
2241 return size;
2242}
2243
2244int
2245lpfc_fdmi_smart_attr_guid(struct lpfc_vport *vport,
2246 struct lpfc_fdmi_attr_def *ad)
2247{
2248 struct lpfc_fdmi_attr_entry *ae;
2249 uint32_t size;
2250
2251 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
2252 memset(ae, 0, 256);
2253
2254 memcpy(&ae->un.AttrString, &vport->fc_sparam.nodeName,
2255 sizeof(struct lpfc_name));
2256 memcpy((((uint8_t *)&ae->un.AttrString) +
2257 sizeof(struct lpfc_name)),
2258 &vport->fc_sparam.portName, sizeof(struct lpfc_name));
2259 size = FOURBYTES + (2 * sizeof(struct lpfc_name));
2260 ad->AttrLen = cpu_to_be16(size);
2261 ad->AttrType = cpu_to_be16(RPRT_SMART_GUID);
2262 return size;
2263}
2264
2265int
2266lpfc_fdmi_smart_attr_version(struct lpfc_vport *vport,
2267 struct lpfc_fdmi_attr_def *ad)
2268{
2269 struct lpfc_fdmi_attr_entry *ae;
2270 uint32_t len, size;
2271
2272 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
2273 memset(ae, 0, 256);
2274
2275 strncpy(ae->un.AttrString, "Smart SAN Version 1.0",
2276 sizeof(ae->un.AttrString));
2277 len = strnlen(ae->un.AttrString,
2278 sizeof(ae->un.AttrString));
2279 len += (len & 3) ? (4 - (len & 3)) : 4;
2280 size = FOURBYTES + len;
2281 ad->AttrLen = cpu_to_be16(size);
2282 ad->AttrType = cpu_to_be16(RPRT_SMART_VERSION);
2283 return size;
2284}
2285
2286int
2287lpfc_fdmi_smart_attr_model(struct lpfc_vport *vport,
2288 struct lpfc_fdmi_attr_def *ad)
2289{
2290 struct lpfc_hba *phba = vport->phba;
2291 struct lpfc_fdmi_attr_entry *ae;
2292 uint32_t len, size;
2293
2294 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
2295 memset(ae, 0, 256);
2296
2297 strncpy(ae->un.AttrString, phba->ModelName,
2298 sizeof(ae->un.AttrString));
2299 len = strnlen(ae->un.AttrString, sizeof(ae->un.AttrString));
2300 len += (len & 3) ? (4 - (len & 3)) : 4;
2301 size = FOURBYTES + len;
2302 ad->AttrLen = cpu_to_be16(size);
2303 ad->AttrType = cpu_to_be16(RPRT_SMART_MODEL);
2304 return size;
2305}
2306
2307int
2308lpfc_fdmi_smart_attr_port_info(struct lpfc_vport *vport,
2309 struct lpfc_fdmi_attr_def *ad)
2310{
2311 struct lpfc_fdmi_attr_entry *ae;
2312 uint32_t size;
2313
2314 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
2315
2316 /* SRIOV (type 3) is not supported */
2317 if (vport->vpi)
2318 ae->un.AttrInt = cpu_to_be32(2); /* NPIV */
2319 else
2320 ae->un.AttrInt = cpu_to_be32(1); /* Physical */
2321 size = FOURBYTES + sizeof(uint32_t);
2322 ad->AttrLen = cpu_to_be16(size);
2323 ad->AttrType = cpu_to_be16(RPRT_SMART_PORT_INFO);
2324 return size;
2325}
2326
2327int
2328lpfc_fdmi_smart_attr_qos(struct lpfc_vport *vport,
2329 struct lpfc_fdmi_attr_def *ad)
2330{
2331 struct lpfc_fdmi_attr_entry *ae;
2332 uint32_t size;
2333
2334 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
2335 ae->un.AttrInt = cpu_to_be32(0);
2336 size = FOURBYTES + sizeof(uint32_t);
2337 ad->AttrLen = cpu_to_be16(size);
2338 ad->AttrType = cpu_to_be16(RPRT_SMART_QOS);
2339 return size;
2340}
2341
2342int
2343lpfc_fdmi_smart_attr_security(struct lpfc_vport *vport,
2344 struct lpfc_fdmi_attr_def *ad)
2345{
2346 struct lpfc_fdmi_attr_entry *ae;
2347 uint32_t size;
2348
2349 ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue;
2350 ae->un.AttrInt = cpu_to_be32(0);
2351 size = FOURBYTES + sizeof(uint32_t);
2352 ad->AttrLen = cpu_to_be16(size);
2353 ad->AttrType = cpu_to_be16(RPRT_SMART_SECURITY);
2354 return size;
2355}
2356
2357/* RHBA attribute jump table */
2358int (*lpfc_fdmi_hba_action[])
2359 (struct lpfc_vport *vport, struct lpfc_fdmi_attr_def *ad) = {
2360 /* Action routine Mask bit Attribute type */
2361 lpfc_fdmi_hba_attr_wwnn, /* bit0 RHBA_NODENAME */
2362 lpfc_fdmi_hba_attr_manufacturer, /* bit1 RHBA_MANUFACTURER */
2363 lpfc_fdmi_hba_attr_sn, /* bit2 RHBA_SERIAL_NUMBER */
2364 lpfc_fdmi_hba_attr_model, /* bit3 RHBA_MODEL */
2365 lpfc_fdmi_hba_attr_description, /* bit4 RHBA_MODEL_DESCRIPTION */
2366 lpfc_fdmi_hba_attr_hdw_ver, /* bit5 RHBA_HARDWARE_VERSION */
2367 lpfc_fdmi_hba_attr_drvr_ver, /* bit6 RHBA_DRIVER_VERSION */
2368 lpfc_fdmi_hba_attr_rom_ver, /* bit7 RHBA_OPTION_ROM_VERSION */
2369 lpfc_fdmi_hba_attr_fmw_ver, /* bit8 RHBA_FIRMWARE_VERSION */
2370 lpfc_fdmi_hba_attr_os_ver, /* bit9 RHBA_OS_NAME_VERSION */
2371 lpfc_fdmi_hba_attr_ct_len, /* bit10 RHBA_MAX_CT_PAYLOAD_LEN */
2372 lpfc_fdmi_hba_attr_symbolic_name, /* bit11 RHBA_SYM_NODENAME */
2373 lpfc_fdmi_hba_attr_vendor_info, /* bit12 RHBA_VENDOR_INFO */
2374 lpfc_fdmi_hba_attr_num_ports, /* bit13 RHBA_NUM_PORTS */
2375 lpfc_fdmi_hba_attr_fabric_wwnn, /* bit14 RHBA_FABRIC_WWNN */
2376 lpfc_fdmi_hba_attr_bios_ver, /* bit15 RHBA_BIOS_VERSION */
2377 lpfc_fdmi_hba_attr_bios_state, /* bit16 RHBA_BIOS_STATE */
2378 lpfc_fdmi_hba_attr_vendor_id, /* bit17 RHBA_VENDOR_ID */
2379};
2380
2381/* RPA / RPRT attribute jump table */
2382int (*lpfc_fdmi_port_action[])
2383 (struct lpfc_vport *vport, struct lpfc_fdmi_attr_def *ad) = {
2384 /* Action routine Mask bit Attribute type */
2385 lpfc_fdmi_port_attr_fc4type, /* bit0 RPRT_SUPPORT_FC4_TYPES */
2386 lpfc_fdmi_port_attr_support_speed, /* bit1 RPRT_SUPPORTED_SPEED */
2387 lpfc_fdmi_port_attr_speed, /* bit2 RPRT_PORT_SPEED */
2388 lpfc_fdmi_port_attr_max_frame, /* bit3 RPRT_MAX_FRAME_SIZE */
2389 lpfc_fdmi_port_attr_os_devname, /* bit4 RPRT_OS_DEVICE_NAME */
2390 lpfc_fdmi_port_attr_host_name, /* bit5 RPRT_HOST_NAME */
2391 lpfc_fdmi_port_attr_wwnn, /* bit6 RPRT_NODENAME */
2392 lpfc_fdmi_port_attr_wwpn, /* bit7 RPRT_PORTNAME */
2393 lpfc_fdmi_port_attr_symbolic_name, /* bit8 RPRT_SYM_PORTNAME */
2394 lpfc_fdmi_port_attr_port_type, /* bit9 RPRT_PORT_TYPE */
2395 lpfc_fdmi_port_attr_class, /* bit10 RPRT_SUPPORTED_CLASS */
2396 lpfc_fdmi_port_attr_fabric_wwpn, /* bit11 RPRT_FABRICNAME */
2397 lpfc_fdmi_port_attr_active_fc4type, /* bit12 RPRT_ACTIVE_FC4_TYPES */
2398 lpfc_fdmi_port_attr_port_state, /* bit13 RPRT_PORT_STATE */
2399 lpfc_fdmi_port_attr_num_disc, /* bit14 RPRT_DISC_PORT */
2400 lpfc_fdmi_port_attr_nportid, /* bit15 RPRT_PORT_ID */
2401 lpfc_fdmi_smart_attr_service, /* bit16 RPRT_SMART_SERVICE */
2402 lpfc_fdmi_smart_attr_guid, /* bit17 RPRT_SMART_GUID */
2403 lpfc_fdmi_smart_attr_version, /* bit18 RPRT_SMART_VERSION */
2404 lpfc_fdmi_smart_attr_model, /* bit19 RPRT_SMART_MODEL */
2405 lpfc_fdmi_smart_attr_port_info, /* bit20 RPRT_SMART_PORT_INFO */
2406 lpfc_fdmi_smart_attr_qos, /* bit21 RPRT_SMART_QOS */
2407 lpfc_fdmi_smart_attr_security, /* bit22 RPRT_SMART_SECURITY */
2408};
2409
2410/**
2411 * lpfc_fdmi_cmd - Build and send a FDMI cmd to the specified NPort
2412 * @vport: pointer to a host virtual N_Port data structure.
2413 * @ndlp: ndlp to send FDMI cmd to (if NULL use FDMI_DID)
2414 * cmdcode: FDMI command to send
2415 * mask: Mask of HBA or PORT Attributes to send
2416 *
2417 * Builds and sends a FDMI command using the CT subsystem.
2418 */
2419int
2420lpfc_fdmi_cmd(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
2421 int cmdcode, uint32_t new_mask)
dea31012005-04-17 16:05:31 -05002422{
James Smart2e0fef82007-06-17 19:56:36 -05002423 struct lpfc_hba *phba = vport->phba;
dea31012005-04-17 16:05:31 -05002424 struct lpfc_dmabuf *mp, *bmp;
2425 struct lpfc_sli_ct_request *CtReq;
2426 struct ulp_bde64 *bpl;
James Smart4258e982015-12-16 18:11:58 -05002427 uint32_t bit_pos;
dea31012005-04-17 16:05:31 -05002428 uint32_t size;
James Smart76b2c342015-04-07 15:07:19 -04002429 uint32_t rsp_size;
James Smart4258e982015-12-16 18:11:58 -05002430 uint32_t mask;
James Smart76b2c342015-04-07 15:07:19 -04002431 struct lpfc_fdmi_reg_hba *rh;
2432 struct lpfc_fdmi_port_entry *pe;
2433 struct lpfc_fdmi_reg_portattr *pab = NULL;
2434 struct lpfc_fdmi_attr_block *ab = NULL;
James Smart4258e982015-12-16 18:11:58 -05002435 int (*func)(struct lpfc_vport *vport, struct lpfc_fdmi_attr_def *ad);
2436 void (*cmpl)(struct lpfc_hba *, struct lpfc_iocbq *,
2437 struct lpfc_iocbq *);
dea31012005-04-17 16:05:31 -05002438
James Smart4258e982015-12-16 18:11:58 -05002439 if (!ndlp || !NLP_CHK_NODE_ACT(ndlp))
2440 return 0;
2441
2442 cmpl = lpfc_cmpl_ct_disc_fdmi; /* called from discovery */
dea31012005-04-17 16:05:31 -05002443
2444 /* fill in BDEs for command */
2445 /* Allocate buffer for command payload */
James Smart76b2c342015-04-07 15:07:19 -04002446 mp = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL);
dea31012005-04-17 16:05:31 -05002447 if (!mp)
2448 goto fdmi_cmd_exit;
2449
2450 mp->virt = lpfc_mbuf_alloc(phba, 0, &(mp->phys));
2451 if (!mp->virt)
2452 goto fdmi_cmd_free_mp;
2453
2454 /* Allocate buffer for Buffer ptr list */
James Smart76b2c342015-04-07 15:07:19 -04002455 bmp = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL);
dea31012005-04-17 16:05:31 -05002456 if (!bmp)
2457 goto fdmi_cmd_free_mpvirt;
2458
2459 bmp->virt = lpfc_mbuf_alloc(phba, 0, &(bmp->phys));
2460 if (!bmp->virt)
2461 goto fdmi_cmd_free_bmp;
2462
2463 INIT_LIST_HEAD(&mp->list);
2464 INIT_LIST_HEAD(&bmp->list);
2465
2466 /* FDMI request */
James Smarte8b62012007-08-02 11:10:09 -04002467 lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
2468 "0218 FDMI Request Data: x%x x%x x%x\n",
2469 vport->fc_flag, vport->port_state, cmdcode);
James Smart76b2c342015-04-07 15:07:19 -04002470 CtReq = (struct lpfc_sli_ct_request *)mp->virt;
dea31012005-04-17 16:05:31 -05002471
James Smart76b2c342015-04-07 15:07:19 -04002472 /* First populate the CT_IU preamble */
dea31012005-04-17 16:05:31 -05002473 memset(CtReq, 0, sizeof(struct lpfc_sli_ct_request));
2474 CtReq->RevisionId.bits.Revision = SLI_CT_REVISION;
2475 CtReq->RevisionId.bits.InId = 0;
2476
2477 CtReq->FsType = SLI_CT_MANAGEMENT_SERVICE;
2478 CtReq->FsSubType = SLI_CT_FDMI_Subtypes;
James Smart76b2c342015-04-07 15:07:19 -04002479
2480 CtReq->CommandResponse.bits.CmdRsp = cpu_to_be16(cmdcode);
2481 rsp_size = LPFC_BPL_SIZE;
dea31012005-04-17 16:05:31 -05002482 size = 0;
2483
James Smart76b2c342015-04-07 15:07:19 -04002484 /* Next fill in the specific FDMI cmd information */
dea31012005-04-17 16:05:31 -05002485 switch (cmdcode) {
James Smart76b2c342015-04-07 15:07:19 -04002486 case SLI_MGMT_RHAT:
dea31012005-04-17 16:05:31 -05002487 case SLI_MGMT_RHBA:
James Smart4258e982015-12-16 18:11:58 -05002488 rh = (struct lpfc_fdmi_reg_hba *)&CtReq->un.PortID;
2489 /* HBA Identifier */
2490 memcpy(&rh->hi.PortName, &phba->pport->fc_sparam.portName,
2491 sizeof(struct lpfc_name));
dea31012005-04-17 16:05:31 -05002492
James Smart4258e982015-12-16 18:11:58 -05002493 if (cmdcode == SLI_MGMT_RHBA) {
2494 /* Registered Port List */
2495 /* One entry (port) per adapter */
2496 rh->rpl.EntryCnt = cpu_to_be32(1);
2497 memcpy(&rh->rpl.pe, &phba->pport->fc_sparam.portName,
James Smart76b2c342015-04-07 15:07:19 -04002498 sizeof(struct lpfc_name));
dea31012005-04-17 16:05:31 -05002499
James Smart4258e982015-12-16 18:11:58 -05002500 /* point to the HBA attribute block */
2501 size = 2 * sizeof(struct lpfc_name) +
2502 FOURBYTES;
2503 } else {
2504 size = sizeof(struct lpfc_name);
dea31012005-04-17 16:05:31 -05002505 }
James Smart4258e982015-12-16 18:11:58 -05002506 ab = (struct lpfc_fdmi_attr_block *)((uint8_t *)rh + size);
2507 ab->EntryCnt = 0;
2508 size += FOURBYTES;
2509 bit_pos = 0;
2510 if (new_mask)
2511 mask = new_mask;
2512 else
2513 mask = vport->fdmi_hba_mask;
2514
2515 /* Mask will dictate what attributes to build in the request */
2516 while (mask) {
2517 if (mask & 0x1) {
2518 func = lpfc_fdmi_hba_action[bit_pos];
2519 size += func(vport,
2520 (struct lpfc_fdmi_attr_def *)
2521 ((uint8_t *)rh + size));
2522 ab->EntryCnt++;
2523 if ((size + 256) >
2524 (LPFC_BPL_SIZE - LPFC_CT_PREAMBLE))
2525 goto hba_out;
2526 }
2527 mask = mask >> 1;
2528 bit_pos++;
2529 }
2530hba_out:
2531 ab->EntryCnt = cpu_to_be32(ab->EntryCnt);
2532 /* Total size */
2533 size = GID_REQUEST_SZ - 4 + size;
dea31012005-04-17 16:05:31 -05002534 break;
2535
James Smart76b2c342015-04-07 15:07:19 -04002536 case SLI_MGMT_RPRT:
dea31012005-04-17 16:05:31 -05002537 case SLI_MGMT_RPA:
James Smart4258e982015-12-16 18:11:58 -05002538 pab = (struct lpfc_fdmi_reg_portattr *)&CtReq->un.PortID;
2539 if (cmdcode == SLI_MGMT_RPRT) {
2540 rh = (struct lpfc_fdmi_reg_hba *)pab;
2541 /* HBA Identifier */
2542 memcpy(&rh->hi.PortName,
2543 &phba->pport->fc_sparam.portName,
James Smart76b2c342015-04-07 15:07:19 -04002544 sizeof(struct lpfc_name));
James Smart4258e982015-12-16 18:11:58 -05002545 pab = (struct lpfc_fdmi_reg_portattr *)
2546 ((uint8_t *)pab + sizeof(struct lpfc_name));
dea31012005-04-17 16:05:31 -05002547 }
James Smart4258e982015-12-16 18:11:58 -05002548
2549 memcpy((uint8_t *)&pab->PortName,
2550 (uint8_t *)&vport->fc_sparam.portName,
2551 sizeof(struct lpfc_name));
2552 size += sizeof(struct lpfc_name) + FOURBYTES;
2553 pab->ab.EntryCnt = 0;
2554 bit_pos = 0;
2555 if (new_mask)
2556 mask = new_mask;
2557 else
2558 mask = vport->fdmi_port_mask;
2559
2560 /* Mask will dictate what attributes to build in the request */
2561 while (mask) {
2562 if (mask & 0x1) {
2563 func = lpfc_fdmi_port_action[bit_pos];
2564 size += func(vport,
2565 (struct lpfc_fdmi_attr_def *)
2566 ((uint8_t *)pab + size));
2567 pab->ab.EntryCnt++;
2568 if ((size + 256) >
2569 (LPFC_BPL_SIZE - LPFC_CT_PREAMBLE))
2570 goto port_out;
2571 }
2572 mask = mask >> 1;
2573 bit_pos++;
2574 }
2575port_out:
2576 pab->ab.EntryCnt = cpu_to_be32(pab->ab.EntryCnt);
2577 /* Total size */
2578 if (cmdcode == SLI_MGMT_RPRT)
2579 size += sizeof(struct lpfc_name);
2580 size = GID_REQUEST_SZ - 4 + size;
dea31012005-04-17 16:05:31 -05002581 break;
2582
James Smart76b2c342015-04-07 15:07:19 -04002583 case SLI_MGMT_GHAT:
2584 case SLI_MGMT_GRPL:
2585 rsp_size = FC_MAX_NS_RSP;
dea31012005-04-17 16:05:31 -05002586 case SLI_MGMT_DHBA:
James Smart76b2c342015-04-07 15:07:19 -04002587 case SLI_MGMT_DHAT:
2588 pe = (struct lpfc_fdmi_port_entry *)&CtReq->un.PortID;
2589 memcpy((uint8_t *)&pe->PortName,
2590 (uint8_t *)&vport->fc_sparam.portName,
2591 sizeof(struct lpfc_name));
2592 size = GID_REQUEST_SZ - 4 + sizeof(struct lpfc_name);
dea31012005-04-17 16:05:31 -05002593 break;
2594
James Smart76b2c342015-04-07 15:07:19 -04002595 case SLI_MGMT_GPAT:
2596 case SLI_MGMT_GPAS:
2597 rsp_size = FC_MAX_NS_RSP;
dea31012005-04-17 16:05:31 -05002598 case SLI_MGMT_DPRT:
James Smart76b2c342015-04-07 15:07:19 -04002599 case SLI_MGMT_DPA:
2600 pe = (struct lpfc_fdmi_port_entry *)&CtReq->un.PortID;
2601 memcpy((uint8_t *)&pe->PortName,
2602 (uint8_t *)&vport->fc_sparam.portName,
2603 sizeof(struct lpfc_name));
2604 size = GID_REQUEST_SZ - 4 + sizeof(struct lpfc_name);
dea31012005-04-17 16:05:31 -05002605 break;
James Smart76b2c342015-04-07 15:07:19 -04002606 case SLI_MGMT_GRHL:
2607 size = GID_REQUEST_SZ - 4;
2608 break;
2609 default:
2610 lpfc_printf_vlog(vport, KERN_WARNING, LOG_DISCOVERY,
2611 "0298 FDMI cmdcode x%x not supported\n",
2612 cmdcode);
2613 goto fdmi_cmd_free_bmpvirt;
dea31012005-04-17 16:05:31 -05002614 }
James Smart76b2c342015-04-07 15:07:19 -04002615 CtReq->CommandResponse.bits.Size = cpu_to_be16(rsp_size);
dea31012005-04-17 16:05:31 -05002616
James Smart76b2c342015-04-07 15:07:19 -04002617 bpl = (struct ulp_bde64 *)bmp->virt;
2618 bpl->addrHigh = le32_to_cpu(putPaddrHigh(mp->phys));
2619 bpl->addrLow = le32_to_cpu(putPaddrLow(mp->phys));
dea31012005-04-17 16:05:31 -05002620 bpl->tus.f.bdeFlags = 0;
2621 bpl->tus.f.bdeSize = size;
dea31012005-04-17 16:05:31 -05002622
James Smart76b2c342015-04-07 15:07:19 -04002623 /*
2624 * The lpfc_ct_cmd/lpfc_get_req shall increment ndlp reference count
James Smarte47c9092008-02-08 18:49:26 -05002625 * to hold ndlp reference for the corresponding callback function.
2626 */
James Smart76b2c342015-04-07 15:07:19 -04002627 if (!lpfc_ct_cmd(vport, mp, bmp, ndlp, cmpl, rsp_size, 0))
dea31012005-04-17 16:05:31 -05002628 return 0;
2629
James Smart76b2c342015-04-07 15:07:19 -04002630 /*
2631 * Decrement ndlp reference count to release ndlp reference held
James Smarte47c9092008-02-08 18:49:26 -05002632 * for the failed command's callback function.
2633 */
James Smart51ef4c22007-08-02 11:10:31 -04002634 lpfc_nlp_put(ndlp);
James Smarte47c9092008-02-08 18:49:26 -05002635
James Smart76b2c342015-04-07 15:07:19 -04002636fdmi_cmd_free_bmpvirt:
dea31012005-04-17 16:05:31 -05002637 lpfc_mbuf_free(phba, bmp->virt, bmp->phys);
2638fdmi_cmd_free_bmp:
2639 kfree(bmp);
2640fdmi_cmd_free_mpvirt:
2641 lpfc_mbuf_free(phba, mp->virt, mp->phys);
2642fdmi_cmd_free_mp:
2643 kfree(mp);
2644fdmi_cmd_exit:
2645 /* Issue FDMI request failed */
James Smarte8b62012007-08-02 11:10:09 -04002646 lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
2647 "0244 Issue FDMI request failed Data: x%x\n",
2648 cmdcode);
dea31012005-04-17 16:05:31 -05002649 return 1;
2650}
2651
James Smart92494142011-02-16 12:39:44 -05002652/**
2653 * lpfc_delayed_disc_tmo - Timeout handler for delayed discovery timer.
2654 * @ptr - Context object of the timer.
2655 *
2656 * This function set the WORKER_DELAYED_DISC_TMO flag and wake up
2657 * the worker thread.
2658 **/
2659void
2660lpfc_delayed_disc_tmo(unsigned long ptr)
2661{
2662 struct lpfc_vport *vport = (struct lpfc_vport *)ptr;
2663 struct lpfc_hba *phba = vport->phba;
2664 uint32_t tmo_posted;
2665 unsigned long iflag;
2666
2667 spin_lock_irqsave(&vport->work_port_lock, iflag);
2668 tmo_posted = vport->work_port_events & WORKER_DELAYED_DISC_TMO;
2669 if (!tmo_posted)
2670 vport->work_port_events |= WORKER_DELAYED_DISC_TMO;
2671 spin_unlock_irqrestore(&vport->work_port_lock, iflag);
2672
2673 if (!tmo_posted)
2674 lpfc_worker_wake_up(phba);
2675 return;
2676}
2677
2678/**
2679 * lpfc_delayed_disc_timeout_handler - Function called by worker thread to
2680 * handle delayed discovery.
2681 * @vport: pointer to a host virtual N_Port data structure.
2682 *
2683 * This function start nport discovery of the vport.
2684 **/
2685void
2686lpfc_delayed_disc_timeout_handler(struct lpfc_vport *vport)
2687{
2688 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
2689
2690 spin_lock_irq(shost->host_lock);
2691 if (!(vport->fc_flag & FC_DISC_DELAYED)) {
2692 spin_unlock_irq(shost->host_lock);
2693 return;
2694 }
2695 vport->fc_flag &= ~FC_DISC_DELAYED;
2696 spin_unlock_irq(shost->host_lock);
2697
2698 lpfc_do_scr_ns_plogi(vport->phba, vport);
2699}
2700
dea31012005-04-17 16:05:31 -05002701void
James Smart2e0fef82007-06-17 19:56:36 -05002702lpfc_decode_firmware_rev(struct lpfc_hba *phba, char *fwrevision, int flag)
dea31012005-04-17 16:05:31 -05002703{
2704 struct lpfc_sli *psli = &phba->sli;
2705 lpfc_vpd_t *vp = &phba->vpd;
2706 uint32_t b1, b2, b3, b4, i, rev;
2707 char c;
2708 uint32_t *ptr, str[4];
2709 uint8_t *fwname;
2710
James Smartf1126682009-06-10 17:22:44 -04002711 if (phba->sli_rev == LPFC_SLI_REV4)
James Smart6b5151f2012-01-18 16:24:06 -05002712 snprintf(fwrevision, FW_REV_STR_SIZE, "%s", vp->rev.opFwName);
James Smartf1126682009-06-10 17:22:44 -04002713 else if (vp->rev.rBit) {
James Smartf4b4c682009-05-22 14:53:12 -04002714 if (psli->sli_flag & LPFC_SLI_ACTIVE)
dea31012005-04-17 16:05:31 -05002715 rev = vp->rev.sli2FwRev;
2716 else
2717 rev = vp->rev.sli1FwRev;
2718
2719 b1 = (rev & 0x0000f000) >> 12;
2720 b2 = (rev & 0x00000f00) >> 8;
2721 b3 = (rev & 0x000000c0) >> 6;
2722 b4 = (rev & 0x00000030) >> 4;
2723
2724 switch (b4) {
2725 case 0:
2726 c = 'N';
2727 break;
2728 case 1:
2729 c = 'A';
2730 break;
2731 case 2:
2732 c = 'B';
2733 break;
James Smart73d91e52011-10-10 21:32:10 -04002734 case 3:
2735 c = 'X';
2736 break;
dea31012005-04-17 16:05:31 -05002737 default:
2738 c = 0;
2739 break;
2740 }
2741 b4 = (rev & 0x0000000f);
2742
James Smartf4b4c682009-05-22 14:53:12 -04002743 if (psli->sli_flag & LPFC_SLI_ACTIVE)
dea31012005-04-17 16:05:31 -05002744 fwname = vp->rev.sli2FwName;
2745 else
2746 fwname = vp->rev.sli1FwName;
2747
2748 for (i = 0; i < 16; i++)
2749 if (fwname[i] == 0x20)
2750 fwname[i] = 0;
2751
2752 ptr = (uint32_t*)fwname;
2753
2754 for (i = 0; i < 3; i++)
2755 str[i] = be32_to_cpu(*ptr++);
2756
2757 if (c == 0) {
2758 if (flag)
2759 sprintf(fwrevision, "%d.%d%d (%s)",
2760 b1, b2, b3, (char *)str);
2761 else
2762 sprintf(fwrevision, "%d.%d%d", b1,
2763 b2, b3);
2764 } else {
2765 if (flag)
2766 sprintf(fwrevision, "%d.%d%d%c%d (%s)",
2767 b1, b2, b3, c,
2768 b4, (char *)str);
2769 else
2770 sprintf(fwrevision, "%d.%d%d%c%d",
2771 b1, b2, b3, c, b4);
2772 }
2773 } else {
2774 rev = vp->rev.smFwRev;
2775
2776 b1 = (rev & 0xff000000) >> 24;
2777 b2 = (rev & 0x00f00000) >> 20;
2778 b3 = (rev & 0x000f0000) >> 16;
2779 c = (rev & 0x0000ff00) >> 8;
2780 b4 = (rev & 0x000000ff);
2781
Roel Kluind44a6d22010-01-17 16:15:57 +01002782 sprintf(fwrevision, "%d.%d%d%c%d", b1, b2, b3, c, b4);
dea31012005-04-17 16:05:31 -05002783 }
2784 return;
2785}