From: Oliver Smith-Denny <osmithde@cisco.com>
To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Sesidhar Baddela <sebaddel@cisco.com>,
Gian Carlo Boffa <gcboffa@cisco.com>,
linux-scsi@vger.kernel.org, target-devel@vger.kernel.org,
linux-kernel@vger.kernel.org,
Oliver Smith-Denny <osmithde@cisco.com>
Subject: [PATCH 03/10] staging: fnic2 add fip handling
Date: Thu, 5 Apr 2018 14:18:37 -0700 [thread overview]
Message-ID: <20180405211837.GD12584@osmithde-lnx.cisco.com> (raw)
In-Reply-To: <20180405211519.GA12584@osmithde-lnx.cisco.com>
These files contain structures and functions for handling
FIP frames.
Signed-off-by: Oliver Smith-Denny <osmithde@cisco.com>
Signed-off-by: Sesidhar Baddela <sebaddel@cisco.com>
Signed-off-by: Anil Chintalapati <achintal@cisco.com>
Signed-off-by: Arulprabhu Ponnusamy <arulponn@cisco.com>
Signed-off-by: Gian Carlo Boffa <gcboffa@cisco.com>
Co-Developed-by: Arulprabhu Ponnusamy <arulponn@cisco.com>
Co-Developed-by: Gian Carlo Boffa <gcboffa@cisco.com>
Co-Developed-by: Oliver Smith-Denny <osmithde@cisco.com>
---
drivers/staging/fnic2/src/fip.c | 804 ++++++++++++++++++++++++++++++++++++++++
drivers/staging/fnic2/src/fip.h | 336 +++++++++++++++++
2 files changed, 1140 insertions(+)
create mode 100644 drivers/staging/fnic2/src/fip.c
create mode 100644 drivers/staging/fnic2/src/fip.h
diff --git a/drivers/staging/fnic2/src/fip.c b/drivers/staging/fnic2/src/fip.c
new file mode 100644
index 0000000..42c2cf3
--- /dev/null
+++ b/drivers/staging/fnic2/src/fip.c
@@ -0,0 +1,804 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0
+ * Copyright 2018 Cisco Systems, Inc. All rights reserved.
+ *
+ * This program is free software; you may redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/*! \file */
+#include "fnic2.h"
+#include "fip.h"
+
+extern struct workqueue_struct *fip_event_queue;
+
+void fnic2_fcoe_send_vlan_req(struct fnic2 *fnic2);
+static void fnic2_fcoe_start_fcf_discovery(struct fnic2 *fnic2);
+static void fnic2_fcoe_start_flogi(struct fnic2 *fnic2);
+static void fnic2_fcoe_process_cvl(struct fnic2 *fnic2, struct fip_header *fiph);
+static void fnic2_vlan_discovery_timeout(struct fnic2 *fnic2);
+
+int drop_rsp = true;
+
+/****************************** Functions ***********************************/
+
+/**
+ * fnic2_fcoe_reset_vlans
+ *
+ * Frees up the list of discovered vlans
+ *
+ * @param fnic2 fnic2 driver instance
+ */
+
+void fnic2_fcoe_reset_vlans(struct fnic2 *fnic2)
+{
+ unsigned long flags;
+ struct fcoe_vlan *vlan, *next;
+
+ pr_debug("fnic2 0x%pK enter reset vlan\n", fnic2);
+ spin_lock_irqsave(&fnic2->vlans_lock, flags);
+ if (!list_empty(&fnic2->vlan_list)) {
+ list_for_each_entry_safe(vlan, next, &fnic2->vlan_list, list) {
+ list_del(&vlan->list);
+ kfree(vlan);
+ }
+ }
+
+ spin_unlock_irqrestore(&fnic2->vlans_lock, flags);
+ pr_debug("fnic2 0x%pK reset vlan done\n", fnic2);
+}
+
+/*
+ * fnic2_fcoe_send_vlan_req
+ *
+ * Sends FIP vlan request to all FCFs MAC
+ *
+ * @param fnic2 fnic2 driver instance
+ */
+
+void fnic2_fcoe_send_vlan_req(struct fnic2 *fnic2)
+{
+ struct fnic2_lport *lport = &fnic2->lport;
+ uint64_t vlan_tov;
+
+ int fr_len;
+ struct fip_vlan_req vlan_req;
+
+ pr_debug("fnic2 0x%pK Enter send vlan req\n", fnic2);
+ fnic2_fcoe_reset_vlans(fnic2);
+
+ fnic2->set_vlan(fnic2, 0);
+ pr_debug("fnic2 0x%pK set vlan done\n", fnic2);
+
+ fr_len = sizeof(struct fip_vlan_req);
+
+ pr_debug("got MAC %x %x %x %x %x %x\n",
+ lport->hwmac[0], lport->hwmac[1], lport->hwmac[2],
+ lport->hwmac[3], lport->hwmac[4], lport->hwmac[5]);
+
+ memcpy(&vlan_req, &fip_vlan_reqmpl, fr_len);
+ memcpy(vlan_req.eth.smac, lport->hwmac, ETH_ALEN);
+ memcpy(vlan_req.mac_desc.mac, lport->hwmac, ETH_ALEN);
+
+ fnic2_send_fip_frame(lport, &vlan_req, fr_len);
+ pr_debug("fnic2 0x%pK vlan req frame sent\n", fnic2);
+
+ lport->fip.state = FDLS_FIP_VLAN_DISCOVERY_STARTED;
+
+ pr_debug("fnic2 0x%pK set timer\n", fnic2);
+ vlan_tov = jiffies + msecs_to_jiffies(FCOE_CTLR_FIPVLAN_TOV);
+ mod_timer(&fnic2->retry_fip_timer, round_jiffies(vlan_tov));
+ pr_debug("fnic2 0x%pK timer done\n", fnic2);
+}
+
+/**
+ * fnic2_fcoe_process_vlan_resp
+ *
+ * Processes the vlan response from one FCF and populates VLAN list.
+ * Will wait for responses from multiple FCFs until timeout.
+ *
+ * @param fnic2 fnic2 driver instance
+ * @param fiph received fip frame
+ */
+
+static void fnic2_fcoe_process_vlan_resp(struct fnic2 *fnic2, struct fip_header *fiph)
+{
+ struct fip_vlan_notif *vlan_notif = (struct fip_vlan_notif *) fiph;
+ uint16_t vid;
+ int num_vlan = 0;
+ int cur_desc, desc_len;
+ struct fcoe_vlan *vlan;
+ struct fip_vlan_desc *vlan_desc;
+ unsigned long flags;
+
+ pr_debug("fnic2 0x%pK got vlan resp\n", fnic2);
+
+ desc_len = ntohs(vlan_notif->fip.desc_len);
+ pr_debug("desc_len %d\n", desc_len);
+
+ spin_lock_irqsave(&fnic2->vlans_lock, flags);
+
+ cur_desc = 0;
+ while (desc_len > 0) {
+ vlan_desc = (struct fip_vlan_desc *)
+ (((char *)vlan_notif->vlans_desc) + cur_desc * 4);
+ if (vlan_desc->type == FIP_TYPE_VLAN) {
+ if (vlan_desc->len != 1) {
+ pr_debug("Invalid descriptor length %x in VLan response\n",
+ vlan_desc->len);
+
+ }
+ num_vlan++;
+ vid = ntohs(vlan_desc->vlan);
+ pr_debug("process_vlan_resp: FIP VLAN %d\n", vid);
+ vlan = kmalloc(sizeof(*vlan), GFP_ATOMIC);
+
+ if (!vlan) {
+ /* retry from timer */
+ spin_unlock_irqrestore(&fnic2->vlans_lock, flags);
+ goto out;
+ }
+ memset(vlan, 0, sizeof(struct fcoe_vlan));
+ vlan->vid = vid & 0x0fff;
+ vlan->state = FIP_VLAN_AVAIL;
+ list_add_tail(&vlan->list, &fnic2->vlan_list);
+ break;
+ } else {
+ pr_debug("Invalid descriptor type %x in VLan response\n",
+ vlan_desc->type);
+ // Note : received a type=2 descriptor here i.e. FIP
+ // MAC Address Descriptor
+ }
+ cur_desc += vlan_desc->len;
+ desc_len -= vlan_desc->len;
+ }
+
+ /* any VLAN descriptors present ? */
+ if (num_vlan == 0) {
+ pr_debug("fnic2 0x%pK No VLAN descriptors in FIP VLAN response\n", fnic2);
+ }
+
+ spin_unlock_irqrestore(&fnic2->vlans_lock, flags);
+
+out:
+ return;
+}
+
+/**
+ * fnic2_fcoe_start_fcf_discovery
+ *
+ * Starts FIP FCF discovery in a selected vlan
+ *
+ * @param fnic2 fnic2 driver instance
+ */
+
+static void fnic2_fcoe_start_fcf_discovery(struct fnic2 *fnic2)
+{
+ struct fnic2_lport *lport = &fnic2->lport;
+ uint64_t fcs_tov;
+
+ int fr_len;
+ struct fip_discovery disc_sol;
+
+ pr_debug("fnic2 0x%pK start fcf discovery\n", fnic2);
+ fr_len = sizeof(struct fip_discovery);
+ memset(lport->selected_fcf.fcf_mac, 0, ETH_ALEN);
+
+ memcpy(&disc_sol, &fip_discoverympl, fr_len);
+ memcpy(disc_sol.eth.smac, lport->hwmac, ETH_ALEN);
+ memcpy(disc_sol.mac_desc.mac, lport->hwmac, ETH_ALEN);
+ lport->selected_fcf.fcf_priority = 0xFF;
+
+ disc_sol.name_desc.name = cpu_to_be64(lport->wwnn);
+ fnic2_send_fip_frame(lport, &disc_sol, fr_len);
+
+ lport->fip.state = FDLS_FIP_FCF_DISCOVERY_STARTED;
+
+ fcs_tov = jiffies + msecs_to_jiffies(FCOE_CTLR_FCS_TOV);
+ mod_timer(&fnic2->retry_fip_timer, round_jiffies(fcs_tov));
+
+ pr_debug("fnic2 0x%pK Started FCF discovery", fnic2);
+
+}
+
+/*
+ * fnic2_fcoe_fip_discovery_resp
+ *
+ * Processes FCF advertisements.
+ * They can be:
+ * solicited Sent in response of a discover FCF FIP request
+ * We will only store the information of the FCF with
+ * highest priority.
+ * We wait until timeout in case of multiple FCFs.
+ * unsolicited Sent periodically by the FCF for keep alive.
+ * If FLOGI is in progress or completed and the advertisement is
+ * received by our selected FCF, refresh the keep alive timer.
+ *
+ * @param fnic2 fnic2 driver instance
+ * @param fiph received frame
+ */
+
+static void fnic2_fcoe_fip_discovery_resp(struct fnic2 *fnic2, struct fip_header *fiph)
+{
+ struct fnic2_lport *lport = &fnic2->lport;
+ struct fip_disc_adv *disc_adv = (struct fip_disc_adv *) fiph;
+ uint64_t fcs_ka_tov;
+ int desc_len = ntohs(disc_adv->fip.desc_len);
+
+ pr_debug("fnic2 0x%pK In fcf discovery resp\n", fnic2);
+ pr_debug("fip state %d\n", lport->fip.state);
+
+ if (!(desc_len == 12)) {
+ pr_debug("struct fip_disc_adv invalid Descriptor List len %x\n",
+ desc_len);
+ }
+ if (!((disc_adv->prio_desc.type == 1) && (disc_adv->prio_desc.len == 1)) ||
+ !((disc_adv->mac_desc.type == 2) && (disc_adv->mac_desc.len == 2)) ||
+ !((disc_adv->name_desc.type == 4) && (disc_adv->name_desc.len == 3)) ||
+ !((disc_adv->fabric_desc.type == 5) &&
+ (disc_adv->fabric_desc.len == 4)) ||
+ !((disc_adv->fka_adv_desc.type == 12) &&
+ (disc_adv->fabric_desc.len == 2))) {// this len comes 4 ??
+ pr_debug("struct fip_disc_adv invalid Descriptor type and len mix: type %x len %x | type %x len %x | type %x len%x |type %x len %x | type %x len %x\n",
+ disc_adv->prio_desc.type, disc_adv->prio_desc.len,
+ disc_adv->mac_desc.type, disc_adv->mac_desc.len,
+ disc_adv->name_desc.type, disc_adv->name_desc.len,
+ disc_adv->fabric_desc.type, disc_adv->fabric_desc.len,
+ disc_adv->fka_adv_desc.type, disc_adv->fabric_desc.len);
+ }
+
+ if (lport->fip.state == FDLS_FIP_FCF_DISCOVERY_STARTED) {
+ if (ntohs(disc_adv->fip.flags) & FIP_FLAG_S) {
+ pr_debug("fnic2 0x%pK Solicited adv\n", fnic2);
+
+ if ((disc_adv->prio_desc.priority <
+ lport->selected_fcf.fcf_priority) &&
+ (ntohs(disc_adv->fip.flags) & FIP_FLAG_A)) {
+
+ pr_debug("fnic2 0x%pK FCF Available\n", fnic2);
+ memcpy(lport->selected_fcf.fcf_mac,
+ disc_adv->mac_desc.mac, ETH_ALEN);
+ lport->selected_fcf.fcf_priority =
+ disc_adv->prio_desc.priority;
+ lport->selected_fcf.fka_adv_period =
+ ntohl(disc_adv->fka_adv_desc.fka_adv);
+ pr_debug("adv time %d",
+ lport->selected_fcf.fka_adv_period);
+ lport->selected_fcf.ka_disabled =
+ (disc_adv->fka_adv_desc.rsvd_D & 1);
+ }
+ } else {
+ // ignore
+ }
+ } else if ((lport->fip.state == FDLS_FIP_FLOGI_STARTED) ||
+ (lport->fip.state == FDLS_FIP_FLOGI_COMPLETE)) {
+ if (!(ntohs(disc_adv->fip.flags) & FIP_FLAG_S)) {
+ // same fcf
+ if (memcmp(lport->selected_fcf.fcf_mac,
+ disc_adv->mac_desc.mac, ETH_ALEN) == 0) {
+ if (lport->selected_fcf.fka_adv_period !=
+ ntohl(disc_adv->fka_adv_desc.fka_adv)) {
+ lport->selected_fcf.fka_adv_period =
+ ntohl(disc_adv->fka_adv_desc.fka_adv);
+ pr_debug("change fka to %d",
+ lport->selected_fcf.fka_adv_period);
+ }
+ if (!((lport->selected_fcf.ka_disabled) ||
+ (lport->selected_fcf.fka_adv_period == 0))) {
+
+ fcs_ka_tov = jiffies +
+ 3 * msecs_to_jiffies(lport->selected_fcf.fka_adv_period);
+ mod_timer(&fnic2->fcs_ka_timer, round_jiffies(fcs_ka_tov));
+
+ }
+ }
+ }
+ }
+}
+
+/*
+ * fnic2_fcoe_start_flogi
+ *
+ * Sends FIP FLOGI to the selected FCF
+ *
+ * @param fnic2 fnic2 driver instance
+ */
+
+static void fnic2_fcoe_start_flogi(struct fnic2 *fnic2)
+{
+ struct fnic2_lport *lport = &fnic2->lport;
+
+ int fr_len;
+ struct fip_flogi flogi_req;
+ uint64_t flogi_tov;
+
+ fr_len = sizeof(struct fip_flogi);
+ pr_debug("fnic2 0x%pK Start fip FLOGI\n", fnic2);
+
+ memcpy(&flogi_req, &fip_flogimpl, fr_len);
+ memcpy(flogi_req.eth.smac, lport->hwmac, ETH_ALEN);
+ if (lport->usefip) {
+ memcpy(flogi_req.eth.dmac, lport->selected_fcf.fcf_mac, ETH_ALEN);
+ }
+ flogi_req.flogi_desc.flogi.nport_name = cpu_to_be64(lport->wwpn);
+ flogi_req.flogi_desc.flogi.node_name = cpu_to_be64(lport->wwnn);
+
+ fnic2_send_fip_frame(lport, &flogi_req, fr_len);
+ lport->fip.flogi_retry++;
+
+ lport->fip.state = FDLS_FIP_FLOGI_STARTED;
+ flogi_tov = jiffies + msecs_to_jiffies(fnic2->config.flogi_timeout);
+ mod_timer(&fnic2->retry_fip_timer, round_jiffies(flogi_tov));
+}
+
+/*
+ * fnic2_fcoe_process_flogi_resp
+ *
+ * Processes FLOGI response from FCF.
+ * If successful saves assigned fc_id and MAC, programs firmware
+ * and starts fdls discovery.
+ * Else restarts vlan discovery.
+ *
+ * @param fnic2 fnic2 driver instance
+ * @param fiph received frame
+ */
+
+void fnic2_fcoe_process_flogi_resp(struct fnic2 *fnic2, struct fip_header *fiph)
+{
+ struct fnic2_lport *lport = &fnic2->lport;
+ struct fip_flogi_rsp *flogi_rsp = (struct fip_flogi_rsp *) fiph;
+ int desc_len;
+ uint32_t s_id;
+
+ pr_debug("fnic2 0x%pK FIP FLOGI rsp\n", fnic2);
+ desc_len = ntohs(flogi_rsp->fip.desc_len);
+ if (desc_len != 38) {
+ pr_debug("%s invalid Descriptor List len %x\n",
+ __func__, desc_len);
+ }
+ if (!((flogi_rsp->rsp_desc.type == 7) && (flogi_rsp->rsp_desc.len == 36)) ||
+ !((flogi_rsp->mac_desc.type == 2) && (flogi_rsp->mac_desc.len == 2))) {
+ pr_debug("dropping frame. %s invalid Descriptor type and len mix:\n flogi_rsp->rsp_desc.type %x flogi_rsp->rsp_desc.len %x flogi_rsp->mac_desc.type %x flogi_rsp->mac_desc.len %x\n",
+ __func__, flogi_rsp->rsp_desc.type, flogi_rsp->rsp_desc.len,
+ flogi_rsp->mac_desc.type, flogi_rsp->mac_desc.len);
+
+ }
+ s_id = ntoh24(flogi_rsp->rsp_desc.els.fchdr.s_id);
+ if ((flogi_rsp->rsp_desc.els.fchdr.f_ctl[0] != 0x98) ||
+ (flogi_rsp->rsp_desc.els.fchdr.r_ctl != 0x23) ||
+ (s_id != 0xFFFFFE) ||
+ (flogi_rsp->rsp_desc.els.fchdr.ox_id != FNIC2_FLOGI_OXID) ||
+ (flogi_rsp->rsp_desc.els.fchdr.type != 0x01)) {
+ pr_debug("fnic2_fcoe_process_flogi_resp received Flogi resp with some Invalid fc frame bits s_id %x FCTL %x R_CTL %x type %x OX_ID %x Dropping the frame\n",
+ s_id,
+ ntoh24(flogi_rsp->rsp_desc.els.fchdr.f_ctl),
+ flogi_rsp->rsp_desc.els.fchdr.r_ctl,
+ flogi_rsp->rsp_desc.els.fchdr.type,
+ flogi_rsp->rsp_desc.els.fchdr.ox_id);
+ return;
+ }
+
+ if (lport->fip.state == FDLS_FIP_FLOGI_STARTED) {
+ pr_debug("fnic2 0x%pK rsp for pending FLOGI\n", fnic2);
+
+ del_timer_sync(&fnic2->retry_fip_timer);
+
+ if ((ntohs(flogi_rsp->fip.desc_len) == 38) &&
+ (flogi_rsp->rsp_desc.els.command == FC_LS_ACC)) {
+
+ pr_debug("fnic2 0x%pK FLOGI success\n", fnic2);
+ memcpy(lport->fpma, flogi_rsp->mac_desc.mac, ETH_ALEN);
+ lport->fcid = ntoh24(flogi_rsp->rsp_desc.els.fchdr.d_id);
+
+ lport->r_a_tov =
+ ntohl(flogi_rsp->rsp_desc.els.u.csp_flogi.r_a_tov);
+ lport->e_d_tov =
+ ntohl(flogi_rsp->rsp_desc.els.u.csp_flogi.e_d_tov);
+ memcpy(fnic2->lport.fcfmac, lport->selected_fcf.fcf_mac,
+ ETH_ALEN);
+ vnic_dev_add_addr(fnic2->vdev, flogi_rsp->mac_desc.mac);
+
+ if (fnic2_fdls_register_portid(lport, lport->fcid, NULL) != 0) {
+ pr_debug("fnic2 0x%pK flogi registration failed\n", fnic2);
+ return;
+ }
+
+ lport->fip.state = FDLS_FIP_FLOGI_COMPLETE;
+ lport->state = FNIC2_IPORT_STATE_FABRIC_DISC;
+ pr_debug("lport->state: %d\n",
+ lport->state);
+ fnic2_fdls_disc_start(lport);
+ if (!lport->selected_fcf.ka_disabled) {
+ uint64_t tov;
+
+ tov = jiffies + msecs_to_jiffies(FCOE_CTLR_ENODE_KA_TOV);
+ mod_timer(&fnic2->enode_ka_timer, round_jiffies(tov));
+
+ tov = jiffies + msecs_to_jiffies(FCOE_CTLR_VN_KA_TOV);
+ mod_timer(&fnic2->vn_ka_timer, round_jiffies(tov));
+
+ }
+ } else {
+ /*
+ * If there's FLOGI rejects - clear all
+ * fcf's & restart from scratch
+ * start FCoE VLAN discovery
+ */
+ fnic2_fcoe_send_vlan_req(fnic2);
+
+ lport->fip.state = FDLS_FIP_VLAN_DISCOVERY_STARTED;
+ }
+ }
+}
+
+/*
+ * fnic2_common_fip_cleanup
+ *
+ * Cleans up FCF info and timers in case of link down/CVL
+ *
+ * @param fnic2 fnic2 driver instance
+ */
+
+void fnic2_common_fip_cleanup(struct fnic2 *fnic2)
+{
+
+ struct fnic2_lport *lport = &fnic2->lport;
+
+ if (!lport->usefip)
+ return;
+ pr_debug("fnic2 0x%pK fip cleanup\n", fnic2);
+
+ // cleanup flogi form hw
+ fnic2_fw_reset_handler(fnic2);
+
+ lport->fip.state = FDLS_FIP_INIT;
+
+ del_timer_sync(&fnic2->retry_fip_timer);
+ del_timer_sync(&fnic2->fcs_ka_timer);
+ del_timer_sync(&fnic2->enode_ka_timer);
+ del_timer_sync(&fnic2->vn_ka_timer);
+
+ vnic_dev_del_addr(fnic2->vdev, lport->fpma);
+
+ memset(lport->fpma, 0, ETH_ALEN);
+ lport->fcid = 0;
+ lport->r_a_tov = 0;
+ lport->e_d_tov = 0;
+ memset(fnic2->lport.fcfmac, 0, ETH_ALEN);
+ memset(lport->selected_fcf.fcf_mac, 0, ETH_ALEN);
+ lport->selected_fcf.fcf_priority = 0;
+ lport->selected_fcf.fka_adv_period = 0;
+ lport->selected_fcf.ka_disabled = 0;
+
+ fnic2_fcoe_reset_vlans(fnic2);
+}
+
+/*
+ * fnic2_fcoe_process_cvl
+ *
+ * Processes Clear Virtual Link from FCF
+ * Verifies that cvl is received from our current FCF for our assigned MAC
+ * Cleans up and restarts the vlan discovery
+ *
+ * @param fnic2 fnic2 driver instance
+ * @param fiph received frame
+ */
+
+static void fnic2_fcoe_process_cvl(struct fnic2 *fnic2, struct fip_header *fiph)
+{
+ struct fnic2_lport *lport = &fnic2->lport;
+ struct fip_cvl *cvl_msg = (struct fip_cvl *) fiph;
+ int i;
+ int found = false;
+
+ pr_debug("fnic2 0x%pK clear virtual link handler\n", fnic2);
+
+ if (!((cvl_msg->fcf_mac_desc.type == 2) &&
+ (cvl_msg->fcf_mac_desc.len == 2)) ||
+ !((cvl_msg->name_desc.type == 4) &&
+ (cvl_msg->name_desc.len == 3))) {
+
+ pr_debug("fnic2_fcoe_process_cvl invalid Descriptor type and len mix: fcf_mac_desc.type %x fcf_mac_desc.len %x cvl_msg->name_desc.type %x cvl_msg->name_desc.len %x\n",
+ cvl_msg->fcf_mac_desc.type, cvl_msg->fcf_mac_desc.len,
+ cvl_msg->name_desc.type, cvl_msg->name_desc.len);
+ }
+
+ if (memcmp(lport->selected_fcf.fcf_mac, cvl_msg->fcf_mac_desc.mac,
+ ETH_ALEN) == 0) {
+ for (i = 0; i < ((ntohs(fiph->desc_len) / 5) - 1); i++) {
+ if (!((cvl_msg->vn_ports_desc[i].type == 11) &&
+ (cvl_msg->vn_ports_desc[i].len == 5))) {
+
+ pr_debug("fnic2_fcoe_process_cvl invalid Descriptor type and len mix: vn_ports_desc[i].type %d vn_ports_desc[i].len %d\n",
+ cvl_msg->vn_ports_desc[i].type,
+ cvl_msg->vn_ports_desc[i].len);
+ }
+ if (memcmp(lport->fpma,
+ cvl_msg->vn_ports_desc[i].vn_port_mac,
+ ETH_ALEN) == 0) {
+ found = true;
+ break;
+ }
+ }
+ if (!found)
+ return;
+ fnic2_common_fip_cleanup(fnic2);
+ fnic2_fdls_link_down(lport);
+
+ fnic2_fcoe_send_vlan_req(fnic2);
+ }
+}
+
+/*
+ * fdls_fip_recv_frame
+ *
+ * Demultiplexer for FIP frames
+ *
+ * @param fnic2 driver instance
+ * @param frame received ethernet frame
+ * @return Frame processed by FIP
+ */
+
+int fdls_fip_recv_frame(struct fnic2 *fnic2, void *frame)
+{
+ struct eth_hdr *eth = (struct eth_hdr *) frame;
+ struct fip_header *fiph;
+ uint16_t protocol;
+ uint8_t sub;
+
+ if (eth->eth_type == ntohs(FIP_ETH_TYPE)) {
+
+ fiph = (struct fip_header *) (eth+1);
+ protocol = ntohs(fiph->protocol);
+ sub = ntohs(fiph->subcode);
+
+ pr_debug("recv fip frame op %x sub %x\n",
+ protocol, sub);
+
+ if (protocol == FIP_DISCOVERY && sub == FIP_SUBCODE_RESP) {
+ fnic2_fcoe_fip_discovery_resp(fnic2, fiph);
+ } else if (protocol == FIP_VLAN_DISC && sub == FIP_SUBCODE_RESP) {
+ fnic2_fcoe_process_vlan_resp(fnic2, fiph);
+ } else if (protocol == FIP_KA_CVL && sub == FIP_SUBCODE_RESP) {
+ fnic2_fcoe_process_cvl(fnic2, fiph);
+ } else if (protocol == FIP_FLOGI && sub == FIP_SUBCODE_RESP) {
+ fnic2_fcoe_process_flogi_resp(fnic2, fiph);
+ }
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ * fnic2_handle_fip_timer
+ *
+ * Timeout handler for FIP discover phase.
+ * Based on the current state, starts next phase or restarts discovery
+ *
+ * @param data Opaque pointer to fnic2 structure
+ */
+
+void fnic2_handle_fip_timer(struct timer_list *timer)
+{
+ struct fnic2 *fnic2 = container_of(timer, struct fnic2, retry_fip_timer);
+ struct fnic2_lport *lport = &fnic2->lport;
+
+ pr_debug("fnic2 0x%pK fip timeout\n", fnic2);
+
+ if (lport->fip.state == FDLS_FIP_VLAN_DISCOVERY_STARTED) {
+ // pr_debug("vlan discovey timeout\n");
+ fnic2_vlan_discovery_timeout(fnic2);
+ } else if (lport->fip.state == FDLS_FIP_FCF_DISCOVERY_STARTED) {
+ uint8_t zmac[ETH_ALEN] = {0, 0, 0, 0, 0, 0};
+
+ pr_debug("fnic2 0x%pK fcf discovey timeout\n", fnic2);
+ if (memcmp(lport->selected_fcf.fcf_mac, zmac, ETH_ALEN) != 0) {
+ fnic2_fcoe_start_flogi(fnic2);
+ if (!((lport->selected_fcf.ka_disabled) ||
+ (lport->selected_fcf.fka_adv_period == 0))) {
+ uint64_t fcf_tov;
+
+ fcf_tov = jiffies +
+ 3 * msecs_to_jiffies(lport->selected_fcf.fka_adv_period);
+ mod_timer(&fnic2->fcs_ka_timer, round_jiffies(fcf_tov));
+ }
+ } else {
+ pr_debug("fnic2 0x%pK FCF discovey timeout\n", fnic2);
+ fnic2_vlan_discovery_timeout(fnic2);
+ }
+ } else if (lport->fip.state == FDLS_FIP_FLOGI_STARTED) {
+ pr_debug("fnic2 0x%pK flogi timeout\n", fnic2);
+ if (lport->fip.flogi_retry < fnic2->config.flogi_retries) {
+ fnic2_fcoe_start_flogi(fnic2);
+ } else {
+ fnic2_vlan_discovery_timeout(fnic2);
+ }
+ }
+}
+
+/*
+ * fnic2_handle_enode_ka_timer
+ *
+ * FIP node keep alive.
+ *
+ * @param data Opaque pointer to fnic2 struct
+ */
+void fnic2_handle_enode_ka_timer(struct timer_list *timer)
+{
+ struct fnic2 *fnic2 = container_of(timer, struct fnic2, enode_ka_timer);
+ struct fnic2_lport *lport = &fnic2->lport;
+ int fr_len;
+ struct fip_enode_ka enode_ka;
+ uint64_t enode_ka_tov;
+
+ pr_debug("fnic2 0x%pK ka timer\n", fnic2);
+
+ if (lport->fip.state != FDLS_FIP_FLOGI_COMPLETE) {
+ return;
+ }
+
+ fr_len = sizeof(struct fip_enode_ka);
+
+ memcpy(&enode_ka, &fip_enode_kampl, fr_len);
+ memcpy(enode_ka.eth.smac, lport->hwmac, ETH_ALEN);
+ memcpy(enode_ka.eth.dmac, lport->selected_fcf.fcf_mac, ETH_ALEN);
+ memcpy(enode_ka.mac_desc.mac, lport->hwmac, ETH_ALEN);
+
+ fnic2_send_fip_frame(lport, &enode_ka, fr_len);
+ enode_ka_tov = jiffies + msecs_to_jiffies(FCOE_CTLR_ENODE_KA_TOV);
+ mod_timer(&fnic2->enode_ka_timer, round_jiffies(enode_ka_tov));
+}
+
+/*
+ * fnic2_handle_vn_ka_timer
+ *
+ * FIP virtual port keep alive.
+ *
+ * @param data Opaque pointer to fnic2 structure
+ */
+
+void fnic2_handle_vn_ka_timer(struct timer_list *timer)
+{
+ struct fnic2 *fnic2 = container_of(timer, struct fnic2, vn_ka_timer);
+ struct fnic2_lport *lport = &fnic2->lport;
+ int fr_len;
+ struct fip_vn_port_ka vn_port_ka;
+ uint64_t vn_ka_tov;
+ uint8_t fcid[3];
+
+ pr_debug("fnic2 0x%pK vn port ka timer\n", fnic2);
+
+ if (lport->fip.state != FDLS_FIP_FLOGI_COMPLETE) {
+ return;
+ }
+
+ fr_len = sizeof(struct fip_vn_port_ka);
+
+ memcpy(&vn_port_ka, &fip_vn_port_kampl, fr_len);
+ memcpy(vn_port_ka.eth.smac, lport->hwmac, ETH_ALEN);
+ memcpy(vn_port_ka.eth.dmac, lport->selected_fcf.fcf_mac, ETH_ALEN);
+ memcpy(vn_port_ka.mac_desc.mac, lport->hwmac, ETH_ALEN);
+ memcpy(vn_port_ka.vn_port_desc.vn_port_mac, lport->fpma, ETH_ALEN);
+ hton24(fcid, lport->fcid);
+ memcpy(vn_port_ka.vn_port_desc.vn_port_id, fcid, 3);
+ vn_port_ka.vn_port_desc.vn_port_name = cpu_to_be64(lport->wwpn);
+
+ fnic2_send_fip_frame(lport, &vn_port_ka, fr_len);
+ vn_ka_tov = jiffies + msecs_to_jiffies(FCOE_CTLR_VN_KA_TOV);
+ mod_timer(&fnic2->vn_ka_timer, round_jiffies(vn_ka_tov));
+}
+
+/*
+ * fnic2_vlan_discovery_timeout
+ *
+ * End of VLAN discovery or FCF discovery time window
+ * Start the FCF discovery if VLAN was never used
+ * Retry in case of FCF not responding or move to next VLAN
+ *
+ * @param fnic2 fnic2 driver instance
+ */
+
+static void fnic2_vlan_discovery_timeout(struct fnic2 *fnic2)
+{
+ struct fcoe_vlan *vlan;
+ struct fnic2_lport *lport = &fnic2->lport;
+ unsigned long flags;
+
+ spin_lock_irqsave(&fnic2->fnic2_lock, flags);
+ if (fnic2->stop_rx_link_events) {
+ spin_unlock_irqrestore(&fnic2->fnic2_lock, flags);
+ return;
+ }
+ spin_unlock_irqrestore(&fnic2->fnic2_lock, flags);
+
+ if (!lport->usefip)
+ return;
+
+ spin_lock_irqsave(&fnic2->vlans_lock, flags);
+ if (list_empty(&fnic2->vlan_list)) {
+ /* no vlans available, try again */
+ spin_unlock_irqrestore(&fnic2->vlans_lock, flags);
+ fnic2_fcoe_send_vlan_req(fnic2);
+ return;
+ }
+
+ vlan = list_first_entry(&fnic2->vlan_list, struct fcoe_vlan, list);
+
+ if (vlan->state == FIP_VLAN_SENT) {
+ if (vlan->sol_count >= FCOE_CTLR_MAX_SOL) {
+ /*
+ * no response on this vlan, remove from the list.
+ * Try the next vlan
+ */
+ list_del(&vlan->list);
+ kfree(vlan);
+ vlan = NULL;
+ if (list_empty(&fnic2->vlan_list)) {
+ /* we exhausted all vlans, restart vlan disc */
+ spin_unlock_irqrestore(&fnic2->vlans_lock, flags);
+ fnic2_fcoe_send_vlan_req(fnic2);
+ return;
+ }
+ /* check the next vlan */
+ vlan = list_first_entry(&fnic2->vlan_list, struct fcoe_vlan, list);
+
+ fnic2->set_vlan(fnic2, vlan->vid);
+ vlan->state = FIP_VLAN_SENT; /* sent now */
+
+ }
+ } else {
+ fnic2->set_vlan(fnic2, vlan->vid);
+ vlan->state = FIP_VLAN_SENT; /* sent now */
+ }
+ vlan->sol_count++;
+ spin_unlock_irqrestore(&fnic2->vlans_lock, flags);
+ fnic2_fcoe_start_fcf_discovery(fnic2);
+}
+
+/*
+ * fnic2_work_on_fcs_ka_timer - finish handling fcs_ka_timer in process context
+ *
+ * We need to finish this timer in a process context so that we do
+ * not hand in fip_common_cleanup. Here we clean up, bring the link down
+ * and restart all FIP discovery.
+ *
+ * @work - the work queue that we will be servicing
+ */
+void fnic2_work_on_fcs_ka_timer(struct work_struct *work)
+{
+ struct fnic2 *fnic2 = container_of(work, struct fnic2, fip_work);
+ struct fnic2_lport *lport = &fnic2->lport;
+
+ pr_debug("fnic2 0x%pK fcs ka timeout\n", fnic2);
+
+ fnic2_common_fip_cleanup(fnic2);
+ fnic2_fdls_link_down(lport);
+
+ lport->state = FNIC2_IPORT_STATE_FIP;
+ fnic2_fcoe_send_vlan_req(fnic2);
+}
+
+/*
+ * fnic2_handle_fcs_ka_timer
+ *
+ * No keep alives received from FCF. Clean up, bring the link down
+ * and restart all the FIP discovery.
+ *
+ * @param data Opaque pointer to fnic2 structure
+ */
+void fnic2_handle_fcs_ka_timer(struct timer_list *timer)
+{
+ struct fnic2 *fnic2 = container_of(timer, struct fnic2, fcs_ka_timer);
+ INIT_WORK(&fnic2->fip_work, fnic2_work_on_fcs_ka_timer);
+ queue_work(fip_event_queue, &fnic2->fip_work);
+}
diff --git a/drivers/staging/fnic2/src/fip.h b/drivers/staging/fnic2/src/fip.h
new file mode 100644
index 0000000..04a522e
--- /dev/null
+++ b/drivers/staging/fnic2/src/fip.h
@@ -0,0 +1,336 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0
+ * Copyright 2018 Cisco Systems, Inc. All rights reserved.
+ *
+ * This program is free software; you may redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef _FIP_H_
+#define _FIP_H_
+
+#include "fdls_fc.h"
+
+#define FCOE_ALL_FCFS_MAC {0x01, 0x10, 0x18, 0x01, 0x00, 0x02}
+#define FIP_ETH_TYPE 0x8914
+
+#define FIP_ETH_TYPE_LE 0x1489
+#define FCOE_MAX_SIZE_LE 0x2E08
+
+enum fcoe_ctlr {
+ FCOE_CTLR_MAX_SOL = 5,
+ FCOE_CTLR_FIPVLAN_TOV = (3*1000),
+ FCOE_CTLR_FCS_TOV = (3*1000),
+ FCOE_CTLR_ENODE_KA_TOV = (8*1000),
+ FCOE_CTLR_VN_KA_TOV = (90*1000),
+};
+
+/*
+ * VLAN entry.
+ */
+struct fcoe_vlan {
+ struct list_head list;
+ uint16_t vid; /* vlan ID */
+ uint16_t sol_count; /* no. of sols sent */
+ uint16_t state; /* state */
+};
+
+enum fdls_vlan_state {
+ FIP_VLAN_AVAIL,
+ FIP_VLAN_SENT
+};
+
+enum fdls_fip_state {
+ FDLS_FIP_INIT,
+ FDLS_FIP_VLAN_DISCOVERY_STARTED,
+ FDLS_FIP_FCF_DISCOVERY_STARTED,
+ FDLS_FIP_FLOGI_STARTED,
+ FDLS_FIP_FLOGI_COMPLETE,
+};
+
+enum fip_protocol_code {
+ FIP_DISCOVERY = 1,
+ FIP_FLOGI,
+ FIP_KA_CVL,
+ FIP_VLAN_DISC
+};
+
+#define FIP_SUBCODE_REQ 1
+#define FIP_SUBCODE_RESP 2
+
+struct eth_hdr {
+ uint8_t dmac[6];
+ uint8_t smac[6];
+ uint16_t eth_type;
+};
+
+struct fip_header {
+ uint16_t ver;
+
+ uint16_t protocol;
+ uint16_t subcode;
+
+ uint16_t desc_len;
+ uint16_t flags;
+} __attribute__((__packed__));
+
+#define FIP_FLAG_S 0x2
+#define FIP_FLAG_A 0x4
+
+enum fip_desc_type {
+ FIP_TYPE_MAC = 2,
+ FIP_TYPE_NAME_ID = 4,
+ FIP_TYPE_MAX_FCOE = 6,
+ FIP_TYPE_FLOGI = 7,
+ FIP_TYPE_VX_PORT = 11,
+ FIP_TYPE_VLAN = 14
+};
+
+struct fip_mac_desc {
+ uint8_t type;
+ uint8_t len;
+ uint8_t mac[6];
+} __attribute__((__packed__));
+
+struct fip_vlan_desc {
+ uint8_t type;
+ uint8_t len;
+ uint16_t vlan;
+} __attribute__((__packed__));
+
+struct fip_vlan_req {
+ struct eth_hdr eth;
+ struct fip_header fip;
+ struct fip_mac_desc mac_desc;
+} __attribute__((__packed__));
+
+ /*
+ * Variables:
+ * eth.smac, mac_desc.mac
+ */
+struct fip_vlan_req fip_vlan_reqmpl = {
+ .eth = { .dmac = FCOE_ALL_FCFS_MAC,
+ .eth_type = FIP_ETH_TYPE_LE},
+ .fip = { .ver = 0x10,
+ .protocol = FIP_VLAN_DISC << 8,
+ .subcode = FIP_SUBCODE_REQ << 8,
+ .desc_len = 2 << 8},
+ .mac_desc = {.type = FIP_TYPE_MAC, .len = 2 }
+};
+
+struct fip_vlan_notif {
+ struct fip_header fip;
+ struct fip_vlan_desc vlans_desc[0];
+} __attribute__((__packed__));
+
+struct fip_vn_port_desc {
+ uint8_t type;
+ uint8_t len;
+ uint8_t vn_port_mac[6];
+ uint8_t rsvd[1];
+ uint8_t vn_port_id[3];
+ uint64_t vn_port_name;
+} __attribute__((__packed__));
+
+struct fip_vn_port_ka {
+ struct eth_hdr eth;
+ struct fip_header fip;
+ struct fip_mac_desc mac_desc;
+ struct fip_vn_port_desc vn_port_desc;
+} __attribute__((__packed__));
+
+/*
+ * Variables:
+ * fcf_mac, eth.smac, mac_desc.enode_mac
+ * vn_port_desc:mac, id, port_name
+ */
+struct fip_vn_port_ka fip_vn_port_kampl = {
+
+ .eth = {
+ .eth_type = FIP_ETH_TYPE_LE},
+ .fip = {
+ .ver = 0x10,
+ .protocol = FIP_KA_CVL << 8,
+ .subcode = FIP_SUBCODE_REQ << 8,
+ .desc_len = 7 << 8
+ },
+ .mac_desc = {.type = FIP_TYPE_MAC, .len = 2 },
+ .vn_port_desc = {.type = FIP_TYPE_VX_PORT, .len = 5}
+};
+
+struct fip_enode_ka {
+ struct eth_hdr eth;
+ struct fip_header fip;
+ struct fip_mac_desc mac_desc;
+} __attribute__((__packed__));
+
+/*
+ * Variables:
+ * fcf_mac, eth.smac, mac_desc.enode_mac
+ */
+struct fip_enode_ka fip_enode_kampl = {
+
+ .eth = {
+ .eth_type = FIP_ETH_TYPE_LE},
+ .fip = {
+ .ver = 0x10,
+ .protocol = FIP_KA_CVL << 8,
+ .subcode = FIP_SUBCODE_REQ << 8,
+ .desc_len = 2 << 8
+ },
+ .mac_desc = {.type = FIP_TYPE_MAC, .len = 2 }
+};
+
+struct fip_name_desc {
+ uint8_t type;
+ uint8_t len;
+ uint8_t rsvd[2];
+ uint64_t name;
+} __attribute__((__packed__));
+
+struct fip_cvl {
+ struct fip_header fip;
+ struct fip_mac_desc fcf_mac_desc;
+ struct fip_name_desc name_desc;
+ struct fip_vn_port_desc vn_ports_desc[0];
+} __attribute__((__packed__));
+
+struct fip_flogi_desc {
+ uint8_t type;
+ uint8_t len;
+ uint16_t rsvd;
+ struct fc_els flogi;
+} __attribute__((__packed__));
+
+struct fip_flogi_rsp_desc {
+ uint8_t type;
+ uint8_t len;
+ uint16_t rsvd;
+ struct fc_els els;
+} __attribute__((__packed__));
+
+struct fip_flogi {
+ struct eth_hdr eth;
+ struct fip_header fip;
+ struct fip_flogi_desc flogi_desc;
+ struct fip_mac_desc mac_desc;
+} __attribute__((__packed__));
+
+struct fip_flogi_rsp {
+ struct fip_header fip;
+ struct fip_flogi_rsp_desc rsp_desc;
+ struct fip_mac_desc mac_desc;
+} __attribute__((__packed__));
+
+/*
+ * Variables:
+ * fcf_mac, eth.smac, mac_desc.enode_mac
+ */
+struct fip_flogi fip_flogimpl = {
+
+ .eth = {
+ .eth_type = FIP_ETH_TYPE_LE},
+ .fip = {
+ .ver = 0x10,
+ .protocol = FIP_FLOGI << 8,
+ .subcode = FIP_SUBCODE_REQ << 8,
+ .desc_len = 38 << 8,
+ .flags = 0x80 },
+ .flogi_desc = {
+ .type = FIP_TYPE_FLOGI, .len = 36,
+ .flogi = {
+ .fchdr = {
+ .r_ctl = 0x22,
+ .d_id = {0xFF, 0xFF, 0xFE},
+ .type = 0x01,
+ .f_ctl = {FNIC2_ELS_REQ_FCTL, 0x00, 0x00},
+ .ox_id = FNIC2_FLOGI_OXID,
+ .rx_id = 0xFFFF },
+ .command = FC_ELS_FLOGI_REQ,
+ .u.csp_flogi = {
+ .fc_ph_ver = FNIC2_FC_PH_VER,
+ .b2b_credits = FNIC2_FC_B2B_CREDIT,
+ .b2b_rdf_size = FNIC2_FC_B2B_RDF_SZ },
+ .spc3 = {0x88, 0x00}
+ }
+ },
+ .mac_desc = {.type = FIP_TYPE_MAC, .len = 2 }
+};
+
+struct fip_fcoe_desc {
+ uint8_t type;
+ uint8_t len;
+ uint16_t max_fcoe_size;
+} __attribute__((__packed__));
+
+struct fip_discovery {
+ struct eth_hdr eth;
+ struct fip_header fip;
+ struct fip_mac_desc mac_desc;
+ struct fip_name_desc name_desc;
+ struct fip_fcoe_desc fcoe_desc;
+} __attribute__((__packed__));
+
+/*
+ * Variables:
+ * eth.smac, mac_desc.enode_mac, node_name
+ */
+struct fip_discovery fip_discoverympl = {
+
+ .eth = {.dmac = FCOE_ALL_FCFS_MAC,
+ .eth_type = FIP_ETH_TYPE_LE},
+ .fip = {
+ .ver = 0x10, .protocol = FIP_DISCOVERY << 8,
+ .subcode = FIP_SUBCODE_REQ << 8, .desc_len = 6 << 8,
+ .flags = 0x80},
+ .mac_desc = {.type = FIP_TYPE_MAC, .len = 2 },
+ .name_desc = {.type = FIP_TYPE_NAME_ID, .len = 3},
+ .fcoe_desc = {
+ .type = FIP_TYPE_MAX_FCOE, .len = 1,
+ .max_fcoe_size = FCOE_MAX_SIZE_LE
+ }
+};
+
+struct fip_prio_desc {
+ uint8_t type;
+ uint8_t len;
+ uint8_t rsvd;
+ uint8_t priority;
+} __attribute__((__packed__));
+
+struct fip_fabric_desc {
+ uint8_t type;
+ uint8_t len;
+ uint16_t vf_id;
+ uint8_t rsvd;
+ uint8_t fc_map[3];
+ uint64_t fabric_name;
+} __attribute__((__packed__));
+
+struct fip_fka_adv_desc {
+ uint8_t type;
+ uint8_t len;
+ uint8_t rsvd;
+ uint8_t rsvd_D;
+ uint32_t fka_adv;
+} __attribute__((__packed__));
+
+struct fip_disc_adv {
+ struct fip_header fip;
+ struct fip_prio_desc prio_desc;
+ struct fip_mac_desc mac_desc;
+ struct fip_name_desc name_desc;
+ struct fip_fabric_desc fabric_desc;
+ struct fip_fka_adv_desc fka_adv_desc;
+} __attribute__((__packed__));
+#endif /* _FIP_H_ */
--
1.8.3.1
next prev parent reply other threads:[~2018-04-05 21:18 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-04-05 21:15 [PATCH 00/10] staging: fnic2 Driver Introduction Oliver Smith-Denny
2018-04-05 21:16 ` [PATCH 01/10] staging: fnic2 add initialization Oliver Smith-Denny
2018-04-06 5:07 ` Greg Kroah-Hartman
2018-04-06 22:00 ` Oliver Smith-Denny
2018-04-07 6:09 ` Greg Kroah-Hartman
2018-04-09 19:49 ` Oliver Smith-Denny
2018-04-09 20:57 ` Martin K. Petersen
2018-04-12 17:32 ` Oliver Smith-Denny
2018-04-05 21:17 ` [PATCH 02/10] staging: fnic2 add resource allocation Oliver Smith-Denny
2018-04-06 5:08 ` Greg Kroah-Hartman
2018-04-05 21:18 ` Oliver Smith-Denny [this message]
2018-04-06 5:08 ` [PATCH 03/10] staging: fnic2 add fip handling Greg Kroah-Hartman
2018-04-05 21:19 ` [PATCH 04/10] staging: fnic2 add fdls system Oliver Smith-Denny
2018-04-05 21:20 ` [PATCH 05/10] staging: fnic2 add LIO interface Oliver Smith-Denny
2018-04-05 21:21 ` [PATCH 06/10] staging: fnic2 add main frame processing Oliver Smith-Denny
2018-04-05 21:21 ` [PATCH 07/10] staging: fnic2 add queue descriptors Oliver Smith-Denny
2018-04-05 21:22 ` [PATCH 08/10] staging: fnic2 add vnic queue interface Oliver Smith-Denny
2018-04-05 21:23 ` [PATCH 09/10] staging: fnic2 add vnic handling Oliver Smith-Denny
2018-04-05 21:24 ` [PATCH 10/10] staging: fnic2 add build and config Oliver Smith-Denny
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20180405211837.GD12584@osmithde-lnx.cisco.com \
--to=osmithde@cisco.com \
--cc=gcboffa@cisco.com \
--cc=gregkh@linuxfoundation.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-scsi@vger.kernel.org \
--cc=sebaddel@cisco.com \
--cc=target-devel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox