19b34ecffd59d6ed66fdd6906e8a092a33e7c8564Vasu Dev/* 297c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt * Copyright (c) 2008-2009 Cisco Systems, Inc. All rights reserved. 397c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt * Copyright (c) 2009 Intel Corporation. All rights reserved. 49b34ecffd59d6ed66fdd6906e8a092a33e7c8564Vasu Dev * 59b34ecffd59d6ed66fdd6906e8a092a33e7c8564Vasu Dev * This program is free software; you can redistribute it and/or modify it 69b34ecffd59d6ed66fdd6906e8a092a33e7c8564Vasu Dev * under the terms and conditions of the GNU General Public License, 79b34ecffd59d6ed66fdd6906e8a092a33e7c8564Vasu Dev * version 2, as published by the Free Software Foundation. 89b34ecffd59d6ed66fdd6906e8a092a33e7c8564Vasu Dev * 99b34ecffd59d6ed66fdd6906e8a092a33e7c8564Vasu Dev * This program is distributed in the hope it will be useful, but WITHOUT 109b34ecffd59d6ed66fdd6906e8a092a33e7c8564Vasu Dev * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 119b34ecffd59d6ed66fdd6906e8a092a33e7c8564Vasu Dev * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 129b34ecffd59d6ed66fdd6906e8a092a33e7c8564Vasu Dev * more details. 139b34ecffd59d6ed66fdd6906e8a092a33e7c8564Vasu Dev * 149b34ecffd59d6ed66fdd6906e8a092a33e7c8564Vasu Dev * You should have received a copy of the GNU General Public License along with 159b34ecffd59d6ed66fdd6906e8a092a33e7c8564Vasu Dev * this program; if not, write to the Free Software Foundation, Inc., 169b34ecffd59d6ed66fdd6906e8a092a33e7c8564Vasu Dev * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. 179b34ecffd59d6ed66fdd6906e8a092a33e7c8564Vasu Dev * 189b34ecffd59d6ed66fdd6906e8a092a33e7c8564Vasu Dev * Maintained at www.Open-FCoE.org 199b34ecffd59d6ed66fdd6906e8a092a33e7c8564Vasu Dev */ 209b34ecffd59d6ed66fdd6906e8a092a33e7c8564Vasu Dev 2197c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt#include <linux/types.h> 229b34ecffd59d6ed66fdd6906e8a092a33e7c8564Vasu Dev#include <linux/module.h> 2397c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt#include <linux/kernel.h> 2497c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt#include <linux/list.h> 2597c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt#include <linux/spinlock.h> 2697c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt#include <linux/timer.h> 275e80f7f7c87990ffe7856a0d35a94ea52b8f4c59Vasu Dev#include <linux/netdevice.h> 2897c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt#include <linux/etherdevice.h> 2997c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt#include <linux/ethtool.h> 3097c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt#include <linux/if_ether.h> 3197c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt#include <linux/if_vlan.h> 3297c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt#include <linux/errno.h> 3397c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt#include <linux/bitops.h> 345a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 3597c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt#include <net/rtnetlink.h> 3697c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt 3797c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt#include <scsi/fc/fc_els.h> 3897c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt#include <scsi/fc/fc_fs.h> 3997c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt#include <scsi/fc/fc_fip.h> 4097c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt#include <scsi/fc/fc_encaps.h> 4197c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt#include <scsi/fc/fc_fcoe.h> 42e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt#include <scsi/fc/fc_fcp.h> 435e80f7f7c87990ffe7856a0d35a94ea52b8f4c59Vasu Dev 445e80f7f7c87990ffe7856a0d35a94ea52b8f4c59Vasu Dev#include <scsi/libfc.h> 4597c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt#include <scsi/libfcoe.h> 469b34ecffd59d6ed66fdd6906e8a092a33e7c8564Vasu Dev 4721b7b2f557f4b105a4b7d739671d1ce6b867d3e6Yi Zou#include "libfcoe.h" 4821b7b2f557f4b105a4b7d739671d1ce6b867d3e6Yi Zou 4997c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt#define FCOE_CTLR_MIN_FKA 500 /* min keep alive (mS) */ 5097c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt#define FCOE_CTLR_DEF_FKA FIP_DEF_FKA /* default keep alive (mS) */ 5197c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt 5297c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholtstatic void fcoe_ctlr_timeout(unsigned long); 534291365784c9622c9d643cf23421f9c7b9662d71Joe Eykholtstatic void fcoe_ctlr_timer_work(struct work_struct *); 5497c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholtstatic void fcoe_ctlr_recv_work(struct work_struct *); 55794d98e77f5901ceded697f1633463e88f078038Joe Eykholtstatic int fcoe_ctlr_flogi_retry(struct fcoe_ctlr *); 5697c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt 57e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholtstatic void fcoe_ctlr_vn_start(struct fcoe_ctlr *); 58e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholtstatic int fcoe_ctlr_vn_recv(struct fcoe_ctlr *, struct sk_buff *); 59e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholtstatic void fcoe_ctlr_vn_timeout(struct fcoe_ctlr *); 60e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholtstatic int fcoe_ctlr_vn_lookup(struct fcoe_ctlr *, u32, u8 *); 61e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt 6297c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholtstatic u8 fcoe_all_fcfs[ETH_ALEN] = FIP_ALL_FCF_MACS; 63e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholtstatic u8 fcoe_all_enode[ETH_ALEN] = FIP_ALL_ENODE_MACS; 64e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholtstatic u8 fcoe_all_vn2vn[ETH_ALEN] = FIP_ALL_VN2VN_MACS; 65e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholtstatic u8 fcoe_all_p2p[ETH_ALEN] = FIP_ALL_P2P_MACS; 6697c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt 670095a9213324a4466c10de98837a27ab1b7e72beYi Zoustatic const char * const fcoe_ctlr_states[] = { 689b651da900ccfe5581befb46eb06ef781a1d7e74Joe Eykholt [FIP_ST_DISABLED] = "DISABLED", 699b651da900ccfe5581befb46eb06ef781a1d7e74Joe Eykholt [FIP_ST_LINK_WAIT] = "LINK_WAIT", 709b651da900ccfe5581befb46eb06ef781a1d7e74Joe Eykholt [FIP_ST_AUTO] = "AUTO", 719b651da900ccfe5581befb46eb06ef781a1d7e74Joe Eykholt [FIP_ST_NON_FIP] = "NON_FIP", 729b651da900ccfe5581befb46eb06ef781a1d7e74Joe Eykholt [FIP_ST_ENABLED] = "ENABLED", 73e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt [FIP_ST_VNMP_START] = "VNMP_START", 74e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt [FIP_ST_VNMP_PROBE1] = "VNMP_PROBE1", 75e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt [FIP_ST_VNMP_PROBE2] = "VNMP_PROBE2", 76e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt [FIP_ST_VNMP_CLAIM] = "VNMP_CLAIM", 77e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt [FIP_ST_VNMP_UP] = "VNMP_UP", 789b651da900ccfe5581befb46eb06ef781a1d7e74Joe Eykholt}; 799b651da900ccfe5581befb46eb06ef781a1d7e74Joe Eykholt 809b651da900ccfe5581befb46eb06ef781a1d7e74Joe Eykholtstatic const char *fcoe_ctlr_state(enum fip_state state) 819b651da900ccfe5581befb46eb06ef781a1d7e74Joe Eykholt{ 829b651da900ccfe5581befb46eb06ef781a1d7e74Joe Eykholt const char *cp = "unknown"; 839b651da900ccfe5581befb46eb06ef781a1d7e74Joe Eykholt 849b651da900ccfe5581befb46eb06ef781a1d7e74Joe Eykholt if (state < ARRAY_SIZE(fcoe_ctlr_states)) 859b651da900ccfe5581befb46eb06ef781a1d7e74Joe Eykholt cp = fcoe_ctlr_states[state]; 869b651da900ccfe5581befb46eb06ef781a1d7e74Joe Eykholt if (!cp) 879b651da900ccfe5581befb46eb06ef781a1d7e74Joe Eykholt cp = "unknown"; 889b651da900ccfe5581befb46eb06ef781a1d7e74Joe Eykholt return cp; 899b651da900ccfe5581befb46eb06ef781a1d7e74Joe Eykholt} 909b651da900ccfe5581befb46eb06ef781a1d7e74Joe Eykholt 919b651da900ccfe5581befb46eb06ef781a1d7e74Joe Eykholt/** 929b651da900ccfe5581befb46eb06ef781a1d7e74Joe Eykholt * fcoe_ctlr_set_state() - Set and do debug printing for the new FIP state. 939b651da900ccfe5581befb46eb06ef781a1d7e74Joe Eykholt * @fip: The FCoE controller 949b651da900ccfe5581befb46eb06ef781a1d7e74Joe Eykholt * @state: The new state 959b651da900ccfe5581befb46eb06ef781a1d7e74Joe Eykholt */ 969b651da900ccfe5581befb46eb06ef781a1d7e74Joe Eykholtstatic void fcoe_ctlr_set_state(struct fcoe_ctlr *fip, enum fip_state state) 979b651da900ccfe5581befb46eb06ef781a1d7e74Joe Eykholt{ 989b651da900ccfe5581befb46eb06ef781a1d7e74Joe Eykholt if (state == fip->state) 999b651da900ccfe5581befb46eb06ef781a1d7e74Joe Eykholt return; 1009b651da900ccfe5581befb46eb06ef781a1d7e74Joe Eykholt if (fip->lp) 1019b651da900ccfe5581befb46eb06ef781a1d7e74Joe Eykholt LIBFCOE_FIP_DBG(fip, "state %s -> %s\n", 1029b651da900ccfe5581befb46eb06ef781a1d7e74Joe Eykholt fcoe_ctlr_state(fip->state), fcoe_ctlr_state(state)); 1039b651da900ccfe5581befb46eb06ef781a1d7e74Joe Eykholt fip->state = state; 1049b651da900ccfe5581befb46eb06ef781a1d7e74Joe Eykholt} 1059b651da900ccfe5581befb46eb06ef781a1d7e74Joe Eykholt 10670b51aabf3b03fbf8d61c14847ccce4c69fb0cddRobert Love/** 10770b51aabf3b03fbf8d61c14847ccce4c69fb0cddRobert Love * fcoe_ctlr_mtu_valid() - Check if a FCF's MTU is valid 10870b51aabf3b03fbf8d61c14847ccce4c69fb0cddRobert Love * @fcf: The FCF to check 10970b51aabf3b03fbf8d61c14847ccce4c69fb0cddRobert Love * 11097c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt * Return non-zero if FCF fcoe_size has been validated. 11197c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt */ 11297c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholtstatic inline int fcoe_ctlr_mtu_valid(const struct fcoe_fcf *fcf) 11397c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt{ 11497c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt return (fcf->flags & FIP_FL_SOL) != 0; 11597c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt} 11697c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt 11770b51aabf3b03fbf8d61c14847ccce4c69fb0cddRobert Love/** 11870b51aabf3b03fbf8d61c14847ccce4c69fb0cddRobert Love * fcoe_ctlr_fcf_usable() - Check if a FCF is usable 11970b51aabf3b03fbf8d61c14847ccce4c69fb0cddRobert Love * @fcf: The FCF to check 12070b51aabf3b03fbf8d61c14847ccce4c69fb0cddRobert Love * 12197c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt * Return non-zero if the FCF is usable. 12297c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt */ 12397c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholtstatic inline int fcoe_ctlr_fcf_usable(struct fcoe_fcf *fcf) 12497c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt{ 12597c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt u16 flags = FIP_FL_SOL | FIP_FL_AVAIL; 12697c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt 12797c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt return (fcf->flags & flags) == flags; 12897c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt} 12997c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt 13097c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt/** 131cd229e42eb8cdfdcbe15dfeec39c3641f62de43aJoe Eykholt * fcoe_ctlr_map_dest() - Set flag and OUI for mapping destination addresses 132cd229e42eb8cdfdcbe15dfeec39c3641f62de43aJoe Eykholt * @fip: The FCoE controller 133cd229e42eb8cdfdcbe15dfeec39c3641f62de43aJoe Eykholt */ 134cd229e42eb8cdfdcbe15dfeec39c3641f62de43aJoe Eykholtstatic void fcoe_ctlr_map_dest(struct fcoe_ctlr *fip) 135cd229e42eb8cdfdcbe15dfeec39c3641f62de43aJoe Eykholt{ 136cd229e42eb8cdfdcbe15dfeec39c3641f62de43aJoe Eykholt if (fip->mode == FIP_MODE_VN2VN) 137cd229e42eb8cdfdcbe15dfeec39c3641f62de43aJoe Eykholt hton24(fip->dest_addr, FIP_VN_FC_MAP); 138cd229e42eb8cdfdcbe15dfeec39c3641f62de43aJoe Eykholt else 139cd229e42eb8cdfdcbe15dfeec39c3641f62de43aJoe Eykholt hton24(fip->dest_addr, FIP_DEF_FC_MAP); 140cd229e42eb8cdfdcbe15dfeec39c3641f62de43aJoe Eykholt hton24(fip->dest_addr + 3, 0); 141cd229e42eb8cdfdcbe15dfeec39c3641f62de43aJoe Eykholt fip->map_dest = 1; 142cd229e42eb8cdfdcbe15dfeec39c3641f62de43aJoe Eykholt} 143cd229e42eb8cdfdcbe15dfeec39c3641f62de43aJoe Eykholt 144cd229e42eb8cdfdcbe15dfeec39c3641f62de43aJoe Eykholt/** 14570b51aabf3b03fbf8d61c14847ccce4c69fb0cddRobert Love * fcoe_ctlr_init() - Initialize the FCoE Controller instance 14670b51aabf3b03fbf8d61c14847ccce4c69fb0cddRobert Love * @fip: The FCoE controller to initialize 14797c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt */ 1483d902ac09a2812b359edf633425d1327a18399e9Joe Eykholtvoid fcoe_ctlr_init(struct fcoe_ctlr *fip, enum fip_state mode) 14997c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt{ 1509b651da900ccfe5581befb46eb06ef781a1d7e74Joe Eykholt fcoe_ctlr_set_state(fip, FIP_ST_LINK_WAIT); 1513d902ac09a2812b359edf633425d1327a18399e9Joe Eykholt fip->mode = mode; 15297c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt INIT_LIST_HEAD(&fip->fcfs); 153fdb068c6cd6e30d43664f856d3530715a5742713Joe Eykholt mutex_init(&fip->ctlr_mutex); 154794d98e77f5901ceded697f1633463e88f078038Joe Eykholt spin_lock_init(&fip->ctlr_lock); 15597c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt fip->flogi_oxid = FC_XID_UNKNOWN; 15697c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt setup_timer(&fip->timer, fcoe_ctlr_timeout, (unsigned long)fip); 1574291365784c9622c9d643cf23421f9c7b9662d71Joe Eykholt INIT_WORK(&fip->timer_work, fcoe_ctlr_timer_work); 15897c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt INIT_WORK(&fip->recv_work, fcoe_ctlr_recv_work); 15997c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt skb_queue_head_init(&fip->fip_recv_list); 16097c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt} 16197c8389d54b9665c38105ea72a428a44b97ff2f6Joe EykholtEXPORT_SYMBOL(fcoe_ctlr_init); 16297c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt 16397c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt/** 16470b51aabf3b03fbf8d61c14847ccce4c69fb0cddRobert Love * fcoe_ctlr_reset_fcfs() - Reset and free all FCFs for a controller 16570b51aabf3b03fbf8d61c14847ccce4c69fb0cddRobert Love * @fip: The FCoE controller whose FCFs are to be reset 16697c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt * 16797c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt * Called with &fcoe_ctlr lock held. 16897c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt */ 16997c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholtstatic void fcoe_ctlr_reset_fcfs(struct fcoe_ctlr *fip) 17097c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt{ 17197c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt struct fcoe_fcf *fcf; 17297c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt struct fcoe_fcf *next; 17397c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt 17497c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt fip->sel_fcf = NULL; 17597c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt list_for_each_entry_safe(fcf, next, &fip->fcfs, list) { 17697c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt list_del(&fcf->list); 17797c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt kfree(fcf); 17897c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt } 17997c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt fip->fcf_count = 0; 18097c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt fip->sel_time = 0; 18197c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt} 18297c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt 18397c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt/** 18470b51aabf3b03fbf8d61c14847ccce4c69fb0cddRobert Love * fcoe_ctlr_destroy() - Disable and tear down a FCoE controller 18570b51aabf3b03fbf8d61c14847ccce4c69fb0cddRobert Love * @fip: The FCoE controller to tear down 18697c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt * 18797c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt * This is called by FCoE drivers before freeing the &fcoe_ctlr. 18897c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt * 18997c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt * The receive handler will have been deleted before this to guarantee 19097c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt * that no more recv_work will be scheduled. 19197c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt * 19297c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt * The timer routine will simply return once we set FIP_ST_DISABLED. 19397c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt * This guarantees that no further timeouts or work will be scheduled. 19497c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt */ 19597c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholtvoid fcoe_ctlr_destroy(struct fcoe_ctlr *fip) 19697c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt{ 197a4b7cfaee487caef913be978dce60896fe741268Chris Leech cancel_work_sync(&fip->recv_work); 1981f4aed818d26eb9ed54520fbeb85d5ee691baa94Joe Eykholt skb_queue_purge(&fip->fip_recv_list); 199a4b7cfaee487caef913be978dce60896fe741268Chris Leech 200fdb068c6cd6e30d43664f856d3530715a5742713Joe Eykholt mutex_lock(&fip->ctlr_mutex); 2019b651da900ccfe5581befb46eb06ef781a1d7e74Joe Eykholt fcoe_ctlr_set_state(fip, FIP_ST_DISABLED); 20297c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt fcoe_ctlr_reset_fcfs(fip); 203fdb068c6cd6e30d43664f856d3530715a5742713Joe Eykholt mutex_unlock(&fip->ctlr_mutex); 20497c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt del_timer_sync(&fip->timer); 2054291365784c9622c9d643cf23421f9c7b9662d71Joe Eykholt cancel_work_sync(&fip->timer_work); 20697c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt} 20797c8389d54b9665c38105ea72a428a44b97ff2f6Joe EykholtEXPORT_SYMBOL(fcoe_ctlr_destroy); 20897c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt 20997c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt/** 210794d98e77f5901ceded697f1633463e88f078038Joe Eykholt * fcoe_ctlr_announce() - announce new FCF selection 21169316ee2e375c5af0cf1f8d2d30f9aa277f0b454Joe Eykholt * @fip: The FCoE controller 21269316ee2e375c5af0cf1f8d2d30f9aa277f0b454Joe Eykholt * 21369316ee2e375c5af0cf1f8d2d30f9aa277f0b454Joe Eykholt * Also sets the destination MAC for FCoE and control packets 214794d98e77f5901ceded697f1633463e88f078038Joe Eykholt * 215794d98e77f5901ceded697f1633463e88f078038Joe Eykholt * Called with neither ctlr_mutex nor ctlr_lock held. 21669316ee2e375c5af0cf1f8d2d30f9aa277f0b454Joe Eykholt */ 21769316ee2e375c5af0cf1f8d2d30f9aa277f0b454Joe Eykholtstatic void fcoe_ctlr_announce(struct fcoe_ctlr *fip) 21869316ee2e375c5af0cf1f8d2d30f9aa277f0b454Joe Eykholt{ 219794d98e77f5901ceded697f1633463e88f078038Joe Eykholt struct fcoe_fcf *sel; 220794d98e77f5901ceded697f1633463e88f078038Joe Eykholt struct fcoe_fcf *fcf; 221794d98e77f5901ceded697f1633463e88f078038Joe Eykholt 222794d98e77f5901ceded697f1633463e88f078038Joe Eykholt mutex_lock(&fip->ctlr_mutex); 223794d98e77f5901ceded697f1633463e88f078038Joe Eykholt spin_lock_bh(&fip->ctlr_lock); 224794d98e77f5901ceded697f1633463e88f078038Joe Eykholt 225794d98e77f5901ceded697f1633463e88f078038Joe Eykholt kfree_skb(fip->flogi_req); 226794d98e77f5901ceded697f1633463e88f078038Joe Eykholt fip->flogi_req = NULL; 227794d98e77f5901ceded697f1633463e88f078038Joe Eykholt list_for_each_entry(fcf, &fip->fcfs, list) 228794d98e77f5901ceded697f1633463e88f078038Joe Eykholt fcf->flogi_sent = 0; 229794d98e77f5901ceded697f1633463e88f078038Joe Eykholt 230794d98e77f5901ceded697f1633463e88f078038Joe Eykholt spin_unlock_bh(&fip->ctlr_lock); 231794d98e77f5901ceded697f1633463e88f078038Joe Eykholt sel = fip->sel_fcf; 23269316ee2e375c5af0cf1f8d2d30f9aa277f0b454Joe Eykholt 23369316ee2e375c5af0cf1f8d2d30f9aa277f0b454Joe Eykholt if (sel && !compare_ether_addr(sel->fcf_mac, fip->dest_addr)) 234794d98e77f5901ceded697f1633463e88f078038Joe Eykholt goto unlock; 23569316ee2e375c5af0cf1f8d2d30f9aa277f0b454Joe Eykholt if (!is_zero_ether_addr(fip->dest_addr)) { 23669316ee2e375c5af0cf1f8d2d30f9aa277f0b454Joe Eykholt printk(KERN_NOTICE "libfcoe: host%d: " 23769316ee2e375c5af0cf1f8d2d30f9aa277f0b454Joe Eykholt "FIP Fibre-Channel Forwarder MAC %pM deselected\n", 23869316ee2e375c5af0cf1f8d2d30f9aa277f0b454Joe Eykholt fip->lp->host->host_no, fip->dest_addr); 23969316ee2e375c5af0cf1f8d2d30f9aa277f0b454Joe Eykholt memset(fip->dest_addr, 0, ETH_ALEN); 24069316ee2e375c5af0cf1f8d2d30f9aa277f0b454Joe Eykholt } 24169316ee2e375c5af0cf1f8d2d30f9aa277f0b454Joe Eykholt if (sel) { 24269316ee2e375c5af0cf1f8d2d30f9aa277f0b454Joe Eykholt printk(KERN_INFO "libfcoe: host%d: FIP selected " 24369316ee2e375c5af0cf1f8d2d30f9aa277f0b454Joe Eykholt "Fibre-Channel Forwarder MAC %pM\n", 24469316ee2e375c5af0cf1f8d2d30f9aa277f0b454Joe Eykholt fip->lp->host->host_no, sel->fcf_mac); 24581c11dd2ed154b351eb6ee3443e07094a1d53ce1Bhanu Prakash Gollapudi memcpy(fip->dest_addr, sel->fcoe_mac, ETH_ALEN); 24669316ee2e375c5af0cf1f8d2d30f9aa277f0b454Joe Eykholt fip->map_dest = 0; 24769316ee2e375c5af0cf1f8d2d30f9aa277f0b454Joe Eykholt } 248794d98e77f5901ceded697f1633463e88f078038Joe Eykholtunlock: 249794d98e77f5901ceded697f1633463e88f078038Joe Eykholt mutex_unlock(&fip->ctlr_mutex); 25069316ee2e375c5af0cf1f8d2d30f9aa277f0b454Joe Eykholt} 25169316ee2e375c5af0cf1f8d2d30f9aa277f0b454Joe Eykholt 25269316ee2e375c5af0cf1f8d2d30f9aa277f0b454Joe Eykholt/** 25370b51aabf3b03fbf8d61c14847ccce4c69fb0cddRobert Love * fcoe_ctlr_fcoe_size() - Return the maximum FCoE size required for VN_Port 25470b51aabf3b03fbf8d61c14847ccce4c69fb0cddRobert Love * @fip: The FCoE controller to get the maximum FCoE size from 25597c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt * 25697c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt * Returns the maximum packet size including the FCoE header and trailer, 25797c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt * but not including any Ethernet or VLAN headers. 25897c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt */ 25997c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholtstatic inline u32 fcoe_ctlr_fcoe_size(struct fcoe_ctlr *fip) 26097c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt{ 26197c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt /* 26297c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt * Determine the max FCoE frame size allowed, including 26397c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt * FCoE header and trailer. 26497c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt * Note: lp->mfs is currently the payload size, not the frame size. 26597c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt */ 26697c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt return fip->lp->mfs + sizeof(struct fc_frame_header) + 26797c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt sizeof(struct fcoe_hdr) + sizeof(struct fcoe_crc_eof); 26897c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt} 26997c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt 27097c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt/** 27170b51aabf3b03fbf8d61c14847ccce4c69fb0cddRobert Love * fcoe_ctlr_solicit() - Send a FIP solicitation 27270b51aabf3b03fbf8d61c14847ccce4c69fb0cddRobert Love * @fip: The FCoE controller to send the solicitation on 27370b51aabf3b03fbf8d61c14847ccce4c69fb0cddRobert Love * @fcf: The destination FCF (if NULL, a multicast solicitation is sent) 27497c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt */ 27597c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholtstatic void fcoe_ctlr_solicit(struct fcoe_ctlr *fip, struct fcoe_fcf *fcf) 27697c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt{ 27797c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt struct sk_buff *skb; 27897c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt struct fip_sol { 27997c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt struct ethhdr eth; 28097c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt struct fip_header fip; 28197c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt struct { 28297c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt struct fip_mac_desc mac; 28397c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt struct fip_wwn_desc wwnn; 28497c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt struct fip_size_desc size; 2850095a9213324a4466c10de98837a27ab1b7e72beYi Zou } __packed desc; 2860095a9213324a4466c10de98837a27ab1b7e72beYi Zou } __packed * sol; 28797c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt u32 fcoe_size; 28897c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt 28997c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt skb = dev_alloc_skb(sizeof(*sol)); 29097c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt if (!skb) 29197c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt return; 29297c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt 29397c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt sol = (struct fip_sol *)skb->data; 29497c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt 29597c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt memset(sol, 0, sizeof(*sol)); 29697c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt memcpy(sol->eth.h_dest, fcf ? fcf->fcf_mac : fcoe_all_fcfs, ETH_ALEN); 29797c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt memcpy(sol->eth.h_source, fip->ctl_src_addr, ETH_ALEN); 29897c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt sol->eth.h_proto = htons(ETH_P_FIP); 29997c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt 30097c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt sol->fip.fip_ver = FIP_VER_ENCAPS(FIP_VER); 30197c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt sol->fip.fip_op = htons(FIP_OP_DISC); 30297c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt sol->fip.fip_subcode = FIP_SC_SOL; 30397c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt sol->fip.fip_dl_len = htons(sizeof(sol->desc) / FIP_BPW); 30497c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt sol->fip.fip_flags = htons(FIP_FL_FPMA); 305184dd3459bb334d9061b58faed3610d08d6c7ff8Vasu Dev if (fip->spma) 306184dd3459bb334d9061b58faed3610d08d6c7ff8Vasu Dev sol->fip.fip_flags |= htons(FIP_FL_SPMA); 30797c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt 30897c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt sol->desc.mac.fd_desc.fip_dtype = FIP_DT_MAC; 30997c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt sol->desc.mac.fd_desc.fip_dlen = sizeof(sol->desc.mac) / FIP_BPW; 31097c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt memcpy(sol->desc.mac.fd_mac, fip->ctl_src_addr, ETH_ALEN); 31197c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt 31297c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt sol->desc.wwnn.fd_desc.fip_dtype = FIP_DT_NAME; 31397c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt sol->desc.wwnn.fd_desc.fip_dlen = sizeof(sol->desc.wwnn) / FIP_BPW; 31497c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt put_unaligned_be64(fip->lp->wwnn, &sol->desc.wwnn.fd_wwn); 31597c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt 31697c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt fcoe_size = fcoe_ctlr_fcoe_size(fip); 31797c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt sol->desc.size.fd_desc.fip_dtype = FIP_DT_FCOE_SIZE; 31897c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt sol->desc.size.fd_desc.fip_dlen = sizeof(sol->desc.size) / FIP_BPW; 31997c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt sol->desc.size.fd_size = htons(fcoe_size); 32097c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt 32197c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt skb_put(skb, sizeof(*sol)); 3220f4915398a4233cdbfc4e9bf4436323546945b3fChris Leech skb->protocol = htons(ETH_P_FIP); 3236f6c2aa33b915c574543f176dee89d7aefc115c1john fastabend skb->priority = fip->priority; 32497c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt skb_reset_mac_header(skb); 32597c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt skb_reset_network_header(skb); 32697c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt fip->send(fip, skb); 32797c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt 32897c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt if (!fcf) 32997c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt fip->sol_time = jiffies; 33097c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt} 33197c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt 33297c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt/** 33370b51aabf3b03fbf8d61c14847ccce4c69fb0cddRobert Love * fcoe_ctlr_link_up() - Start FCoE controller 33470b51aabf3b03fbf8d61c14847ccce4c69fb0cddRobert Love * @fip: The FCoE controller to start 33597c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt * 33697c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt * Called from the LLD when the network link is ready. 33797c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt */ 33897c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholtvoid fcoe_ctlr_link_up(struct fcoe_ctlr *fip) 33997c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt{ 340fdb068c6cd6e30d43664f856d3530715a5742713Joe Eykholt mutex_lock(&fip->ctlr_mutex); 34197c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt if (fip->state == FIP_ST_NON_FIP || fip->state == FIP_ST_AUTO) { 342fdb068c6cd6e30d43664f856d3530715a5742713Joe Eykholt mutex_unlock(&fip->ctlr_mutex); 34397c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt fc_linkup(fip->lp); 34497c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt } else if (fip->state == FIP_ST_LINK_WAIT) { 3459b651da900ccfe5581befb46eb06ef781a1d7e74Joe Eykholt fcoe_ctlr_set_state(fip, fip->mode); 346e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt switch (fip->mode) { 347e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt default: 348e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt LIBFCOE_FIP_DBG(fip, "invalid mode %d\n", fip->mode); 349e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt /* fall-through */ 350e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt case FIP_MODE_AUTO: 3510f51c2e54c0bfdb6b02c53f6d7dd9b35f91821b6Joe Eykholt LIBFCOE_FIP_DBG(fip, "%s", "setting AUTO mode.\n"); 352e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt /* fall-through */ 353e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt case FIP_MODE_FABRIC: 354e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt case FIP_MODE_NON_FIP: 355e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt mutex_unlock(&fip->ctlr_mutex); 356e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt fc_linkup(fip->lp); 357e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt fcoe_ctlr_solicit(fip, NULL); 358e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt break; 359e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt case FIP_MODE_VN2VN: 360e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt fcoe_ctlr_vn_start(fip); 361e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt mutex_unlock(&fip->ctlr_mutex); 362e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt fc_linkup(fip->lp); 363e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt break; 364e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt } 36597c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt } else 366fdb068c6cd6e30d43664f856d3530715a5742713Joe Eykholt mutex_unlock(&fip->ctlr_mutex); 36797c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt} 36897c8389d54b9665c38105ea72a428a44b97ff2f6Joe EykholtEXPORT_SYMBOL(fcoe_ctlr_link_up); 36997c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt 37097c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt/** 37170b51aabf3b03fbf8d61c14847ccce4c69fb0cddRobert Love * fcoe_ctlr_reset() - Reset a FCoE controller 37270b51aabf3b03fbf8d61c14847ccce4c69fb0cddRobert Love * @fip: The FCoE controller to reset 37397c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt */ 374dd42dac4ecd1799077c132aab35d3c36b26d4d8cJoe Eykholtstatic void fcoe_ctlr_reset(struct fcoe_ctlr *fip) 37597c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt{ 37697c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt fcoe_ctlr_reset_fcfs(fip); 37797c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt del_timer(&fip->timer); 37897c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt fip->ctlr_ka_time = 0; 37997c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt fip->port_ka_time = 0; 38097c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt fip->sol_time = 0; 38197c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt fip->flogi_oxid = FC_XID_UNKNOWN; 382cd229e42eb8cdfdcbe15dfeec39c3641f62de43aJoe Eykholt fcoe_ctlr_map_dest(fip); 38397c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt} 38497c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt 38597c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt/** 38670b51aabf3b03fbf8d61c14847ccce4c69fb0cddRobert Love * fcoe_ctlr_link_down() - Stop a FCoE controller 38770b51aabf3b03fbf8d61c14847ccce4c69fb0cddRobert Love * @fip: The FCoE controller to be stopped 38897c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt * 38997c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt * Returns non-zero if the link was up and now isn't. 39097c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt * 39197c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt * Called from the LLD when the network link is not ready. 39297c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt * There may be multiple calls while the link is down. 39397c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt */ 39497c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholtint fcoe_ctlr_link_down(struct fcoe_ctlr *fip) 39597c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt{ 396dd42dac4ecd1799077c132aab35d3c36b26d4d8cJoe Eykholt int link_dropped; 397dd42dac4ecd1799077c132aab35d3c36b26d4d8cJoe Eykholt 398dd42dac4ecd1799077c132aab35d3c36b26d4d8cJoe Eykholt LIBFCOE_FIP_DBG(fip, "link down.\n"); 399fdb068c6cd6e30d43664f856d3530715a5742713Joe Eykholt mutex_lock(&fip->ctlr_mutex); 400dd42dac4ecd1799077c132aab35d3c36b26d4d8cJoe Eykholt fcoe_ctlr_reset(fip); 4014291365784c9622c9d643cf23421f9c7b9662d71Joe Eykholt link_dropped = fip->state != FIP_ST_LINK_WAIT; 4029b651da900ccfe5581befb46eb06ef781a1d7e74Joe Eykholt fcoe_ctlr_set_state(fip, FIP_ST_LINK_WAIT); 403fdb068c6cd6e30d43664f856d3530715a5742713Joe Eykholt mutex_unlock(&fip->ctlr_mutex); 404dd42dac4ecd1799077c132aab35d3c36b26d4d8cJoe Eykholt 405dd42dac4ecd1799077c132aab35d3c36b26d4d8cJoe Eykholt if (link_dropped) 406dd42dac4ecd1799077c132aab35d3c36b26d4d8cJoe Eykholt fc_linkdown(fip->lp); 407dd42dac4ecd1799077c132aab35d3c36b26d4d8cJoe Eykholt return link_dropped; 40897c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt} 40997c8389d54b9665c38105ea72a428a44b97ff2f6Joe EykholtEXPORT_SYMBOL(fcoe_ctlr_link_down); 41097c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt 41197c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt/** 41270b51aabf3b03fbf8d61c14847ccce4c69fb0cddRobert Love * fcoe_ctlr_send_keep_alive() - Send a keep-alive to the selected FCF 41370b51aabf3b03fbf8d61c14847ccce4c69fb0cddRobert Love * @fip: The FCoE controller to send the FKA on 41470b51aabf3b03fbf8d61c14847ccce4c69fb0cddRobert Love * @lport: libfc fc_lport to send from 41570b51aabf3b03fbf8d61c14847ccce4c69fb0cddRobert Love * @ports: 0 for controller keep-alive, 1 for port keep-alive 41670b51aabf3b03fbf8d61c14847ccce4c69fb0cddRobert Love * @sa: The source MAC address 41797c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt * 41897c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt * A controller keep-alive is sent every fka_period (typically 8 seconds). 41997c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt * The source MAC is the native MAC address. 42097c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt * 42197c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt * A port keep-alive is sent every 90 seconds while logged in. 42297c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt * The source MAC is the assigned mapped source address. 42397c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt * The destination is the FCF's F-port. 42497c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt */ 42511b561886643d4e23d0fd58c205d830a448dd0a2Chris Leechstatic void fcoe_ctlr_send_keep_alive(struct fcoe_ctlr *fip, 42611b561886643d4e23d0fd58c205d830a448dd0a2Chris Leech struct fc_lport *lport, 42711b561886643d4e23d0fd58c205d830a448dd0a2Chris Leech int ports, u8 *sa) 42897c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt{ 42997c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt struct sk_buff *skb; 43097c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt struct fip_kal { 43197c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt struct ethhdr eth; 43297c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt struct fip_header fip; 43397c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt struct fip_mac_desc mac; 4340095a9213324a4466c10de98837a27ab1b7e72beYi Zou } __packed * kal; 43597c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt struct fip_vn_desc *vn; 43697c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt u32 len; 43797c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt struct fc_lport *lp; 43897c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt struct fcoe_fcf *fcf; 43997c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt 44097c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt fcf = fip->sel_fcf; 44197c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt lp = fip->lp; 442281ae642a6475ede25ff86ec124214e346c25e22Joe Eykholt if (!fcf || (ports && !lp->port_id)) 44397c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt return; 44497c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt 445be276cbe1bd680ab1f6c297017dd658e5a6b10d2Yi Zou len = sizeof(*kal) + ports * sizeof(*vn); 44697c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt skb = dev_alloc_skb(len); 44797c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt if (!skb) 44897c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt return; 44997c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt 45097c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt kal = (struct fip_kal *)skb->data; 45197c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt memset(kal, 0, len); 45297c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt memcpy(kal->eth.h_dest, fcf->fcf_mac, ETH_ALEN); 45397c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt memcpy(kal->eth.h_source, sa, ETH_ALEN); 45497c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt kal->eth.h_proto = htons(ETH_P_FIP); 45597c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt 45697c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt kal->fip.fip_ver = FIP_VER_ENCAPS(FIP_VER); 45797c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt kal->fip.fip_op = htons(FIP_OP_CTRL); 45897c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt kal->fip.fip_subcode = FIP_SC_KEEP_ALIVE; 45997c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt kal->fip.fip_dl_len = htons((sizeof(kal->mac) + 46070b51aabf3b03fbf8d61c14847ccce4c69fb0cddRobert Love ports * sizeof(*vn)) / FIP_BPW); 46197c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt kal->fip.fip_flags = htons(FIP_FL_FPMA); 462184dd3459bb334d9061b58faed3610d08d6c7ff8Vasu Dev if (fip->spma) 463184dd3459bb334d9061b58faed3610d08d6c7ff8Vasu Dev kal->fip.fip_flags |= htons(FIP_FL_SPMA); 46497c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt 46597c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt kal->mac.fd_desc.fip_dtype = FIP_DT_MAC; 46697c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt kal->mac.fd_desc.fip_dlen = sizeof(kal->mac) / FIP_BPW; 46797c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt memcpy(kal->mac.fd_mac, fip->ctl_src_addr, ETH_ALEN); 46897c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt if (ports) { 46997c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt vn = (struct fip_vn_desc *)(kal + 1); 47097c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt vn->fd_desc.fip_dtype = FIP_DT_VN_ID; 47197c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt vn->fd_desc.fip_dlen = sizeof(*vn) / FIP_BPW; 47211b561886643d4e23d0fd58c205d830a448dd0a2Chris Leech memcpy(vn->fd_mac, fip->get_src_addr(lport), ETH_ALEN); 473fb83153d7308e1344f1d4a2e287b6aaab2f6d14cKaladhar Musunuru hton24(vn->fd_fc_id, lport->port_id); 474fb83153d7308e1344f1d4a2e287b6aaab2f6d14cKaladhar Musunuru put_unaligned_be64(lport->wwpn, &vn->fd_wwpn); 47597c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt } 47697c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt skb_put(skb, len); 4770f4915398a4233cdbfc4e9bf4436323546945b3fChris Leech skb->protocol = htons(ETH_P_FIP); 4786f6c2aa33b915c574543f176dee89d7aefc115c1john fastabend skb->priority = fip->priority; 47997c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt skb_reset_mac_header(skb); 48097c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt skb_reset_network_header(skb); 48197c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt fip->send(fip, skb); 48297c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt} 48397c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt 48497c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt/** 48570b51aabf3b03fbf8d61c14847ccce4c69fb0cddRobert Love * fcoe_ctlr_encaps() - Encapsulate an ELS frame for FIP, without sending it 48670b51aabf3b03fbf8d61c14847ccce4c69fb0cddRobert Love * @fip: The FCoE controller for the ELS frame 48770b51aabf3b03fbf8d61c14847ccce4c69fb0cddRobert Love * @dtype: The FIP descriptor type for the frame 48870b51aabf3b03fbf8d61c14847ccce4c69fb0cddRobert Love * @skb: The FCoE ELS frame including FC header but no FCoE headers 489e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * @d_id: The destination port ID. 49097c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt * 49197c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt * Returns non-zero error code on failure. 49297c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt * 49397c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt * The caller must check that the length is a multiple of 4. 49497c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt * 49597c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt * The @skb must have enough headroom (28 bytes) and tailroom (8 bytes). 49697c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt * Headroom includes the FIP encapsulation description, FIP header, and 49797c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt * Ethernet header. The tailroom is for the FIP MAC descriptor. 49897c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt */ 49911b561886643d4e23d0fd58c205d830a448dd0a2Chris Leechstatic int fcoe_ctlr_encaps(struct fcoe_ctlr *fip, struct fc_lport *lport, 500e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt u8 dtype, struct sk_buff *skb, u32 d_id) 50197c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt{ 50297c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt struct fip_encaps_head { 50397c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt struct ethhdr eth; 50497c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt struct fip_header fip; 50597c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt struct fip_encaps encaps; 5060095a9213324a4466c10de98837a27ab1b7e72beYi Zou } __packed * cap; 5075554345bc5275afed760631277fdab0a5a19472eJoe Eykholt struct fc_frame_header *fh; 50897c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt struct fip_mac_desc *mac; 50997c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt struct fcoe_fcf *fcf; 51097c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt size_t dlen; 5115a84baeaf7b8bb4188219140cb326a3e859b2312Yi Zou u16 fip_flags; 5125554345bc5275afed760631277fdab0a5a19472eJoe Eykholt u8 op; 51397c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt 5145554345bc5275afed760631277fdab0a5a19472eJoe Eykholt fh = (struct fc_frame_header *)skb->data; 5155554345bc5275afed760631277fdab0a5a19472eJoe Eykholt op = *(u8 *)(fh + 1); 51697c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt dlen = sizeof(struct fip_encaps) + skb->len; /* len before push */ 51797c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt cap = (struct fip_encaps_head *)skb_push(skb, sizeof(*cap)); 51897c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt memset(cap, 0, sizeof(*cap)); 519e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt 520e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt if (lport->point_to_multipoint) { 521e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt if (fcoe_ctlr_vn_lookup(fip, d_id, cap->eth.h_dest)) 522e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt return -ENODEV; 5235554345bc5275afed760631277fdab0a5a19472eJoe Eykholt fip_flags = 0; 524e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt } else { 525e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt fcf = fip->sel_fcf; 526e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt if (!fcf) 527e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt return -ENODEV; 528e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt fip_flags = fcf->flags; 529e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt fip_flags &= fip->spma ? FIP_FL_SPMA | FIP_FL_FPMA : 530e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt FIP_FL_FPMA; 531e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt if (!fip_flags) 532e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt return -ENODEV; 533e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt memcpy(cap->eth.h_dest, fcf->fcf_mac, ETH_ALEN); 534e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt } 53597c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt memcpy(cap->eth.h_source, fip->ctl_src_addr, ETH_ALEN); 53697c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt cap->eth.h_proto = htons(ETH_P_FIP); 53797c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt 53897c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt cap->fip.fip_ver = FIP_VER_ENCAPS(FIP_VER); 53997c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt cap->fip.fip_op = htons(FIP_OP_LS); 5405554345bc5275afed760631277fdab0a5a19472eJoe Eykholt if (op == ELS_LS_ACC || op == ELS_LS_RJT) 5415554345bc5275afed760631277fdab0a5a19472eJoe Eykholt cap->fip.fip_subcode = FIP_SC_REP; 5425554345bc5275afed760631277fdab0a5a19472eJoe Eykholt else 5435554345bc5275afed760631277fdab0a5a19472eJoe Eykholt cap->fip.fip_subcode = FIP_SC_REQ; 5445a84baeaf7b8bb4188219140cb326a3e859b2312Yi Zou cap->fip.fip_flags = htons(fip_flags); 54597c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt 54697c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt cap->encaps.fd_desc.fip_dtype = dtype; 54797c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt cap->encaps.fd_desc.fip_dlen = dlen / FIP_BPW; 54897c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt 5495554345bc5275afed760631277fdab0a5a19472eJoe Eykholt if (op != ELS_LS_RJT) { 5505554345bc5275afed760631277fdab0a5a19472eJoe Eykholt dlen += sizeof(*mac); 5515554345bc5275afed760631277fdab0a5a19472eJoe Eykholt mac = (struct fip_mac_desc *)skb_put(skb, sizeof(*mac)); 5525554345bc5275afed760631277fdab0a5a19472eJoe Eykholt memset(mac, 0, sizeof(*mac)); 5535554345bc5275afed760631277fdab0a5a19472eJoe Eykholt mac->fd_desc.fip_dtype = FIP_DT_MAC; 5545554345bc5275afed760631277fdab0a5a19472eJoe Eykholt mac->fd_desc.fip_dlen = sizeof(*mac) / FIP_BPW; 5555554345bc5275afed760631277fdab0a5a19472eJoe Eykholt if (dtype != FIP_DT_FLOGI && dtype != FIP_DT_FDISC) { 5565554345bc5275afed760631277fdab0a5a19472eJoe Eykholt memcpy(mac->fd_mac, fip->get_src_addr(lport), ETH_ALEN); 5575554345bc5275afed760631277fdab0a5a19472eJoe Eykholt } else if (fip->mode == FIP_MODE_VN2VN) { 5585554345bc5275afed760631277fdab0a5a19472eJoe Eykholt hton24(mac->fd_mac, FIP_VN_FC_MAP); 5595554345bc5275afed760631277fdab0a5a19472eJoe Eykholt hton24(mac->fd_mac + 3, fip->port_id); 5605554345bc5275afed760631277fdab0a5a19472eJoe Eykholt } else if (fip_flags & FIP_FL_SPMA) { 5615554345bc5275afed760631277fdab0a5a19472eJoe Eykholt LIBFCOE_FIP_DBG(fip, "FLOGI/FDISC sent with SPMA\n"); 5625554345bc5275afed760631277fdab0a5a19472eJoe Eykholt memcpy(mac->fd_mac, fip->ctl_src_addr, ETH_ALEN); 5635554345bc5275afed760631277fdab0a5a19472eJoe Eykholt } else { 5645554345bc5275afed760631277fdab0a5a19472eJoe Eykholt LIBFCOE_FIP_DBG(fip, "FLOGI/FDISC sent with FPMA\n"); 5655554345bc5275afed760631277fdab0a5a19472eJoe Eykholt /* FPMA only FLOGI. Must leave the MAC desc zeroed. */ 5665554345bc5275afed760631277fdab0a5a19472eJoe Eykholt } 567593abc0720d5639ba21834b082adf83762af39beRobert Love } 5685554345bc5275afed760631277fdab0a5a19472eJoe Eykholt cap->fip.fip_dl_len = htons(dlen / FIP_BPW); 56997c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt 5700f4915398a4233cdbfc4e9bf4436323546945b3fChris Leech skb->protocol = htons(ETH_P_FIP); 5716f6c2aa33b915c574543f176dee89d7aefc115c1john fastabend skb->priority = fip->priority; 57297c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt skb_reset_mac_header(skb); 57397c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt skb_reset_network_header(skb); 57497c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt return 0; 57597c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt} 57697c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt 57797c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt/** 57897c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt * fcoe_ctlr_els_send() - Send an ELS frame encapsulated by FIP if appropriate. 57997c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt * @fip: FCoE controller. 58011b561886643d4e23d0fd58c205d830a448dd0a2Chris Leech * @lport: libfc fc_lport to send from 58197c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt * @skb: FCoE ELS frame including FC header but no FCoE headers. 58297c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt * 58397c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt * Returns a non-zero error code if the frame should not be sent. 58497c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt * Returns zero if the caller should send the frame with FCoE encapsulation. 58597c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt * 58697c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt * The caller must check that the length is a multiple of 4. 58797c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt * The SKB must have enough headroom (28 bytes) and tailroom (8 bytes). 588e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * The the skb must also be an fc_frame. 589794d98e77f5901ceded697f1633463e88f078038Joe Eykholt * 590794d98e77f5901ceded697f1633463e88f078038Joe Eykholt * This is called from the lower-level driver with spinlocks held, 591794d98e77f5901ceded697f1633463e88f078038Joe Eykholt * so we must not take a mutex here. 59297c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt */ 59311b561886643d4e23d0fd58c205d830a448dd0a2Chris Leechint fcoe_ctlr_els_send(struct fcoe_ctlr *fip, struct fc_lport *lport, 59411b561886643d4e23d0fd58c205d830a448dd0a2Chris Leech struct sk_buff *skb) 59597c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt{ 596e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt struct fc_frame *fp; 59797c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt struct fc_frame_header *fh; 59897c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt u16 old_xid; 59997c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt u8 op; 60011b561886643d4e23d0fd58c205d830a448dd0a2Chris Leech u8 mac[ETH_ALEN]; 60197c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt 602e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt fp = container_of(skb, struct fc_frame, skb); 60397c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt fh = (struct fc_frame_header *)skb->data; 60497c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt op = *(u8 *)(fh + 1); 60597c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt 606e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt if (op == ELS_FLOGI && fip->mode != FIP_MODE_VN2VN) { 60797c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt old_xid = fip->flogi_oxid; 60897c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt fip->flogi_oxid = ntohs(fh->fh_ox_id); 60997c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt if (fip->state == FIP_ST_AUTO) { 61097c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt if (old_xid == FC_XID_UNKNOWN) 61197c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt fip->flogi_count = 0; 61297c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt fip->flogi_count++; 61397c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt if (fip->flogi_count < 3) 61497c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt goto drop; 615cd229e42eb8cdfdcbe15dfeec39c3641f62de43aJoe Eykholt fcoe_ctlr_map_dest(fip); 61697c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt return 0; 61797c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt } 6185f48f70ecef25df93e122985272ff647f5653836Joe Eykholt if (fip->state == FIP_ST_NON_FIP) 619cd229e42eb8cdfdcbe15dfeec39c3641f62de43aJoe Eykholt fcoe_ctlr_map_dest(fip); 6205f48f70ecef25df93e122985272ff647f5653836Joe Eykholt } 6215f48f70ecef25df93e122985272ff647f5653836Joe Eykholt 6225f48f70ecef25df93e122985272ff647f5653836Joe Eykholt if (fip->state == FIP_ST_NON_FIP) 6235f48f70ecef25df93e122985272ff647f5653836Joe Eykholt return 0; 624e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt if (!fip->sel_fcf && fip->mode != FIP_MODE_VN2VN) 625f31f2a1c3215e96fbff2152486d0fb590f72634eJoe Eykholt goto drop; 6265f48f70ecef25df93e122985272ff647f5653836Joe Eykholt switch (op) { 6275f48f70ecef25df93e122985272ff647f5653836Joe Eykholt case ELS_FLOGI: 62897c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt op = FIP_DT_FLOGI; 629794d98e77f5901ceded697f1633463e88f078038Joe Eykholt if (fip->mode == FIP_MODE_VN2VN) 630794d98e77f5901ceded697f1633463e88f078038Joe Eykholt break; 631794d98e77f5901ceded697f1633463e88f078038Joe Eykholt spin_lock_bh(&fip->ctlr_lock); 632794d98e77f5901ceded697f1633463e88f078038Joe Eykholt kfree_skb(fip->flogi_req); 633794d98e77f5901ceded697f1633463e88f078038Joe Eykholt fip->flogi_req = skb; 634794d98e77f5901ceded697f1633463e88f078038Joe Eykholt fip->flogi_req_send = 1; 635794d98e77f5901ceded697f1633463e88f078038Joe Eykholt spin_unlock_bh(&fip->ctlr_lock); 636794d98e77f5901ceded697f1633463e88f078038Joe Eykholt schedule_work(&fip->timer_work); 637794d98e77f5901ceded697f1633463e88f078038Joe Eykholt return -EINPROGRESS; 63897c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt case ELS_FDISC: 63997c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt if (ntoh24(fh->fh_s_id)) 64097c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt return 0; 64197c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt op = FIP_DT_FDISC; 64297c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt break; 64397c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt case ELS_LOGO: 644e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt if (fip->mode == FIP_MODE_VN2VN) { 645e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt if (fip->state != FIP_ST_VNMP_UP) 646e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt return -EINVAL; 647e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt if (ntoh24(fh->fh_d_id) == FC_FID_FLOGI) 648e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt return -EINVAL; 649e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt } else { 650e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt if (fip->state != FIP_ST_ENABLED) 651e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt return 0; 652e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt if (ntoh24(fh->fh_d_id) != FC_FID_FLOGI) 653e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt return 0; 654e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt } 65597c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt op = FIP_DT_LOGO; 65697c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt break; 65797c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt case ELS_LS_ACC: 65897c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt /* 659e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * If non-FIP, we may have gotten an SID by accepting an FLOGI 66097c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt * from a point-to-point connection. Switch to using 66197c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt * the source mac based on the SID. The destination 66225985edcedea6396277003854657b5f3cb31a628Lucas De Marchi * MAC in this case would have been set by receiving the 66397c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt * FLOGI. 66497c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt */ 665e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt if (fip->state == FIP_ST_NON_FIP) { 666e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt if (fip->flogi_oxid == FC_XID_UNKNOWN) 667e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt return 0; 668e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt fip->flogi_oxid = FC_XID_UNKNOWN; 669e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt fc_fcoe_set_mac(mac, fh->fh_d_id); 670e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt fip->update_mac(lport, mac); 671e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt } 672e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt /* fall through */ 673e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt case ELS_LS_RJT: 674e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt op = fr_encaps(fp); 675e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt if (op) 676e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt break; 67797c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt return 0; 67897c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt default: 679e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt if (fip->state != FIP_ST_ENABLED && 680e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt fip->state != FIP_ST_VNMP_UP) 68197c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt goto drop; 68297c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt return 0; 68397c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt } 684e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt LIBFCOE_FIP_DBG(fip, "els_send op %u d_id %x\n", 685e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt op, ntoh24(fh->fh_d_id)); 686e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt if (fcoe_ctlr_encaps(fip, lport, op, skb, ntoh24(fh->fh_d_id))) 68797c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt goto drop; 68897c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt fip->send(fip, skb); 68997c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt return -EINPROGRESS; 69097c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholtdrop: 69197c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt kfree_skb(skb); 69297c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt return -EINVAL; 69397c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt} 69497c8389d54b9665c38105ea72a428a44b97ff2f6Joe EykholtEXPORT_SYMBOL(fcoe_ctlr_els_send); 69597c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt 69670b51aabf3b03fbf8d61c14847ccce4c69fb0cddRobert Love/** 69770b51aabf3b03fbf8d61c14847ccce4c69fb0cddRobert Love * fcoe_ctlr_age_fcfs() - Reset and free all old FCFs for a controller 69870b51aabf3b03fbf8d61c14847ccce4c69fb0cddRobert Love * @fip: The FCoE controller to free FCFs on 69997c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt * 700f018b73af6db4f330ad5da9ac53997a699c30c42Joe Eykholt * Called with lock held and preemption disabled. 70197c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt * 7028690cb8359d8e9f8d7ca12791ef7ea32b709df8bJoe Eykholt * An FCF is considered old if we have missed two advertisements. 7038690cb8359d8e9f8d7ca12791ef7ea32b709df8bJoe Eykholt * That is, there have been no valid advertisement from it for 2.5 7048690cb8359d8e9f8d7ca12791ef7ea32b709df8bJoe Eykholt * times its keep-alive period. 70597c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt * 70697c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt * In addition, determine the time when an FCF selection can occur. 707f3da80e76142d63a6849556461906fbe118d1442Yi Zou * 708f3da80e76142d63a6849556461906fbe118d1442Yi Zou * Also, increment the MissDiscAdvCount when no advertisement is received 709f3da80e76142d63a6849556461906fbe118d1442Yi Zou * for the corresponding FCF for 1.5 * FKA_ADV_PERIOD (FC-BB-5 LESB). 7108690cb8359d8e9f8d7ca12791ef7ea32b709df8bJoe Eykholt * 7118690cb8359d8e9f8d7ca12791ef7ea32b709df8bJoe Eykholt * Returns the time in jiffies for the next call. 71297c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt */ 7138690cb8359d8e9f8d7ca12791ef7ea32b709df8bJoe Eykholtstatic unsigned long fcoe_ctlr_age_fcfs(struct fcoe_ctlr *fip) 71497c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt{ 71597c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt struct fcoe_fcf *fcf; 71697c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt struct fcoe_fcf *next; 7178690cb8359d8e9f8d7ca12791ef7ea32b709df8bJoe Eykholt unsigned long next_timer = jiffies + msecs_to_jiffies(FIP_VN_KA_PERIOD); 7188690cb8359d8e9f8d7ca12791ef7ea32b709df8bJoe Eykholt unsigned long deadline; 71997c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt unsigned long sel_time = 0; 720f018b73af6db4f330ad5da9ac53997a699c30c42Joe Eykholt struct fcoe_dev_stats *stats; 72197c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt 722fdb068c6cd6e30d43664f856d3530715a5742713Joe Eykholt stats = per_cpu_ptr(fip->lp->dev_stats, get_cpu()); 723fdb068c6cd6e30d43664f856d3530715a5742713Joe Eykholt 72497c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt list_for_each_entry_safe(fcf, next, &fip->fcfs, list) { 7258690cb8359d8e9f8d7ca12791ef7ea32b709df8bJoe Eykholt deadline = fcf->time + fcf->fka_period + fcf->fka_period / 2; 7268690cb8359d8e9f8d7ca12791ef7ea32b709df8bJoe Eykholt if (fip->sel_fcf == fcf) { 7278690cb8359d8e9f8d7ca12791ef7ea32b709df8bJoe Eykholt if (time_after(jiffies, deadline)) { 7288690cb8359d8e9f8d7ca12791ef7ea32b709df8bJoe Eykholt stats->MissDiscAdvCount++; 7298690cb8359d8e9f8d7ca12791ef7ea32b709df8bJoe Eykholt printk(KERN_INFO "libfcoe: host%d: " 7308690cb8359d8e9f8d7ca12791ef7ea32b709df8bJoe Eykholt "Missing Discovery Advertisement " 7318690cb8359d8e9f8d7ca12791ef7ea32b709df8bJoe Eykholt "for fab %16.16llx count %lld\n", 7328690cb8359d8e9f8d7ca12791ef7ea32b709df8bJoe Eykholt fip->lp->host->host_no, fcf->fabric_name, 7338690cb8359d8e9f8d7ca12791ef7ea32b709df8bJoe Eykholt stats->MissDiscAdvCount); 7348690cb8359d8e9f8d7ca12791ef7ea32b709df8bJoe Eykholt } else if (time_after(next_timer, deadline)) 7358690cb8359d8e9f8d7ca12791ef7ea32b709df8bJoe Eykholt next_timer = deadline; 736f3da80e76142d63a6849556461906fbe118d1442Yi Zou } 7378690cb8359d8e9f8d7ca12791ef7ea32b709df8bJoe Eykholt 7388690cb8359d8e9f8d7ca12791ef7ea32b709df8bJoe Eykholt deadline += fcf->fka_period; 739d99ee45b7cb89803b79745dc3014ba64bfd02b7dJoe Eykholt if (time_after_eq(jiffies, deadline)) { 74097c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt if (fip->sel_fcf == fcf) 74197c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt fip->sel_fcf = NULL; 74297c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt list_del(&fcf->list); 74397c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt WARN_ON(!fip->fcf_count); 74497c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt fip->fcf_count--; 74597c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt kfree(fcf); 746f018b73af6db4f330ad5da9ac53997a699c30c42Joe Eykholt stats->VLinkFailureCount++; 7478690cb8359d8e9f8d7ca12791ef7ea32b709df8bJoe Eykholt } else { 7488690cb8359d8e9f8d7ca12791ef7ea32b709df8bJoe Eykholt if (time_after(next_timer, deadline)) 7498690cb8359d8e9f8d7ca12791ef7ea32b709df8bJoe Eykholt next_timer = deadline; 7508690cb8359d8e9f8d7ca12791ef7ea32b709df8bJoe Eykholt if (fcoe_ctlr_mtu_valid(fcf) && 7518690cb8359d8e9f8d7ca12791ef7ea32b709df8bJoe Eykholt (!sel_time || time_before(sel_time, fcf->time))) 7528690cb8359d8e9f8d7ca12791ef7ea32b709df8bJoe Eykholt sel_time = fcf->time; 75397c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt } 75497c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt } 755fdb068c6cd6e30d43664f856d3530715a5742713Joe Eykholt put_cpu(); 756d99ee45b7cb89803b79745dc3014ba64bfd02b7dJoe Eykholt if (sel_time && !fip->sel_fcf && !fip->sel_time) { 75797c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt sel_time += msecs_to_jiffies(FCOE_CTLR_START_DELAY); 75897c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt fip->sel_time = sel_time; 75997c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt } 760d99ee45b7cb89803b79745dc3014ba64bfd02b7dJoe Eykholt 7618690cb8359d8e9f8d7ca12791ef7ea32b709df8bJoe Eykholt return next_timer; 76297c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt} 76397c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt 76497c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt/** 76570b51aabf3b03fbf8d61c14847ccce4c69fb0cddRobert Love * fcoe_ctlr_parse_adv() - Decode a FIP advertisement into a new FCF entry 7660f51c2e54c0bfdb6b02c53f6d7dd9b35f91821b6Joe Eykholt * @fip: The FCoE controller receiving the advertisement 76770b51aabf3b03fbf8d61c14847ccce4c69fb0cddRobert Love * @skb: The received FIP advertisement frame 76870b51aabf3b03fbf8d61c14847ccce4c69fb0cddRobert Love * @fcf: The resulting FCF entry 76997c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt * 77097c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt * Returns zero on a valid parsed advertisement, 77197c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt * otherwise returns non zero value. 77297c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt */ 7730f51c2e54c0bfdb6b02c53f6d7dd9b35f91821b6Joe Eykholtstatic int fcoe_ctlr_parse_adv(struct fcoe_ctlr *fip, 7740f51c2e54c0bfdb6b02c53f6d7dd9b35f91821b6Joe Eykholt struct sk_buff *skb, struct fcoe_fcf *fcf) 77597c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt{ 77697c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt struct fip_header *fiph; 77797c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt struct fip_desc *desc = NULL; 77897c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt struct fip_wwn_desc *wwn; 77997c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt struct fip_fab_desc *fab; 78097c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt struct fip_fka_desc *fka; 78197c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt unsigned long t; 78297c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt size_t rlen; 78397c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt size_t dlen; 7840a9c5d344dbd983af59865f9880621e5cbbda899Bhanu Prakash Gollapudi u32 desc_mask; 78597c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt 78697c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt memset(fcf, 0, sizeof(*fcf)); 78797c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt fcf->fka_period = msecs_to_jiffies(FCOE_CTLR_DEF_FKA); 78897c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt 78997c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt fiph = (struct fip_header *)skb->data; 79097c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt fcf->flags = ntohs(fiph->fip_flags); 79197c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt 7920a9c5d344dbd983af59865f9880621e5cbbda899Bhanu Prakash Gollapudi /* 7930a9c5d344dbd983af59865f9880621e5cbbda899Bhanu Prakash Gollapudi * mask of required descriptors. validating each one clears its bit. 7940a9c5d344dbd983af59865f9880621e5cbbda899Bhanu Prakash Gollapudi */ 7950a9c5d344dbd983af59865f9880621e5cbbda899Bhanu Prakash Gollapudi desc_mask = BIT(FIP_DT_PRI) | BIT(FIP_DT_MAC) | BIT(FIP_DT_NAME) | 7960a9c5d344dbd983af59865f9880621e5cbbda899Bhanu Prakash Gollapudi BIT(FIP_DT_FAB) | BIT(FIP_DT_FKA); 7970a9c5d344dbd983af59865f9880621e5cbbda899Bhanu Prakash Gollapudi 79897c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt rlen = ntohs(fiph->fip_dl_len) * 4; 79997c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt if (rlen + sizeof(*fiph) > skb->len) 80097c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt return -EINVAL; 80197c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt 80297c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt desc = (struct fip_desc *)(fiph + 1); 80397c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt while (rlen > 0) { 80497c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt dlen = desc->fip_dlen * FIP_BPW; 80597c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt if (dlen < sizeof(*desc) || dlen > rlen) 80697c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt return -EINVAL; 8070a9c5d344dbd983af59865f9880621e5cbbda899Bhanu Prakash Gollapudi /* Drop Adv if there are duplicate critical descriptors */ 8080a9c5d344dbd983af59865f9880621e5cbbda899Bhanu Prakash Gollapudi if ((desc->fip_dtype < 32) && 8090a9c5d344dbd983af59865f9880621e5cbbda899Bhanu Prakash Gollapudi !(desc_mask & 1U << desc->fip_dtype)) { 8100a9c5d344dbd983af59865f9880621e5cbbda899Bhanu Prakash Gollapudi LIBFCOE_FIP_DBG(fip, "Duplicate Critical " 8110a9c5d344dbd983af59865f9880621e5cbbda899Bhanu Prakash Gollapudi "Descriptors in FIP adv\n"); 8120a9c5d344dbd983af59865f9880621e5cbbda899Bhanu Prakash Gollapudi return -EINVAL; 8130a9c5d344dbd983af59865f9880621e5cbbda899Bhanu Prakash Gollapudi } 81497c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt switch (desc->fip_dtype) { 81597c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt case FIP_DT_PRI: 81697c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt if (dlen != sizeof(struct fip_pri_desc)) 81797c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt goto len_err; 81897c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt fcf->pri = ((struct fip_pri_desc *)desc)->fd_pri; 8190a9c5d344dbd983af59865f9880621e5cbbda899Bhanu Prakash Gollapudi desc_mask &= ~BIT(FIP_DT_PRI); 82097c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt break; 82197c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt case FIP_DT_MAC: 82297c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt if (dlen != sizeof(struct fip_mac_desc)) 82397c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt goto len_err; 82497c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt memcpy(fcf->fcf_mac, 82597c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt ((struct fip_mac_desc *)desc)->fd_mac, 82697c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt ETH_ALEN); 82781c11dd2ed154b351eb6ee3443e07094a1d53ce1Bhanu Prakash Gollapudi memcpy(fcf->fcoe_mac, fcf->fcf_mac, ETH_ALEN); 82897c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt if (!is_valid_ether_addr(fcf->fcf_mac)) { 829e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt LIBFCOE_FIP_DBG(fip, 830e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt "Invalid MAC addr %pM in FIP adv\n", 831e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt fcf->fcf_mac); 83297c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt return -EINVAL; 83397c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt } 8340a9c5d344dbd983af59865f9880621e5cbbda899Bhanu Prakash Gollapudi desc_mask &= ~BIT(FIP_DT_MAC); 83597c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt break; 83697c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt case FIP_DT_NAME: 83797c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt if (dlen != sizeof(struct fip_wwn_desc)) 83897c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt goto len_err; 83997c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt wwn = (struct fip_wwn_desc *)desc; 84097c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt fcf->switch_name = get_unaligned_be64(&wwn->fd_wwn); 8410a9c5d344dbd983af59865f9880621e5cbbda899Bhanu Prakash Gollapudi desc_mask &= ~BIT(FIP_DT_NAME); 84297c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt break; 84397c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt case FIP_DT_FAB: 84497c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt if (dlen != sizeof(struct fip_fab_desc)) 84597c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt goto len_err; 84697c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt fab = (struct fip_fab_desc *)desc; 84797c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt fcf->fabric_name = get_unaligned_be64(&fab->fd_wwn); 84897c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt fcf->vfid = ntohs(fab->fd_vfid); 84997c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt fcf->fc_map = ntoh24(fab->fd_map); 8500a9c5d344dbd983af59865f9880621e5cbbda899Bhanu Prakash Gollapudi desc_mask &= ~BIT(FIP_DT_FAB); 85197c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt break; 85297c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt case FIP_DT_FKA: 85397c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt if (dlen != sizeof(struct fip_fka_desc)) 85497c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt goto len_err; 85597c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt fka = (struct fip_fka_desc *)desc; 8568cdffdccd948ea4872b7b65280bc04f2fa93fc96Yi Zou if (fka->fd_flags & FIP_FKA_ADV_D) 8578cdffdccd948ea4872b7b65280bc04f2fa93fc96Yi Zou fcf->fd_flags = 1; 85897c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt t = ntohl(fka->fd_fka_period); 85997c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt if (t >= FCOE_CTLR_MIN_FKA) 86097c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt fcf->fka_period = msecs_to_jiffies(t); 8610a9c5d344dbd983af59865f9880621e5cbbda899Bhanu Prakash Gollapudi desc_mask &= ~BIT(FIP_DT_FKA); 86297c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt break; 86397c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt case FIP_DT_MAP_OUI: 86497c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt case FIP_DT_FCOE_SIZE: 86597c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt case FIP_DT_FLOGI: 86697c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt case FIP_DT_FDISC: 86797c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt case FIP_DT_LOGO: 86897c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt case FIP_DT_ELP: 86997c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt default: 8700f51c2e54c0bfdb6b02c53f6d7dd9b35f91821b6Joe Eykholt LIBFCOE_FIP_DBG(fip, "unexpected descriptor type %x " 871650bd12b9e31ec51d7ad0df3c4f94d863b827976Robert Love "in FIP adv\n", desc->fip_dtype); 87297c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt /* standard says ignore unknown descriptors >= 128 */ 87397c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt if (desc->fip_dtype < FIP_DT_VENDOR_BASE) 87497c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt return -EINVAL; 8751508f3ecd991ecbf272e08f5ee70d2618f49159eBhanu Prakash Gollapudi break; 87697c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt } 87797c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt desc = (struct fip_desc *)((char *)desc + dlen); 87897c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt rlen -= dlen; 87997c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt } 88097c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt if (!fcf->fc_map || (fcf->fc_map & 0x10000)) 88197c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt return -EINVAL; 882240778e821f596a6954116107c5cc3456df84f81Vasu Dev if (!fcf->switch_name) 88397c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt return -EINVAL; 8840a9c5d344dbd983af59865f9880621e5cbbda899Bhanu Prakash Gollapudi if (desc_mask) { 8850a9c5d344dbd983af59865f9880621e5cbbda899Bhanu Prakash Gollapudi LIBFCOE_FIP_DBG(fip, "adv missing descriptors mask %x\n", 8860a9c5d344dbd983af59865f9880621e5cbbda899Bhanu Prakash Gollapudi desc_mask); 8870a9c5d344dbd983af59865f9880621e5cbbda899Bhanu Prakash Gollapudi return -EINVAL; 8880a9c5d344dbd983af59865f9880621e5cbbda899Bhanu Prakash Gollapudi } 88997c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt return 0; 89097c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt 89197c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholtlen_err: 8920f51c2e54c0bfdb6b02c53f6d7dd9b35f91821b6Joe Eykholt LIBFCOE_FIP_DBG(fip, "FIP length error in descriptor type %x len %zu\n", 893650bd12b9e31ec51d7ad0df3c4f94d863b827976Robert Love desc->fip_dtype, dlen); 89497c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt return -EINVAL; 89597c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt} 89697c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt 89797c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt/** 89870b51aabf3b03fbf8d61c14847ccce4c69fb0cddRobert Love * fcoe_ctlr_recv_adv() - Handle an incoming advertisement 89970b51aabf3b03fbf8d61c14847ccce4c69fb0cddRobert Love * @fip: The FCoE controller receiving the advertisement 90070b51aabf3b03fbf8d61c14847ccce4c69fb0cddRobert Love * @skb: The received FIP packet 90197c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt */ 90297c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholtstatic void fcoe_ctlr_recv_adv(struct fcoe_ctlr *fip, struct sk_buff *skb) 90397c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt{ 90497c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt struct fcoe_fcf *fcf; 90597c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt struct fcoe_fcf new; 90697c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt struct fcoe_fcf *found; 90797c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt unsigned long sol_tov = msecs_to_jiffies(FCOE_CTRL_SOL_TOV); 90897c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt int first = 0; 90997c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt int mtu_valid; 91097c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt 9110f51c2e54c0bfdb6b02c53f6d7dd9b35f91821b6Joe Eykholt if (fcoe_ctlr_parse_adv(fip, skb, &new)) 91297c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt return; 91397c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt 914fdb068c6cd6e30d43664f856d3530715a5742713Joe Eykholt mutex_lock(&fip->ctlr_mutex); 91597c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt first = list_empty(&fip->fcfs); 91697c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt found = NULL; 91797c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt list_for_each_entry(fcf, &fip->fcfs, list) { 91897c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt if (fcf->switch_name == new.switch_name && 91997c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt fcf->fabric_name == new.fabric_name && 92097c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt fcf->fc_map == new.fc_map && 92197c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt compare_ether_addr(fcf->fcf_mac, new.fcf_mac) == 0) { 92297c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt found = fcf; 92397c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt break; 92497c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt } 92597c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt } 92697c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt if (!found) { 92797c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt if (fip->fcf_count >= FCOE_CTLR_FCF_LIMIT) 92897c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt goto out; 92997c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt 93097c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt fcf = kmalloc(sizeof(*fcf), GFP_ATOMIC); 93197c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt if (!fcf) 93297c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt goto out; 93397c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt 93497c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt fip->fcf_count++; 93597c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt memcpy(fcf, &new, sizeof(new)); 93697c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt list_add(&fcf->list, &fip->fcfs); 93797c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt } else { 93897c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt /* 939c600fea2d813e8734748202970722c3b6a76b9a1Joe Eykholt * Update the FCF's keep-alive descriptor flags. 940c600fea2d813e8734748202970722c3b6a76b9a1Joe Eykholt * Other flag changes from new advertisements are 941c600fea2d813e8734748202970722c3b6a76b9a1Joe Eykholt * ignored after a solicited advertisement is 942c600fea2d813e8734748202970722c3b6a76b9a1Joe Eykholt * received and the FCF is selectable (usable). 94397c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt */ 944c600fea2d813e8734748202970722c3b6a76b9a1Joe Eykholt fcf->fd_flags = new.fd_flags; 945c600fea2d813e8734748202970722c3b6a76b9a1Joe Eykholt if (!fcoe_ctlr_fcf_usable(fcf)) 946c600fea2d813e8734748202970722c3b6a76b9a1Joe Eykholt fcf->flags = new.flags; 947c600fea2d813e8734748202970722c3b6a76b9a1Joe Eykholt 948d99ee45b7cb89803b79745dc3014ba64bfd02b7dJoe Eykholt if (fcf == fip->sel_fcf && !fcf->fd_flags) { 94997c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt fip->ctlr_ka_time -= fcf->fka_period; 95097c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt fip->ctlr_ka_time += new.fka_period; 95197c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt if (time_before(fip->ctlr_ka_time, fip->timer.expires)) 95297c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt mod_timer(&fip->timer, fip->ctlr_ka_time); 953c600fea2d813e8734748202970722c3b6a76b9a1Joe Eykholt } 95497c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt fcf->fka_period = new.fka_period; 95597c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt memcpy(fcf->fcf_mac, new.fcf_mac, ETH_ALEN); 95697c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt } 95797c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt mtu_valid = fcoe_ctlr_mtu_valid(fcf); 95897c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt fcf->time = jiffies; 9599069f5c433e402be5707f37f3d0dfb376659c1e4Joe Eykholt if (!found) 9609069f5c433e402be5707f37f3d0dfb376659c1e4Joe Eykholt LIBFCOE_FIP_DBG(fip, "New FCF fab %16.16llx mac %pM\n", 9619069f5c433e402be5707f37f3d0dfb376659c1e4Joe Eykholt fcf->fabric_name, fcf->fcf_mac); 96297c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt 96397c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt /* 96497c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt * If this advertisement is not solicited and our max receive size 96597c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt * hasn't been verified, send a solicited advertisement. 96697c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt */ 96797c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt if (!mtu_valid) 96897c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt fcoe_ctlr_solicit(fip, fcf); 96997c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt 97097c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt /* 97197c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt * If its been a while since we did a solicit, and this is 97297c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt * the first advertisement we've received, do a multicast 97397c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt * solicitation to gather as many advertisements as we can 97497c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt * before selection occurs. 97597c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt */ 97697c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt if (first && time_after(jiffies, fip->sol_time + sol_tov)) 97797c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt fcoe_ctlr_solicit(fip, NULL); 97897c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt 97997c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt /* 980981c1154b240ee77133a478fcd3853ac18111672Joe Eykholt * Put this FCF at the head of the list for priority among equals. 981981c1154b240ee77133a478fcd3853ac18111672Joe Eykholt * This helps in the case of an NPV switch which insists we use 982981c1154b240ee77133a478fcd3853ac18111672Joe Eykholt * the FCF that answers multicast solicitations, not the others that 983981c1154b240ee77133a478fcd3853ac18111672Joe Eykholt * are sending periodic multicast advertisements. 984981c1154b240ee77133a478fcd3853ac18111672Joe Eykholt */ 98563ce2499947683dcc026373e24a4cb5a9d086e7dKirill A. Shutemov if (mtu_valid) 98663ce2499947683dcc026373e24a4cb5a9d086e7dKirill A. Shutemov list_move(&fcf->list, &fip->fcfs); 987981c1154b240ee77133a478fcd3853ac18111672Joe Eykholt 988981c1154b240ee77133a478fcd3853ac18111672Joe Eykholt /* 98997c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt * If this is the first validated FCF, note the time and 99097c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt * set a timer to trigger selection. 99197c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt */ 992d99ee45b7cb89803b79745dc3014ba64bfd02b7dJoe Eykholt if (mtu_valid && !fip->sel_fcf && fcoe_ctlr_fcf_usable(fcf)) { 99397c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt fip->sel_time = jiffies + 99470b51aabf3b03fbf8d61c14847ccce4c69fb0cddRobert Love msecs_to_jiffies(FCOE_CTLR_START_DELAY); 99597c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt if (!timer_pending(&fip->timer) || 99697c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt time_before(fip->sel_time, fip->timer.expires)) 99797c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt mod_timer(&fip->timer, fip->sel_time); 99897c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt } 99997c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholtout: 1000fdb068c6cd6e30d43664f856d3530715a5742713Joe Eykholt mutex_unlock(&fip->ctlr_mutex); 100197c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt} 100297c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt 100397c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt/** 100470b51aabf3b03fbf8d61c14847ccce4c69fb0cddRobert Love * fcoe_ctlr_recv_els() - Handle an incoming FIP encapsulated ELS frame 100570b51aabf3b03fbf8d61c14847ccce4c69fb0cddRobert Love * @fip: The FCoE controller which received the packet 100670b51aabf3b03fbf8d61c14847ccce4c69fb0cddRobert Love * @skb: The received FIP packet 100797c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt */ 100897c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholtstatic void fcoe_ctlr_recv_els(struct fcoe_ctlr *fip, struct sk_buff *skb) 100997c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt{ 101070b51aabf3b03fbf8d61c14847ccce4c69fb0cddRobert Love struct fc_lport *lport = fip->lp; 101197c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt struct fip_header *fiph; 101211b561886643d4e23d0fd58c205d830a448dd0a2Chris Leech struct fc_frame *fp = (struct fc_frame *)skb; 101397c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt struct fc_frame_header *fh = NULL; 101497c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt struct fip_desc *desc; 101597c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt struct fip_encaps *els; 101697c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt struct fcoe_dev_stats *stats; 101781c11dd2ed154b351eb6ee3443e07094a1d53ce1Bhanu Prakash Gollapudi struct fcoe_fcf *sel; 101897c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt enum fip_desc_type els_dtype = 0; 101997c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt u8 els_op; 102097c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt u8 sub; 102197c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt u8 granted_mac[ETH_ALEN] = { 0 }; 102297c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt size_t els_len = 0; 102397c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt size_t rlen; 102497c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt size_t dlen; 1025be61331d902e63011138723da3f737d34506f797Bhanu Prakash Gollapudi u32 desc_mask = 0; 1026be61331d902e63011138723da3f737d34506f797Bhanu Prakash Gollapudi u32 desc_cnt = 0; 102797c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt 102897c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt fiph = (struct fip_header *)skb->data; 102997c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt sub = fiph->fip_subcode; 103097c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt if (sub != FIP_SC_REQ && sub != FIP_SC_REP) 103197c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt goto drop; 103297c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt 103397c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt rlen = ntohs(fiph->fip_dl_len) * 4; 103497c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt if (rlen + sizeof(*fiph) > skb->len) 103597c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt goto drop; 103697c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt 103797c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt desc = (struct fip_desc *)(fiph + 1); 103897c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt while (rlen > 0) { 1039be61331d902e63011138723da3f737d34506f797Bhanu Prakash Gollapudi desc_cnt++; 104097c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt dlen = desc->fip_dlen * FIP_BPW; 104197c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt if (dlen < sizeof(*desc) || dlen > rlen) 104297c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt goto drop; 10430a9c5d344dbd983af59865f9880621e5cbbda899Bhanu Prakash Gollapudi /* Drop ELS if there are duplicate critical descriptors */ 10440a9c5d344dbd983af59865f9880621e5cbbda899Bhanu Prakash Gollapudi if (desc->fip_dtype < 32) { 104581c11dd2ed154b351eb6ee3443e07094a1d53ce1Bhanu Prakash Gollapudi if ((desc->fip_dtype != FIP_DT_MAC) && 104681c11dd2ed154b351eb6ee3443e07094a1d53ce1Bhanu Prakash Gollapudi (desc_mask & 1U << desc->fip_dtype)) { 10470a9c5d344dbd983af59865f9880621e5cbbda899Bhanu Prakash Gollapudi LIBFCOE_FIP_DBG(fip, "Duplicate Critical " 10480a9c5d344dbd983af59865f9880621e5cbbda899Bhanu Prakash Gollapudi "Descriptors in FIP ELS\n"); 10490a9c5d344dbd983af59865f9880621e5cbbda899Bhanu Prakash Gollapudi goto drop; 10500a9c5d344dbd983af59865f9880621e5cbbda899Bhanu Prakash Gollapudi } 1051be61331d902e63011138723da3f737d34506f797Bhanu Prakash Gollapudi desc_mask |= (1 << desc->fip_dtype); 10520a9c5d344dbd983af59865f9880621e5cbbda899Bhanu Prakash Gollapudi } 105397c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt switch (desc->fip_dtype) { 105497c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt case FIP_DT_MAC: 105581c11dd2ed154b351eb6ee3443e07094a1d53ce1Bhanu Prakash Gollapudi sel = fip->sel_fcf; 1056be61331d902e63011138723da3f737d34506f797Bhanu Prakash Gollapudi if (desc_cnt == 1) { 1057be61331d902e63011138723da3f737d34506f797Bhanu Prakash Gollapudi LIBFCOE_FIP_DBG(fip, "FIP descriptors " 1058be61331d902e63011138723da3f737d34506f797Bhanu Prakash Gollapudi "received out of order\n"); 1059be61331d902e63011138723da3f737d34506f797Bhanu Prakash Gollapudi goto drop; 1060be61331d902e63011138723da3f737d34506f797Bhanu Prakash Gollapudi } 106181c11dd2ed154b351eb6ee3443e07094a1d53ce1Bhanu Prakash Gollapudi /* 106281c11dd2ed154b351eb6ee3443e07094a1d53ce1Bhanu Prakash Gollapudi * Some switch implementations send two MAC descriptors, 106381c11dd2ed154b351eb6ee3443e07094a1d53ce1Bhanu Prakash Gollapudi * with first MAC(granted_mac) being the FPMA, and the 106481c11dd2ed154b351eb6ee3443e07094a1d53ce1Bhanu Prakash Gollapudi * second one(fcoe_mac) is used as destination address 106581c11dd2ed154b351eb6ee3443e07094a1d53ce1Bhanu Prakash Gollapudi * for sending/receiving FCoE packets. FIP traffic is 106681c11dd2ed154b351eb6ee3443e07094a1d53ce1Bhanu Prakash Gollapudi * sent using fip_mac. For regular switches, both 106781c11dd2ed154b351eb6ee3443e07094a1d53ce1Bhanu Prakash Gollapudi * fip_mac and fcoe_mac would be the same. 106881c11dd2ed154b351eb6ee3443e07094a1d53ce1Bhanu Prakash Gollapudi */ 106981c11dd2ed154b351eb6ee3443e07094a1d53ce1Bhanu Prakash Gollapudi if (desc_cnt == 2) 107081c11dd2ed154b351eb6ee3443e07094a1d53ce1Bhanu Prakash Gollapudi memcpy(granted_mac, 107181c11dd2ed154b351eb6ee3443e07094a1d53ce1Bhanu Prakash Gollapudi ((struct fip_mac_desc *)desc)->fd_mac, 107281c11dd2ed154b351eb6ee3443e07094a1d53ce1Bhanu Prakash Gollapudi ETH_ALEN); 1073be61331d902e63011138723da3f737d34506f797Bhanu Prakash Gollapudi 107497c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt if (dlen != sizeof(struct fip_mac_desc)) 107597c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt goto len_err; 107681c11dd2ed154b351eb6ee3443e07094a1d53ce1Bhanu Prakash Gollapudi 107781c11dd2ed154b351eb6ee3443e07094a1d53ce1Bhanu Prakash Gollapudi if ((desc_cnt == 3) && (sel)) 107881c11dd2ed154b351eb6ee3443e07094a1d53ce1Bhanu Prakash Gollapudi memcpy(sel->fcoe_mac, 107981c11dd2ed154b351eb6ee3443e07094a1d53ce1Bhanu Prakash Gollapudi ((struct fip_mac_desc *)desc)->fd_mac, 108081c11dd2ed154b351eb6ee3443e07094a1d53ce1Bhanu Prakash Gollapudi ETH_ALEN); 108197c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt break; 108297c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt case FIP_DT_FLOGI: 108397c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt case FIP_DT_FDISC: 108497c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt case FIP_DT_LOGO: 108597c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt case FIP_DT_ELP: 1086be61331d902e63011138723da3f737d34506f797Bhanu Prakash Gollapudi if (desc_cnt != 1) { 1087be61331d902e63011138723da3f737d34506f797Bhanu Prakash Gollapudi LIBFCOE_FIP_DBG(fip, "FIP descriptors " 1088be61331d902e63011138723da3f737d34506f797Bhanu Prakash Gollapudi "received out of order\n"); 1089be61331d902e63011138723da3f737d34506f797Bhanu Prakash Gollapudi goto drop; 1090be61331d902e63011138723da3f737d34506f797Bhanu Prakash Gollapudi } 109197c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt if (fh) 109297c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt goto drop; 109397c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt if (dlen < sizeof(*els) + sizeof(*fh) + 1) 109497c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt goto len_err; 109597c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt els_len = dlen - sizeof(*els); 109697c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt els = (struct fip_encaps *)desc; 109797c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt fh = (struct fc_frame_header *)(els + 1); 109897c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt els_dtype = desc->fip_dtype; 109997c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt break; 110097c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt default: 11010f51c2e54c0bfdb6b02c53f6d7dd9b35f91821b6Joe Eykholt LIBFCOE_FIP_DBG(fip, "unexpected descriptor type %x " 1102650bd12b9e31ec51d7ad0df3c4f94d863b827976Robert Love "in FIP adv\n", desc->fip_dtype); 110397c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt /* standard says ignore unknown descriptors >= 128 */ 110497c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt if (desc->fip_dtype < FIP_DT_VENDOR_BASE) 110597c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt goto drop; 1106be61331d902e63011138723da3f737d34506f797Bhanu Prakash Gollapudi if (desc_cnt <= 2) { 1107be61331d902e63011138723da3f737d34506f797Bhanu Prakash Gollapudi LIBFCOE_FIP_DBG(fip, "FIP descriptors " 1108be61331d902e63011138723da3f737d34506f797Bhanu Prakash Gollapudi "received out of order\n"); 1109be61331d902e63011138723da3f737d34506f797Bhanu Prakash Gollapudi goto drop; 1110be61331d902e63011138723da3f737d34506f797Bhanu Prakash Gollapudi } 11111508f3ecd991ecbf272e08f5ee70d2618f49159eBhanu Prakash Gollapudi break; 111297c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt } 111397c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt desc = (struct fip_desc *)((char *)desc + dlen); 111497c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt rlen -= dlen; 111597c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt } 111697c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt 111797c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt if (!fh) 111897c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt goto drop; 111997c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt els_op = *(u8 *)(fh + 1); 112097c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt 1121e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt if ((els_dtype == FIP_DT_FLOGI || els_dtype == FIP_DT_FDISC) && 1122794d98e77f5901ceded697f1633463e88f078038Joe Eykholt sub == FIP_SC_REP && fip->mode != FIP_MODE_VN2VN) { 1123794d98e77f5901ceded697f1633463e88f078038Joe Eykholt if (els_op == ELS_LS_ACC) { 1124794d98e77f5901ceded697f1633463e88f078038Joe Eykholt if (!is_valid_ether_addr(granted_mac)) { 1125794d98e77f5901ceded697f1633463e88f078038Joe Eykholt LIBFCOE_FIP_DBG(fip, 1126794d98e77f5901ceded697f1633463e88f078038Joe Eykholt "Invalid MAC address %pM in FIP ELS\n", 1127794d98e77f5901ceded697f1633463e88f078038Joe Eykholt granted_mac); 1128794d98e77f5901ceded697f1633463e88f078038Joe Eykholt goto drop; 1129794d98e77f5901ceded697f1633463e88f078038Joe Eykholt } 1130794d98e77f5901ceded697f1633463e88f078038Joe Eykholt memcpy(fr_cb(fp)->granted_mac, granted_mac, ETH_ALEN); 1131e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt 1132794d98e77f5901ceded697f1633463e88f078038Joe Eykholt if (fip->flogi_oxid == ntohs(fh->fh_ox_id)) { 1133794d98e77f5901ceded697f1633463e88f078038Joe Eykholt fip->flogi_oxid = FC_XID_UNKNOWN; 1134794d98e77f5901ceded697f1633463e88f078038Joe Eykholt if (els_dtype == FIP_DT_FLOGI) 1135794d98e77f5901ceded697f1633463e88f078038Joe Eykholt fcoe_ctlr_announce(fip); 1136794d98e77f5901ceded697f1633463e88f078038Joe Eykholt } 1137794d98e77f5901ceded697f1633463e88f078038Joe Eykholt } else if (els_dtype == FIP_DT_FLOGI && 1138794d98e77f5901ceded697f1633463e88f078038Joe Eykholt !fcoe_ctlr_flogi_retry(fip)) 1139794d98e77f5901ceded697f1633463e88f078038Joe Eykholt goto drop; /* retrying FLOGI so drop reject */ 1140e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt } 114197c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt 1142be61331d902e63011138723da3f737d34506f797Bhanu Prakash Gollapudi if ((desc_cnt == 0) || ((els_op != ELS_LS_RJT) && 1143be61331d902e63011138723da3f737d34506f797Bhanu Prakash Gollapudi (!(1U << FIP_DT_MAC & desc_mask)))) { 1144be61331d902e63011138723da3f737d34506f797Bhanu Prakash Gollapudi LIBFCOE_FIP_DBG(fip, "Missing critical descriptors " 1145be61331d902e63011138723da3f737d34506f797Bhanu Prakash Gollapudi "in FIP ELS\n"); 1146be61331d902e63011138723da3f737d34506f797Bhanu Prakash Gollapudi goto drop; 1147be61331d902e63011138723da3f737d34506f797Bhanu Prakash Gollapudi } 1148be61331d902e63011138723da3f737d34506f797Bhanu Prakash Gollapudi 114997c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt /* 115097c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt * Convert skb into an fc_frame containing only the ELS. 115197c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt */ 115297c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt skb_pull(skb, (u8 *)fh - skb->data); 115397c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt skb_trim(skb, els_len); 115497c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt fp = (struct fc_frame *)skb; 115597c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt fc_frame_init(fp); 115697c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt fr_sof(fp) = FC_SOF_I3; 115797c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt fr_eof(fp) = FC_EOF_T; 115870b51aabf3b03fbf8d61c14847ccce4c69fb0cddRobert Love fr_dev(fp) = lport; 1159e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt fr_encaps(fp) = els_dtype; 116097c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt 1161f018b73af6db4f330ad5da9ac53997a699c30c42Joe Eykholt stats = per_cpu_ptr(lport->dev_stats, get_cpu()); 116297c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt stats->RxFrames++; 116397c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt stats->RxWords += skb->len / FIP_BPW; 1164f018b73af6db4f330ad5da9ac53997a699c30c42Joe Eykholt put_cpu(); 116597c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt 116670b51aabf3b03fbf8d61c14847ccce4c69fb0cddRobert Love fc_exch_recv(lport, fp); 116797c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt return; 116897c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt 116997c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholtlen_err: 11700f51c2e54c0bfdb6b02c53f6d7dd9b35f91821b6Joe Eykholt LIBFCOE_FIP_DBG(fip, "FIP length error in descriptor type %x len %zu\n", 1171650bd12b9e31ec51d7ad0df3c4f94d863b827976Robert Love desc->fip_dtype, dlen); 117297c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholtdrop: 117397c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt kfree_skb(skb); 117497c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt} 117597c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt 117697c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt/** 117770b51aabf3b03fbf8d61c14847ccce4c69fb0cddRobert Love * fcoe_ctlr_recv_els() - Handle an incoming link reset frame 117870b51aabf3b03fbf8d61c14847ccce4c69fb0cddRobert Love * @fip: The FCoE controller that received the frame 117970b51aabf3b03fbf8d61c14847ccce4c69fb0cddRobert Love * @fh: The received FIP header 118097c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt * 118197c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt * There may be multiple VN_Port descriptors. 118297c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt * The overall length has already been checked. 118397c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt */ 118497c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholtstatic void fcoe_ctlr_recv_clr_vlink(struct fcoe_ctlr *fip, 118570b51aabf3b03fbf8d61c14847ccce4c69fb0cddRobert Love struct fip_header *fh) 118697c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt{ 118797c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt struct fip_desc *desc; 118897c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt struct fip_mac_desc *mp; 118997c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt struct fip_wwn_desc *wp; 119097c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt struct fip_vn_desc *vp; 119197c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt size_t rlen; 119297c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt size_t dlen; 119397c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt struct fcoe_fcf *fcf = fip->sel_fcf; 119470b51aabf3b03fbf8d61c14847ccce4c69fb0cddRobert Love struct fc_lport *lport = fip->lp; 11955550fda73d8bd3bed454e28c46f5a4e5288769bbBhanu Prakash Gollapudi struct fc_lport *vn_port = NULL; 11965550fda73d8bd3bed454e28c46f5a4e5288769bbBhanu Prakash Gollapudi u32 desc_mask; 1197c051ad2e57e379e07e4ec28b2a54eeb0d04c5d59Bhanu Prakash Gollapudi int num_vlink_desc; 1198c051ad2e57e379e07e4ec28b2a54eeb0d04c5d59Bhanu Prakash Gollapudi int reset_phys_port = 0; 1199c051ad2e57e379e07e4ec28b2a54eeb0d04c5d59Bhanu Prakash Gollapudi struct fip_vn_desc **vlink_desc_arr = NULL; 120097c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt 12010f51c2e54c0bfdb6b02c53f6d7dd9b35f91821b6Joe Eykholt LIBFCOE_FIP_DBG(fip, "Clear Virtual Link received\n"); 1202d29510a2968f87eaf455c606cd8802b6f8a0774bRobert Love 12037b2787ec15b9d1c2f716da61b0eec21a3f5e6520Robert Love if (!fcf || !lport->port_id) 120497c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt return; 120597c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt 120697c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt /* 120797c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt * mask of required descriptors. Validating each one clears its bit. 120897c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt */ 1209c051ad2e57e379e07e4ec28b2a54eeb0d04c5d59Bhanu Prakash Gollapudi desc_mask = BIT(FIP_DT_MAC) | BIT(FIP_DT_NAME); 121097c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt 121197c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt rlen = ntohs(fh->fip_dl_len) * FIP_BPW; 121297c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt desc = (struct fip_desc *)(fh + 1); 1213c051ad2e57e379e07e4ec28b2a54eeb0d04c5d59Bhanu Prakash Gollapudi 1214c051ad2e57e379e07e4ec28b2a54eeb0d04c5d59Bhanu Prakash Gollapudi /* 1215c051ad2e57e379e07e4ec28b2a54eeb0d04c5d59Bhanu Prakash Gollapudi * Actually need to subtract 'sizeof(*mp) - sizeof(*wp)' from 'rlen' 1216c051ad2e57e379e07e4ec28b2a54eeb0d04c5d59Bhanu Prakash Gollapudi * before determining max Vx_Port descriptor but a buggy FCF could have 1217c051ad2e57e379e07e4ec28b2a54eeb0d04c5d59Bhanu Prakash Gollapudi * omited either or both MAC Address and Name Identifier descriptors 1218c051ad2e57e379e07e4ec28b2a54eeb0d04c5d59Bhanu Prakash Gollapudi */ 1219c051ad2e57e379e07e4ec28b2a54eeb0d04c5d59Bhanu Prakash Gollapudi num_vlink_desc = rlen / sizeof(*vp); 1220c051ad2e57e379e07e4ec28b2a54eeb0d04c5d59Bhanu Prakash Gollapudi if (num_vlink_desc) 1221c051ad2e57e379e07e4ec28b2a54eeb0d04c5d59Bhanu Prakash Gollapudi vlink_desc_arr = kmalloc(sizeof(vp) * num_vlink_desc, 1222c051ad2e57e379e07e4ec28b2a54eeb0d04c5d59Bhanu Prakash Gollapudi GFP_ATOMIC); 1223c051ad2e57e379e07e4ec28b2a54eeb0d04c5d59Bhanu Prakash Gollapudi if (!vlink_desc_arr) 1224c051ad2e57e379e07e4ec28b2a54eeb0d04c5d59Bhanu Prakash Gollapudi return; 1225c051ad2e57e379e07e4ec28b2a54eeb0d04c5d59Bhanu Prakash Gollapudi num_vlink_desc = 0; 1226c051ad2e57e379e07e4ec28b2a54eeb0d04c5d59Bhanu Prakash Gollapudi 122797c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt while (rlen >= sizeof(*desc)) { 122897c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt dlen = desc->fip_dlen * FIP_BPW; 122997c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt if (dlen > rlen) 1230c051ad2e57e379e07e4ec28b2a54eeb0d04c5d59Bhanu Prakash Gollapudi goto err; 12310a9c5d344dbd983af59865f9880621e5cbbda899Bhanu Prakash Gollapudi /* Drop CVL if there are duplicate critical descriptors */ 12320a9c5d344dbd983af59865f9880621e5cbbda899Bhanu Prakash Gollapudi if ((desc->fip_dtype < 32) && 1233c051ad2e57e379e07e4ec28b2a54eeb0d04c5d59Bhanu Prakash Gollapudi (desc->fip_dtype != FIP_DT_VN_ID) && 12340a9c5d344dbd983af59865f9880621e5cbbda899Bhanu Prakash Gollapudi !(desc_mask & 1U << desc->fip_dtype)) { 12350a9c5d344dbd983af59865f9880621e5cbbda899Bhanu Prakash Gollapudi LIBFCOE_FIP_DBG(fip, "Duplicate Critical " 12360a9c5d344dbd983af59865f9880621e5cbbda899Bhanu Prakash Gollapudi "Descriptors in FIP CVL\n"); 1237c051ad2e57e379e07e4ec28b2a54eeb0d04c5d59Bhanu Prakash Gollapudi goto err; 12380a9c5d344dbd983af59865f9880621e5cbbda899Bhanu Prakash Gollapudi } 123997c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt switch (desc->fip_dtype) { 124097c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt case FIP_DT_MAC: 124197c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt mp = (struct fip_mac_desc *)desc; 124297c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt if (dlen < sizeof(*mp)) 1243c051ad2e57e379e07e4ec28b2a54eeb0d04c5d59Bhanu Prakash Gollapudi goto err; 124497c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt if (compare_ether_addr(mp->fd_mac, fcf->fcf_mac)) 1245c051ad2e57e379e07e4ec28b2a54eeb0d04c5d59Bhanu Prakash Gollapudi goto err; 124697c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt desc_mask &= ~BIT(FIP_DT_MAC); 124797c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt break; 124897c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt case FIP_DT_NAME: 124997c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt wp = (struct fip_wwn_desc *)desc; 125097c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt if (dlen < sizeof(*wp)) 1251c051ad2e57e379e07e4ec28b2a54eeb0d04c5d59Bhanu Prakash Gollapudi goto err; 125297c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt if (get_unaligned_be64(&wp->fd_wwn) != fcf->switch_name) 1253c051ad2e57e379e07e4ec28b2a54eeb0d04c5d59Bhanu Prakash Gollapudi goto err; 125497c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt desc_mask &= ~BIT(FIP_DT_NAME); 125597c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt break; 125697c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt case FIP_DT_VN_ID: 125797c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt vp = (struct fip_vn_desc *)desc; 125897c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt if (dlen < sizeof(*vp)) 1259c051ad2e57e379e07e4ec28b2a54eeb0d04c5d59Bhanu Prakash Gollapudi goto err; 1260c051ad2e57e379e07e4ec28b2a54eeb0d04c5d59Bhanu Prakash Gollapudi vlink_desc_arr[num_vlink_desc++] = vp; 1261c051ad2e57e379e07e4ec28b2a54eeb0d04c5d59Bhanu Prakash Gollapudi vn_port = fc_vport_id_lookup(lport, 1262c051ad2e57e379e07e4ec28b2a54eeb0d04c5d59Bhanu Prakash Gollapudi ntoh24(vp->fd_fc_id)); 1263c051ad2e57e379e07e4ec28b2a54eeb0d04c5d59Bhanu Prakash Gollapudi if (vn_port && (vn_port == lport)) { 1264c051ad2e57e379e07e4ec28b2a54eeb0d04c5d59Bhanu Prakash Gollapudi mutex_lock(&fip->ctlr_mutex); 1265c051ad2e57e379e07e4ec28b2a54eeb0d04c5d59Bhanu Prakash Gollapudi per_cpu_ptr(lport->dev_stats, 1266c051ad2e57e379e07e4ec28b2a54eeb0d04c5d59Bhanu Prakash Gollapudi get_cpu())->VLinkFailureCount++; 1267c051ad2e57e379e07e4ec28b2a54eeb0d04c5d59Bhanu Prakash Gollapudi put_cpu(); 1268c051ad2e57e379e07e4ec28b2a54eeb0d04c5d59Bhanu Prakash Gollapudi fcoe_ctlr_reset(fip); 1269c051ad2e57e379e07e4ec28b2a54eeb0d04c5d59Bhanu Prakash Gollapudi mutex_unlock(&fip->ctlr_mutex); 12705550fda73d8bd3bed454e28c46f5a4e5288769bbBhanu Prakash Gollapudi } 127197c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt break; 127297c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt default: 127397c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt /* standard says ignore unknown descriptors >= 128 */ 127497c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt if (desc->fip_dtype < FIP_DT_VENDOR_BASE) 1275c051ad2e57e379e07e4ec28b2a54eeb0d04c5d59Bhanu Prakash Gollapudi goto err; 127697c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt break; 127797c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt } 127897c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt desc = (struct fip_desc *)((char *)desc + dlen); 127997c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt rlen -= dlen; 128097c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt } 128197c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt 128297c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt /* 128397c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt * reset only if all required descriptors were present and valid. 128497c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt */ 1285c051ad2e57e379e07e4ec28b2a54eeb0d04c5d59Bhanu Prakash Gollapudi if (desc_mask) 12860f51c2e54c0bfdb6b02c53f6d7dd9b35f91821b6Joe Eykholt LIBFCOE_FIP_DBG(fip, "missing descriptors mask %x\n", 12870f51c2e54c0bfdb6b02c53f6d7dd9b35f91821b6Joe Eykholt desc_mask); 1288c051ad2e57e379e07e4ec28b2a54eeb0d04c5d59Bhanu Prakash Gollapudi else if (!num_vlink_desc) { 1289c051ad2e57e379e07e4ec28b2a54eeb0d04c5d59Bhanu Prakash Gollapudi LIBFCOE_FIP_DBG(fip, "CVL: no Vx_Port descriptor found\n"); 1290c051ad2e57e379e07e4ec28b2a54eeb0d04c5d59Bhanu Prakash Gollapudi /* 1291c051ad2e57e379e07e4ec28b2a54eeb0d04c5d59Bhanu Prakash Gollapudi * No Vx_Port description. Clear all NPIV ports, 1292c051ad2e57e379e07e4ec28b2a54eeb0d04c5d59Bhanu Prakash Gollapudi * followed by physical port 1293c051ad2e57e379e07e4ec28b2a54eeb0d04c5d59Bhanu Prakash Gollapudi */ 1294c051ad2e57e379e07e4ec28b2a54eeb0d04c5d59Bhanu Prakash Gollapudi mutex_lock(&fip->ctlr_mutex); 1295c051ad2e57e379e07e4ec28b2a54eeb0d04c5d59Bhanu Prakash Gollapudi per_cpu_ptr(lport->dev_stats, 1296c051ad2e57e379e07e4ec28b2a54eeb0d04c5d59Bhanu Prakash Gollapudi get_cpu())->VLinkFailureCount++; 1297c051ad2e57e379e07e4ec28b2a54eeb0d04c5d59Bhanu Prakash Gollapudi put_cpu(); 1298c051ad2e57e379e07e4ec28b2a54eeb0d04c5d59Bhanu Prakash Gollapudi fcoe_ctlr_reset(fip); 1299c051ad2e57e379e07e4ec28b2a54eeb0d04c5d59Bhanu Prakash Gollapudi mutex_unlock(&fip->ctlr_mutex); 1300c051ad2e57e379e07e4ec28b2a54eeb0d04c5d59Bhanu Prakash Gollapudi 130114619ea689cc0b257cf998469005d0515133d7bcBhanu Prakash Gollapudi mutex_lock(&lport->lp_mutex); 130214619ea689cc0b257cf998469005d0515133d7bcBhanu Prakash Gollapudi list_for_each_entry(vn_port, &lport->vports, list) 130314619ea689cc0b257cf998469005d0515133d7bcBhanu Prakash Gollapudi fc_lport_reset(vn_port); 130414619ea689cc0b257cf998469005d0515133d7bcBhanu Prakash Gollapudi mutex_unlock(&lport->lp_mutex); 130514619ea689cc0b257cf998469005d0515133d7bcBhanu Prakash Gollapudi 1306c051ad2e57e379e07e4ec28b2a54eeb0d04c5d59Bhanu Prakash Gollapudi fc_lport_reset(fip->lp); 1307c051ad2e57e379e07e4ec28b2a54eeb0d04c5d59Bhanu Prakash Gollapudi fcoe_ctlr_solicit(fip, NULL); 130897c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt } else { 1309c051ad2e57e379e07e4ec28b2a54eeb0d04c5d59Bhanu Prakash Gollapudi int i; 1310dd42dac4ecd1799077c132aab35d3c36b26d4d8cJoe Eykholt 1311c051ad2e57e379e07e4ec28b2a54eeb0d04c5d59Bhanu Prakash Gollapudi LIBFCOE_FIP_DBG(fip, "performing Clear Virtual Link\n"); 1312c051ad2e57e379e07e4ec28b2a54eeb0d04c5d59Bhanu Prakash Gollapudi for (i = 0; i < num_vlink_desc; i++) { 1313c051ad2e57e379e07e4ec28b2a54eeb0d04c5d59Bhanu Prakash Gollapudi vp = vlink_desc_arr[i]; 1314c051ad2e57e379e07e4ec28b2a54eeb0d04c5d59Bhanu Prakash Gollapudi vn_port = fc_vport_id_lookup(lport, 1315c051ad2e57e379e07e4ec28b2a54eeb0d04c5d59Bhanu Prakash Gollapudi ntoh24(vp->fd_fc_id)); 1316c051ad2e57e379e07e4ec28b2a54eeb0d04c5d59Bhanu Prakash Gollapudi if (!vn_port) 1317c051ad2e57e379e07e4ec28b2a54eeb0d04c5d59Bhanu Prakash Gollapudi continue; 1318c051ad2e57e379e07e4ec28b2a54eeb0d04c5d59Bhanu Prakash Gollapudi 1319c051ad2e57e379e07e4ec28b2a54eeb0d04c5d59Bhanu Prakash Gollapudi /* 1320c051ad2e57e379e07e4ec28b2a54eeb0d04c5d59Bhanu Prakash Gollapudi * 'port_id' is already validated, check MAC address and 1321c051ad2e57e379e07e4ec28b2a54eeb0d04c5d59Bhanu Prakash Gollapudi * wwpn 1322c051ad2e57e379e07e4ec28b2a54eeb0d04c5d59Bhanu Prakash Gollapudi */ 1323c051ad2e57e379e07e4ec28b2a54eeb0d04c5d59Bhanu Prakash Gollapudi if (compare_ether_addr(fip->get_src_addr(vn_port), 1324c051ad2e57e379e07e4ec28b2a54eeb0d04c5d59Bhanu Prakash Gollapudi vp->fd_mac) != 0 || 1325c051ad2e57e379e07e4ec28b2a54eeb0d04c5d59Bhanu Prakash Gollapudi get_unaligned_be64(&vp->fd_wwpn) != 1326c051ad2e57e379e07e4ec28b2a54eeb0d04c5d59Bhanu Prakash Gollapudi vn_port->wwpn) 1327c051ad2e57e379e07e4ec28b2a54eeb0d04c5d59Bhanu Prakash Gollapudi continue; 1328c051ad2e57e379e07e4ec28b2a54eeb0d04c5d59Bhanu Prakash Gollapudi 1329c051ad2e57e379e07e4ec28b2a54eeb0d04c5d59Bhanu Prakash Gollapudi if (vn_port == lport) 1330c051ad2e57e379e07e4ec28b2a54eeb0d04c5d59Bhanu Prakash Gollapudi /* 1331c051ad2e57e379e07e4ec28b2a54eeb0d04c5d59Bhanu Prakash Gollapudi * Physical port, defer processing till all 1332c051ad2e57e379e07e4ec28b2a54eeb0d04c5d59Bhanu Prakash Gollapudi * listed NPIV ports are cleared 1333c051ad2e57e379e07e4ec28b2a54eeb0d04c5d59Bhanu Prakash Gollapudi */ 1334c051ad2e57e379e07e4ec28b2a54eeb0d04c5d59Bhanu Prakash Gollapudi reset_phys_port = 1; 1335c051ad2e57e379e07e4ec28b2a54eeb0d04c5d59Bhanu Prakash Gollapudi else /* NPIV port */ 1336c051ad2e57e379e07e4ec28b2a54eeb0d04c5d59Bhanu Prakash Gollapudi fc_lport_reset(vn_port); 1337c051ad2e57e379e07e4ec28b2a54eeb0d04c5d59Bhanu Prakash Gollapudi } 13385550fda73d8bd3bed454e28c46f5a4e5288769bbBhanu Prakash Gollapudi 1339c051ad2e57e379e07e4ec28b2a54eeb0d04c5d59Bhanu Prakash Gollapudi if (reset_phys_port) { 13405550fda73d8bd3bed454e28c46f5a4e5288769bbBhanu Prakash Gollapudi fc_lport_reset(fip->lp); 13415550fda73d8bd3bed454e28c46f5a4e5288769bbBhanu Prakash Gollapudi fcoe_ctlr_solicit(fip, NULL); 13425550fda73d8bd3bed454e28c46f5a4e5288769bbBhanu Prakash Gollapudi } 134397c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt } 1344c051ad2e57e379e07e4ec28b2a54eeb0d04c5d59Bhanu Prakash Gollapudi 1345c051ad2e57e379e07e4ec28b2a54eeb0d04c5d59Bhanu Prakash Gollapudierr: 1346c051ad2e57e379e07e4ec28b2a54eeb0d04c5d59Bhanu Prakash Gollapudi kfree(vlink_desc_arr); 134797c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt} 134897c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt 134997c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt/** 135070b51aabf3b03fbf8d61c14847ccce4c69fb0cddRobert Love * fcoe_ctlr_recv() - Receive a FIP packet 135170b51aabf3b03fbf8d61c14847ccce4c69fb0cddRobert Love * @fip: The FCoE controller that received the packet 135270b51aabf3b03fbf8d61c14847ccce4c69fb0cddRobert Love * @skb: The received FIP packet 135397c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt * 13541f4aed818d26eb9ed54520fbeb85d5ee691baa94Joe Eykholt * This may be called from either NET_RX_SOFTIRQ or IRQ. 135597c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt */ 135697c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholtvoid fcoe_ctlr_recv(struct fcoe_ctlr *fip, struct sk_buff *skb) 135797c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt{ 13581f4aed818d26eb9ed54520fbeb85d5ee691baa94Joe Eykholt skb_queue_tail(&fip->fip_recv_list, skb); 135997c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt schedule_work(&fip->recv_work); 136097c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt} 136197c8389d54b9665c38105ea72a428a44b97ff2f6Joe EykholtEXPORT_SYMBOL(fcoe_ctlr_recv); 136297c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt 136397c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt/** 136470b51aabf3b03fbf8d61c14847ccce4c69fb0cddRobert Love * fcoe_ctlr_recv_handler() - Receive a FIP frame 136570b51aabf3b03fbf8d61c14847ccce4c69fb0cddRobert Love * @fip: The FCoE controller that received the frame 136670b51aabf3b03fbf8d61c14847ccce4c69fb0cddRobert Love * @skb: The received FIP frame 136797c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt * 136897c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt * Returns non-zero if the frame is dropped. 136997c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt */ 137097c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholtstatic int fcoe_ctlr_recv_handler(struct fcoe_ctlr *fip, struct sk_buff *skb) 137197c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt{ 137297c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt struct fip_header *fiph; 137397c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt struct ethhdr *eh; 137497c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt enum fip_state state; 137597c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt u16 op; 137697c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt u8 sub; 137797c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt 137897c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt if (skb_linearize(skb)) 137997c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt goto drop; 138097c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt if (skb->len < sizeof(*fiph)) 138197c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt goto drop; 138297c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt eh = eth_hdr(skb); 1383e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt if (fip->mode == FIP_MODE_VN2VN) { 1384e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt if (compare_ether_addr(eh->h_dest, fip->ctl_src_addr) && 1385e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt compare_ether_addr(eh->h_dest, fcoe_all_vn2vn) && 1386e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt compare_ether_addr(eh->h_dest, fcoe_all_p2p)) 1387e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt goto drop; 1388e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt } else if (compare_ether_addr(eh->h_dest, fip->ctl_src_addr) && 1389e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt compare_ether_addr(eh->h_dest, fcoe_all_enode)) 139097c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt goto drop; 139197c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt fiph = (struct fip_header *)skb->data; 139297c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt op = ntohs(fiph->fip_op); 139397c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt sub = fiph->fip_subcode; 139497c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt 139597c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt if (FIP_VER_DECAPS(fiph->fip_ver) != FIP_VER) 139697c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt goto drop; 139797c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt if (ntohs(fiph->fip_dl_len) * FIP_BPW + sizeof(*fiph) > skb->len) 139897c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt goto drop; 139997c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt 1400fdb068c6cd6e30d43664f856d3530715a5742713Joe Eykholt mutex_lock(&fip->ctlr_mutex); 140197c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt state = fip->state; 140297c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt if (state == FIP_ST_AUTO) { 140397c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt fip->map_dest = 0; 14049b651da900ccfe5581befb46eb06ef781a1d7e74Joe Eykholt fcoe_ctlr_set_state(fip, FIP_ST_ENABLED); 140597c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt state = FIP_ST_ENABLED; 14060f51c2e54c0bfdb6b02c53f6d7dd9b35f91821b6Joe Eykholt LIBFCOE_FIP_DBG(fip, "Using FIP mode\n"); 140797c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt } 1408fdb068c6cd6e30d43664f856d3530715a5742713Joe Eykholt mutex_unlock(&fip->ctlr_mutex); 1409e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt 1410e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt if (fip->mode == FIP_MODE_VN2VN && op == FIP_OP_VN2VN) 1411e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt return fcoe_ctlr_vn_recv(fip, skb); 1412e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt 1413e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt if (state != FIP_ST_ENABLED && state != FIP_ST_VNMP_UP && 1414e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt state != FIP_ST_VNMP_CLAIM) 141597c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt goto drop; 141697c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt 141797c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt if (op == FIP_OP_LS) { 141897c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt fcoe_ctlr_recv_els(fip, skb); /* consumes skb */ 141997c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt return 0; 142097c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt } 1421e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt 1422e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt if (state != FIP_ST_ENABLED) 1423e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt goto drop; 1424e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt 142597c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt if (op == FIP_OP_DISC && sub == FIP_SC_ADV) 142697c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt fcoe_ctlr_recv_adv(fip, skb); 142797c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt else if (op == FIP_OP_CTRL && sub == FIP_SC_CLR_VLINK) 142897c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt fcoe_ctlr_recv_clr_vlink(fip, fiph); 142997c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt kfree_skb(skb); 143097c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt return 0; 143197c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholtdrop: 143297c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt kfree_skb(skb); 143397c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt return -1; 143497c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt} 143597c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt 143697c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt/** 143770b51aabf3b03fbf8d61c14847ccce4c69fb0cddRobert Love * fcoe_ctlr_select() - Select the best FCF (if possible) 143870b51aabf3b03fbf8d61c14847ccce4c69fb0cddRobert Love * @fip: The FCoE controller 143997c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt * 1440ba9cd5d095b42271588c20ccd6ddd561d0e4cc1eJoe Eykholt * Returns the selected FCF, or NULL if none are usable. 1441ba9cd5d095b42271588c20ccd6ddd561d0e4cc1eJoe Eykholt * 144297c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt * If there are conflicting advertisements, no FCF can be chosen. 144397c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt * 1444794d98e77f5901ceded697f1633463e88f078038Joe Eykholt * If there is already a selected FCF, this will choose a better one or 1445794d98e77f5901ceded697f1633463e88f078038Joe Eykholt * an equivalent one that hasn't already been sent a FLOGI. 1446794d98e77f5901ceded697f1633463e88f078038Joe Eykholt * 144797c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt * Called with lock held. 144897c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt */ 1449ba9cd5d095b42271588c20ccd6ddd561d0e4cc1eJoe Eykholtstatic struct fcoe_fcf *fcoe_ctlr_select(struct fcoe_ctlr *fip) 145097c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt{ 145197c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt struct fcoe_fcf *fcf; 1452794d98e77f5901ceded697f1633463e88f078038Joe Eykholt struct fcoe_fcf *best = fip->sel_fcf; 1453b69ae0ae3f322d9a6bc4e209049b5b6e193ad652Joe Eykholt struct fcoe_fcf *first; 1454b69ae0ae3f322d9a6bc4e209049b5b6e193ad652Joe Eykholt 1455b69ae0ae3f322d9a6bc4e209049b5b6e193ad652Joe Eykholt first = list_first_entry(&fip->fcfs, struct fcoe_fcf, list); 145697c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt 145797c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt list_for_each_entry(fcf, &fip->fcfs, list) { 14589069f5c433e402be5707f37f3d0dfb376659c1e4Joe Eykholt LIBFCOE_FIP_DBG(fip, "consider FCF fab %16.16llx " 14599069f5c433e402be5707f37f3d0dfb376659c1e4Joe Eykholt "VFID %d mac %pM map %x val %d " 14609069f5c433e402be5707f37f3d0dfb376659c1e4Joe Eykholt "sent %u pri %u\n", 14619069f5c433e402be5707f37f3d0dfb376659c1e4Joe Eykholt fcf->fabric_name, fcf->vfid, fcf->fcf_mac, 14629069f5c433e402be5707f37f3d0dfb376659c1e4Joe Eykholt fcf->fc_map, fcoe_ctlr_mtu_valid(fcf), 14639069f5c433e402be5707f37f3d0dfb376659c1e4Joe Eykholt fcf->flogi_sent, fcf->pri); 1464b69ae0ae3f322d9a6bc4e209049b5b6e193ad652Joe Eykholt if (fcf->fabric_name != first->fabric_name || 1465b69ae0ae3f322d9a6bc4e209049b5b6e193ad652Joe Eykholt fcf->vfid != first->vfid || 1466b69ae0ae3f322d9a6bc4e209049b5b6e193ad652Joe Eykholt fcf->fc_map != first->fc_map) { 1467b69ae0ae3f322d9a6bc4e209049b5b6e193ad652Joe Eykholt LIBFCOE_FIP_DBG(fip, "Conflicting fabric, VFID, " 1468b69ae0ae3f322d9a6bc4e209049b5b6e193ad652Joe Eykholt "or FC-MAP\n"); 1469b69ae0ae3f322d9a6bc4e209049b5b6e193ad652Joe Eykholt return NULL; 1470b69ae0ae3f322d9a6bc4e209049b5b6e193ad652Joe Eykholt } 1471794d98e77f5901ceded697f1633463e88f078038Joe Eykholt if (fcf->flogi_sent) 1472794d98e77f5901ceded697f1633463e88f078038Joe Eykholt continue; 147397c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt if (!fcoe_ctlr_fcf_usable(fcf)) { 14749f8f3aa640ae5da220eea95215317f19ace91481Chris Leech LIBFCOE_FIP_DBG(fip, "FCF for fab %16.16llx " 14759f8f3aa640ae5da220eea95215317f19ace91481Chris Leech "map %x %svalid %savailable\n", 14769f8f3aa640ae5da220eea95215317f19ace91481Chris Leech fcf->fabric_name, fcf->fc_map, 14779f8f3aa640ae5da220eea95215317f19ace91481Chris Leech (fcf->flags & FIP_FL_SOL) ? "" : "in", 14789f8f3aa640ae5da220eea95215317f19ace91481Chris Leech (fcf->flags & FIP_FL_AVAIL) ? 14799f8f3aa640ae5da220eea95215317f19ace91481Chris Leech "" : "un"); 148097c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt continue; 148197c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt } 1482794d98e77f5901ceded697f1633463e88f078038Joe Eykholt if (!best || fcf->pri < best->pri || best->flogi_sent) 148397c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt best = fcf; 148497c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt } 148597c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt fip->sel_fcf = best; 1486c47036a7cd378533495d8cc06a7cf8a881072a9dJoe Eykholt if (best) { 14879069f5c433e402be5707f37f3d0dfb376659c1e4Joe Eykholt LIBFCOE_FIP_DBG(fip, "using FCF mac %pM\n", best->fcf_mac); 1488c47036a7cd378533495d8cc06a7cf8a881072a9dJoe Eykholt fip->port_ka_time = jiffies + 1489c47036a7cd378533495d8cc06a7cf8a881072a9dJoe Eykholt msecs_to_jiffies(FIP_VN_KA_PERIOD); 1490c47036a7cd378533495d8cc06a7cf8a881072a9dJoe Eykholt fip->ctlr_ka_time = jiffies + best->fka_period; 1491c47036a7cd378533495d8cc06a7cf8a881072a9dJoe Eykholt if (time_before(fip->ctlr_ka_time, fip->timer.expires)) 1492c47036a7cd378533495d8cc06a7cf8a881072a9dJoe Eykholt mod_timer(&fip->timer, fip->ctlr_ka_time); 1493c47036a7cd378533495d8cc06a7cf8a881072a9dJoe Eykholt } 1494ba9cd5d095b42271588c20ccd6ddd561d0e4cc1eJoe Eykholt return best; 149597c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt} 149697c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt 149797c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt/** 1498794d98e77f5901ceded697f1633463e88f078038Joe Eykholt * fcoe_ctlr_flogi_send_locked() - send FIP-encapsulated FLOGI to current FCF 1499794d98e77f5901ceded697f1633463e88f078038Joe Eykholt * @fip: The FCoE controller 1500794d98e77f5901ceded697f1633463e88f078038Joe Eykholt * 1501794d98e77f5901ceded697f1633463e88f078038Joe Eykholt * Returns non-zero error if it could not be sent. 1502794d98e77f5901ceded697f1633463e88f078038Joe Eykholt * 1503794d98e77f5901ceded697f1633463e88f078038Joe Eykholt * Called with ctlr_mutex and ctlr_lock held. 1504794d98e77f5901ceded697f1633463e88f078038Joe Eykholt * Caller must verify that fip->sel_fcf is not NULL. 1505794d98e77f5901ceded697f1633463e88f078038Joe Eykholt */ 1506794d98e77f5901ceded697f1633463e88f078038Joe Eykholtstatic int fcoe_ctlr_flogi_send_locked(struct fcoe_ctlr *fip) 1507794d98e77f5901ceded697f1633463e88f078038Joe Eykholt{ 1508794d98e77f5901ceded697f1633463e88f078038Joe Eykholt struct sk_buff *skb; 1509794d98e77f5901ceded697f1633463e88f078038Joe Eykholt struct sk_buff *skb_orig; 1510794d98e77f5901ceded697f1633463e88f078038Joe Eykholt struct fc_frame_header *fh; 1511794d98e77f5901ceded697f1633463e88f078038Joe Eykholt int error; 1512794d98e77f5901ceded697f1633463e88f078038Joe Eykholt 1513794d98e77f5901ceded697f1633463e88f078038Joe Eykholt skb_orig = fip->flogi_req; 1514794d98e77f5901ceded697f1633463e88f078038Joe Eykholt if (!skb_orig) 1515794d98e77f5901ceded697f1633463e88f078038Joe Eykholt return -EINVAL; 1516794d98e77f5901ceded697f1633463e88f078038Joe Eykholt 1517794d98e77f5901ceded697f1633463e88f078038Joe Eykholt /* 1518794d98e77f5901ceded697f1633463e88f078038Joe Eykholt * Clone and send the FLOGI request. If clone fails, use original. 1519794d98e77f5901ceded697f1633463e88f078038Joe Eykholt */ 1520794d98e77f5901ceded697f1633463e88f078038Joe Eykholt skb = skb_clone(skb_orig, GFP_ATOMIC); 1521794d98e77f5901ceded697f1633463e88f078038Joe Eykholt if (!skb) { 1522794d98e77f5901ceded697f1633463e88f078038Joe Eykholt skb = skb_orig; 1523794d98e77f5901ceded697f1633463e88f078038Joe Eykholt fip->flogi_req = NULL; 1524794d98e77f5901ceded697f1633463e88f078038Joe Eykholt } 1525794d98e77f5901ceded697f1633463e88f078038Joe Eykholt fh = (struct fc_frame_header *)skb->data; 1526794d98e77f5901ceded697f1633463e88f078038Joe Eykholt error = fcoe_ctlr_encaps(fip, fip->lp, FIP_DT_FLOGI, skb, 1527794d98e77f5901ceded697f1633463e88f078038Joe Eykholt ntoh24(fh->fh_d_id)); 1528794d98e77f5901ceded697f1633463e88f078038Joe Eykholt if (error) { 1529794d98e77f5901ceded697f1633463e88f078038Joe Eykholt kfree_skb(skb); 1530794d98e77f5901ceded697f1633463e88f078038Joe Eykholt return error; 1531794d98e77f5901ceded697f1633463e88f078038Joe Eykholt } 1532794d98e77f5901ceded697f1633463e88f078038Joe Eykholt fip->send(fip, skb); 1533794d98e77f5901ceded697f1633463e88f078038Joe Eykholt fip->sel_fcf->flogi_sent = 1; 1534794d98e77f5901ceded697f1633463e88f078038Joe Eykholt return 0; 1535794d98e77f5901ceded697f1633463e88f078038Joe Eykholt} 1536794d98e77f5901ceded697f1633463e88f078038Joe Eykholt 1537794d98e77f5901ceded697f1633463e88f078038Joe Eykholt/** 1538794d98e77f5901ceded697f1633463e88f078038Joe Eykholt * fcoe_ctlr_flogi_retry() - resend FLOGI request to a new FCF if possible 1539794d98e77f5901ceded697f1633463e88f078038Joe Eykholt * @fip: The FCoE controller 1540794d98e77f5901ceded697f1633463e88f078038Joe Eykholt * 1541794d98e77f5901ceded697f1633463e88f078038Joe Eykholt * Returns non-zero error code if there's no FLOGI request to retry or 1542794d98e77f5901ceded697f1633463e88f078038Joe Eykholt * no alternate FCF available. 1543794d98e77f5901ceded697f1633463e88f078038Joe Eykholt */ 1544794d98e77f5901ceded697f1633463e88f078038Joe Eykholtstatic int fcoe_ctlr_flogi_retry(struct fcoe_ctlr *fip) 1545794d98e77f5901ceded697f1633463e88f078038Joe Eykholt{ 1546794d98e77f5901ceded697f1633463e88f078038Joe Eykholt struct fcoe_fcf *fcf; 1547794d98e77f5901ceded697f1633463e88f078038Joe Eykholt int error; 1548794d98e77f5901ceded697f1633463e88f078038Joe Eykholt 1549794d98e77f5901ceded697f1633463e88f078038Joe Eykholt mutex_lock(&fip->ctlr_mutex); 1550794d98e77f5901ceded697f1633463e88f078038Joe Eykholt spin_lock_bh(&fip->ctlr_lock); 1551794d98e77f5901ceded697f1633463e88f078038Joe Eykholt LIBFCOE_FIP_DBG(fip, "re-sending FLOGI - reselect\n"); 1552ba9cd5d095b42271588c20ccd6ddd561d0e4cc1eJoe Eykholt fcf = fcoe_ctlr_select(fip); 1553794d98e77f5901ceded697f1633463e88f078038Joe Eykholt if (!fcf || fcf->flogi_sent) { 1554794d98e77f5901ceded697f1633463e88f078038Joe Eykholt kfree_skb(fip->flogi_req); 1555794d98e77f5901ceded697f1633463e88f078038Joe Eykholt fip->flogi_req = NULL; 1556794d98e77f5901ceded697f1633463e88f078038Joe Eykholt error = -ENOENT; 1557794d98e77f5901ceded697f1633463e88f078038Joe Eykholt } else { 1558794d98e77f5901ceded697f1633463e88f078038Joe Eykholt fcoe_ctlr_solicit(fip, NULL); 1559794d98e77f5901ceded697f1633463e88f078038Joe Eykholt error = fcoe_ctlr_flogi_send_locked(fip); 1560794d98e77f5901ceded697f1633463e88f078038Joe Eykholt } 1561794d98e77f5901ceded697f1633463e88f078038Joe Eykholt spin_unlock_bh(&fip->ctlr_lock); 1562794d98e77f5901ceded697f1633463e88f078038Joe Eykholt mutex_unlock(&fip->ctlr_mutex); 1563794d98e77f5901ceded697f1633463e88f078038Joe Eykholt return error; 1564794d98e77f5901ceded697f1633463e88f078038Joe Eykholt} 1565794d98e77f5901ceded697f1633463e88f078038Joe Eykholt 1566794d98e77f5901ceded697f1633463e88f078038Joe Eykholt 1567794d98e77f5901ceded697f1633463e88f078038Joe Eykholt/** 1568794d98e77f5901ceded697f1633463e88f078038Joe Eykholt * fcoe_ctlr_flogi_send() - Handle sending of FIP FLOGI. 1569794d98e77f5901ceded697f1633463e88f078038Joe Eykholt * @fip: The FCoE controller that timed out 1570794d98e77f5901ceded697f1633463e88f078038Joe Eykholt * 1571794d98e77f5901ceded697f1633463e88f078038Joe Eykholt * Done here because fcoe_ctlr_els_send() can't get mutex. 1572794d98e77f5901ceded697f1633463e88f078038Joe Eykholt * 1573794d98e77f5901ceded697f1633463e88f078038Joe Eykholt * Called with ctlr_mutex held. The caller must not hold ctlr_lock. 1574794d98e77f5901ceded697f1633463e88f078038Joe Eykholt */ 1575794d98e77f5901ceded697f1633463e88f078038Joe Eykholtstatic void fcoe_ctlr_flogi_send(struct fcoe_ctlr *fip) 1576794d98e77f5901ceded697f1633463e88f078038Joe Eykholt{ 1577794d98e77f5901ceded697f1633463e88f078038Joe Eykholt struct fcoe_fcf *fcf; 1578794d98e77f5901ceded697f1633463e88f078038Joe Eykholt 1579794d98e77f5901ceded697f1633463e88f078038Joe Eykholt spin_lock_bh(&fip->ctlr_lock); 1580794d98e77f5901ceded697f1633463e88f078038Joe Eykholt fcf = fip->sel_fcf; 1581794d98e77f5901ceded697f1633463e88f078038Joe Eykholt if (!fcf || !fip->flogi_req_send) 1582794d98e77f5901ceded697f1633463e88f078038Joe Eykholt goto unlock; 1583794d98e77f5901ceded697f1633463e88f078038Joe Eykholt 1584794d98e77f5901ceded697f1633463e88f078038Joe Eykholt LIBFCOE_FIP_DBG(fip, "sending FLOGI\n"); 1585794d98e77f5901ceded697f1633463e88f078038Joe Eykholt 1586794d98e77f5901ceded697f1633463e88f078038Joe Eykholt /* 1587794d98e77f5901ceded697f1633463e88f078038Joe Eykholt * If this FLOGI is being sent due to a timeout retry 1588794d98e77f5901ceded697f1633463e88f078038Joe Eykholt * to the same FCF as before, select a different FCF if possible. 1589794d98e77f5901ceded697f1633463e88f078038Joe Eykholt */ 1590794d98e77f5901ceded697f1633463e88f078038Joe Eykholt if (fcf->flogi_sent) { 1591794d98e77f5901ceded697f1633463e88f078038Joe Eykholt LIBFCOE_FIP_DBG(fip, "sending FLOGI - reselect\n"); 1592ba9cd5d095b42271588c20ccd6ddd561d0e4cc1eJoe Eykholt fcf = fcoe_ctlr_select(fip); 1593794d98e77f5901ceded697f1633463e88f078038Joe Eykholt if (!fcf || fcf->flogi_sent) { 1594794d98e77f5901ceded697f1633463e88f078038Joe Eykholt LIBFCOE_FIP_DBG(fip, "sending FLOGI - clearing\n"); 1595794d98e77f5901ceded697f1633463e88f078038Joe Eykholt list_for_each_entry(fcf, &fip->fcfs, list) 1596794d98e77f5901ceded697f1633463e88f078038Joe Eykholt fcf->flogi_sent = 0; 1597ba9cd5d095b42271588c20ccd6ddd561d0e4cc1eJoe Eykholt fcf = fcoe_ctlr_select(fip); 1598794d98e77f5901ceded697f1633463e88f078038Joe Eykholt } 1599794d98e77f5901ceded697f1633463e88f078038Joe Eykholt } 1600794d98e77f5901ceded697f1633463e88f078038Joe Eykholt if (fcf) { 1601794d98e77f5901ceded697f1633463e88f078038Joe Eykholt fcoe_ctlr_flogi_send_locked(fip); 1602794d98e77f5901ceded697f1633463e88f078038Joe Eykholt fip->flogi_req_send = 0; 1603794d98e77f5901ceded697f1633463e88f078038Joe Eykholt } else /* XXX */ 1604794d98e77f5901ceded697f1633463e88f078038Joe Eykholt LIBFCOE_FIP_DBG(fip, "No FCF selected - defer send\n"); 1605794d98e77f5901ceded697f1633463e88f078038Joe Eykholtunlock: 1606794d98e77f5901ceded697f1633463e88f078038Joe Eykholt spin_unlock_bh(&fip->ctlr_lock); 1607794d98e77f5901ceded697f1633463e88f078038Joe Eykholt} 1608794d98e77f5901ceded697f1633463e88f078038Joe Eykholt 1609794d98e77f5901ceded697f1633463e88f078038Joe Eykholt/** 161070b51aabf3b03fbf8d61c14847ccce4c69fb0cddRobert Love * fcoe_ctlr_timeout() - FIP timeout handler 161170b51aabf3b03fbf8d61c14847ccce4c69fb0cddRobert Love * @arg: The FCoE controller that timed out 161297c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt */ 161397c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholtstatic void fcoe_ctlr_timeout(unsigned long arg) 161497c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt{ 161597c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt struct fcoe_ctlr *fip = (struct fcoe_ctlr *)arg; 1616fdb068c6cd6e30d43664f856d3530715a5742713Joe Eykholt 1617fdb068c6cd6e30d43664f856d3530715a5742713Joe Eykholt schedule_work(&fip->timer_work); 1618fdb068c6cd6e30d43664f856d3530715a5742713Joe Eykholt} 1619fdb068c6cd6e30d43664f856d3530715a5742713Joe Eykholt 1620fdb068c6cd6e30d43664f856d3530715a5742713Joe Eykholt/** 1621fdb068c6cd6e30d43664f856d3530715a5742713Joe Eykholt * fcoe_ctlr_timer_work() - Worker thread function for timer work 1622fdb068c6cd6e30d43664f856d3530715a5742713Joe Eykholt * @work: Handle to a FCoE controller 1623fdb068c6cd6e30d43664f856d3530715a5742713Joe Eykholt * 1624fdb068c6cd6e30d43664f856d3530715a5742713Joe Eykholt * Ages FCFs. Triggers FCF selection if possible. 1625fdb068c6cd6e30d43664f856d3530715a5742713Joe Eykholt * Sends keep-alives and resets. 1626fdb068c6cd6e30d43664f856d3530715a5742713Joe Eykholt */ 1627fdb068c6cd6e30d43664f856d3530715a5742713Joe Eykholtstatic void fcoe_ctlr_timer_work(struct work_struct *work) 1628fdb068c6cd6e30d43664f856d3530715a5742713Joe Eykholt{ 1629fdb068c6cd6e30d43664f856d3530715a5742713Joe Eykholt struct fcoe_ctlr *fip; 1630fdb068c6cd6e30d43664f856d3530715a5742713Joe Eykholt struct fc_lport *vport; 1631fdb068c6cd6e30d43664f856d3530715a5742713Joe Eykholt u8 *mac; 1632fdb068c6cd6e30d43664f856d3530715a5742713Joe Eykholt u8 reset = 0; 1633fdb068c6cd6e30d43664f856d3530715a5742713Joe Eykholt u8 send_ctlr_ka = 0; 1634fdb068c6cd6e30d43664f856d3530715a5742713Joe Eykholt u8 send_port_ka = 0; 163597c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt struct fcoe_fcf *sel; 163697c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt struct fcoe_fcf *fcf; 16378690cb8359d8e9f8d7ca12791ef7ea32b709df8bJoe Eykholt unsigned long next_timer; 163897c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt 1639fdb068c6cd6e30d43664f856d3530715a5742713Joe Eykholt fip = container_of(work, struct fcoe_ctlr, timer_work); 1640e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt if (fip->mode == FIP_MODE_VN2VN) 1641e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt return fcoe_ctlr_vn_timeout(fip); 1642fdb068c6cd6e30d43664f856d3530715a5742713Joe Eykholt mutex_lock(&fip->ctlr_mutex); 164397c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt if (fip->state == FIP_ST_DISABLED) { 1644fdb068c6cd6e30d43664f856d3530715a5742713Joe Eykholt mutex_unlock(&fip->ctlr_mutex); 164597c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt return; 164697c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt } 164797c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt 164897c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt fcf = fip->sel_fcf; 16498690cb8359d8e9f8d7ca12791ef7ea32b709df8bJoe Eykholt next_timer = fcoe_ctlr_age_fcfs(fip); 165097c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt 165197c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt sel = fip->sel_fcf; 16528690cb8359d8e9f8d7ca12791ef7ea32b709df8bJoe Eykholt if (!sel && fip->sel_time) { 16538690cb8359d8e9f8d7ca12791ef7ea32b709df8bJoe Eykholt if (time_after_eq(jiffies, fip->sel_time)) { 1654ba9cd5d095b42271588c20ccd6ddd561d0e4cc1eJoe Eykholt sel = fcoe_ctlr_select(fip); 16558690cb8359d8e9f8d7ca12791ef7ea32b709df8bJoe Eykholt fip->sel_time = 0; 16568690cb8359d8e9f8d7ca12791ef7ea32b709df8bJoe Eykholt } else if (time_after(next_timer, fip->sel_time)) 16578690cb8359d8e9f8d7ca12791ef7ea32b709df8bJoe Eykholt next_timer = fip->sel_time; 165897c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt } 165997c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt 1660794d98e77f5901ceded697f1633463e88f078038Joe Eykholt if (sel && fip->flogi_req_send) 1661794d98e77f5901ceded697f1633463e88f078038Joe Eykholt fcoe_ctlr_flogi_send(fip); 1662794d98e77f5901ceded697f1633463e88f078038Joe Eykholt else if (!sel && fcf) 1663794d98e77f5901ceded697f1633463e88f078038Joe Eykholt reset = 1; 166497c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt 16658cdffdccd948ea4872b7b65280bc04f2fa93fc96Yi Zou if (sel && !sel->fd_flags) { 166697c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt if (time_after_eq(jiffies, fip->ctlr_ka_time)) { 166797c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt fip->ctlr_ka_time = jiffies + sel->fka_period; 1668fdb068c6cd6e30d43664f856d3530715a5742713Joe Eykholt send_ctlr_ka = 1; 166997c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt } 167097c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt if (time_after(next_timer, fip->ctlr_ka_time)) 167197c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt next_timer = fip->ctlr_ka_time; 167297c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt 167397c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt if (time_after_eq(jiffies, fip->port_ka_time)) { 1674f47dd855d9e64a5d499a93e858a82bc5e7b21345Bhanu Prakash Gollapudi fip->port_ka_time = jiffies + 167570b51aabf3b03fbf8d61c14847ccce4c69fb0cddRobert Love msecs_to_jiffies(FIP_VN_KA_PERIOD); 1676fdb068c6cd6e30d43664f856d3530715a5742713Joe Eykholt send_port_ka = 1; 167797c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt } 167897c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt if (time_after(next_timer, fip->port_ka_time)) 167997c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt next_timer = fip->port_ka_time; 168097c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt } 16818690cb8359d8e9f8d7ca12791ef7ea32b709df8bJoe Eykholt if (!list_empty(&fip->fcfs)) 16828690cb8359d8e9f8d7ca12791ef7ea32b709df8bJoe Eykholt mod_timer(&fip->timer, next_timer); 1683fdb068c6cd6e30d43664f856d3530715a5742713Joe Eykholt mutex_unlock(&fip->ctlr_mutex); 168497c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt 1685516a648631c912e84e0035590f98eef1d716f4eaBhanu Prakash Gollapudi if (reset) { 1686dd42dac4ecd1799077c132aab35d3c36b26d4d8cJoe Eykholt fc_lport_reset(fip->lp); 1687516a648631c912e84e0035590f98eef1d716f4eaBhanu Prakash Gollapudi /* restart things with a solicitation */ 1688516a648631c912e84e0035590f98eef1d716f4eaBhanu Prakash Gollapudi fcoe_ctlr_solicit(fip, NULL); 1689516a648631c912e84e0035590f98eef1d716f4eaBhanu Prakash Gollapudi } 169011b561886643d4e23d0fd58c205d830a448dd0a2Chris Leech 1691fdb068c6cd6e30d43664f856d3530715a5742713Joe Eykholt if (send_ctlr_ka) 169211b561886643d4e23d0fd58c205d830a448dd0a2Chris Leech fcoe_ctlr_send_keep_alive(fip, NULL, 0, fip->ctl_src_addr); 1693fdb068c6cd6e30d43664f856d3530715a5742713Joe Eykholt 1694fdb068c6cd6e30d43664f856d3530715a5742713Joe Eykholt if (send_port_ka) { 169511b561886643d4e23d0fd58c205d830a448dd0a2Chris Leech mutex_lock(&fip->lp->lp_mutex); 169611b561886643d4e23d0fd58c205d830a448dd0a2Chris Leech mac = fip->get_src_addr(fip->lp); 169711b561886643d4e23d0fd58c205d830a448dd0a2Chris Leech fcoe_ctlr_send_keep_alive(fip, fip->lp, 1, mac); 169811b561886643d4e23d0fd58c205d830a448dd0a2Chris Leech list_for_each_entry(vport, &fip->lp->vports, list) { 169911b561886643d4e23d0fd58c205d830a448dd0a2Chris Leech mac = fip->get_src_addr(vport); 170011b561886643d4e23d0fd58c205d830a448dd0a2Chris Leech fcoe_ctlr_send_keep_alive(fip, vport, 1, mac); 170111b561886643d4e23d0fd58c205d830a448dd0a2Chris Leech } 170211b561886643d4e23d0fd58c205d830a448dd0a2Chris Leech mutex_unlock(&fip->lp->lp_mutex); 170311b561886643d4e23d0fd58c205d830a448dd0a2Chris Leech } 170497c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt} 170597c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt 170697c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt/** 170770b51aabf3b03fbf8d61c14847ccce4c69fb0cddRobert Love * fcoe_ctlr_recv_work() - Worker thread function for receiving FIP frames 170870b51aabf3b03fbf8d61c14847ccce4c69fb0cddRobert Love * @recv_work: Handle to a FCoE controller 170997c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt */ 171097c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholtstatic void fcoe_ctlr_recv_work(struct work_struct *recv_work) 171197c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt{ 171297c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt struct fcoe_ctlr *fip; 171397c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt struct sk_buff *skb; 171497c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt 171597c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt fip = container_of(recv_work, struct fcoe_ctlr, recv_work); 17161f4aed818d26eb9ed54520fbeb85d5ee691baa94Joe Eykholt while ((skb = skb_dequeue(&fip->fip_recv_list))) 171797c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt fcoe_ctlr_recv_handler(fip, skb); 171897c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt} 171997c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt 172097c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt/** 1721386309ce927a308d7742a6fb24a536d3383fbd49Joe Eykholt * fcoe_ctlr_recv_flogi() - Snoop pre-FIP receipt of FLOGI response 172270b51aabf3b03fbf8d61c14847ccce4c69fb0cddRobert Love * @fip: The FCoE controller 172370b51aabf3b03fbf8d61c14847ccce4c69fb0cddRobert Love * @fp: The FC frame to snoop 172497c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt * 172597c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt * Snoop potential response to FLOGI or even incoming FLOGI. 172697c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt * 172797c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt * The caller has checked that we are waiting for login as indicated 172897c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt * by fip->flogi_oxid != FC_XID_UNKNOWN. 172997c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt * 173097c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt * The caller is responsible for freeing the frame. 1731386309ce927a308d7742a6fb24a536d3383fbd49Joe Eykholt * Fill in the granted_mac address. 173297c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt * 173397c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt * Return non-zero if the frame should not be delivered to libfc. 173497c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt */ 173511b561886643d4e23d0fd58c205d830a448dd0a2Chris Leechint fcoe_ctlr_recv_flogi(struct fcoe_ctlr *fip, struct fc_lport *lport, 1736386309ce927a308d7742a6fb24a536d3383fbd49Joe Eykholt struct fc_frame *fp) 173797c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt{ 173897c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt struct fc_frame_header *fh; 173997c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt u8 op; 1740386309ce927a308d7742a6fb24a536d3383fbd49Joe Eykholt u8 *sa; 174197c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt 1742386309ce927a308d7742a6fb24a536d3383fbd49Joe Eykholt sa = eth_hdr(&fp->skb)->h_source; 174397c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt fh = fc_frame_header_get(fp); 174497c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt if (fh->fh_type != FC_TYPE_ELS) 174597c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt return 0; 174697c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt 174797c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt op = fc_frame_payload_op(fp); 174897c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt if (op == ELS_LS_ACC && fh->fh_r_ctl == FC_RCTL_ELS_REP && 174997c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt fip->flogi_oxid == ntohs(fh->fh_ox_id)) { 175097c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt 1751fdb068c6cd6e30d43664f856d3530715a5742713Joe Eykholt mutex_lock(&fip->ctlr_mutex); 175297c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt if (fip->state != FIP_ST_AUTO && fip->state != FIP_ST_NON_FIP) { 1753fdb068c6cd6e30d43664f856d3530715a5742713Joe Eykholt mutex_unlock(&fip->ctlr_mutex); 175497c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt return -EINVAL; 175597c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt } 17569b651da900ccfe5581befb46eb06ef781a1d7e74Joe Eykholt fcoe_ctlr_set_state(fip, FIP_ST_NON_FIP); 17570f51c2e54c0bfdb6b02c53f6d7dd9b35f91821b6Joe Eykholt LIBFCOE_FIP_DBG(fip, 17580f51c2e54c0bfdb6b02c53f6d7dd9b35f91821b6Joe Eykholt "received FLOGI LS_ACC using non-FIP mode\n"); 175997c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt 176097c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt /* 176197c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt * FLOGI accepted. 176297c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt * If the src mac addr is FC_OUI-based, then we mark the 176397c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt * address_mode flag to use FC_OUI-based Ethernet DA. 176497c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt * Otherwise we use the FCoE gateway addr 176597c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt */ 176697c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt if (!compare_ether_addr(sa, (u8[6])FC_FCOE_FLOGI_MAC)) { 1767cd229e42eb8cdfdcbe15dfeec39c3641f62de43aJoe Eykholt fcoe_ctlr_map_dest(fip); 176897c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt } else { 176997c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt memcpy(fip->dest_addr, sa, ETH_ALEN); 177097c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt fip->map_dest = 0; 177197c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt } 177297c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt fip->flogi_oxid = FC_XID_UNKNOWN; 1773fdb068c6cd6e30d43664f856d3530715a5742713Joe Eykholt mutex_unlock(&fip->ctlr_mutex); 1774386309ce927a308d7742a6fb24a536d3383fbd49Joe Eykholt fc_fcoe_set_mac(fr_cb(fp)->granted_mac, fh->fh_d_id); 177597c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt } else if (op == ELS_FLOGI && fh->fh_r_ctl == FC_RCTL_ELS_REQ && sa) { 177697c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt /* 177797c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt * Save source MAC for point-to-point responses. 177897c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt */ 1779fdb068c6cd6e30d43664f856d3530715a5742713Joe Eykholt mutex_lock(&fip->ctlr_mutex); 178097c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt if (fip->state == FIP_ST_AUTO || fip->state == FIP_ST_NON_FIP) { 178197c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt memcpy(fip->dest_addr, sa, ETH_ALEN); 178297c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt fip->map_dest = 0; 1783e49bf6145f50da2d95f9fab605ce74f8fb44cb16Joe Eykholt if (fip->state == FIP_ST_AUTO) 1784e49bf6145f50da2d95f9fab605ce74f8fb44cb16Joe Eykholt LIBFCOE_FIP_DBG(fip, "received non-FIP FLOGI. " 1785e49bf6145f50da2d95f9fab605ce74f8fb44cb16Joe Eykholt "Setting non-FIP mode\n"); 17869b651da900ccfe5581befb46eb06ef781a1d7e74Joe Eykholt fcoe_ctlr_set_state(fip, FIP_ST_NON_FIP); 178797c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt } 1788fdb068c6cd6e30d43664f856d3530715a5742713Joe Eykholt mutex_unlock(&fip->ctlr_mutex); 178997c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt } 179097c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt return 0; 179197c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt} 179297c8389d54b9665c38105ea72a428a44b97ff2f6Joe EykholtEXPORT_SYMBOL(fcoe_ctlr_recv_flogi); 179397c8389d54b9665c38105ea72a428a44b97ff2f6Joe Eykholt 17945e80f7f7c87990ffe7856a0d35a94ea52b8f4c59Vasu Dev/** 179570b51aabf3b03fbf8d61c14847ccce4c69fb0cddRobert Love * fcoe_wwn_from_mac() - Converts a 48-bit IEEE MAC address to a 64-bit FC WWN 179670b51aabf3b03fbf8d61c14847ccce4c69fb0cddRobert Love * @mac: The MAC address to convert 179770b51aabf3b03fbf8d61c14847ccce4c69fb0cddRobert Love * @scheme: The scheme to use when converting 179870b51aabf3b03fbf8d61c14847ccce4c69fb0cddRobert Love * @port: The port indicator for converting 17995e80f7f7c87990ffe7856a0d35a94ea52b8f4c59Vasu Dev * 18005e80f7f7c87990ffe7856a0d35a94ea52b8f4c59Vasu Dev * Returns: u64 fc world wide name 18015e80f7f7c87990ffe7856a0d35a94ea52b8f4c59Vasu Dev */ 18025e80f7f7c87990ffe7856a0d35a94ea52b8f4c59Vasu Devu64 fcoe_wwn_from_mac(unsigned char mac[MAX_ADDR_LEN], 18035e80f7f7c87990ffe7856a0d35a94ea52b8f4c59Vasu Dev unsigned int scheme, unsigned int port) 18045e80f7f7c87990ffe7856a0d35a94ea52b8f4c59Vasu Dev{ 18055e80f7f7c87990ffe7856a0d35a94ea52b8f4c59Vasu Dev u64 wwn; 18065e80f7f7c87990ffe7856a0d35a94ea52b8f4c59Vasu Dev u64 host_mac; 18075e80f7f7c87990ffe7856a0d35a94ea52b8f4c59Vasu Dev 18085e80f7f7c87990ffe7856a0d35a94ea52b8f4c59Vasu Dev /* The MAC is in NO, so flip only the low 48 bits */ 18095e80f7f7c87990ffe7856a0d35a94ea52b8f4c59Vasu Dev host_mac = ((u64) mac[0] << 40) | 18105e80f7f7c87990ffe7856a0d35a94ea52b8f4c59Vasu Dev ((u64) mac[1] << 32) | 18115e80f7f7c87990ffe7856a0d35a94ea52b8f4c59Vasu Dev ((u64) mac[2] << 24) | 18125e80f7f7c87990ffe7856a0d35a94ea52b8f4c59Vasu Dev ((u64) mac[3] << 16) | 18135e80f7f7c87990ffe7856a0d35a94ea52b8f4c59Vasu Dev ((u64) mac[4] << 8) | 18145e80f7f7c87990ffe7856a0d35a94ea52b8f4c59Vasu Dev (u64) mac[5]; 18155e80f7f7c87990ffe7856a0d35a94ea52b8f4c59Vasu Dev 18165e80f7f7c87990ffe7856a0d35a94ea52b8f4c59Vasu Dev WARN_ON(host_mac >= (1ULL << 48)); 18175e80f7f7c87990ffe7856a0d35a94ea52b8f4c59Vasu Dev wwn = host_mac | ((u64) scheme << 60); 18185e80f7f7c87990ffe7856a0d35a94ea52b8f4c59Vasu Dev switch (scheme) { 18195e80f7f7c87990ffe7856a0d35a94ea52b8f4c59Vasu Dev case 1: 18205e80f7f7c87990ffe7856a0d35a94ea52b8f4c59Vasu Dev WARN_ON(port != 0); 18215e80f7f7c87990ffe7856a0d35a94ea52b8f4c59Vasu Dev break; 18225e80f7f7c87990ffe7856a0d35a94ea52b8f4c59Vasu Dev case 2: 18235e80f7f7c87990ffe7856a0d35a94ea52b8f4c59Vasu Dev WARN_ON(port >= 0xfff); 18245e80f7f7c87990ffe7856a0d35a94ea52b8f4c59Vasu Dev wwn |= (u64) port << 48; 18255e80f7f7c87990ffe7856a0d35a94ea52b8f4c59Vasu Dev break; 18265e80f7f7c87990ffe7856a0d35a94ea52b8f4c59Vasu Dev default: 18275e80f7f7c87990ffe7856a0d35a94ea52b8f4c59Vasu Dev WARN_ON(1); 18285e80f7f7c87990ffe7856a0d35a94ea52b8f4c59Vasu Dev break; 18295e80f7f7c87990ffe7856a0d35a94ea52b8f4c59Vasu Dev } 18305e80f7f7c87990ffe7856a0d35a94ea52b8f4c59Vasu Dev 18315e80f7f7c87990ffe7856a0d35a94ea52b8f4c59Vasu Dev return wwn; 18325e80f7f7c87990ffe7856a0d35a94ea52b8f4c59Vasu Dev} 18335e80f7f7c87990ffe7856a0d35a94ea52b8f4c59Vasu DevEXPORT_SYMBOL_GPL(fcoe_wwn_from_mac); 18345e80f7f7c87990ffe7856a0d35a94ea52b8f4c59Vasu Dev 18355e80f7f7c87990ffe7856a0d35a94ea52b8f4c59Vasu Dev/** 1836e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * fcoe_ctlr_rport() - return the fcoe_rport for a given fc_rport_priv 1837e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * @rdata: libfc remote port 1838e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt */ 1839e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholtstatic inline struct fcoe_rport *fcoe_ctlr_rport(struct fc_rport_priv *rdata) 1840e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt{ 1841e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt return (struct fcoe_rport *)(rdata + 1); 1842e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt} 1843e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt 1844e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt/** 1845e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * fcoe_ctlr_vn_send() - Send a FIP VN2VN Probe Request or Reply. 1846e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * @fip: The FCoE controller 1847e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * @sub: sub-opcode for probe request, reply, or advertisement. 1848e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * @dest: The destination Ethernet MAC address 1849e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * @min_len: minimum size of the Ethernet payload to be sent 1850e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt */ 1851e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholtstatic void fcoe_ctlr_vn_send(struct fcoe_ctlr *fip, 1852e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt enum fip_vn2vn_subcode sub, 1853e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt const u8 *dest, size_t min_len) 1854e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt{ 1855e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt struct sk_buff *skb; 1856e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt struct fip_frame { 1857e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt struct ethhdr eth; 1858e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt struct fip_header fip; 1859e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt struct fip_mac_desc mac; 1860e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt struct fip_wwn_desc wwnn; 1861e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt struct fip_vn_desc vn; 18620095a9213324a4466c10de98837a27ab1b7e72beYi Zou } __packed * frame; 1863e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt struct fip_fc4_feat *ff; 1864e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt struct fip_size_desc *size; 1865e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt u32 fcp_feat; 1866e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt size_t len; 1867e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt size_t dlen; 1868e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt 1869e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt len = sizeof(*frame); 1870e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt dlen = 0; 1871e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt if (sub == FIP_SC_VN_CLAIM_NOTIFY || sub == FIP_SC_VN_CLAIM_REP) { 1872e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt dlen = sizeof(struct fip_fc4_feat) + 1873e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt sizeof(struct fip_size_desc); 1874e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt len += dlen; 1875e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt } 1876e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt dlen += sizeof(frame->mac) + sizeof(frame->wwnn) + sizeof(frame->vn); 1877e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt len = max(len, min_len + sizeof(struct ethhdr)); 1878e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt 1879e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt skb = dev_alloc_skb(len); 1880e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt if (!skb) 1881e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt return; 1882e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt 1883e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt frame = (struct fip_frame *)skb->data; 1884e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt memset(frame, 0, len); 1885e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt memcpy(frame->eth.h_dest, dest, ETH_ALEN); 1886e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt memcpy(frame->eth.h_source, fip->ctl_src_addr, ETH_ALEN); 1887e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt frame->eth.h_proto = htons(ETH_P_FIP); 1888e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt 1889e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt frame->fip.fip_ver = FIP_VER_ENCAPS(FIP_VER); 1890e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt frame->fip.fip_op = htons(FIP_OP_VN2VN); 1891e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt frame->fip.fip_subcode = sub; 1892e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt frame->fip.fip_dl_len = htons(dlen / FIP_BPW); 1893e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt 1894e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt frame->mac.fd_desc.fip_dtype = FIP_DT_MAC; 1895e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt frame->mac.fd_desc.fip_dlen = sizeof(frame->mac) / FIP_BPW; 1896e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt memcpy(frame->mac.fd_mac, fip->ctl_src_addr, ETH_ALEN); 1897e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt 1898e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt frame->wwnn.fd_desc.fip_dtype = FIP_DT_NAME; 1899e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt frame->wwnn.fd_desc.fip_dlen = sizeof(frame->wwnn) / FIP_BPW; 1900e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt put_unaligned_be64(fip->lp->wwnn, &frame->wwnn.fd_wwn); 1901e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt 1902e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt frame->vn.fd_desc.fip_dtype = FIP_DT_VN_ID; 1903e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt frame->vn.fd_desc.fip_dlen = sizeof(frame->vn) / FIP_BPW; 1904e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt hton24(frame->vn.fd_mac, FIP_VN_FC_MAP); 1905e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt hton24(frame->vn.fd_mac + 3, fip->port_id); 1906e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt hton24(frame->vn.fd_fc_id, fip->port_id); 1907e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt put_unaligned_be64(fip->lp->wwpn, &frame->vn.fd_wwpn); 1908e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt 1909e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt /* 1910e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * For claims, add FC-4 features. 1911e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * TBD: Add interface to get fc-4 types and features from libfc. 1912e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt */ 1913e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt if (sub == FIP_SC_VN_CLAIM_NOTIFY || sub == FIP_SC_VN_CLAIM_REP) { 1914e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt ff = (struct fip_fc4_feat *)(frame + 1); 1915e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt ff->fd_desc.fip_dtype = FIP_DT_FC4F; 1916e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt ff->fd_desc.fip_dlen = sizeof(*ff) / FIP_BPW; 1917e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt ff->fd_fts = fip->lp->fcts; 1918e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt 1919e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt fcp_feat = 0; 1920e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt if (fip->lp->service_params & FCP_SPPF_INIT_FCN) 1921e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt fcp_feat |= FCP_FEAT_INIT; 1922e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt if (fip->lp->service_params & FCP_SPPF_TARG_FCN) 1923e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt fcp_feat |= FCP_FEAT_TARG; 1924e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt fcp_feat <<= (FC_TYPE_FCP * 4) % 32; 1925e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt ff->fd_ff.fd_feat[FC_TYPE_FCP * 4 / 32] = htonl(fcp_feat); 1926e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt 1927e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt size = (struct fip_size_desc *)(ff + 1); 1928e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt size->fd_desc.fip_dtype = FIP_DT_FCOE_SIZE; 1929e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt size->fd_desc.fip_dlen = sizeof(*size) / FIP_BPW; 1930e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt size->fd_size = htons(fcoe_ctlr_fcoe_size(fip)); 1931e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt } 1932e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt 1933e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt skb_put(skb, len); 1934e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt skb->protocol = htons(ETH_P_FIP); 19356f6c2aa33b915c574543f176dee89d7aefc115c1john fastabend skb->priority = fip->priority; 1936e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt skb_reset_mac_header(skb); 1937e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt skb_reset_network_header(skb); 1938e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt 1939e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt fip->send(fip, skb); 1940e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt} 1941e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt 1942e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt/** 1943e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * fcoe_ctlr_vn_rport_callback - Event handler for rport events. 1944e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * @lport: The lport which is receiving the event 1945e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * @rdata: remote port private data 194625985edcedea6396277003854657b5f3cb31a628Lucas De Marchi * @event: The event that occurred 1947e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * 1948e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * Locking Note: The rport lock must not be held when calling this function. 1949e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt */ 1950e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholtstatic void fcoe_ctlr_vn_rport_callback(struct fc_lport *lport, 1951e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt struct fc_rport_priv *rdata, 1952e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt enum fc_rport_event event) 1953e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt{ 1954e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt struct fcoe_ctlr *fip = lport->disc.priv; 1955e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt struct fcoe_rport *frport = fcoe_ctlr_rport(rdata); 1956e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt 1957e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt LIBFCOE_FIP_DBG(fip, "vn_rport_callback %x event %d\n", 1958e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt rdata->ids.port_id, event); 1959e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt 1960e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt mutex_lock(&fip->ctlr_mutex); 1961e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt switch (event) { 1962e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt case RPORT_EV_READY: 1963e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt frport->login_count = 0; 1964e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt break; 1965e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt case RPORT_EV_LOGO: 1966e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt case RPORT_EV_FAILED: 1967e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt case RPORT_EV_STOP: 1968e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt frport->login_count++; 1969e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt if (frport->login_count > FCOE_CTLR_VN2VN_LOGIN_LIMIT) { 1970e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt LIBFCOE_FIP_DBG(fip, 1971e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt "rport FLOGI limited port_id %6.6x\n", 1972e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt rdata->ids.port_id); 1973e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt lport->tt.rport_logoff(rdata); 1974e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt } 1975e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt break; 1976e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt default: 1977e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt break; 1978e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt } 1979e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt mutex_unlock(&fip->ctlr_mutex); 1980e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt} 1981e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt 1982e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholtstatic struct fc_rport_operations fcoe_ctlr_vn_rport_ops = { 1983e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt .event_callback = fcoe_ctlr_vn_rport_callback, 1984e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt}; 1985e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt 1986e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt/** 1987e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * fcoe_ctlr_disc_stop_locked() - stop discovery in VN2VN mode 1988e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * @fip: The FCoE controller 1989e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * 1990e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * Called with ctlr_mutex held. 1991e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt */ 1992e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholtstatic void fcoe_ctlr_disc_stop_locked(struct fc_lport *lport) 1993e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt{ 1994e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt mutex_lock(&lport->disc.disc_mutex); 1995e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt lport->disc.disc_callback = NULL; 1996e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt mutex_unlock(&lport->disc.disc_mutex); 1997e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt} 1998e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt 1999e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt/** 2000e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * fcoe_ctlr_disc_stop() - stop discovery in VN2VN mode 2001e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * @fip: The FCoE controller 2002e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * 2003e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * Called through the local port template for discovery. 2004e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * Called without the ctlr_mutex held. 2005e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt */ 2006e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholtstatic void fcoe_ctlr_disc_stop(struct fc_lport *lport) 2007e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt{ 2008e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt struct fcoe_ctlr *fip = lport->disc.priv; 2009e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt 2010e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt mutex_lock(&fip->ctlr_mutex); 2011e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt fcoe_ctlr_disc_stop_locked(lport); 2012e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt mutex_unlock(&fip->ctlr_mutex); 2013e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt} 2014e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt 2015e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt/** 2016e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * fcoe_ctlr_disc_stop_final() - stop discovery for shutdown in VN2VN mode 2017e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * @fip: The FCoE controller 2018e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * 2019e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * Called through the local port template for discovery. 2020e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * Called without the ctlr_mutex held. 2021e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt */ 2022e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholtstatic void fcoe_ctlr_disc_stop_final(struct fc_lport *lport) 2023e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt{ 2024e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt fcoe_ctlr_disc_stop(lport); 2025e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt lport->tt.rport_flush_queue(); 2026e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt synchronize_rcu(); 2027e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt} 2028e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt 2029e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt/** 2030e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * fcoe_ctlr_vn_restart() - VN2VN probe restart with new port_id 2031e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * @fip: The FCoE controller 2032e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * 2033e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * Called with fcoe_ctlr lock held. 2034e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt */ 2035e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholtstatic void fcoe_ctlr_vn_restart(struct fcoe_ctlr *fip) 2036e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt{ 2037e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt unsigned long wait; 2038e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt u32 port_id; 2039e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt 2040e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt fcoe_ctlr_disc_stop_locked(fip->lp); 2041e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt 2042e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt /* 2043e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * Get proposed port ID. 2044e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * If this is the first try after link up, use any previous port_id. 2045e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * If there was none, use the low bits of the port_name. 2046e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * On subsequent tries, get the next random one. 2047e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * Don't use reserved IDs, use another non-zero value, just as random. 2048e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt */ 2049e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt port_id = fip->port_id; 2050e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt if (fip->probe_tries) 2051e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt port_id = prandom32(&fip->rnd_state) & 0xffff; 2052e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt else if (!port_id) 2053e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt port_id = fip->lp->wwpn & 0xffff; 2054e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt if (!port_id || port_id == 0xffff) 2055e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt port_id = 1; 2056e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt fip->port_id = port_id; 2057e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt 2058e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt if (fip->probe_tries < FIP_VN_RLIM_COUNT) { 2059e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt fip->probe_tries++; 2060e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt wait = random32() % FIP_VN_PROBE_WAIT; 2061e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt } else 2062e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt wait = FIP_VN_RLIM_INT; 2063e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt mod_timer(&fip->timer, jiffies + msecs_to_jiffies(wait)); 2064e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt fcoe_ctlr_set_state(fip, FIP_ST_VNMP_START); 2065e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt} 2066e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt 2067e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt/** 2068e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * fcoe_ctlr_vn_start() - Start in VN2VN mode 2069e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * @fip: The FCoE controller 2070e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * 2071e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * Called with fcoe_ctlr lock held. 2072e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt */ 2073e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholtstatic void fcoe_ctlr_vn_start(struct fcoe_ctlr *fip) 2074e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt{ 2075e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt fip->probe_tries = 0; 2076e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt prandom32_seed(&fip->rnd_state, fip->lp->wwpn); 2077e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt fcoe_ctlr_vn_restart(fip); 2078e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt} 2079e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt 2080e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt/** 2081e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * fcoe_ctlr_vn_parse - parse probe request or response 2082e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * @fip: The FCoE controller 2083e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * @skb: incoming packet 2084e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * @rdata: buffer for resulting parsed VN entry plus fcoe_rport 2085e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * 2086e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * Returns non-zero error number on error. 2087e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * Does not consume the packet. 2088e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt */ 2089e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholtstatic int fcoe_ctlr_vn_parse(struct fcoe_ctlr *fip, 2090e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt struct sk_buff *skb, 2091e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt struct fc_rport_priv *rdata) 2092e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt{ 2093e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt struct fip_header *fiph; 2094e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt struct fip_desc *desc = NULL; 2095e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt struct fip_mac_desc *macd = NULL; 2096e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt struct fip_wwn_desc *wwn = NULL; 2097e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt struct fip_vn_desc *vn = NULL; 2098e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt struct fip_size_desc *size = NULL; 2099e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt struct fcoe_rport *frport; 2100e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt size_t rlen; 2101e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt size_t dlen; 2102e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt u32 desc_mask = 0; 2103e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt u32 dtype; 2104e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt u8 sub; 2105e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt 2106e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt memset(rdata, 0, sizeof(*rdata) + sizeof(*frport)); 2107e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt frport = fcoe_ctlr_rport(rdata); 2108e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt 2109e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt fiph = (struct fip_header *)skb->data; 2110e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt frport->flags = ntohs(fiph->fip_flags); 2111e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt 2112e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt sub = fiph->fip_subcode; 2113e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt switch (sub) { 2114e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt case FIP_SC_VN_PROBE_REQ: 2115e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt case FIP_SC_VN_PROBE_REP: 2116e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt case FIP_SC_VN_BEACON: 2117e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt desc_mask = BIT(FIP_DT_MAC) | BIT(FIP_DT_NAME) | 2118e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt BIT(FIP_DT_VN_ID); 2119e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt break; 2120e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt case FIP_SC_VN_CLAIM_NOTIFY: 2121e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt case FIP_SC_VN_CLAIM_REP: 2122e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt desc_mask = BIT(FIP_DT_MAC) | BIT(FIP_DT_NAME) | 2123e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt BIT(FIP_DT_VN_ID) | BIT(FIP_DT_FC4F) | 2124e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt BIT(FIP_DT_FCOE_SIZE); 2125e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt break; 2126e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt default: 2127e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt LIBFCOE_FIP_DBG(fip, "vn_parse unknown subcode %u\n", sub); 2128e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt return -EINVAL; 2129e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt } 2130e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt 2131e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt rlen = ntohs(fiph->fip_dl_len) * 4; 2132e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt if (rlen + sizeof(*fiph) > skb->len) 2133e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt return -EINVAL; 2134e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt 2135e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt desc = (struct fip_desc *)(fiph + 1); 2136e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt while (rlen > 0) { 2137e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt dlen = desc->fip_dlen * FIP_BPW; 2138e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt if (dlen < sizeof(*desc) || dlen > rlen) 2139e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt return -EINVAL; 2140e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt 2141e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt dtype = desc->fip_dtype; 2142e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt if (dtype < 32) { 2143e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt if (!(desc_mask & BIT(dtype))) { 2144e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt LIBFCOE_FIP_DBG(fip, 2145e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt "unexpected or duplicated desc " 2146e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt "desc type %u in " 2147e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt "FIP VN2VN subtype %u\n", 2148e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt dtype, sub); 2149e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt return -EINVAL; 2150e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt } 2151e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt desc_mask &= ~BIT(dtype); 2152e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt } 2153e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt 2154e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt switch (dtype) { 2155e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt case FIP_DT_MAC: 2156e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt if (dlen != sizeof(struct fip_mac_desc)) 2157e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt goto len_err; 2158e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt macd = (struct fip_mac_desc *)desc; 2159e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt if (!is_valid_ether_addr(macd->fd_mac)) { 2160e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt LIBFCOE_FIP_DBG(fip, 2161e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt "Invalid MAC addr %pM in FIP VN2VN\n", 2162e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt macd->fd_mac); 2163e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt return -EINVAL; 2164e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt } 2165e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt memcpy(frport->enode_mac, macd->fd_mac, ETH_ALEN); 2166e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt break; 2167e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt case FIP_DT_NAME: 2168e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt if (dlen != sizeof(struct fip_wwn_desc)) 2169e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt goto len_err; 2170e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt wwn = (struct fip_wwn_desc *)desc; 2171e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt rdata->ids.node_name = get_unaligned_be64(&wwn->fd_wwn); 2172e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt break; 2173e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt case FIP_DT_VN_ID: 2174e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt if (dlen != sizeof(struct fip_vn_desc)) 2175e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt goto len_err; 2176e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt vn = (struct fip_vn_desc *)desc; 2177e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt memcpy(frport->vn_mac, vn->fd_mac, ETH_ALEN); 2178e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt rdata->ids.port_id = ntoh24(vn->fd_fc_id); 2179e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt rdata->ids.port_name = get_unaligned_be64(&vn->fd_wwpn); 2180e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt break; 2181e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt case FIP_DT_FC4F: 2182e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt if (dlen != sizeof(struct fip_fc4_feat)) 2183e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt goto len_err; 2184e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt break; 2185e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt case FIP_DT_FCOE_SIZE: 2186e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt if (dlen != sizeof(struct fip_size_desc)) 2187e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt goto len_err; 2188e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt size = (struct fip_size_desc *)desc; 2189e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt frport->fcoe_len = ntohs(size->fd_size); 2190e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt break; 2191e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt default: 2192e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt LIBFCOE_FIP_DBG(fip, "unexpected descriptor type %x " 2193e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt "in FIP probe\n", dtype); 2194e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt /* standard says ignore unknown descriptors >= 128 */ 2195e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt if (dtype < FIP_DT_VENDOR_BASE) 2196e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt return -EINVAL; 2197e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt break; 2198e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt } 2199e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt desc = (struct fip_desc *)((char *)desc + dlen); 2200e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt rlen -= dlen; 2201e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt } 2202e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt return 0; 2203e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt 2204e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholtlen_err: 2205e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt LIBFCOE_FIP_DBG(fip, "FIP length error in descriptor type %x len %zu\n", 2206e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt dtype, dlen); 2207e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt return -EINVAL; 2208e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt} 2209e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt 2210e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt/** 2211e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * fcoe_ctlr_vn_send_claim() - send multicast FIP VN2VN Claim Notification. 2212e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * @fip: The FCoE controller 2213e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * 2214e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * Called with ctlr_mutex held. 2215e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt */ 2216e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholtstatic void fcoe_ctlr_vn_send_claim(struct fcoe_ctlr *fip) 2217e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt{ 2218e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt fcoe_ctlr_vn_send(fip, FIP_SC_VN_CLAIM_NOTIFY, fcoe_all_vn2vn, 0); 2219e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt fip->sol_time = jiffies; 2220e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt} 2221e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt 2222e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt/** 2223e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * fcoe_ctlr_vn_probe_req() - handle incoming VN2VN probe request. 2224e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * @fip: The FCoE controller 2225e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * @rdata: parsed remote port with frport from the probe request 2226e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * 2227e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * Called with ctlr_mutex held. 2228e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt */ 2229e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholtstatic void fcoe_ctlr_vn_probe_req(struct fcoe_ctlr *fip, 2230e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt struct fc_rport_priv *rdata) 2231e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt{ 2232e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt struct fcoe_rport *frport = fcoe_ctlr_rport(rdata); 2233e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt 2234e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt if (rdata->ids.port_id != fip->port_id) 2235e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt return; 2236e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt 2237e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt switch (fip->state) { 2238e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt case FIP_ST_VNMP_CLAIM: 2239e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt case FIP_ST_VNMP_UP: 2240e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt fcoe_ctlr_vn_send(fip, FIP_SC_VN_PROBE_REP, 2241e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt frport->enode_mac, 0); 2242e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt break; 2243e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt case FIP_ST_VNMP_PROBE1: 2244e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt case FIP_ST_VNMP_PROBE2: 2245e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt /* 2246e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * Decide whether to reply to the Probe. 2247e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * Our selected address is never a "recorded" one, so 2248e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * only reply if our WWPN is greater and the 2249e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * Probe's REC bit is not set. 2250e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * If we don't reply, we will change our address. 2251e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt */ 2252e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt if (fip->lp->wwpn > rdata->ids.port_name && 2253e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt !(frport->flags & FIP_FL_REC_OR_P2P)) { 2254e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt fcoe_ctlr_vn_send(fip, FIP_SC_VN_PROBE_REP, 2255e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt frport->enode_mac, 0); 2256e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt break; 2257e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt } 2258e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt /* fall through */ 2259e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt case FIP_ST_VNMP_START: 2260e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt fcoe_ctlr_vn_restart(fip); 2261e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt break; 2262e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt default: 2263e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt break; 2264e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt } 2265e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt} 2266e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt 2267e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt/** 2268e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * fcoe_ctlr_vn_probe_reply() - handle incoming VN2VN probe reply. 2269e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * @fip: The FCoE controller 2270e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * @rdata: parsed remote port with frport from the probe request 2271e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * 2272e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * Called with ctlr_mutex held. 2273e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt */ 2274e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholtstatic void fcoe_ctlr_vn_probe_reply(struct fcoe_ctlr *fip, 2275e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt struct fc_rport_priv *rdata) 2276e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt{ 2277e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt if (rdata->ids.port_id != fip->port_id) 2278e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt return; 2279e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt switch (fip->state) { 2280e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt case FIP_ST_VNMP_START: 2281e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt case FIP_ST_VNMP_PROBE1: 2282e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt case FIP_ST_VNMP_PROBE2: 2283e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt case FIP_ST_VNMP_CLAIM: 2284e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt fcoe_ctlr_vn_restart(fip); 2285e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt break; 2286e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt case FIP_ST_VNMP_UP: 2287e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt fcoe_ctlr_vn_send_claim(fip); 2288e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt break; 2289e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt default: 2290e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt break; 2291e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt } 2292e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt} 2293e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt 2294e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt/** 2295e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * fcoe_ctlr_vn_add() - Add a VN2VN entry to the list, based on a claim reply. 2296e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * @fip: The FCoE controller 2297e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * @new: newly-parsed remote port with frport as a template for new rdata 2298e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * 2299e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * Called with ctlr_mutex held. 2300e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt */ 2301e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholtstatic void fcoe_ctlr_vn_add(struct fcoe_ctlr *fip, struct fc_rport_priv *new) 2302e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt{ 2303e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt struct fc_lport *lport = fip->lp; 2304e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt struct fc_rport_priv *rdata; 2305e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt struct fc_rport_identifiers *ids; 2306e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt struct fcoe_rport *frport; 2307e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt u32 port_id; 2308e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt 2309e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt port_id = new->ids.port_id; 2310e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt if (port_id == fip->port_id) 2311e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt return; 2312e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt 2313e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt mutex_lock(&lport->disc.disc_mutex); 2314e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt rdata = lport->tt.rport_create(lport, port_id); 2315e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt if (!rdata) { 2316e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt mutex_unlock(&lport->disc.disc_mutex); 2317e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt return; 2318e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt } 2319e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt 2320e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt rdata->ops = &fcoe_ctlr_vn_rport_ops; 2321e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt rdata->disc_id = lport->disc.disc_id; 2322e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt 2323e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt ids = &rdata->ids; 2324e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt if ((ids->port_name != -1 && ids->port_name != new->ids.port_name) || 2325e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt (ids->node_name != -1 && ids->node_name != new->ids.node_name)) 2326e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt lport->tt.rport_logoff(rdata); 2327e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt ids->port_name = new->ids.port_name; 2328e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt ids->node_name = new->ids.node_name; 2329e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt mutex_unlock(&lport->disc.disc_mutex); 2330e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt 2331e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt frport = fcoe_ctlr_rport(rdata); 2332e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt LIBFCOE_FIP_DBG(fip, "vn_add rport %6.6x %s\n", 2333e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt port_id, frport->fcoe_len ? "old" : "new"); 2334e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt *frport = *fcoe_ctlr_rport(new); 2335e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt frport->time = 0; 2336e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt} 2337e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt 2338e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt/** 2339e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * fcoe_ctlr_vn_lookup() - Find VN remote port's MAC address 2340e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * @fip: The FCoE controller 2341e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * @port_id: The port_id of the remote VN_node 2342e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * @mac: buffer which will hold the VN_NODE destination MAC address, if found. 2343e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * 2344e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * Returns non-zero error if no remote port found. 2345e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt */ 2346e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholtstatic int fcoe_ctlr_vn_lookup(struct fcoe_ctlr *fip, u32 port_id, u8 *mac) 2347e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt{ 2348e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt struct fc_lport *lport = fip->lp; 2349e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt struct fc_rport_priv *rdata; 2350e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt struct fcoe_rport *frport; 2351e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt int ret = -1; 2352e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt 2353e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt rcu_read_lock(); 2354e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt rdata = lport->tt.rport_lookup(lport, port_id); 2355e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt if (rdata) { 2356e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt frport = fcoe_ctlr_rport(rdata); 2357e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt memcpy(mac, frport->enode_mac, ETH_ALEN); 2358e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt ret = 0; 2359e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt } 2360e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt rcu_read_unlock(); 2361e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt return ret; 2362e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt} 2363e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt 2364e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt/** 2365e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * fcoe_ctlr_vn_claim_notify() - handle received FIP VN2VN Claim Notification 2366e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * @fip: The FCoE controller 2367e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * @new: newly-parsed remote port with frport as a template for new rdata 2368e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * 2369e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * Called with ctlr_mutex held. 2370e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt */ 2371e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholtstatic void fcoe_ctlr_vn_claim_notify(struct fcoe_ctlr *fip, 2372e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt struct fc_rport_priv *new) 2373e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt{ 2374e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt struct fcoe_rport *frport = fcoe_ctlr_rport(new); 2375e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt 2376e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt if (frport->flags & FIP_FL_REC_OR_P2P) { 2377e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt fcoe_ctlr_vn_send(fip, FIP_SC_VN_PROBE_REQ, fcoe_all_vn2vn, 0); 2378e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt return; 2379e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt } 2380e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt switch (fip->state) { 2381e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt case FIP_ST_VNMP_START: 2382e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt case FIP_ST_VNMP_PROBE1: 2383e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt case FIP_ST_VNMP_PROBE2: 2384e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt if (new->ids.port_id == fip->port_id) 2385e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt fcoe_ctlr_vn_restart(fip); 2386e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt break; 2387e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt case FIP_ST_VNMP_CLAIM: 2388e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt case FIP_ST_VNMP_UP: 2389e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt if (new->ids.port_id == fip->port_id) { 2390e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt if (new->ids.port_name > fip->lp->wwpn) { 2391e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt fcoe_ctlr_vn_restart(fip); 2392e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt break; 2393e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt } 2394e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt fcoe_ctlr_vn_send_claim(fip); 2395e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt break; 2396e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt } 2397e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt fcoe_ctlr_vn_send(fip, FIP_SC_VN_CLAIM_REP, frport->enode_mac, 2398e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt min((u32)frport->fcoe_len, 2399e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt fcoe_ctlr_fcoe_size(fip))); 2400e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt fcoe_ctlr_vn_add(fip, new); 2401e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt break; 2402e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt default: 2403e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt break; 2404e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt } 2405e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt} 2406e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt 2407e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt/** 2408e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * fcoe_ctlr_vn_claim_resp() - handle received Claim Response 2409e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * @fip: The FCoE controller that received the frame 2410e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * @new: newly-parsed remote port with frport from the Claim Response 2411e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * 2412e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * Called with ctlr_mutex held. 2413e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt */ 2414e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholtstatic void fcoe_ctlr_vn_claim_resp(struct fcoe_ctlr *fip, 2415e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt struct fc_rport_priv *new) 2416e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt{ 2417e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt LIBFCOE_FIP_DBG(fip, "claim resp from from rport %x - state %s\n", 2418e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt new->ids.port_id, fcoe_ctlr_state(fip->state)); 2419e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt if (fip->state == FIP_ST_VNMP_UP || fip->state == FIP_ST_VNMP_CLAIM) 2420e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt fcoe_ctlr_vn_add(fip, new); 2421e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt} 2422e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt 2423e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt/** 2424e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * fcoe_ctlr_vn_beacon() - handle received beacon. 2425e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * @fip: The FCoE controller that received the frame 2426e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * @new: newly-parsed remote port with frport from the Beacon 2427e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * 2428e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * Called with ctlr_mutex held. 2429e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt */ 2430e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholtstatic void fcoe_ctlr_vn_beacon(struct fcoe_ctlr *fip, 2431e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt struct fc_rport_priv *new) 2432e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt{ 2433e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt struct fc_lport *lport = fip->lp; 2434e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt struct fc_rport_priv *rdata; 2435e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt struct fcoe_rport *frport; 2436e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt 2437e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt frport = fcoe_ctlr_rport(new); 2438e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt if (frport->flags & FIP_FL_REC_OR_P2P) { 2439e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt fcoe_ctlr_vn_send(fip, FIP_SC_VN_PROBE_REQ, fcoe_all_vn2vn, 0); 2440e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt return; 2441e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt } 2442e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt mutex_lock(&lport->disc.disc_mutex); 2443e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt rdata = lport->tt.rport_lookup(lport, new->ids.port_id); 2444e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt if (rdata) 2445e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt kref_get(&rdata->kref); 2446e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt mutex_unlock(&lport->disc.disc_mutex); 2447e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt if (rdata) { 2448e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt if (rdata->ids.node_name == new->ids.node_name && 2449e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt rdata->ids.port_name == new->ids.port_name) { 2450e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt frport = fcoe_ctlr_rport(rdata); 2451e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt if (!frport->time && fip->state == FIP_ST_VNMP_UP) 2452e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt lport->tt.rport_login(rdata); 2453e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt frport->time = jiffies; 2454e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt } 2455e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt kref_put(&rdata->kref, lport->tt.rport_destroy); 2456e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt return; 2457e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt } 2458e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt if (fip->state != FIP_ST_VNMP_UP) 2459e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt return; 2460e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt 2461e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt /* 2462e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * Beacon from a new neighbor. 2463e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * Send a claim notify if one hasn't been sent recently. 2464e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * Don't add the neighbor yet. 2465e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt */ 2466e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt LIBFCOE_FIP_DBG(fip, "beacon from new rport %x. sending claim notify\n", 2467e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt new->ids.port_id); 2468e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt if (time_after(jiffies, 2469e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt fip->sol_time + msecs_to_jiffies(FIP_VN_ANN_WAIT))) 2470e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt fcoe_ctlr_vn_send_claim(fip); 2471e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt} 2472e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt 2473e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt/** 2474e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * fcoe_ctlr_vn_age() - Check for VN_ports without recent beacons 2475e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * @fip: The FCoE controller 2476e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * 2477e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * Called with ctlr_mutex held. 2478e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * Called only in state FIP_ST_VNMP_UP. 2479e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * Returns the soonest time for next age-out or a time far in the future. 2480e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt */ 2481e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholtstatic unsigned long fcoe_ctlr_vn_age(struct fcoe_ctlr *fip) 2482e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt{ 2483e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt struct fc_lport *lport = fip->lp; 2484e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt struct fc_rport_priv *rdata; 2485e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt struct fcoe_rport *frport; 2486e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt unsigned long next_time; 2487e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt unsigned long deadline; 2488e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt 2489e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt next_time = jiffies + msecs_to_jiffies(FIP_VN_BEACON_INT * 10); 2490e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt mutex_lock(&lport->disc.disc_mutex); 2491e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt list_for_each_entry_rcu(rdata, &lport->disc.rports, peers) { 2492e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt frport = fcoe_ctlr_rport(rdata); 2493e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt if (!frport->time) 2494e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt continue; 2495e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt deadline = frport->time + 2496e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt msecs_to_jiffies(FIP_VN_BEACON_INT * 25 / 10); 2497e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt if (time_after_eq(jiffies, deadline)) { 2498e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt frport->time = 0; 2499e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt LIBFCOE_FIP_DBG(fip, 2500e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt "port %16.16llx fc_id %6.6x beacon expired\n", 2501e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt rdata->ids.port_name, rdata->ids.port_id); 2502e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt lport->tt.rport_logoff(rdata); 2503e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt } else if (time_before(deadline, next_time)) 2504e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt next_time = deadline; 2505e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt } 2506e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt mutex_unlock(&lport->disc.disc_mutex); 2507e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt return next_time; 2508e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt} 2509e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt 2510e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt/** 2511e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * fcoe_ctlr_vn_recv() - Receive a FIP frame 2512e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * @fip: The FCoE controller that received the frame 2513e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * @skb: The received FIP frame 2514e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * 2515e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * Returns non-zero if the frame is dropped. 2516e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * Always consumes the frame. 2517e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt */ 2518e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholtstatic int fcoe_ctlr_vn_recv(struct fcoe_ctlr *fip, struct sk_buff *skb) 2519e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt{ 2520e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt struct fip_header *fiph; 2521e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt enum fip_vn2vn_subcode sub; 25222dc02ee52f32aac6d8dd1172f104dc30ae1051bbKiran Patil struct { 2523e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt struct fc_rport_priv rdata; 2524e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt struct fcoe_rport frport; 2525e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt } buf; 2526e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt int rc; 2527e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt 2528e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt fiph = (struct fip_header *)skb->data; 2529e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt sub = fiph->fip_subcode; 2530e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt 2531e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt rc = fcoe_ctlr_vn_parse(fip, skb, &buf.rdata); 2532e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt if (rc) { 2533e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt LIBFCOE_FIP_DBG(fip, "vn_recv vn_parse error %d\n", rc); 2534e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt goto drop; 2535e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt } 2536e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt 2537e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt mutex_lock(&fip->ctlr_mutex); 2538e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt switch (sub) { 2539e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt case FIP_SC_VN_PROBE_REQ: 2540e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt fcoe_ctlr_vn_probe_req(fip, &buf.rdata); 2541e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt break; 2542e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt case FIP_SC_VN_PROBE_REP: 2543e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt fcoe_ctlr_vn_probe_reply(fip, &buf.rdata); 2544e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt break; 2545e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt case FIP_SC_VN_CLAIM_NOTIFY: 2546e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt fcoe_ctlr_vn_claim_notify(fip, &buf.rdata); 2547e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt break; 2548e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt case FIP_SC_VN_CLAIM_REP: 2549e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt fcoe_ctlr_vn_claim_resp(fip, &buf.rdata); 2550e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt break; 2551e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt case FIP_SC_VN_BEACON: 2552e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt fcoe_ctlr_vn_beacon(fip, &buf.rdata); 2553e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt break; 2554e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt default: 2555e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt LIBFCOE_FIP_DBG(fip, "vn_recv unknown subcode %d\n", sub); 2556e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt rc = -1; 2557e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt break; 2558e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt } 2559e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt mutex_unlock(&fip->ctlr_mutex); 2560e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholtdrop: 2561e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt kfree_skb(skb); 2562e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt return rc; 2563e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt} 2564e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt 2565e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt/** 2566e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * fcoe_ctlr_disc_recv - discovery receive handler for VN2VN mode. 2567922611569572d3c1aa0ed6491d21583fb3fcca22Joe Eykholt * @lport: The local port 2568922611569572d3c1aa0ed6491d21583fb3fcca22Joe Eykholt * @fp: The received frame 2569e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * 2570e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * This should never be called since we don't see RSCNs or other 2571e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * fabric-generated ELSes. 2572e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt */ 2573922611569572d3c1aa0ed6491d21583fb3fcca22Joe Eykholtstatic void fcoe_ctlr_disc_recv(struct fc_lport *lport, struct fc_frame *fp) 2574e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt{ 2575e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt struct fc_seq_els_data rjt_data; 2576e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt 2577e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt rjt_data.reason = ELS_RJT_UNSUP; 2578e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt rjt_data.explan = ELS_EXPL_NONE; 2579922611569572d3c1aa0ed6491d21583fb3fcca22Joe Eykholt lport->tt.seq_els_rsp_send(fp, ELS_LS_RJT, &rjt_data); 2580e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt fc_frame_free(fp); 2581e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt} 2582e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt 2583e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt/** 2584e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * fcoe_ctlr_disc_recv - start discovery for VN2VN mode. 2585e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * @fip: The FCoE controller 2586e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * 2587e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * This sets a flag indicating that remote ports should be created 2588e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * and started for the peers we discover. We use the disc_callback 2589e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * pointer as that flag. Peers already discovered are created here. 2590e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * 2591e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * The lport lock is held during this call. The callback must be done 2592e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * later, without holding either the lport or discovery locks. 2593e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * The fcoe_ctlr lock may also be held during this call. 2594e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt */ 2595e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholtstatic void fcoe_ctlr_disc_start(void (*callback)(struct fc_lport *, 2596e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt enum fc_disc_event), 2597e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt struct fc_lport *lport) 2598e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt{ 2599e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt struct fc_disc *disc = &lport->disc; 2600e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt struct fcoe_ctlr *fip = disc->priv; 2601e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt 2602e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt mutex_lock(&disc->disc_mutex); 2603e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt disc->disc_callback = callback; 2604e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt disc->disc_id = (disc->disc_id + 2) | 1; 2605e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt disc->pending = 1; 2606e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt schedule_work(&fip->timer_work); 2607e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt mutex_unlock(&disc->disc_mutex); 2608e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt} 2609e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt 2610e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt/** 2611e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * fcoe_ctlr_vn_disc() - report FIP VN_port discovery results after claim state. 2612e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * @fip: The FCoE controller 2613e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * 2614e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * Starts the FLOGI and PLOGI login process to each discovered rport for which 2615e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * we've received at least one beacon. 2616e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * Performs the discovery complete callback. 2617e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt */ 2618e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholtstatic void fcoe_ctlr_vn_disc(struct fcoe_ctlr *fip) 2619e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt{ 2620e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt struct fc_lport *lport = fip->lp; 2621e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt struct fc_disc *disc = &lport->disc; 2622e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt struct fc_rport_priv *rdata; 2623e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt struct fcoe_rport *frport; 2624e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt void (*callback)(struct fc_lport *, enum fc_disc_event); 2625e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt 2626e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt mutex_lock(&disc->disc_mutex); 2627e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt callback = disc->pending ? disc->disc_callback : NULL; 2628e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt disc->pending = 0; 2629e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt list_for_each_entry_rcu(rdata, &disc->rports, peers) { 2630e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt frport = fcoe_ctlr_rport(rdata); 2631e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt if (frport->time) 2632e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt lport->tt.rport_login(rdata); 2633e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt } 2634e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt mutex_unlock(&disc->disc_mutex); 2635e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt if (callback) 2636e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt callback(lport, DISC_EV_SUCCESS); 2637e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt} 2638e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt 2639e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt/** 2640e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * fcoe_ctlr_vn_timeout - timer work function for VN2VN mode. 2641e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * @fip: The FCoE controller 2642e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt */ 2643e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholtstatic void fcoe_ctlr_vn_timeout(struct fcoe_ctlr *fip) 2644e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt{ 2645e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt unsigned long next_time; 2646e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt u8 mac[ETH_ALEN]; 2647e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt u32 new_port_id = 0; 2648e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt 2649e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt mutex_lock(&fip->ctlr_mutex); 2650e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt switch (fip->state) { 2651e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt case FIP_ST_VNMP_START: 2652e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt fcoe_ctlr_set_state(fip, FIP_ST_VNMP_PROBE1); 2653e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt fcoe_ctlr_vn_send(fip, FIP_SC_VN_PROBE_REQ, fcoe_all_vn2vn, 0); 2654e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt next_time = jiffies + msecs_to_jiffies(FIP_VN_PROBE_WAIT); 2655e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt break; 2656e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt case FIP_ST_VNMP_PROBE1: 2657e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt fcoe_ctlr_set_state(fip, FIP_ST_VNMP_PROBE2); 2658e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt fcoe_ctlr_vn_send(fip, FIP_SC_VN_PROBE_REQ, fcoe_all_vn2vn, 0); 2659e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt next_time = jiffies + msecs_to_jiffies(FIP_VN_ANN_WAIT); 2660e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt break; 2661e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt case FIP_ST_VNMP_PROBE2: 2662e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt fcoe_ctlr_set_state(fip, FIP_ST_VNMP_CLAIM); 2663e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt new_port_id = fip->port_id; 2664e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt hton24(mac, FIP_VN_FC_MAP); 2665e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt hton24(mac + 3, new_port_id); 2666cd229e42eb8cdfdcbe15dfeec39c3641f62de43aJoe Eykholt fcoe_ctlr_map_dest(fip); 2667e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt fip->update_mac(fip->lp, mac); 2668e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt fcoe_ctlr_vn_send_claim(fip); 2669e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt next_time = jiffies + msecs_to_jiffies(FIP_VN_ANN_WAIT); 2670e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt break; 2671e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt case FIP_ST_VNMP_CLAIM: 2672e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt /* 2673e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * This may be invoked either by starting discovery so don't 2674e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * go to the next state unless it's been long enough. 2675e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt */ 2676e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt next_time = fip->sol_time + msecs_to_jiffies(FIP_VN_ANN_WAIT); 2677e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt if (time_after_eq(jiffies, next_time)) { 2678e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt fcoe_ctlr_set_state(fip, FIP_ST_VNMP_UP); 2679e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt fcoe_ctlr_vn_send(fip, FIP_SC_VN_BEACON, 2680e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt fcoe_all_vn2vn, 0); 2681e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt next_time = jiffies + msecs_to_jiffies(FIP_VN_ANN_WAIT); 2682e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt fip->port_ka_time = next_time; 2683e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt } 2684e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt fcoe_ctlr_vn_disc(fip); 2685e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt break; 2686e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt case FIP_ST_VNMP_UP: 2687e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt next_time = fcoe_ctlr_vn_age(fip); 2688e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt if (time_after_eq(jiffies, fip->port_ka_time)) { 2689e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt fcoe_ctlr_vn_send(fip, FIP_SC_VN_BEACON, 2690e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt fcoe_all_vn2vn, 0); 2691e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt fip->port_ka_time = jiffies + 2692e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt msecs_to_jiffies(FIP_VN_BEACON_INT + 2693e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt (random32() % FIP_VN_BEACON_FUZZ)); 2694e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt } 2695e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt if (time_before(fip->port_ka_time, next_time)) 2696e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt next_time = fip->port_ka_time; 2697e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt break; 2698e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt case FIP_ST_LINK_WAIT: 2699e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt goto unlock; 2700e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt default: 270111aa99001afdbe5fe152e833aa1fea82b85dbedaJoe Perches WARN(1, "unexpected state %d\n", fip->state); 2702e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt goto unlock; 2703e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt } 2704e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt mod_timer(&fip->timer, next_time); 2705e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholtunlock: 2706e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt mutex_unlock(&fip->ctlr_mutex); 2707e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt 2708e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt /* If port ID is new, notify local port after dropping ctlr_mutex */ 2709e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt if (new_port_id) 2710e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt fc_lport_set_local_id(fip->lp, new_port_id); 2711e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt} 2712e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt 2713e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt/** 271470b51aabf3b03fbf8d61c14847ccce4c69fb0cddRobert Love * fcoe_libfc_config() - Sets up libfc related properties for local port 271570b51aabf3b03fbf8d61c14847ccce4c69fb0cddRobert Love * @lp: The local port to configure libfc for 2716e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * @fip: The FCoE controller in use by the local port 271770b51aabf3b03fbf8d61c14847ccce4c69fb0cddRobert Love * @tt: The libfc function template 2718e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt * @init_fcp: If non-zero, the FCP portion of libfc should be initialized 27195e80f7f7c87990ffe7856a0d35a94ea52b8f4c59Vasu Dev * 27205e80f7f7c87990ffe7856a0d35a94ea52b8f4c59Vasu Dev * Returns : 0 for success 27215e80f7f7c87990ffe7856a0d35a94ea52b8f4c59Vasu Dev */ 2722e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholtint fcoe_libfc_config(struct fc_lport *lport, struct fcoe_ctlr *fip, 2723e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt const struct libfc_function_template *tt, int init_fcp) 27245e80f7f7c87990ffe7856a0d35a94ea52b8f4c59Vasu Dev{ 27255e80f7f7c87990ffe7856a0d35a94ea52b8f4c59Vasu Dev /* Set the function pointers set by the LLDD */ 272670b51aabf3b03fbf8d61c14847ccce4c69fb0cddRobert Love memcpy(&lport->tt, tt, sizeof(*tt)); 2727e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt if (init_fcp && fc_fcp_init(lport)) 27285e80f7f7c87990ffe7856a0d35a94ea52b8f4c59Vasu Dev return -ENOMEM; 272970b51aabf3b03fbf8d61c14847ccce4c69fb0cddRobert Love fc_exch_init(lport); 273070b51aabf3b03fbf8d61c14847ccce4c69fb0cddRobert Love fc_elsct_init(lport); 273170b51aabf3b03fbf8d61c14847ccce4c69fb0cddRobert Love fc_lport_init(lport); 2732e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt if (fip->mode == FIP_MODE_VN2VN) 2733e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt lport->rport_priv_size = sizeof(struct fcoe_rport); 273470b51aabf3b03fbf8d61c14847ccce4c69fb0cddRobert Love fc_rport_init(lport); 2735e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt if (fip->mode == FIP_MODE_VN2VN) { 2736e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt lport->point_to_multipoint = 1; 2737e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt lport->tt.disc_recv_req = fcoe_ctlr_disc_recv; 2738e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt lport->tt.disc_start = fcoe_ctlr_disc_start; 2739e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt lport->tt.disc_stop = fcoe_ctlr_disc_stop; 2740e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt lport->tt.disc_stop_final = fcoe_ctlr_disc_stop_final; 2741e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt mutex_init(&lport->disc.disc_mutex); 2742e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt INIT_LIST_HEAD(&lport->disc.rports); 2743e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt lport->disc.priv = fip; 2744e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt } else { 2745e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt fc_disc_init(lport); 2746e10f8c667b874a57512c936089092a3d1ef7ab8aJoe Eykholt } 27475e80f7f7c87990ffe7856a0d35a94ea52b8f4c59Vasu Dev return 0; 27485e80f7f7c87990ffe7856a0d35a94ea52b8f4c59Vasu Dev} 27495e80f7f7c87990ffe7856a0d35a94ea52b8f4c59Vasu DevEXPORT_SYMBOL_GPL(fcoe_libfc_config); 2750