cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

fc_npiv.c (3781B)


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