blob: 4e36998a266c364d9cf0d1de423386978bb618fa [file] [log] [blame]
James Smart92d7f7b2007-06-17 19:56:38 -05001/*******************************************************************
2 * This file is part of the Emulex Linux Device Driver for *
3 * Fibre Channel Host Bus Adapters. *
James Smart50611572016-03-31 14:12:34 -07004 * Copyright (C) 2004-2016 Emulex. All rights reserved. *
James Smart92d7f7b2007-06-17 19:56:38 -05005 * EMULEX and SLI are trademarks of Emulex. *
6 * www.emulex.com *
7 * Portions Copyright (C) 2004-2005 Christoph Hellwig *
8 * *
9 * This program is free software; you can redistribute it and/or *
10 * modify it under the terms of version 2 of the GNU General *
11 * Public License as published by the Free Software Foundation. *
12 * This program is distributed in the hope that it will be useful. *
13 * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND *
14 * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, *
15 * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE *
16 * DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD *
17 * TO BE LEGALLY INVALID. See the GNU General Public License for *
18 * more details, a copy of which can be found in the file COPYING *
19 * included with this package. *
20 *******************************************************************/
21
22#include <linux/blkdev.h>
23#include <linux/delay.h>
24#include <linux/dma-mapping.h>
25#include <linux/idr.h>
26#include <linux/interrupt.h>
27#include <linux/kthread.h>
28#include <linux/pci.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090029#include <linux/slab.h>
James Smart92d7f7b2007-06-17 19:56:38 -050030#include <linux/spinlock.h>
Ingo Molnar174cd4b2017-02-02 19:15:33 +010031#include <linux/sched/signal.h>
James Smart92d7f7b2007-06-17 19:56:38 -050032
33#include <scsi/scsi.h>
34#include <scsi/scsi_device.h>
35#include <scsi/scsi_host.h>
36#include <scsi/scsi_transport_fc.h>
James Smartda0436e2009-05-22 14:51:39 -040037#include "lpfc_hw4.h"
James Smart92d7f7b2007-06-17 19:56:38 -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"
James Smart92d7f7b2007-06-17 19:56:38 -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"
48#include "lpfc_vport.h"
49
50inline void lpfc_vport_set_state(struct lpfc_vport *vport,
51 enum fc_vport_state new_state)
52{
53 struct fc_vport *fc_vport = vport->fc_vport;
54
55 if (fc_vport) {
56 /*
57 * When the transport defines fc_vport_set state we will replace
58 * this code with the following line
59 */
60 /* fc_vport_set_state(fc_vport, new_state); */
61 if (new_state != FC_VPORT_INITIALIZING)
62 fc_vport->vport_last_state = fc_vport->vport_state;
63 fc_vport->vport_state = new_state;
64 }
65
66 /* for all the error states we will set the invternal state to FAILED */
67 switch (new_state) {
68 case FC_VPORT_NO_FABRIC_SUPP:
69 case FC_VPORT_NO_FABRIC_RSCS:
70 case FC_VPORT_FABRIC_LOGOUT:
71 case FC_VPORT_FABRIC_REJ_WWN:
72 case FC_VPORT_FAILED:
73 vport->port_state = LPFC_VPORT_FAILED;
74 break;
75 case FC_VPORT_LINKDOWN:
76 vport->port_state = LPFC_VPORT_UNKNOWN;
77 break;
78 default:
79 /* do nothing */
80 break;
81 }
82}
83
James Smart16a3a202013-04-17 20:14:38 -040084int
James Smart92d7f7b2007-06-17 19:56:38 -050085lpfc_alloc_vpi(struct lpfc_hba *phba)
86{
James Smart6d368e52011-05-24 11:44:12 -040087 unsigned long vpi;
James Smart92d7f7b2007-06-17 19:56:38 -050088
89 spin_lock_irq(&phba->hbalock);
James Smart858c9f62007-06-17 19:56:39 -050090 /* Start at bit 1 because vpi zero is reserved for the physical port */
91 vpi = find_next_zero_bit(phba->vpi_bmask, (phba->max_vpi + 1), 1);
James Smart92d7f7b2007-06-17 19:56:38 -050092 if (vpi > phba->max_vpi)
93 vpi = 0;
94 else
95 set_bit(vpi, phba->vpi_bmask);
James Smartda0436e2009-05-22 14:51:39 -040096 if (phba->sli_rev == LPFC_SLI_REV4)
97 phba->sli4_hba.max_cfg_param.vpi_used++;
James Smart92d7f7b2007-06-17 19:56:38 -050098 spin_unlock_irq(&phba->hbalock);
99 return vpi;
100}
101
102static void
103lpfc_free_vpi(struct lpfc_hba *phba, int vpi)
104{
James Smartda0436e2009-05-22 14:51:39 -0400105 if (vpi == 0)
106 return;
James Smart92d7f7b2007-06-17 19:56:38 -0500107 spin_lock_irq(&phba->hbalock);
108 clear_bit(vpi, phba->vpi_bmask);
James Smartda0436e2009-05-22 14:51:39 -0400109 if (phba->sli_rev == LPFC_SLI_REV4)
110 phba->sli4_hba.max_cfg_param.vpi_used--;
James Smart92d7f7b2007-06-17 19:56:38 -0500111 spin_unlock_irq(&phba->hbalock);
112}
113
114static int
115lpfc_vport_sparm(struct lpfc_hba *phba, struct lpfc_vport *vport)
116{
117 LPFC_MBOXQ_t *pmb;
118 MAILBOX_t *mb;
119 struct lpfc_dmabuf *mp;
120 int rc;
121
122 pmb = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
123 if (!pmb) {
124 return -ENOMEM;
125 }
James Smartf4b4c682009-05-22 14:53:12 -0400126 mb = &pmb->u.mb;
James Smart92d7f7b2007-06-17 19:56:38 -0500127
James Smart9f1177a2010-02-26 14:12:57 -0500128 rc = lpfc_read_sparam(phba, pmb, vport->vpi);
129 if (rc) {
130 mempool_free(pmb, phba->mbox_mem_pool);
131 return -ENOMEM;
132 }
133
James Smart92d7f7b2007-06-17 19:56:38 -0500134 /*
135 * Grab buffer pointer and clear context1 so we can use
136 * lpfc_sli_issue_box_wait
137 */
138 mp = (struct lpfc_dmabuf *) pmb->context1;
139 pmb->context1 = NULL;
140
141 pmb->vport = vport;
142 rc = lpfc_sli_issue_mbox_wait(phba, pmb, phba->fc_ratov * 2);
143 if (rc != MBX_SUCCESS) {
James Smart98c9ea52007-10-27 13:37:33 -0400144 if (signal_pending(current)) {
145 lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT | LOG_VPORT,
146 "1830 Signal aborted mbxCmd x%x\n",
147 mb->mbxCommand);
148 lpfc_mbuf_free(phba, mp->virt, mp->phys);
149 kfree(mp);
150 if (rc != MBX_TIMEOUT)
151 mempool_free(pmb, phba->mbox_mem_pool);
152 return -EINTR;
153 } else {
154 lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT | LOG_VPORT,
155 "1818 VPort failed init, mbxCmd x%x "
156 "READ_SPARM mbxStatus x%x, rc = x%x\n",
157 mb->mbxCommand, mb->mbxStatus, rc);
158 lpfc_mbuf_free(phba, mp->virt, mp->phys);
159 kfree(mp);
160 if (rc != MBX_TIMEOUT)
161 mempool_free(pmb, phba->mbox_mem_pool);
162 return -EIO;
163 }
James Smart92d7f7b2007-06-17 19:56:38 -0500164 }
165
166 memcpy(&vport->fc_sparam, mp->virt, sizeof (struct serv_parm));
167 memcpy(&vport->fc_nodename, &vport->fc_sparam.nodeName,
168 sizeof (struct lpfc_name));
169 memcpy(&vport->fc_portname, &vport->fc_sparam.portName,
170 sizeof (struct lpfc_name));
171
172 lpfc_mbuf_free(phba, mp->virt, mp->phys);
173 kfree(mp);
174 mempool_free(pmb, phba->mbox_mem_pool);
175
176 return 0;
177}
178
179static int
180lpfc_valid_wwn_format(struct lpfc_hba *phba, struct lpfc_name *wwn,
181 const char *name_type)
182{
183 /* ensure that IEEE format 1 addresses
184 * contain zeros in bits 59-48
185 */
186 if (!((wwn->u.wwn[0] >> 4) == 1 &&
187 ((wwn->u.wwn[0] & 0xf) != 0 || (wwn->u.wwn[1] & 0xf) != 0)))
188 return 1;
189
190 lpfc_printf_log(phba, KERN_ERR, LOG_VPORT,
James Smarte8b62012007-08-02 11:10:09 -0400191 "1822 Invalid %s: %02x:%02x:%02x:%02x:"
James Smart92d7f7b2007-06-17 19:56:38 -0500192 "%02x:%02x:%02x:%02x\n",
James Smarte8b62012007-08-02 11:10:09 -0400193 name_type,
James Smart92d7f7b2007-06-17 19:56:38 -0500194 wwn->u.wwn[0], wwn->u.wwn[1],
195 wwn->u.wwn[2], wwn->u.wwn[3],
196 wwn->u.wwn[4], wwn->u.wwn[5],
197 wwn->u.wwn[6], wwn->u.wwn[7]);
198 return 0;
199}
200
201static int
202lpfc_unique_wwpn(struct lpfc_hba *phba, struct lpfc_vport *new_vport)
203{
204 struct lpfc_vport *vport;
James Smart549e55c2007-08-02 11:09:51 -0400205 unsigned long flags;
James Smart92d7f7b2007-06-17 19:56:38 -0500206
James Smart549e55c2007-08-02 11:09:51 -0400207 spin_lock_irqsave(&phba->hbalock, flags);
James Smart92d7f7b2007-06-17 19:56:38 -0500208 list_for_each_entry(vport, &phba->port_list, listentry) {
209 if (vport == new_vport)
210 continue;
211 /* If they match, return not unique */
212 if (memcmp(&vport->fc_sparam.portName,
James Smart549e55c2007-08-02 11:09:51 -0400213 &new_vport->fc_sparam.portName,
214 sizeof(struct lpfc_name)) == 0) {
215 spin_unlock_irqrestore(&phba->hbalock, flags);
James Smart92d7f7b2007-06-17 19:56:38 -0500216 return 0;
James Smart549e55c2007-08-02 11:09:51 -0400217 }
James Smart92d7f7b2007-06-17 19:56:38 -0500218 }
James Smart549e55c2007-08-02 11:09:51 -0400219 spin_unlock_irqrestore(&phba->hbalock, flags);
James Smart92d7f7b2007-06-17 19:56:38 -0500220 return 1;
221}
222
James Smart90160e02008-08-24 21:49:45 -0400223/**
James Smart3621a712009-04-06 18:47:14 -0400224 * lpfc_discovery_wait - Wait for driver discovery to quiesce
James Smart90160e02008-08-24 21:49:45 -0400225 * @vport: The virtual port for which this call is being executed.
226 *
227 * This driver calls this routine specifically from lpfc_vport_delete
228 * to enforce a synchronous execution of vport
229 * delete relative to discovery activities. The
230 * lpfc_vport_delete routine should not return until it
231 * can reasonably guarantee that discovery has quiesced.
232 * Post FDISC LOGO, the driver must wait until its SAN teardown is
233 * complete and all resources recovered before allowing
234 * cleanup.
235 *
236 * This routine does not require any locks held.
237 **/
238static void lpfc_discovery_wait(struct lpfc_vport *vport)
239{
240 struct lpfc_hba *phba = vport->phba;
241 uint32_t wait_flags = 0;
242 unsigned long wait_time_max;
243 unsigned long start_time;
244
245 wait_flags = FC_RSCN_MODE | FC_RSCN_DISCOVERY | FC_NLP_MORE |
246 FC_RSCN_DEFERRED | FC_NDISC_ACTIVE | FC_DISC_TMO;
247
248 /*
249 * The time constraint on this loop is a balance between the
250 * fabric RA_TOV value and dev_loss tmo. The driver's
251 * devloss_tmo is 10 giving this loop a 3x multiplier minimally.
252 */
253 wait_time_max = msecs_to_jiffies(((phba->fc_ratov * 3) + 3) * 1000);
254 wait_time_max += jiffies;
255 start_time = jiffies;
256 while (time_before(jiffies, wait_time_max)) {
257 if ((vport->num_disc_nodes > 0) ||
258 (vport->fc_flag & wait_flags) ||
259 ((vport->port_state > LPFC_VPORT_FAILED) &&
260 (vport->port_state < LPFC_VPORT_READY))) {
James Smart21e9a0a2009-05-22 14:53:21 -0400261 lpfc_printf_vlog(vport, KERN_INFO, LOG_VPORT,
James Smart90160e02008-08-24 21:49:45 -0400262 "1833 Vport discovery quiesce Wait:"
James Smart21e9a0a2009-05-22 14:53:21 -0400263 " state x%x fc_flags x%x"
James Smart90160e02008-08-24 21:49:45 -0400264 " num_nodes x%x, waiting 1000 msecs"
265 " total wait msecs x%x\n",
James Smart21e9a0a2009-05-22 14:53:21 -0400266 vport->port_state, vport->fc_flag,
267 vport->num_disc_nodes,
James Smart90160e02008-08-24 21:49:45 -0400268 jiffies_to_msecs(jiffies - start_time));
269 msleep(1000);
270 } else {
271 /* Base case. Wait variants satisfied. Break out */
James Smart21e9a0a2009-05-22 14:53:21 -0400272 lpfc_printf_vlog(vport, KERN_INFO, LOG_VPORT,
James Smart90160e02008-08-24 21:49:45 -0400273 "1834 Vport discovery quiesced:"
James Smart21e9a0a2009-05-22 14:53:21 -0400274 " state x%x fc_flags x%x"
James Smart90160e02008-08-24 21:49:45 -0400275 " wait msecs x%x\n",
James Smart21e9a0a2009-05-22 14:53:21 -0400276 vport->port_state, vport->fc_flag,
James Smart90160e02008-08-24 21:49:45 -0400277 jiffies_to_msecs(jiffies
278 - start_time));
279 break;
280 }
281 }
282
283 if (time_after(jiffies, wait_time_max))
James Smart21e9a0a2009-05-22 14:53:21 -0400284 lpfc_printf_vlog(vport, KERN_ERR, LOG_VPORT,
James Smart90160e02008-08-24 21:49:45 -0400285 "1835 Vport discovery quiesce failed:"
James Smart21e9a0a2009-05-22 14:53:21 -0400286 " state x%x fc_flags x%x wait msecs x%x\n",
287 vport->port_state, vport->fc_flag,
James Smart90160e02008-08-24 21:49:45 -0400288 jiffies_to_msecs(jiffies - start_time));
289}
290
James Smart92d7f7b2007-06-17 19:56:38 -0500291int
292lpfc_vport_create(struct fc_vport *fc_vport, bool disable)
293{
294 struct lpfc_nodelist *ndlp;
James Smart3de2a652007-08-02 11:09:59 -0400295 struct Scsi_Host *shost = fc_vport->shost;
296 struct lpfc_vport *pport = (struct lpfc_vport *) shost->hostdata;
James Smart92d7f7b2007-06-17 19:56:38 -0500297 struct lpfc_hba *phba = pport->phba;
298 struct lpfc_vport *vport = NULL;
299 int instance;
300 int vpi;
301 int rc = VPORT_ERROR;
James Smart98c9ea52007-10-27 13:37:33 -0400302 int status;
James Smart92d7f7b2007-06-17 19:56:38 -0500303
James Smarteada2722008-12-04 22:39:13 -0500304 if ((phba->sli_rev < 3) || !(phba->cfg_enable_npiv)) {
James Smart92d7f7b2007-06-17 19:56:38 -0500305 lpfc_printf_log(phba, KERN_ERR, LOG_VPORT,
James Smarte8b62012007-08-02 11:10:09 -0400306 "1808 Create VPORT failed: "
James Smart92d7f7b2007-06-17 19:56:38 -0500307 "NPIV is not enabled: SLImode:%d\n",
James Smarte8b62012007-08-02 11:10:09 -0400308 phba->sli_rev);
James Smart92d7f7b2007-06-17 19:56:38 -0500309 rc = VPORT_INVAL;
310 goto error_out;
311 }
312
313 vpi = lpfc_alloc_vpi(phba);
314 if (vpi == 0) {
315 lpfc_printf_log(phba, KERN_ERR, LOG_VPORT,
James Smarte8b62012007-08-02 11:10:09 -0400316 "1809 Create VPORT failed: "
James Smart92d7f7b2007-06-17 19:56:38 -0500317 "Max VPORTs (%d) exceeded\n",
James Smarte8b62012007-08-02 11:10:09 -0400318 phba->max_vpi);
James Smart92d7f7b2007-06-17 19:56:38 -0500319 rc = VPORT_NORESOURCES;
320 goto error_out;
321 }
322
James Smart92d7f7b2007-06-17 19:56:38 -0500323 /* Assign an unused board number */
324 if ((instance = lpfc_get_instance()) < 0) {
325 lpfc_printf_log(phba, KERN_ERR, LOG_VPORT,
James Smarte8b62012007-08-02 11:10:09 -0400326 "1810 Create VPORT failed: Cannot get "
327 "instance number\n");
James Smart92d7f7b2007-06-17 19:56:38 -0500328 lpfc_free_vpi(phba, vpi);
329 rc = VPORT_NORESOURCES;
330 goto error_out;
331 }
332
James Smart3de2a652007-08-02 11:09:59 -0400333 vport = lpfc_create_port(phba, instance, &fc_vport->dev);
James Smart92d7f7b2007-06-17 19:56:38 -0500334 if (!vport) {
335 lpfc_printf_log(phba, KERN_ERR, LOG_VPORT,
James Smarte8b62012007-08-02 11:10:09 -0400336 "1811 Create VPORT failed: vpi x%x\n", vpi);
James Smart92d7f7b2007-06-17 19:56:38 -0500337 lpfc_free_vpi(phba, vpi);
338 rc = VPORT_NORESOURCES;
339 goto error_out;
340 }
341
342 vport->vpi = vpi;
James Smart858c9f62007-06-17 19:56:39 -0500343 lpfc_debugfs_initialize(vport);
344
James Smart98c9ea52007-10-27 13:37:33 -0400345 if ((status = lpfc_vport_sparm(phba, vport))) {
346 if (status == -EINTR) {
347 lpfc_printf_vlog(vport, KERN_ERR, LOG_VPORT,
348 "1831 Create VPORT Interrupted.\n");
349 rc = VPORT_ERROR;
350 } else {
351 lpfc_printf_vlog(vport, KERN_ERR, LOG_VPORT,
352 "1813 Create VPORT failed. "
353 "Cannot get sparam\n");
354 rc = VPORT_NORESOURCES;
355 }
James Smart92d7f7b2007-06-17 19:56:38 -0500356 lpfc_free_vpi(phba, vpi);
357 destroy_port(vport);
James Smart92d7f7b2007-06-17 19:56:38 -0500358 goto error_out;
359 }
360
James Smart1c6834a2009-07-19 10:01:26 -0400361 u64_to_wwn(fc_vport->node_name, vport->fc_nodename.u.wwn);
362 u64_to_wwn(fc_vport->port_name, vport->fc_portname.u.wwn);
James Smart92d7f7b2007-06-17 19:56:38 -0500363
364 memcpy(&vport->fc_sparam.portName, vport->fc_portname.u.wwn, 8);
365 memcpy(&vport->fc_sparam.nodeName, vport->fc_nodename.u.wwn, 8);
366
367 if (!lpfc_valid_wwn_format(phba, &vport->fc_sparam.nodeName, "WWNN") ||
368 !lpfc_valid_wwn_format(phba, &vport->fc_sparam.portName, "WWPN")) {
James Smarte8b62012007-08-02 11:10:09 -0400369 lpfc_printf_vlog(vport, KERN_ERR, LOG_VPORT,
370 "1821 Create VPORT failed. "
371 "Invalid WWN format\n");
James Smart92d7f7b2007-06-17 19:56:38 -0500372 lpfc_free_vpi(phba, vpi);
373 destroy_port(vport);
374 rc = VPORT_INVAL;
375 goto error_out;
376 }
377
378 if (!lpfc_unique_wwpn(phba, vport)) {
James Smarte8b62012007-08-02 11:10:09 -0400379 lpfc_printf_vlog(vport, KERN_ERR, LOG_VPORT,
380 "1823 Create VPORT failed. "
381 "Duplicate WWN on HBA\n");
James Smart92d7f7b2007-06-17 19:56:38 -0500382 lpfc_free_vpi(phba, vpi);
383 destroy_port(vport);
384 rc = VPORT_INVAL;
385 goto error_out;
386 }
387
James Smarteada2722008-12-04 22:39:13 -0500388 /* Create binary sysfs attribute for vport */
389 lpfc_alloc_sysfs_attr(vport);
390
James Smart572709e2013-07-15 18:32:43 -0400391 /* Set the DFT_LUN_Q_DEPTH accordingly */
392 vport->cfg_lun_queue_depth = phba->pport->cfg_lun_queue_depth;
393
James Smart92d7f7b2007-06-17 19:56:38 -0500394 *(struct lpfc_vport **)fc_vport->dd_data = vport;
395 vport->fc_vport = fc_vport;
396
James Smart4258e982015-12-16 18:11:58 -0500397 /* At this point we are fully registered with SCSI Layer. */
398 vport->load_flag |= FC_ALLOW_FDMI;
James Smart8663cbb2016-03-31 14:12:33 -0700399 if (phba->cfg_enable_SmartSAN ||
400 (phba->cfg_fdmi_on == LPFC_FDMI_SUPPORT)) {
James Smart4258e982015-12-16 18:11:58 -0500401 /* Setup appropriate attribute masks */
402 vport->fdmi_hba_mask = phba->pport->fdmi_hba_mask;
403 vport->fdmi_port_mask = phba->pport->fdmi_port_mask;
404 }
405
James Smart1c6834a2009-07-19 10:01:26 -0400406 /*
407 * In SLI4, the vpi must be activated before it can be used
408 * by the port.
409 */
410 if ((phba->sli_rev == LPFC_SLI_REV4) &&
James Smart76a95d72010-11-20 23:11:48 -0500411 (pport->fc_flag & FC_VFI_REGISTERED)) {
412 rc = lpfc_sli4_init_vpi(vport);
James Smart1c6834a2009-07-19 10:01:26 -0400413 if (rc) {
414 lpfc_printf_log(phba, KERN_ERR, LOG_VPORT,
415 "1838 Failed to INIT_VPI on vpi %d "
416 "status %d\n", vpi, rc);
417 rc = VPORT_NORESOURCES;
418 lpfc_free_vpi(phba, vpi);
419 goto error_out;
420 }
421 } else if (phba->sli_rev == LPFC_SLI_REV4) {
422 /*
423 * Driver cannot INIT_VPI now. Set the flags to
424 * init_vpi when reg_vfi complete.
425 */
426 vport->fc_flag |= FC_VPORT_NEEDS_INIT_VPI;
427 lpfc_vport_set_state(vport, FC_VPORT_LINKDOWN);
428 rc = VPORT_OK;
429 goto out;
430 }
431
James Smart92d7f7b2007-06-17 19:56:38 -0500432 if ((phba->link_state < LPFC_LINK_UP) ||
James Smart1c6834a2009-07-19 10:01:26 -0400433 (pport->port_state < LPFC_FABRIC_CFG_LINK) ||
James Smart76a95d72010-11-20 23:11:48 -0500434 (phba->fc_topology == LPFC_TOPOLOGY_LOOP)) {
James Smart92d7f7b2007-06-17 19:56:38 -0500435 lpfc_vport_set_state(vport, FC_VPORT_LINKDOWN);
436 rc = VPORT_OK;
437 goto out;
438 }
439
440 if (disable) {
James Smarteada2722008-12-04 22:39:13 -0500441 lpfc_vport_set_state(vport, FC_VPORT_DISABLED);
James Smart92d7f7b2007-06-17 19:56:38 -0500442 rc = VPORT_OK;
443 goto out;
444 }
445
446 /* Use the Physical nodes Fabric NDLP to determine if the link is
447 * up and ready to FDISC.
448 */
449 ndlp = lpfc_findnode_did(phba->pport, Fabric_DID);
James Smarte47c9092008-02-08 18:49:26 -0500450 if (ndlp && NLP_CHK_NODE_ACT(ndlp) &&
451 ndlp->nlp_state == NLP_STE_UNMAPPED_NODE) {
James Smart858c9f62007-06-17 19:56:39 -0500452 if (phba->link_flag & LS_NPIV_FAB_SUPPORTED) {
453 lpfc_set_disctmo(vport);
454 lpfc_initial_fdisc(vport);
455 } else {
456 lpfc_vport_set_state(vport, FC_VPORT_NO_FABRIC_SUPP);
James Smarte8b62012007-08-02 11:10:09 -0400457 lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
458 "0262 No NPIV Fabric support\n");
James Smart858c9f62007-06-17 19:56:39 -0500459 }
James Smart92d7f7b2007-06-17 19:56:38 -0500460 } else {
461 lpfc_vport_set_state(vport, FC_VPORT_FAILED);
462 }
463 rc = VPORT_OK;
464
465out:
James Smarta58cbd52007-08-02 11:09:43 -0400466 lpfc_printf_vlog(vport, KERN_ERR, LOG_VPORT,
467 "1825 Vport Created.\n");
James Smart92d7f7b2007-06-17 19:56:38 -0500468 lpfc_host_attrib_init(lpfc_shost_from_vport(vport));
469error_out:
470 return rc;
471}
472
James Smart311464e2007-08-02 11:10:37 -0400473static int
James Smart92d7f7b2007-06-17 19:56:38 -0500474disable_vport(struct fc_vport *fc_vport)
475{
476 struct lpfc_vport *vport = *(struct lpfc_vport **)fc_vport->dd_data;
477 struct lpfc_hba *phba = vport->phba;
478 struct lpfc_nodelist *ndlp = NULL, *next_ndlp = NULL;
479 long timeout;
James Smartfedd3b72011-02-16 12:39:24 -0500480 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
James Smart92d7f7b2007-06-17 19:56:38 -0500481
482 ndlp = lpfc_findnode_did(vport, Fabric_DID);
James Smarte47c9092008-02-08 18:49:26 -0500483 if (ndlp && NLP_CHK_NODE_ACT(ndlp)
484 && phba->link_state >= LPFC_LINK_UP) {
James Smart92d7f7b2007-06-17 19:56:38 -0500485 vport->unreg_vpi_cmpl = VPORT_INVAL;
486 timeout = msecs_to_jiffies(phba->fc_ratov * 2000);
487 if (!lpfc_issue_els_npiv_logo(vport, ndlp))
488 while (vport->unreg_vpi_cmpl == VPORT_INVAL && timeout)
489 timeout = schedule_timeout(timeout);
490 }
491
492 lpfc_sli_host_down(vport);
493
494 /* Mark all nodes for discovery so we can remove them by
495 * calling lpfc_cleanup_rpis(vport, 1)
496 */
497 list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) {
James Smarte47c9092008-02-08 18:49:26 -0500498 if (!NLP_CHK_NODE_ACT(ndlp))
499 continue;
James Smart92d7f7b2007-06-17 19:56:38 -0500500 if (ndlp->nlp_state == NLP_STE_UNUSED_NODE)
501 continue;
502 lpfc_disc_state_machine(vport, ndlp, NULL,
503 NLP_EVT_DEVICE_RECOVERY);
504 }
505 lpfc_cleanup_rpis(vport, 1);
506
507 lpfc_stop_vport_timers(vport);
508 lpfc_unreg_all_rpis(vport);
509 lpfc_unreg_default_rpis(vport);
510 /*
511 * Completion of unreg_vpi (lpfc_mbx_cmpl_unreg_vpi) does the
512 * scsi_host_put() to release the vport.
513 */
514 lpfc_mbx_unreg_vpi(vport);
James Smartfedd3b72011-02-16 12:39:24 -0500515 spin_lock_irq(shost->host_lock);
516 vport->fc_flag |= FC_VPORT_NEEDS_INIT_VPI;
517 spin_unlock_irq(shost->host_lock);
James Smart92d7f7b2007-06-17 19:56:38 -0500518
519 lpfc_vport_set_state(vport, FC_VPORT_DISABLED);
James Smarta58cbd52007-08-02 11:09:43 -0400520 lpfc_printf_vlog(vport, KERN_ERR, LOG_VPORT,
521 "1826 Vport Disabled.\n");
James Smart92d7f7b2007-06-17 19:56:38 -0500522 return VPORT_OK;
523}
524
James Smart311464e2007-08-02 11:10:37 -0400525static int
James Smart92d7f7b2007-06-17 19:56:38 -0500526enable_vport(struct fc_vport *fc_vport)
527{
528 struct lpfc_vport *vport = *(struct lpfc_vport **)fc_vport->dd_data;
529 struct lpfc_hba *phba = vport->phba;
530 struct lpfc_nodelist *ndlp = NULL;
James Smart72100cc2010-02-12 14:43:01 -0500531 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
James Smart92d7f7b2007-06-17 19:56:38 -0500532
533 if ((phba->link_state < LPFC_LINK_UP) ||
James Smart76a95d72010-11-20 23:11:48 -0500534 (phba->fc_topology == LPFC_TOPOLOGY_LOOP)) {
James Smart92d7f7b2007-06-17 19:56:38 -0500535 lpfc_vport_set_state(vport, FC_VPORT_LINKDOWN);
536 return VPORT_OK;
537 }
538
James Smart72100cc2010-02-12 14:43:01 -0500539 spin_lock_irq(shost->host_lock);
James Smart92d7f7b2007-06-17 19:56:38 -0500540 vport->load_flag |= FC_LOADING;
James Smart104450e2016-12-19 15:07:25 -0800541 if (vport->fc_flag & FC_VPORT_NEEDS_INIT_VPI) {
542 spin_unlock_irq(shost->host_lock);
543 lpfc_issue_init_vpi(vport);
544 goto out;
545 }
546
James Smart92d7f7b2007-06-17 19:56:38 -0500547 vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI;
James Smart72100cc2010-02-12 14:43:01 -0500548 spin_unlock_irq(shost->host_lock);
James Smart92d7f7b2007-06-17 19:56:38 -0500549
550 /* Use the Physical nodes Fabric NDLP to determine if the link is
551 * up and ready to FDISC.
552 */
553 ndlp = lpfc_findnode_did(phba->pport, Fabric_DID);
James Smarte47c9092008-02-08 18:49:26 -0500554 if (ndlp && NLP_CHK_NODE_ACT(ndlp)
555 && ndlp->nlp_state == NLP_STE_UNMAPPED_NODE) {
James Smart858c9f62007-06-17 19:56:39 -0500556 if (phba->link_flag & LS_NPIV_FAB_SUPPORTED) {
557 lpfc_set_disctmo(vport);
558 lpfc_initial_fdisc(vport);
559 } else {
560 lpfc_vport_set_state(vport, FC_VPORT_NO_FABRIC_SUPP);
James Smarte8b62012007-08-02 11:10:09 -0400561 lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
562 "0264 No NPIV Fabric support\n");
James Smart858c9f62007-06-17 19:56:39 -0500563 }
James Smart92d7f7b2007-06-17 19:56:38 -0500564 } else {
565 lpfc_vport_set_state(vport, FC_VPORT_FAILED);
566 }
James Smart104450e2016-12-19 15:07:25 -0800567
568out:
James Smarta58cbd52007-08-02 11:09:43 -0400569 lpfc_printf_vlog(vport, KERN_ERR, LOG_VPORT,
570 "1827 Vport Enabled.\n");
James Smart92d7f7b2007-06-17 19:56:38 -0500571 return VPORT_OK;
572}
573
574int
575lpfc_vport_disable(struct fc_vport *fc_vport, bool disable)
576{
577 if (disable)
578 return disable_vport(fc_vport);
579 else
580 return enable_vport(fc_vport);
581}
582
583
584int
585lpfc_vport_delete(struct fc_vport *fc_vport)
586{
587 struct lpfc_nodelist *ndlp = NULL;
James Smart92d7f7b2007-06-17 19:56:38 -0500588 struct lpfc_vport *vport = *(struct lpfc_vport **)fc_vport->dd_data;
James Smartcc823552015-05-21 13:55:26 -0400589 struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
James Smart92d7f7b2007-06-17 19:56:38 -0500590 struct lpfc_hba *phba = vport->phba;
591 long timeout;
James Smart16a3a202013-04-17 20:14:38 -0400592 bool ns_ndlp_referenced = false;
James Smart92d7f7b2007-06-17 19:56:38 -0500593
James Smart51ef4c22007-08-02 11:10:31 -0400594 if (vport->port_type == LPFC_PHYSICAL_PORT) {
595 lpfc_printf_vlog(vport, KERN_ERR, LOG_VPORT,
596 "1812 vport_delete failed: Cannot delete "
597 "physical host\n");
598 return VPORT_ERROR;
599 }
James Smart21e9a0a2009-05-22 14:53:21 -0400600
601 /* If the vport is a static vport fail the deletion. */
602 if ((vport->vport_flag & STATIC_VPORT) &&
603 !(phba->pport->load_flag & FC_UNLOADING)) {
604 lpfc_printf_vlog(vport, KERN_ERR, LOG_VPORT,
605 "1837 vport_delete failed: Cannot delete "
606 "static vport.\n");
607 return VPORT_ERROR;
608 }
James Smartd439d282010-09-29 11:18:45 -0400609 spin_lock_irq(&phba->hbalock);
610 vport->load_flag |= FC_UNLOADING;
611 spin_unlock_irq(&phba->hbalock);
James Smart51ef4c22007-08-02 11:10:31 -0400612 /*
613 * If we are not unloading the driver then prevent the vport_delete
614 * from happening until after this vport's discovery is finished.
615 */
616 if (!(phba->pport->load_flag & FC_UNLOADING)) {
617 int check_count = 0;
618 while (check_count < ((phba->fc_ratov * 3) + 3) &&
619 vport->port_state > LPFC_VPORT_FAILED &&
620 vport->port_state < LPFC_VPORT_READY) {
621 check_count++;
622 msleep(1000);
623 }
624 if (vport->port_state > LPFC_VPORT_FAILED &&
625 vport->port_state < LPFC_VPORT_READY)
626 return -EAGAIN;
627 }
James Smart92d7f7b2007-06-17 19:56:38 -0500628 /*
629 * This is a bit of a mess. We want to ensure the shost doesn't get
630 * torn down until we're done with the embedded lpfc_vport structure.
631 *
632 * Beyond holding a reference for this function, we also need a
633 * reference for outstanding I/O requests we schedule during delete
634 * processing. But once we scsi_remove_host() we can no longer obtain
635 * a reference through scsi_host_get().
636 *
637 * So we take two references here. We release one reference at the
638 * bottom of the function -- after delinking the vport. And we
639 * release the other at the completion of the unreg_vpi that get's
640 * initiated after we've disposed of all other resources associated
641 * with the port.
642 */
James Smartd7c255b2008-08-24 21:50:00 -0400643 if (!scsi_host_get(shost))
James Smart92d7f7b2007-06-17 19:56:38 -0500644 return VPORT_INVAL;
James Smartd7c255b2008-08-24 21:50:00 -0400645 if (!scsi_host_get(shost)) {
646 scsi_host_put(shost);
647 return VPORT_INVAL;
648 }
James Smarteada2722008-12-04 22:39:13 -0500649 lpfc_free_sysfs_attr(vport);
650
James Smart858c9f62007-06-17 19:56:39 -0500651 lpfc_debugfs_terminate(vport);
James Smarteada2722008-12-04 22:39:13 -0500652
James Smart16a3a202013-04-17 20:14:38 -0400653 /*
654 * The call to fc_remove_host might release the NameServer ndlp. Since
655 * we might need to use the ndlp to send the DA_ID CT command,
656 * increment the reference for the NameServer ndlp to prevent it from
657 * being released.
658 */
659 ndlp = lpfc_findnode_did(vport, NameServer_DID);
660 if (ndlp && NLP_CHK_NODE_ACT(ndlp)) {
661 lpfc_nlp_get(ndlp);
662 ns_ndlp_referenced = true;
663 }
664
James Smarteada2722008-12-04 22:39:13 -0500665 /* Remove FC host and then SCSI host with the vport */
James Smartcc823552015-05-21 13:55:26 -0400666 fc_remove_host(shost);
667 scsi_remove_host(shost);
James Smart92d7f7b2007-06-17 19:56:38 -0500668
669 ndlp = lpfc_findnode_did(phba->pport, Fabric_DID);
James Smarte47c9092008-02-08 18:49:26 -0500670
671 /* In case of driver unload, we shall not perform fabric logo as the
672 * worker thread already stopped at this stage and, in this case, we
673 * can safely skip the fabric logo.
674 */
675 if (phba->pport->load_flag & FC_UNLOADING) {
676 if (ndlp && NLP_CHK_NODE_ACT(ndlp) &&
677 ndlp->nlp_state == NLP_STE_UNMAPPED_NODE &&
678 phba->link_state >= LPFC_LINK_UP) {
679 /* First look for the Fabric ndlp */
680 ndlp = lpfc_findnode_did(vport, Fabric_DID);
681 if (!ndlp)
682 goto skip_logo;
683 else if (!NLP_CHK_NODE_ACT(ndlp)) {
684 ndlp = lpfc_enable_node(vport, ndlp,
685 NLP_STE_UNUSED_NODE);
686 if (!ndlp)
687 goto skip_logo;
688 }
689 /* Remove ndlp from vport npld list */
690 lpfc_dequeue_node(vport, ndlp);
691
692 /* Indicate free memory when release */
693 spin_lock_irq(&phba->ndlp_lock);
694 NLP_SET_FREE_REQ(ndlp);
695 spin_unlock_irq(&phba->ndlp_lock);
696 /* Kick off release ndlp when it can be safely done */
697 lpfc_nlp_put(ndlp);
698 }
699 goto skip_logo;
700 }
701
702 /* Otherwise, we will perform fabric logo as needed */
703 if (ndlp && NLP_CHK_NODE_ACT(ndlp) &&
704 ndlp->nlp_state == NLP_STE_UNMAPPED_NODE &&
James Smart58da1ff2008-04-07 10:15:56 -0400705 phba->link_state >= LPFC_LINK_UP &&
James Smart76a95d72010-11-20 23:11:48 -0500706 phba->fc_topology != LPFC_TOPOLOGY_LOOP) {
James Smart7ee5d432007-10-27 13:37:17 -0400707 if (vport->cfg_enable_da_id) {
708 timeout = msecs_to_jiffies(phba->fc_ratov * 2000);
709 if (!lpfc_ns_cmd(vport, SLI_CTNS_DA_ID, 0, 0))
710 while (vport->ct_flags && timeout)
711 timeout = schedule_timeout(timeout);
712 else
713 lpfc_printf_log(vport->phba, KERN_WARNING,
714 LOG_VPORT,
715 "1829 CT command failed to "
James Smarte4e74272009-07-19 10:01:38 -0400716 "delete objects on fabric\n");
James Smart7ee5d432007-10-27 13:37:17 -0400717 }
James Smart92d7f7b2007-06-17 19:56:38 -0500718 /* First look for the Fabric ndlp */
719 ndlp = lpfc_findnode_did(vport, Fabric_DID);
720 if (!ndlp) {
721 /* Cannot find existing Fabric ndlp, allocate one */
722 ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL);
723 if (!ndlp)
724 goto skip_logo;
725 lpfc_nlp_init(vport, ndlp, Fabric_DID);
James Smarte47c9092008-02-08 18:49:26 -0500726 /* Indicate free memory when release */
727 NLP_SET_FREE_REQ(ndlp);
James Smart92d7f7b2007-06-17 19:56:38 -0500728 } else {
James Smart73d91e52011-10-10 21:32:10 -0400729 if (!NLP_CHK_NODE_ACT(ndlp)) {
James Smarte47c9092008-02-08 18:49:26 -0500730 ndlp = lpfc_enable_node(vport, ndlp,
731 NLP_STE_UNUSED_NODE);
732 if (!ndlp)
733 goto skip_logo;
James Smart73d91e52011-10-10 21:32:10 -0400734 }
James Smarte47c9092008-02-08 18:49:26 -0500735
James Smart73d91e52011-10-10 21:32:10 -0400736 /* Remove ndlp from vport list */
James Smart92d7f7b2007-06-17 19:56:38 -0500737 lpfc_dequeue_node(vport, ndlp);
James Smarte47c9092008-02-08 18:49:26 -0500738 spin_lock_irq(&phba->ndlp_lock);
739 if (!NLP_CHK_FREE_REQ(ndlp))
740 /* Indicate free memory when release */
741 NLP_SET_FREE_REQ(ndlp);
742 else {
743 /* Skip this if ndlp is already in free mode */
744 spin_unlock_irq(&phba->ndlp_lock);
745 goto skip_logo;
746 }
747 spin_unlock_irq(&phba->ndlp_lock);
James Smart92d7f7b2007-06-17 19:56:38 -0500748 }
James Smart73d91e52011-10-10 21:32:10 -0400749
750 /*
751 * If the vpi is not registered, then a valid FDISC doesn't
752 * exist and there is no need for a ELS LOGO. Just cleanup
753 * the ndlp.
754 */
755 if (!(vport->vpi_state & LPFC_VPI_REGISTERED)) {
756 lpfc_nlp_put(ndlp);
James Smart5ffc2662009-11-18 15:39:44 -0500757 goto skip_logo;
James Smart73d91e52011-10-10 21:32:10 -0400758 }
759
James Smart92d7f7b2007-06-17 19:56:38 -0500760 vport->unreg_vpi_cmpl = VPORT_INVAL;
761 timeout = msecs_to_jiffies(phba->fc_ratov * 2000);
762 if (!lpfc_issue_els_npiv_logo(vport, ndlp))
763 while (vport->unreg_vpi_cmpl == VPORT_INVAL && timeout)
764 timeout = schedule_timeout(timeout);
765 }
766
James Smart90160e02008-08-24 21:49:45 -0400767 if (!(phba->pport->load_flag & FC_UNLOADING))
768 lpfc_discovery_wait(vport);
769
James Smart92d7f7b2007-06-17 19:56:38 -0500770skip_logo:
James Smart16a3a202013-04-17 20:14:38 -0400771
772 /*
773 * If the NameServer ndlp has been incremented to allow the DA_ID CT
774 * command to be sent, decrement the ndlp now.
775 */
776 if (ns_ndlp_referenced) {
777 ndlp = lpfc_findnode_did(vport, NameServer_DID);
778 lpfc_nlp_put(ndlp);
779 }
780
James Smart87af33f2007-10-27 13:37:43 -0400781 lpfc_cleanup(vport);
James Smart92d7f7b2007-06-17 19:56:38 -0500782 lpfc_sli_host_down(vport);
783
James Smart92d7f7b2007-06-17 19:56:38 -0500784 lpfc_stop_vport_timers(vport);
James Smart87af33f2007-10-27 13:37:43 -0400785
786 if (!(phba->pport->load_flag & FC_UNLOADING)) {
James Smarte47c9092008-02-08 18:49:26 -0500787 lpfc_unreg_all_rpis(vport);
James Smart87af33f2007-10-27 13:37:43 -0400788 lpfc_unreg_default_rpis(vport);
789 /*
790 * Completion of unreg_vpi (lpfc_mbx_cmpl_unreg_vpi)
791 * does the scsi_host_put() to release the vport.
792 */
James Smartcc823552015-05-21 13:55:26 -0400793 if (!(vport->vpi_state & LPFC_VPI_REGISTERED) ||
794 lpfc_mbx_unreg_vpi(vport))
James Smartd7c255b2008-08-24 21:50:00 -0400795 scsi_host_put(shost);
796 } else
797 scsi_host_put(shost);
James Smart92d7f7b2007-06-17 19:56:38 -0500798
799 lpfc_free_vpi(phba, vport->vpi);
800 vport->work_port_events = 0;
801 spin_lock_irq(&phba->hbalock);
802 list_del_init(&vport->listentry);
803 spin_unlock_irq(&phba->hbalock);
James Smarta58cbd52007-08-02 11:09:43 -0400804 lpfc_printf_vlog(vport, KERN_ERR, LOG_VPORT,
805 "1828 Vport Deleted.\n");
James Smart92d7f7b2007-06-17 19:56:38 -0500806 scsi_host_put(shost);
James Smart51ef4c22007-08-02 11:10:31 -0400807 return VPORT_OK;
James Smart92d7f7b2007-06-17 19:56:38 -0500808}
809
James Smart549e55c2007-08-02 11:09:51 -0400810struct lpfc_vport **
811lpfc_create_vport_work_array(struct lpfc_hba *phba)
812{
813 struct lpfc_vport *port_iterator;
814 struct lpfc_vport **vports;
815 int index = 0;
James Smart21e9a0a2009-05-22 14:53:21 -0400816 vports = kzalloc((phba->max_vports + 1) * sizeof(struct lpfc_vport *),
James Smart549e55c2007-08-02 11:09:51 -0400817 GFP_KERNEL);
818 if (vports == NULL)
819 return NULL;
820 spin_lock_irq(&phba->hbalock);
821 list_for_each_entry(port_iterator, &phba->port_list, listentry) {
James Smartdf9e1b52011-12-13 13:22:17 -0500822 if (port_iterator->load_flag & FC_UNLOADING)
823 continue;
James Smarte8b62012007-08-02 11:10:09 -0400824 if (!scsi_host_get(lpfc_shost_from_vport(port_iterator))) {
James Smartdf9e1b52011-12-13 13:22:17 -0500825 lpfc_printf_vlog(port_iterator, KERN_ERR, LOG_VPORT,
James Smarte8b62012007-08-02 11:10:09 -0400826 "1801 Create vport work array FAILED: "
827 "cannot do scsi_host_get\n");
James Smart549e55c2007-08-02 11:09:51 -0400828 continue;
James Smarte8b62012007-08-02 11:10:09 -0400829 }
James Smart549e55c2007-08-02 11:09:51 -0400830 vports[index++] = port_iterator;
831 }
832 spin_unlock_irq(&phba->hbalock);
833 return vports;
834}
835
836void
James Smart09372822008-01-11 01:52:54 -0500837lpfc_destroy_vport_work_array(struct lpfc_hba *phba, struct lpfc_vport **vports)
James Smart549e55c2007-08-02 11:09:51 -0400838{
839 int i;
840 if (vports == NULL)
841 return;
James Smart98fc5dd2010-06-07 15:24:29 -0400842 for (i = 0; i <= phba->max_vports && vports[i] != NULL; i++)
James Smart549e55c2007-08-02 11:09:51 -0400843 scsi_host_put(lpfc_shost_from_vport(vports[i]));
844 kfree(vports);
845}
James Smartea2151b2008-09-07 11:52:10 -0400846
847
848/**
James Smart3621a712009-04-06 18:47:14 -0400849 * lpfc_vport_reset_stat_data - Reset the statistical data for the vport
James Smartea2151b2008-09-07 11:52:10 -0400850 * @vport: Pointer to vport object.
851 *
852 * This function resets the statistical data for the vport. This function
853 * is called with the host_lock held
854 **/
855void
856lpfc_vport_reset_stat_data(struct lpfc_vport *vport)
857{
858 struct lpfc_nodelist *ndlp = NULL, *next_ndlp = NULL;
859
860 list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) {
861 if (!NLP_CHK_NODE_ACT(ndlp))
862 continue;
863 if (ndlp->lat_data)
864 memset(ndlp->lat_data, 0, LPFC_MAX_BUCKET_COUNT *
865 sizeof(struct lpfc_scsicmd_bkt));
866 }
867}
868
869
870/**
James Smart3621a712009-04-06 18:47:14 -0400871 * lpfc_alloc_bucket - Allocate data buffer required for statistical data
James Smartea2151b2008-09-07 11:52:10 -0400872 * @vport: Pointer to vport object.
873 *
874 * This function allocates data buffer required for all the FC
875 * nodes of the vport to collect statistical data.
876 **/
877void
878lpfc_alloc_bucket(struct lpfc_vport *vport)
879{
880 struct lpfc_nodelist *ndlp = NULL, *next_ndlp = NULL;
881
882 list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) {
883 if (!NLP_CHK_NODE_ACT(ndlp))
884 continue;
885
886 kfree(ndlp->lat_data);
887 ndlp->lat_data = NULL;
888
889 if (ndlp->nlp_state == NLP_STE_MAPPED_NODE) {
890 ndlp->lat_data = kcalloc(LPFC_MAX_BUCKET_COUNT,
891 sizeof(struct lpfc_scsicmd_bkt),
892 GFP_ATOMIC);
893
894 if (!ndlp->lat_data)
895 lpfc_printf_vlog(vport, KERN_ERR, LOG_NODE,
896 "0287 lpfc_alloc_bucket failed to "
897 "allocate statistical data buffer DID "
898 "0x%x\n", ndlp->nlp_DID);
899 }
900 }
901}
902
903/**
James Smart3621a712009-04-06 18:47:14 -0400904 * lpfc_free_bucket - Free data buffer required for statistical data
James Smartea2151b2008-09-07 11:52:10 -0400905 * @vport: Pointer to vport object.
906 *
907 * Th function frees statistical data buffer of all the FC
908 * nodes of the vport.
909 **/
910void
911lpfc_free_bucket(struct lpfc_vport *vport)
912{
913 struct lpfc_nodelist *ndlp = NULL, *next_ndlp = NULL;
914
915 list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) {
916 if (!NLP_CHK_NODE_ACT(ndlp))
917 continue;
918
919 kfree(ndlp->lat_data);
920 ndlp->lat_data = NULL;
921 }
922}