3b705ccc771a4e7680f2369c2dbaea88d3b997cb
[pandora-kernel.git] / drivers / scsi / lpfc / lpfc_vport.c
1 /*******************************************************************
2  * This file is part of the Emulex Linux Device Driver for         *
3  * Fibre Channel Host Bus Adapters.                                *
4  * Copyright (C) 2004-2006 Emulex.  All rights reserved.           *
5  * 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>
29 #include <linux/spinlock.h>
30
31 #include <scsi/scsi.h>
32 #include <scsi/scsi_device.h>
33 #include <scsi/scsi_host.h>
34 #include <scsi/scsi_transport_fc.h>
35 #include "lpfc_hw.h"
36 #include "lpfc_sli.h"
37 #include "lpfc_disc.h"
38 #include "lpfc_scsi.h"
39 #include "lpfc.h"
40 #include "lpfc_logmsg.h"
41 #include "lpfc_crtn.h"
42 #include "lpfc_version.h"
43 #include "lpfc_vport.h"
44
45 inline void lpfc_vport_set_state(struct lpfc_vport *vport,
46                                  enum fc_vport_state new_state)
47 {
48         struct fc_vport *fc_vport = vport->fc_vport;
49
50         if (fc_vport) {
51                 /*
52                  * When the transport defines fc_vport_set state we will replace
53                  * this code with the following line
54                  */
55                 /* fc_vport_set_state(fc_vport, new_state); */
56                 if (new_state != FC_VPORT_INITIALIZING)
57                         fc_vport->vport_last_state = fc_vport->vport_state;
58                 fc_vport->vport_state = new_state;
59         }
60
61         /* for all the error states we will set the invternal state to FAILED */
62         switch (new_state) {
63         case FC_VPORT_NO_FABRIC_SUPP:
64         case FC_VPORT_NO_FABRIC_RSCS:
65         case FC_VPORT_FABRIC_LOGOUT:
66         case FC_VPORT_FABRIC_REJ_WWN:
67         case FC_VPORT_FAILED:
68                 vport->port_state = LPFC_VPORT_FAILED;
69                 break;
70         case FC_VPORT_LINKDOWN:
71                 vport->port_state = LPFC_VPORT_UNKNOWN;
72                 break;
73         default:
74                 /* do nothing */
75                 break;
76         }
77 }
78
79 static int
80 lpfc_alloc_vpi(struct lpfc_hba *phba)
81 {
82         int  vpi;
83
84         spin_lock_irq(&phba->hbalock);
85         /* Start at bit 1 because vpi zero is reserved for the physical port */
86         vpi = find_next_zero_bit(phba->vpi_bmask, (phba->max_vpi + 1), 1);
87         if (vpi > phba->max_vpi)
88                 vpi = 0;
89         else
90                 set_bit(vpi, phba->vpi_bmask);
91         spin_unlock_irq(&phba->hbalock);
92         return vpi;
93 }
94
95 static void
96 lpfc_free_vpi(struct lpfc_hba *phba, int vpi)
97 {
98         spin_lock_irq(&phba->hbalock);
99         clear_bit(vpi, phba->vpi_bmask);
100         spin_unlock_irq(&phba->hbalock);
101 }
102
103 static int
104 lpfc_vport_sparm(struct lpfc_hba *phba, struct lpfc_vport *vport)
105 {
106         LPFC_MBOXQ_t *pmb;
107         MAILBOX_t *mb;
108         struct lpfc_dmabuf *mp;
109         int  rc;
110
111         pmb = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
112         if (!pmb) {
113                 return -ENOMEM;
114         }
115         mb = &pmb->mb;
116
117         lpfc_read_sparam(phba, pmb, vport->vpi);
118         /*
119          * Grab buffer pointer and clear context1 so we can use
120          * lpfc_sli_issue_box_wait
121          */
122         mp = (struct lpfc_dmabuf *) pmb->context1;
123         pmb->context1 = NULL;
124
125         pmb->vport = vport;
126         rc = lpfc_sli_issue_mbox_wait(phba, pmb, phba->fc_ratov * 2);
127         if (rc != MBX_SUCCESS) {
128                 lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT | LOG_VPORT,
129                                  "1818 VPort failed init, mbxCmd x%x "
130                                  "READ_SPARM mbxStatus x%x, rc = x%x\n",
131                                  mb->mbxCommand, mb->mbxStatus, rc);
132                 lpfc_mbuf_free(phba, mp->virt, mp->phys);
133                 kfree(mp);
134                 if (rc != MBX_TIMEOUT)
135                         mempool_free(pmb, phba->mbox_mem_pool);
136                 return -EIO;
137         }
138
139         memcpy(&vport->fc_sparam, mp->virt, sizeof (struct serv_parm));
140         memcpy(&vport->fc_nodename, &vport->fc_sparam.nodeName,
141                sizeof (struct lpfc_name));
142         memcpy(&vport->fc_portname, &vport->fc_sparam.portName,
143                sizeof (struct lpfc_name));
144
145         lpfc_mbuf_free(phba, mp->virt, mp->phys);
146         kfree(mp);
147         mempool_free(pmb, phba->mbox_mem_pool);
148
149         return 0;
150 }
151
152 static int
153 lpfc_valid_wwn_format(struct lpfc_hba *phba, struct lpfc_name *wwn,
154                       const char *name_type)
155 {
156                                 /* ensure that IEEE format 1 addresses
157                                  * contain zeros in bits 59-48
158                                  */
159         if (!((wwn->u.wwn[0] >> 4) == 1 &&
160               ((wwn->u.wwn[0] & 0xf) != 0 || (wwn->u.wwn[1] & 0xf) != 0)))
161                 return 1;
162
163         lpfc_printf_log(phba, KERN_ERR, LOG_VPORT,
164                         "1822 Invalid %s: %02x:%02x:%02x:%02x:"
165                         "%02x:%02x:%02x:%02x\n",
166                         name_type,
167                         wwn->u.wwn[0], wwn->u.wwn[1],
168                         wwn->u.wwn[2], wwn->u.wwn[3],
169                         wwn->u.wwn[4], wwn->u.wwn[5],
170                         wwn->u.wwn[6], wwn->u.wwn[7]);
171         return 0;
172 }
173
174 static int
175 lpfc_unique_wwpn(struct lpfc_hba *phba, struct lpfc_vport *new_vport)
176 {
177         struct lpfc_vport *vport;
178         unsigned long flags;
179
180         spin_lock_irqsave(&phba->hbalock, flags);
181         list_for_each_entry(vport, &phba->port_list, listentry) {
182                 if (vport == new_vport)
183                         continue;
184                 /* If they match, return not unique */
185                 if (memcmp(&vport->fc_sparam.portName,
186                            &new_vport->fc_sparam.portName,
187                            sizeof(struct lpfc_name)) == 0) {
188                         spin_unlock_irqrestore(&phba->hbalock, flags);
189                         return 0;
190                 }
191         }
192         spin_unlock_irqrestore(&phba->hbalock, flags);
193         return 1;
194 }
195
196 int
197 lpfc_vport_create(struct fc_vport *fc_vport, bool disable)
198 {
199         struct lpfc_nodelist *ndlp;
200         struct Scsi_Host *shost = fc_vport->shost;
201         struct lpfc_vport *pport = (struct lpfc_vport *) shost->hostdata;
202         struct lpfc_hba   *phba = pport->phba;
203         struct lpfc_vport *vport = NULL;
204         int instance;
205         int vpi;
206         int rc = VPORT_ERROR;
207
208         if ((phba->sli_rev < 3) ||
209                 !(phba->sli3_options & LPFC_SLI3_NPIV_ENABLED)) {
210                 lpfc_printf_log(phba, KERN_ERR, LOG_VPORT,
211                                 "1808 Create VPORT failed: "
212                                 "NPIV is not enabled: SLImode:%d\n",
213                                 phba->sli_rev);
214                 rc = VPORT_INVAL;
215                 goto error_out;
216         }
217
218         vpi = lpfc_alloc_vpi(phba);
219         if (vpi == 0) {
220                 lpfc_printf_log(phba, KERN_ERR, LOG_VPORT,
221                                 "1809 Create VPORT failed: "
222                                 "Max VPORTs (%d) exceeded\n",
223                                 phba->max_vpi);
224                 rc = VPORT_NORESOURCES;
225                 goto error_out;
226         }
227
228
229         /* Assign an unused board number */
230         if ((instance = lpfc_get_instance()) < 0) {
231                 lpfc_printf_log(phba, KERN_ERR, LOG_VPORT,
232                                 "1810 Create VPORT failed: Cannot get "
233                                 "instance number\n");
234                 lpfc_free_vpi(phba, vpi);
235                 rc = VPORT_NORESOURCES;
236                 goto error_out;
237         }
238
239         vport = lpfc_create_port(phba, instance, &fc_vport->dev);
240         if (!vport) {
241                 lpfc_printf_log(phba, KERN_ERR, LOG_VPORT,
242                                 "1811 Create VPORT failed: vpi x%x\n", vpi);
243                 lpfc_free_vpi(phba, vpi);
244                 rc = VPORT_NORESOURCES;
245                 goto error_out;
246         }
247
248         vport->vpi = vpi;
249         lpfc_debugfs_initialize(vport);
250
251         if (lpfc_vport_sparm(phba, vport)) {
252                 lpfc_printf_vlog(vport, KERN_ERR, LOG_VPORT,
253                                  "1813 Create VPORT failed. "
254                                  "Cannot get sparam\n");
255                 lpfc_free_vpi(phba, vpi);
256                 destroy_port(vport);
257                 rc = VPORT_NORESOURCES;
258                 goto error_out;
259         }
260
261         memcpy(vport->fc_portname.u.wwn, vport->fc_sparam.portName.u.wwn, 8);
262         memcpy(vport->fc_nodename.u.wwn, vport->fc_sparam.nodeName.u.wwn, 8);
263
264         if (fc_vport->node_name != 0)
265                 u64_to_wwn(fc_vport->node_name, vport->fc_nodename.u.wwn);
266         if (fc_vport->port_name != 0)
267                 u64_to_wwn(fc_vport->port_name, vport->fc_portname.u.wwn);
268
269         memcpy(&vport->fc_sparam.portName, vport->fc_portname.u.wwn, 8);
270         memcpy(&vport->fc_sparam.nodeName, vport->fc_nodename.u.wwn, 8);
271
272         if (!lpfc_valid_wwn_format(phba, &vport->fc_sparam.nodeName, "WWNN") ||
273             !lpfc_valid_wwn_format(phba, &vport->fc_sparam.portName, "WWPN")) {
274                 lpfc_printf_vlog(vport, KERN_ERR, LOG_VPORT,
275                                  "1821 Create VPORT failed. "
276                                  "Invalid WWN format\n");
277                 lpfc_free_vpi(phba, vpi);
278                 destroy_port(vport);
279                 rc = VPORT_INVAL;
280                 goto error_out;
281         }
282
283         if (!lpfc_unique_wwpn(phba, vport)) {
284                 lpfc_printf_vlog(vport, KERN_ERR, LOG_VPORT,
285                                  "1823 Create VPORT failed. "
286                                  "Duplicate WWN on HBA\n");
287                 lpfc_free_vpi(phba, vpi);
288                 destroy_port(vport);
289                 rc = VPORT_INVAL;
290                 goto error_out;
291         }
292
293         *(struct lpfc_vport **)fc_vport->dd_data = vport;
294         vport->fc_vport = fc_vport;
295
296         if ((phba->link_state < LPFC_LINK_UP) ||
297             (phba->fc_topology == TOPOLOGY_LOOP)) {
298                 lpfc_vport_set_state(vport, FC_VPORT_LINKDOWN);
299                 rc = VPORT_OK;
300                 goto out;
301         }
302
303         if (disable) {
304                 rc = VPORT_OK;
305                 goto out;
306         }
307
308         /* Use the Physical nodes Fabric NDLP to determine if the link is
309          * up and ready to FDISC.
310          */
311         ndlp = lpfc_findnode_did(phba->pport, Fabric_DID);
312         if (ndlp && ndlp->nlp_state == NLP_STE_UNMAPPED_NODE) {
313                 if (phba->link_flag & LS_NPIV_FAB_SUPPORTED) {
314                         lpfc_set_disctmo(vport);
315                         lpfc_initial_fdisc(vport);
316                 } else {
317                         lpfc_vport_set_state(vport, FC_VPORT_NO_FABRIC_SUPP);
318                         lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
319                                          "0262 No NPIV Fabric support\n");
320                 }
321         } else {
322                 lpfc_vport_set_state(vport, FC_VPORT_FAILED);
323         }
324         rc = VPORT_OK;
325
326 out:
327         lpfc_printf_vlog(vport, KERN_ERR, LOG_VPORT,
328                         "1825 Vport Created.\n");
329         lpfc_host_attrib_init(lpfc_shost_from_vport(vport));
330 error_out:
331         return rc;
332 }
333
334 static int
335 disable_vport(struct fc_vport *fc_vport)
336 {
337         struct lpfc_vport *vport = *(struct lpfc_vport **)fc_vport->dd_data;
338         struct lpfc_hba   *phba = vport->phba;
339         struct lpfc_nodelist *ndlp = NULL, *next_ndlp = NULL;
340         long timeout;
341
342         ndlp = lpfc_findnode_did(vport, Fabric_DID);
343         if (ndlp && phba->link_state >= LPFC_LINK_UP) {
344                 vport->unreg_vpi_cmpl = VPORT_INVAL;
345                 timeout = msecs_to_jiffies(phba->fc_ratov * 2000);
346                 if (!lpfc_issue_els_npiv_logo(vport, ndlp))
347                         while (vport->unreg_vpi_cmpl == VPORT_INVAL && timeout)
348                                 timeout = schedule_timeout(timeout);
349         }
350
351         lpfc_sli_host_down(vport);
352
353         /* Mark all nodes for discovery so we can remove them by
354          * calling lpfc_cleanup_rpis(vport, 1)
355          */
356         list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) {
357                 if (ndlp->nlp_state == NLP_STE_UNUSED_NODE)
358                         continue;
359                 lpfc_disc_state_machine(vport, ndlp, NULL,
360                                         NLP_EVT_DEVICE_RECOVERY);
361         }
362         lpfc_cleanup_rpis(vport, 1);
363
364         lpfc_stop_vport_timers(vport);
365         lpfc_unreg_all_rpis(vport);
366         lpfc_unreg_default_rpis(vport);
367         /*
368          * Completion of unreg_vpi (lpfc_mbx_cmpl_unreg_vpi) does the
369          * scsi_host_put() to release the vport.
370          */
371         lpfc_mbx_unreg_vpi(vport);
372
373         lpfc_vport_set_state(vport, FC_VPORT_DISABLED);
374         lpfc_printf_vlog(vport, KERN_ERR, LOG_VPORT,
375                          "1826 Vport Disabled.\n");
376         return VPORT_OK;
377 }
378
379 static int
380 enable_vport(struct fc_vport *fc_vport)
381 {
382         struct lpfc_vport *vport = *(struct lpfc_vport **)fc_vport->dd_data;
383         struct lpfc_hba   *phba = vport->phba;
384         struct lpfc_nodelist *ndlp = NULL;
385
386         if ((phba->link_state < LPFC_LINK_UP) ||
387             (phba->fc_topology == TOPOLOGY_LOOP)) {
388                 lpfc_vport_set_state(vport, FC_VPORT_LINKDOWN);
389                 return VPORT_OK;
390         }
391
392         vport->load_flag |= FC_LOADING;
393         vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI;
394
395         /* Use the Physical nodes Fabric NDLP to determine if the link is
396          * up and ready to FDISC.
397          */
398         ndlp = lpfc_findnode_did(phba->pport, Fabric_DID);
399         if (ndlp && ndlp->nlp_state == NLP_STE_UNMAPPED_NODE) {
400                 if (phba->link_flag & LS_NPIV_FAB_SUPPORTED) {
401                         lpfc_set_disctmo(vport);
402                         lpfc_initial_fdisc(vport);
403                 } else {
404                         lpfc_vport_set_state(vport, FC_VPORT_NO_FABRIC_SUPP);
405                         lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
406                                          "0264 No NPIV Fabric support\n");
407                 }
408         } else {
409                 lpfc_vport_set_state(vport, FC_VPORT_FAILED);
410         }
411         lpfc_printf_vlog(vport, KERN_ERR, LOG_VPORT,
412                          "1827 Vport Enabled.\n");
413         return VPORT_OK;
414 }
415
416 int
417 lpfc_vport_disable(struct fc_vport *fc_vport, bool disable)
418 {
419         if (disable)
420                 return disable_vport(fc_vport);
421         else
422                 return enable_vport(fc_vport);
423 }
424
425
426 int
427 lpfc_vport_delete(struct fc_vport *fc_vport)
428 {
429         struct lpfc_nodelist *ndlp = NULL;
430         struct lpfc_nodelist *next_ndlp;
431         struct Scsi_Host *shost = (struct Scsi_Host *) fc_vport->shost;
432         struct lpfc_vport *vport = *(struct lpfc_vport **)fc_vport->dd_data;
433         struct lpfc_hba   *phba = vport->phba;
434         long timeout;
435
436         if (vport->port_type == LPFC_PHYSICAL_PORT) {
437                 lpfc_printf_vlog(vport, KERN_ERR, LOG_VPORT,
438                                  "1812 vport_delete failed: Cannot delete "
439                                  "physical host\n");
440                 return VPORT_ERROR;
441         }
442         /*
443          * If we are not unloading the driver then prevent the vport_delete
444          * from happening until after this vport's discovery is finished.
445          */
446         if (!(phba->pport->load_flag & FC_UNLOADING)) {
447                 int check_count = 0;
448                 while (check_count < ((phba->fc_ratov * 3) + 3) &&
449                        vport->port_state > LPFC_VPORT_FAILED &&
450                        vport->port_state < LPFC_VPORT_READY) {
451                         check_count++;
452                         msleep(1000);
453                 }
454                 if (vport->port_state > LPFC_VPORT_FAILED &&
455                     vport->port_state < LPFC_VPORT_READY)
456                         return -EAGAIN;
457         }
458         /*
459          * This is a bit of a mess.  We want to ensure the shost doesn't get
460          * torn down until we're done with the embedded lpfc_vport structure.
461          *
462          * Beyond holding a reference for this function, we also need a
463          * reference for outstanding I/O requests we schedule during delete
464          * processing.  But once we scsi_remove_host() we can no longer obtain
465          * a reference through scsi_host_get().
466          *
467          * So we take two references here.  We release one reference at the
468          * bottom of the function -- after delinking the vport.  And we
469          * release the other at the completion of the unreg_vpi that get's
470          * initiated after we've disposed of all other resources associated
471          * with the port.
472          */
473         if (!scsi_host_get(shost) || !scsi_host_get(shost))
474                 return VPORT_INVAL;
475         spin_lock_irq(&phba->hbalock);
476         vport->load_flag |= FC_UNLOADING;
477         spin_unlock_irq(&phba->hbalock);
478         kfree(vport->vname);
479         lpfc_debugfs_terminate(vport);
480         fc_remove_host(lpfc_shost_from_vport(vport));
481         scsi_remove_host(lpfc_shost_from_vport(vport));
482
483         ndlp = lpfc_findnode_did(phba->pport, Fabric_DID);
484         if (ndlp && ndlp->nlp_state == NLP_STE_UNMAPPED_NODE &&
485             phba->link_state >= LPFC_LINK_UP) {
486                 if (vport->cfg_enable_da_id) {
487                         timeout = msecs_to_jiffies(phba->fc_ratov * 2000);
488                         if (!lpfc_ns_cmd(vport, SLI_CTNS_DA_ID, 0, 0))
489                                 while (vport->ct_flags && timeout)
490                                         timeout = schedule_timeout(timeout);
491                         else
492                                 lpfc_printf_log(vport->phba, KERN_WARNING,
493                                                 LOG_VPORT,
494                                                 "1829 CT command failed to "
495                                                 "delete objects on fabric. \n");
496                 }
497                 /* First look for the Fabric ndlp */
498                 ndlp = lpfc_findnode_did(vport, Fabric_DID);
499                 if (!ndlp) {
500                         /* Cannot find existing Fabric ndlp, allocate one */
501                         ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL);
502                         if (!ndlp)
503                                 goto skip_logo;
504                         lpfc_nlp_init(vport, ndlp, Fabric_DID);
505                 } else {
506                         lpfc_dequeue_node(vport, ndlp);
507                 }
508                 vport->unreg_vpi_cmpl = VPORT_INVAL;
509                 timeout = msecs_to_jiffies(phba->fc_ratov * 2000);
510                 if (!lpfc_issue_els_npiv_logo(vport, ndlp))
511                         while (vport->unreg_vpi_cmpl == VPORT_INVAL && timeout)
512                                 timeout = schedule_timeout(timeout);
513         }
514
515 skip_logo:
516         lpfc_sli_host_down(vport);
517
518         list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) {
519                 lpfc_disc_state_machine(vport, ndlp, NULL,
520                                              NLP_EVT_DEVICE_RECOVERY);
521                 lpfc_disc_state_machine(vport, ndlp, NULL,
522                                              NLP_EVT_DEVICE_RM);
523         }
524
525         lpfc_stop_vport_timers(vport);
526         lpfc_unreg_all_rpis(vport);
527         lpfc_unreg_default_rpis(vport);
528         /*
529          * Completion of unreg_vpi (lpfc_mbx_cmpl_unreg_vpi) does the
530          * scsi_host_put() to release the vport.
531          */
532         lpfc_mbx_unreg_vpi(vport);
533
534         lpfc_free_vpi(phba, vport->vpi);
535         vport->work_port_events = 0;
536         spin_lock_irq(&phba->hbalock);
537         list_del_init(&vport->listentry);
538         spin_unlock_irq(&phba->hbalock);
539         lpfc_printf_vlog(vport, KERN_ERR, LOG_VPORT,
540                          "1828 Vport Deleted.\n");
541         scsi_host_put(shost);
542         return VPORT_OK;
543 }
544
545 EXPORT_SYMBOL(lpfc_vport_create);
546 EXPORT_SYMBOL(lpfc_vport_delete);
547
548 struct lpfc_vport **
549 lpfc_create_vport_work_array(struct lpfc_hba *phba)
550 {
551         struct lpfc_vport *port_iterator;
552         struct lpfc_vport **vports;
553         int index = 0;
554         vports = kzalloc(LPFC_MAX_VPORTS * sizeof(struct lpfc_vport *),
555                          GFP_KERNEL);
556         if (vports == NULL)
557                 return NULL;
558         spin_lock_irq(&phba->hbalock);
559         list_for_each_entry(port_iterator, &phba->port_list, listentry) {
560                 if (!scsi_host_get(lpfc_shost_from_vport(port_iterator))) {
561                         lpfc_printf_vlog(port_iterator, KERN_WARNING, LOG_VPORT,
562                                          "1801 Create vport work array FAILED: "
563                                          "cannot do scsi_host_get\n");
564                         continue;
565                 }
566                 vports[index++] = port_iterator;
567         }
568         spin_unlock_irq(&phba->hbalock);
569         return vports;
570 }
571
572 void
573 lpfc_destroy_vport_work_array(struct lpfc_vport **vports)
574 {
575         int i;
576         if (vports == NULL)
577                 return;
578         for (i=0; vports[i] != NULL && i < LPFC_MAX_VPORTS; i++)
579                 scsi_host_put(lpfc_shost_from_vport(vports[i]));
580         kfree(vports);
581 }