linux/drivers/scsi/lpfc/lpfc_vport.c
<<
>>
Prefs
   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
  45inline 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
  79static int
  80lpfc_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
  95static void
  96lpfc_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
 103static int
 104lpfc_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
 152static int
 153lpfc_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
 174static int
 175lpfc_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
 196int
 197lpfc_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
 326out:
 327        lpfc_printf_vlog(vport, KERN_ERR, LOG_VPORT,
 328                        "1825 Vport Created.\n");
 329        lpfc_host_attrib_init(lpfc_shost_from_vport(vport));
 330error_out:
 331        return rc;
 332}
 333
 334static int
 335disable_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
 379static int
 380enable_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
 416int
 417lpfc_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
 426int
 427lpfc_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
 487                /* First look for the Fabric ndlp */
 488                ndlp = lpfc_findnode_did(vport, Fabric_DID);
 489                if (!ndlp) {
 490                        /* Cannot find existing Fabric ndlp, allocate one */
 491                        ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL);
 492                        if (!ndlp)
 493                                goto skip_logo;
 494                        lpfc_nlp_init(vport, ndlp, Fabric_DID);
 495                } else {
 496                        lpfc_dequeue_node(vport, ndlp);
 497                }
 498                vport->unreg_vpi_cmpl = VPORT_INVAL;
 499                timeout = msecs_to_jiffies(phba->fc_ratov * 2000);
 500                if (!lpfc_issue_els_npiv_logo(vport, ndlp))
 501                        while (vport->unreg_vpi_cmpl == VPORT_INVAL && timeout)
 502                                timeout = schedule_timeout(timeout);
 503        }
 504
 505skip_logo:
 506        lpfc_sli_host_down(vport);
 507
 508        list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) {
 509                lpfc_disc_state_machine(vport, ndlp, NULL,
 510                                             NLP_EVT_DEVICE_RECOVERY);
 511                lpfc_disc_state_machine(vport, ndlp, NULL,
 512                                             NLP_EVT_DEVICE_RM);
 513        }
 514
 515        lpfc_stop_vport_timers(vport);
 516        lpfc_unreg_all_rpis(vport);
 517        lpfc_unreg_default_rpis(vport);
 518        /*
 519         * Completion of unreg_vpi (lpfc_mbx_cmpl_unreg_vpi) does the
 520         * scsi_host_put() to release the vport.
 521         */
 522        lpfc_mbx_unreg_vpi(vport);
 523
 524        lpfc_free_vpi(phba, vport->vpi);
 525        vport->work_port_events = 0;
 526        spin_lock_irq(&phba->hbalock);
 527        list_del_init(&vport->listentry);
 528        spin_unlock_irq(&phba->hbalock);
 529        lpfc_printf_vlog(vport, KERN_ERR, LOG_VPORT,
 530                         "1828 Vport Deleted.\n");
 531        scsi_host_put(shost);
 532        return VPORT_OK;
 533}
 534
 535EXPORT_SYMBOL(lpfc_vport_create);
 536EXPORT_SYMBOL(lpfc_vport_delete);
 537
 538struct lpfc_vport **
 539lpfc_create_vport_work_array(struct lpfc_hba *phba)
 540{
 541        struct lpfc_vport *port_iterator;
 542        struct lpfc_vport **vports;
 543        int index = 0;
 544        vports = kzalloc(LPFC_MAX_VPORTS * sizeof(struct lpfc_vport *),
 545                         GFP_KERNEL);
 546        if (vports == NULL)
 547                return NULL;
 548        spin_lock_irq(&phba->hbalock);
 549        list_for_each_entry(port_iterator, &phba->port_list, listentry) {
 550                if (!scsi_host_get(lpfc_shost_from_vport(port_iterator))) {
 551                        lpfc_printf_vlog(port_iterator, KERN_WARNING, LOG_VPORT,
 552                                         "1801 Create vport work array FAILED: "
 553                                         "cannot do scsi_host_get\n");
 554                        continue;
 555                }
 556                vports[index++] = port_iterator;
 557        }
 558        spin_unlock_irq(&phba->hbalock);
 559        return vports;
 560}
 561
 562void
 563lpfc_destroy_vport_work_array(struct lpfc_vport **vports)
 564{
 565        int i;
 566        if (vports == NULL)
 567                return;
 568        for (i=0; vports[i] != NULL && i < LPFC_MAX_VPORTS; i++)
 569                scsi_host_put(lpfc_shost_from_vport(vports[i]));
 570        kfree(vports);
 571}
 572