^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright(c) 2009 Intel Corporation. All rights reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Maintained at www.Open-FCoE.org
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * NPIV VN_Port helper functions for libfc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <scsi/libfc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/export.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * libfc_vport_create() - Create a new NPIV vport instance
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * @vport: fc_vport structure from scsi_transport_fc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * @privsize: driver private data size to allocate along with the Scsi_Host
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) struct fc_lport *libfc_vport_create(struct fc_vport *vport, int privsize)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) struct Scsi_Host *shost = vport_to_shost(vport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) struct fc_lport *n_port = shost_priv(shost);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) struct fc_lport *vn_port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) vn_port = libfc_host_alloc(shost->hostt, privsize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) if (!vn_port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) return vn_port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) vn_port->vport = vport;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) vport->dd_data = vn_port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) mutex_lock(&n_port->lp_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) list_add_tail(&vn_port->list, &n_port->vports);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) mutex_unlock(&n_port->lp_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) return vn_port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) EXPORT_SYMBOL(libfc_vport_create);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) * fc_vport_id_lookup() - find NPIV lport that matches a given fabric ID
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) * @n_port: Top level N_Port which may have multiple NPIV VN_Ports
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) * @port_id: Fabric ID to find a match for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) * Returns: matching lport pointer or NULL if there is no match
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) struct fc_lport *fc_vport_id_lookup(struct fc_lport *n_port, u32 port_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) struct fc_lport *lport = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) struct fc_lport *vn_port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) if (n_port->port_id == port_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) return n_port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) if (port_id == FC_FID_FLOGI)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) return n_port; /* for point-to-point */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) mutex_lock(&n_port->lp_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) list_for_each_entry(vn_port, &n_port->vports, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) if (vn_port->port_id == port_id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) lport = vn_port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) mutex_unlock(&n_port->lp_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) return lport;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) EXPORT_SYMBOL(fc_vport_id_lookup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) * When setting the link state of vports during an lport state change, it's
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) * necessary to hold the lp_mutex of both the N_Port and the VN_Port.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) * This tells the lockdep engine to treat the nested locking of the VN_Port
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) * as a different lock class.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) enum libfc_lport_mutex_class {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) LPORT_MUTEX_NORMAL = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) LPORT_MUTEX_VN_PORT = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) * __fc_vport_setlink() - update link and status on a VN_Port
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) * @n_port: parent N_Port
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) * @vn_port: VN_Port to update
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) * Locking: must be called with both the N_Port and VN_Port lp_mutex held
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) static void __fc_vport_setlink(struct fc_lport *n_port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) struct fc_lport *vn_port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) struct fc_vport *vport = vn_port->vport;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) if (vn_port->state == LPORT_ST_DISABLED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) if (n_port->state == LPORT_ST_READY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) if (n_port->npiv_enabled) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) fc_vport_set_state(vport, FC_VPORT_INITIALIZING);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) __fc_linkup(vn_port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) fc_vport_set_state(vport, FC_VPORT_NO_FABRIC_SUPP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) __fc_linkdown(vn_port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) fc_vport_set_state(vport, FC_VPORT_LINKDOWN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) __fc_linkdown(vn_port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) * fc_vport_setlink() - update link and status on a VN_Port
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) * @vn_port: virtual port to update
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) void fc_vport_setlink(struct fc_lport *vn_port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) struct fc_vport *vport = vn_port->vport;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) struct Scsi_Host *shost = vport_to_shost(vport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) struct fc_lport *n_port = shost_priv(shost);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) mutex_lock(&n_port->lp_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) mutex_lock_nested(&vn_port->lp_mutex, LPORT_MUTEX_VN_PORT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) __fc_vport_setlink(n_port, vn_port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) mutex_unlock(&vn_port->lp_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) mutex_unlock(&n_port->lp_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) EXPORT_SYMBOL(fc_vport_setlink);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) * fc_vports_linkchange() - change the link state of all vports
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) * @n_port: Parent N_Port that has changed state
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) * Locking: called with the n_port lp_mutex held
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) void fc_vports_linkchange(struct fc_lport *n_port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) struct fc_lport *vn_port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) list_for_each_entry(vn_port, &n_port->vports, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) mutex_lock_nested(&vn_port->lp_mutex, LPORT_MUTEX_VN_PORT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) __fc_vport_setlink(n_port, vn_port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) mutex_unlock(&vn_port->lp_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)