Files
@ bd21c8aa7237
Branch filter:
Location: vmkdrivers/vmkdrivers/src_92/drivers/scsi/libfc/fc_npiv.c
bd21c8aa7237
4.9 KiB
text/x-csrc
ESXi-6.0.0b
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 | /*
* Copyright(c) 2009 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
*
* Maintained at www.Open-FCoE.org
*/
/*
* NPIV VN_Port helper functions for libfc
*/
#include <scsi/libfc.h>
/**
* fc_vport_create() - Create a new NPIV vport instance
* @vport: fc_vport structure from scsi_transport_fc
* @privsize: driver private data size to allocate along with the Scsi_Host
*/
/* _VMKLNX_CODECHECK_: libfc_vport_create */
struct fc_lport *libfc_vport_create(struct fc_vport *vport, int privsize)
{
struct Scsi_Host *shost = vport_to_shost(vport);
struct fc_lport *n_port = shost_priv(shost);
struct fc_lport *vn_port;
vn_port = libfc_host_alloc(shost->hostt, privsize);
if (!vn_port)
goto err_out;
if (fc_exch_mgr_list_clone(n_port, vn_port))
goto err_put;
vn_port->vport = vport;
vport->dd_data = vn_port;
mutex_lock(&n_port->lp_mutex);
list_add_tail(&vn_port->list, &n_port->vports);
mutex_unlock(&n_port->lp_mutex);
return vn_port;
err_put:
scsi_host_put(vn_port->host);
err_out:
return NULL;
}
EXPORT_SYMBOL(libfc_vport_create);
/**
* fc_vport_id_lookup() - find NPIV lport that matches a given fabric ID
* @n_port: Top level N_Port which may have multiple NPIV VN_Ports
* @port_id: Fabric ID to find a match for
*
* Returns: matching lport pointer or NULL if there is no match
*/
/* _VMKLNX_CODECHECK_: fc_vport_id_lookup */
struct fc_lport *fc_vport_id_lookup(struct fc_lport *n_port, u32 port_id)
{
struct fc_lport *lport = NULL;
#if !defined(__VMKLNX__)
struct fc_lport *vn_port;
#endif /* !defined(__VMKLNX__) */
if (fc_host_port_id(n_port->host) == port_id)
return n_port;
#if !defined(__VMKLNX__)
/* PR632000 NPIV not supported by SW FCoE in M/N */
mutex_lock(&n_port->lp_mutex);
list_for_each_entry(vn_port, &n_port->vports, list) {
if (fc_host_port_id(vn_port->host) == port_id) {
lport = vn_port;
break;
}
}
mutex_unlock(&n_port->lp_mutex);
#endif /* !defined(__VMKLNX__) */
return lport;
}
/*
* When setting the link state of vports during an lport state change, it's
* necessary to hold the lp_mutex of both the N_Port and the VN_Port.
* This tells the lockdep engine to treat the nested locking of the VN_Port
* as a different lock class.
*/
enum libfc_lport_mutex_class {
LPORT_MUTEX_NORMAL = 0,
LPORT_MUTEX_VN_PORT = 1,
};
/**
* __fc_vport_setlink() - update link and status on a VN_Port
* @n_port: parent N_Port
* @vn_port: VN_Port to update
*
* Locking: must be called with both the N_Port and VN_Port lp_mutex held
*/
static void __fc_vport_setlink(struct fc_lport *n_port,
struct fc_lport *vn_port)
{
struct fc_vport *vport = vn_port->vport;
if (vn_port->state == LPORT_ST_DISABLED)
return;
if (n_port->state == LPORT_ST_READY) {
if (n_port->npiv_enabled) {
fc_vport_set_state(vport, FC_VPORT_INITIALIZING);
__fc_linkup(vn_port);
} else {
fc_vport_set_state(vport, FC_VPORT_NO_FABRIC_SUPP);
__fc_linkdown(vn_port);
}
} else {
fc_vport_set_state(vport, FC_VPORT_LINKDOWN);
__fc_linkdown(vn_port);
}
}
/**
* fc_vport_setlink() - update link and status on a VN_Port
* @vn_port: virtual port to update
*/
/* _VMKLNX_CODECHECK_: fc_vport_setlink */
void fc_vport_setlink(struct fc_lport *vn_port)
{
struct fc_vport *vport = vn_port->vport;
struct Scsi_Host *shost = vport_to_shost(vport);
struct fc_lport *n_port = shost_priv(shost);
mutex_lock(&n_port->lp_mutex);
#if defined(__VMKLNX__)
mutex_lock(&vn_port->lp_mutex);
#else /* !defined(__VMKLNX__) */
mutex_lock_nested(&vn_port->lp_mutex, LPORT_MUTEX_VN_PORT);
#endif /* defined(__VMKLNX__) */
__fc_vport_setlink(n_port, vn_port);
mutex_unlock(&vn_port->lp_mutex);
mutex_unlock(&n_port->lp_mutex);
}
EXPORT_SYMBOL(fc_vport_setlink);
/**
* fc_vports_linkchange() - change the link state of all vports
* @n_port: Parent N_Port that has changed state
*
* Locking: called with the n_port lp_mutex held
*/
/* _VMKLNX_CODECHECK_: fc_vports_linkchange */
void fc_vports_linkchange(struct fc_lport *n_port)
{
struct fc_lport *vn_port;
list_for_each_entry(vn_port, &n_port->vports, list) {
#if defined(__VMKLNX__)
mutex_lock(&vn_port->lp_mutex);
#else /* !defined(__VMKLNX__) */
mutex_lock_nested(&vn_port->lp_mutex, LPORT_MUTEX_VN_PORT);
#endif /* defined(__VMKLNX__) */
__fc_vport_setlink(n_port, vn_port);
mutex_unlock(&vn_port->lp_mutex);
}
}
|