// SPDX-License-Identifier: GPL-2.0-only /* * Copyright(c) 2007 - 2009 Intel Corporation. All rights reserved. * * Maintained at www.Open-FCoE.org */ #include <linux/module.h> #include <linux/spinlock.h> #include <linux/netdevice.h> #include <linux/etherdevice.h> #include <linux/ethtool.h> #include <linux/if_ether.h> #include <linux/if_vlan.h> #include <linux/crc32.h> #include <linux/slab.h> #include <linux/cpu.h> #include <linux/fs.h> #include <linux/sysfs.h> #include <linux/ctype.h> #include <linux/workqueue.h> #include <net/dcbnl.h> #include <net/dcbevent.h> #include <scsi/scsi_tcq.h> #include <scsi/scsicam.h> #include <scsi/scsi_transport.h> #include <scsi/scsi_transport_fc.h> #include <net/rtnetlink.h> #include <scsi/fc/fc_encaps.h> #include <scsi/fc/fc_fip.h> #include <scsi/fc/fc_fcoe.h> #include <scsi/libfc.h> #include <scsi/fc_frame.h> #include <scsi/libfcoe.h> #include "fcoe.h" MODULE_AUTHOR(…) …; MODULE_DESCRIPTION(…) …; MODULE_LICENSE(…) …; /* Performance tuning parameters for fcoe */ static unsigned int fcoe_ddp_min = …; module_param_named(ddp_min, fcoe_ddp_min, uint, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(…) …; unsigned int fcoe_debug_logging; module_param_named(debug_logging, fcoe_debug_logging, int, S_IRUGO|S_IWUSR); MODULE_PARM_DESC(…) …; static unsigned int fcoe_e_d_tov = …; module_param_named(e_d_tov, fcoe_e_d_tov, int, S_IRUGO|S_IWUSR); MODULE_PARM_DESC(…) …; static unsigned int fcoe_r_a_tov = …; module_param_named(r_a_tov, fcoe_r_a_tov, int, S_IRUGO|S_IWUSR); MODULE_PARM_DESC(…) …; static DEFINE_MUTEX(fcoe_config_mutex); static struct workqueue_struct *fcoe_wq; /* fcoe host list */ /* must only by accessed under the RTNL mutex */ static LIST_HEAD(fcoe_hostlist); static DEFINE_PER_CPU(struct fcoe_percpu_s, fcoe_percpu); /* Function Prototypes */ static int fcoe_reset(struct Scsi_Host *); static int fcoe_xmit(struct fc_lport *, struct fc_frame *); static int fcoe_rcv(struct sk_buff *, struct net_device *, struct packet_type *, struct net_device *); static void fcoe_percpu_clean(struct fc_lport *); static int fcoe_link_ok(struct fc_lport *); static struct fc_lport *fcoe_hostlist_lookup(const struct net_device *); static int fcoe_hostlist_add(const struct fc_lport *); static void fcoe_hostlist_del(const struct fc_lport *); static int fcoe_device_notification(struct notifier_block *, ulong, void *); static void fcoe_dev_setup(void); static void fcoe_dev_cleanup(void); static struct fcoe_interface *fcoe_hostlist_lookup_port(const struct net_device *); static int fcoe_fip_recv(struct sk_buff *, struct net_device *, struct packet_type *, struct net_device *); static int fcoe_fip_vlan_recv(struct sk_buff *, struct net_device *, struct packet_type *, struct net_device *); static void fcoe_fip_send(struct fcoe_ctlr *, struct sk_buff *); static void fcoe_update_src_mac(struct fc_lport *, u8 *); static u8 *fcoe_get_src_mac(struct fc_lport *); static void fcoe_destroy_work(struct work_struct *); static int fcoe_ddp_setup(struct fc_lport *, u16, struct scatterlist *, unsigned int); static int fcoe_ddp_done(struct fc_lport *, u16); static int fcoe_ddp_target(struct fc_lport *, u16, struct scatterlist *, unsigned int); static int fcoe_dcb_app_notification(struct notifier_block *notifier, ulong event, void *ptr); static bool fcoe_match(struct net_device *netdev); static int fcoe_create(struct net_device *netdev, enum fip_mode fip_mode); static int fcoe_destroy(struct net_device *netdev); static int fcoe_enable(struct net_device *netdev); static int fcoe_disable(struct net_device *netdev); /* fcoe_syfs control interface handlers */ static int fcoe_ctlr_alloc(struct net_device *netdev); static int fcoe_ctlr_enabled(struct fcoe_ctlr_device *cdev); static void fcoe_ctlr_mode(struct fcoe_ctlr_device *ctlr_dev); static struct fc_seq *fcoe_elsct_send(struct fc_lport *, u32 did, struct fc_frame *, unsigned int op, void (*resp)(struct fc_seq *, struct fc_frame *, void *), void *, u32 timeout); static void fcoe_recv_frame(struct sk_buff *skb); /* notification function for packets from net device */ static struct notifier_block fcoe_notifier = …; /* notification function for DCB events */ static struct notifier_block dcb_notifier = …; static struct scsi_transport_template *fcoe_nport_scsi_transport; static struct scsi_transport_template *fcoe_vport_scsi_transport; static int fcoe_vport_destroy(struct fc_vport *); static int fcoe_vport_create(struct fc_vport *, bool disabled); static int fcoe_vport_disable(struct fc_vport *, bool disable); static void fcoe_set_vport_symbolic_name(struct fc_vport *); static void fcoe_set_port_id(struct fc_lport *, u32, struct fc_frame *); static void fcoe_fcf_get_vlan_id(struct fcoe_fcf_device *); static void fcoe_vport_remove(struct fc_lport *); static struct fcoe_sysfs_function_template fcoe_sysfs_templ = …; static struct libfc_function_template fcoe_libfc_fcn_templ = …; static struct fc_function_template fcoe_nport_fc_functions = …; static struct fc_function_template fcoe_vport_fc_functions = …; static const struct scsi_host_template fcoe_shost_template = …; /** * fcoe_interface_setup() - Setup a FCoE interface * @fcoe: The new FCoE interface * @netdev: The net device that the fcoe interface is on * * Returns : 0 for success * Locking: must be called with the RTNL mutex held */ static int fcoe_interface_setup(struct fcoe_interface *fcoe, struct net_device *netdev) { … } /** * fcoe_interface_create() - Create a FCoE interface on a net device * @netdev: The net device to create the FCoE interface on * @fip_mode: The mode to use for FIP * * Returns: pointer to a struct fcoe_interface or NULL on error */ static struct fcoe_interface *fcoe_interface_create(struct net_device *netdev, enum fip_mode fip_mode) { … } /** * fcoe_interface_remove() - remove FCoE interface from netdev * @fcoe: The FCoE interface to be cleaned up * * Caller must be holding the RTNL mutex */ static void fcoe_interface_remove(struct fcoe_interface *fcoe) { … } /** * fcoe_interface_cleanup() - Clean up a FCoE interface * @fcoe: The FCoE interface to be cleaned up */ static void fcoe_interface_cleanup(struct fcoe_interface *fcoe) { … } /** * fcoe_fip_recv() - Handler for received FIP frames * @skb: The receive skb * @netdev: The associated net device * @ptype: The packet_type structure which was used to register this handler * @orig_dev: The original net_device the skb was received on. * (in case dev is a bond) * * Returns: 0 for success */ static int fcoe_fip_recv(struct sk_buff *skb, struct net_device *netdev, struct packet_type *ptype, struct net_device *orig_dev) { … } /** * fcoe_fip_vlan_recv() - Handler for received FIP VLAN discovery frames * @skb: The receive skb * @netdev: The associated net device * @ptype: The packet_type structure which was used to register this handler * @orig_dev: The original net_device the skb was received on. * (in case dev is a bond) * * Returns: 0 for success */ static int fcoe_fip_vlan_recv(struct sk_buff *skb, struct net_device *netdev, struct packet_type *ptype, struct net_device *orig_dev) { … } /** * fcoe_port_send() - Send an Ethernet-encapsulated FIP/FCoE frame * @port: The FCoE port * @skb: The FIP/FCoE packet to be sent */ static void fcoe_port_send(struct fcoe_port *port, struct sk_buff *skb) { … } /** * fcoe_fip_send() - Send an Ethernet-encapsulated FIP frame * @fip: The FCoE controller * @skb: The FIP packet to be sent */ static void fcoe_fip_send(struct fcoe_ctlr *fip, struct sk_buff *skb) { … } /** * fcoe_update_src_mac() - Update the Ethernet MAC filters * @lport: The local port to update the source MAC on * @addr: Unicast MAC address to add * * Remove any previously-set unicast MAC filter. * Add secondary FCoE MAC address filter for our OUI. */ static void fcoe_update_src_mac(struct fc_lport *lport, u8 *addr) { … } /** * fcoe_get_src_mac() - return the Ethernet source address for an lport * @lport: libfc lport */ static u8 *fcoe_get_src_mac(struct fc_lport *lport) { … } /** * fcoe_lport_config() - Set up a local port * @lport: The local port to be setup * * Returns: 0 for success */ static int fcoe_lport_config(struct fc_lport *lport) { … } /* * fcoe_netdev_features_change - Updates the lport's offload flags based * on the LLD netdev's FCoE feature flags */ static void fcoe_netdev_features_change(struct fc_lport *lport, struct net_device *netdev) { … } /** * fcoe_netdev_config() - Set up net devive for SW FCoE * @lport: The local port that is associated with the net device * @netdev: The associated net device * * Must be called after fcoe_lport_config() as it will use local port mutex * * Returns: 0 for success */ static int fcoe_netdev_config(struct fc_lport *lport, struct net_device *netdev) { … } /** * fcoe_shost_config() - Set up the SCSI host associated with a local port * @lport: The local port * @dev: The device associated with the SCSI host * * Must be called after fcoe_lport_config() and fcoe_netdev_config() * * Returns: 0 for success */ static int fcoe_shost_config(struct fc_lport *lport, struct device *dev) { … } /** * fcoe_fdmi_info() - Get FDMI related info from net devive for SW FCoE * @lport: The local port that is associated with the net device * @netdev: The associated net device * * Must be called after fcoe_shost_config() as it will use local port mutex * */ static void fcoe_fdmi_info(struct fc_lport *lport, struct net_device *netdev) { … } /** * fcoe_oem_match() - The match routine for the offloaded exchange manager * @fp: The I/O frame * * This routine will be associated with an exchange manager (EM). When * the libfc exchange handling code is looking for an EM to use it will * call this routine and pass it the frame that it wishes to send. This * routine will return True if the associated EM is to be used and False * if the echange code should continue looking for an EM. * * The offload EM that this routine is associated with will handle any * packets that are for SCSI read requests. * * This has been enhanced to work when FCoE stack is operating in target * mode. * * Returns: True for read types I/O, otherwise returns false. */ static bool fcoe_oem_match(struct fc_frame *fp) { … } /** * fcoe_em_config() - Allocate and configure an exchange manager * @lport: The local port that the new EM will be associated with * * Returns: 0 on success */ static inline int fcoe_em_config(struct fc_lport *lport) { … } /** * fcoe_if_destroy() - Tear down a SW FCoE instance * @lport: The local port to be destroyed * * Locking: Must be called with the RTNL mutex held. * */ static void fcoe_if_destroy(struct fc_lport *lport) { … } /** * fcoe_ddp_setup() - Call a LLD's ddp_setup through the net device * @lport: The local port to setup DDP for * @xid: The exchange ID for this DDP transfer * @sgl: The scatterlist describing this transfer * @sgc: The number of sg items * * Returns: 0 if the DDP context was not configured */ static int fcoe_ddp_setup(struct fc_lport *lport, u16 xid, struct scatterlist *sgl, unsigned int sgc) { … } /** * fcoe_ddp_target() - Call a LLD's ddp_target through the net device * @lport: The local port to setup DDP for * @xid: The exchange ID for this DDP transfer * @sgl: The scatterlist describing this transfer * @sgc: The number of sg items * * Returns: 0 if the DDP context was not configured */ static int fcoe_ddp_target(struct fc_lport *lport, u16 xid, struct scatterlist *sgl, unsigned int sgc) { … } /** * fcoe_ddp_done() - Call a LLD's ddp_done through the net device * @lport: The local port to complete DDP on * @xid: The exchange ID for this DDP transfer * * Returns: the length of data that have been completed by DDP */ static int fcoe_ddp_done(struct fc_lport *lport, u16 xid) { … } /** * fcoe_if_create() - Create a FCoE instance on an interface * @fcoe: The FCoE interface to create a local port on * @parent: The device pointer to be the parent in sysfs for the SCSI host * @npiv: Indicates if the port is a vport or not * * Creates a fc_lport instance and a Scsi_Host instance and configure them. * * Returns: The allocated fc_lport or an error pointer */ static struct fc_lport *fcoe_if_create(struct fcoe_interface *fcoe, struct device *parent, int npiv) { … } /** * fcoe_if_init() - Initialization routine for fcoe.ko * * Attaches the SW FCoE transport to the FC transport * * Returns: 0 on success */ static int __init fcoe_if_init(void) { … } /** * fcoe_if_exit() - Tear down fcoe.ko * * Detaches the SW FCoE transport from the FC transport * * Returns: 0 on success */ static int __exit fcoe_if_exit(void) { … } static void fcoe_thread_cleanup_local(unsigned int cpu) { … } /** * fcoe_select_cpu() - Selects CPU to handle post-processing of incoming * command. * * This routine selects next CPU based on cpumask to distribute * incoming requests in round robin. * * Returns: int CPU number */ static inline unsigned int fcoe_select_cpu(void) { … } /** * fcoe_rcv() - Receive packets from a net device * @skb: The received packet * @netdev: The net device that the packet was received on * @ptype: The packet type context * @olddev: The last device net device * * This routine is called by NET_RX_SOFTIRQ. It receives a packet, builds a * FC frame and passes the frame to libfc. * * Returns: 0 for success */ static int fcoe_rcv(struct sk_buff *skb, struct net_device *netdev, struct packet_type *ptype, struct net_device *olddev) { … } /** * fcoe_alloc_paged_crc_eof() - Allocate a page to be used for the trailer CRC * @skb: The packet to be transmitted * @tlen: The total length of the trailer * * Returns: 0 for success */ static int fcoe_alloc_paged_crc_eof(struct sk_buff *skb, int tlen) { … } /** * fcoe_xmit() - Transmit a FCoE frame * @lport: The local port that the frame is to be transmitted for * @fp: The frame to be transmitted * * Return: 0 for success */ static int fcoe_xmit(struct fc_lport *lport, struct fc_frame *fp) { … } /** * fcoe_filter_frames() - filter out bad fcoe frames, i.e. bad CRC * @lport: The local port the frame was received on * @fp: The received frame * * Return: 0 on passing filtering checks */ static inline int fcoe_filter_frames(struct fc_lport *lport, struct fc_frame *fp) { … } /** * fcoe_recv_frame() - process a single received frame * @skb: frame to process */ static void fcoe_recv_frame(struct sk_buff *skb) { … } /** * fcoe_receive_work() - The per-CPU worker * @work: The work struct * */ static void fcoe_receive_work(struct work_struct *work) { … } /** * fcoe_dev_setup() - Setup the link change notification interface */ static void fcoe_dev_setup(void) { … } /** * fcoe_dev_cleanup() - Cleanup the link change notification interface */ static void fcoe_dev_cleanup(void) { … } static struct fcoe_interface * fcoe_hostlist_lookup_realdev_port(struct net_device *netdev) { … } static int fcoe_dcb_app_notification(struct notifier_block *notifier, ulong event, void *ptr) { … } /** * fcoe_device_notification() - Handler for net device events * @notifier: The context of the notification * @event: The type of event * @ptr: The net device that the event was on * * This function is called by the Ethernet driver in case of link change event. * * Returns: 0 for success */ static int fcoe_device_notification(struct notifier_block *notifier, ulong event, void *ptr) { … } /** * fcoe_disable() - Disables a FCoE interface * @netdev : The net_device object the Ethernet interface to create on * * Called from fcoe transport. * * Returns: 0 for success * * Deprecated: use fcoe_ctlr_enabled() */ static int fcoe_disable(struct net_device *netdev) { … } /** * fcoe_enable() - Enables a FCoE interface * @netdev : The net_device object the Ethernet interface to create on * * Called from fcoe transport. * * Returns: 0 for success */ static int fcoe_enable(struct net_device *netdev) { … } /** * fcoe_ctlr_enabled() - Enable or disable an FCoE Controller * @cdev: The FCoE Controller that is being enabled or disabled * * fcoe_sysfs will ensure that the state of 'enabled' has * changed, so no checking is necessary here. This routine simply * calls fcoe_enable or fcoe_disable, both of which are deprecated. * When those routines are removed the functionality can be merged * here. */ static int fcoe_ctlr_enabled(struct fcoe_ctlr_device *cdev) { … } /** * fcoe_ctlr_mode() - Switch FIP mode * @ctlr_dev: The FCoE Controller that is being modified * * When the FIP mode has been changed we need to update * the multicast addresses to ensure we get the correct * frames. */ static void fcoe_ctlr_mode(struct fcoe_ctlr_device *ctlr_dev) { … } /** * fcoe_destroy() - Destroy a FCoE interface * @netdev : The net_device object the Ethernet interface to create on * * Called from fcoe transport * * Returns: 0 for success */ static int fcoe_destroy(struct net_device *netdev) { … } /** * fcoe_destroy_work() - Destroy a FCoE port in a deferred work context * @work: Handle to the FCoE port to be destroyed */ static void fcoe_destroy_work(struct work_struct *work) { … } /** * fcoe_match() - Check if the FCoE is supported on the given netdevice * @netdev : The net_device object the Ethernet interface to create on * * Called from fcoe transport. * * Returns: always returns true as this is the default FCoE transport, * i.e., support all netdevs. */ static bool fcoe_match(struct net_device *netdev) { … } /** * fcoe_dcb_create() - Initialize DCB attributes and hooks * @fcoe: The new FCoE interface */ static void fcoe_dcb_create(struct fcoe_interface *fcoe) { … } enum fcoe_create_link_state { … }; /** * _fcoe_create() - (internal) Create a fcoe interface * @netdev : The net_device object the Ethernet interface to create on * @fip_mode: The FIP mode for this creation * @link_state: The ctlr link state on creation * * Called from either the libfcoe 'create' module parameter * via fcoe_create or from fcoe_syfs's ctlr_create file. * * libfcoe's 'create' module parameter is deprecated so some * consolidation of code can be done when that interface is * removed. */ static int _fcoe_create(struct net_device *netdev, enum fip_mode fip_mode, enum fcoe_create_link_state link_state) { … } /** * fcoe_create() - Create a fcoe interface * @netdev : The net_device object the Ethernet interface to create on * @fip_mode: The FIP mode for this creation * * Called from fcoe transport * * Returns: 0 for success */ static int fcoe_create(struct net_device *netdev, enum fip_mode fip_mode) { … } /** * fcoe_ctlr_alloc() - Allocate a fcoe interface from fcoe_sysfs * @netdev: The net_device to be used by the allocated FCoE Controller * * This routine is called from fcoe_sysfs. It will start the fcoe_ctlr * in a link_down state. The allows the user an opportunity to configure * the FCoE Controller from sysfs before enabling the FCoE Controller. * * Creating in with this routine starts the FCoE Controller in Fabric * mode. The user can change to VN2VN or another mode before enabling. */ static int fcoe_ctlr_alloc(struct net_device *netdev) { … } /** * fcoe_link_ok() - Check if the link is OK for a local port * @lport: The local port to check link on * * Returns: 0 if link is UP and OK, -1 if not * */ static int fcoe_link_ok(struct fc_lport *lport) { … } /** * fcoe_percpu_clean() - Clear all pending skbs for an local port * @lport: The local port whose skbs are to be cleared * * Must be called with fcoe_create_mutex held to single-thread completion. * * This flushes the pending skbs by flush the work item for each CPU. The work * item on each possible CPU is flushed because we may have used the per-CPU * struct of an offline CPU. */ static void fcoe_percpu_clean(struct fc_lport *lport) { … } /** * fcoe_reset() - Reset a local port * @shost: The SCSI host associated with the local port to be reset * * Returns: Always 0 (return value required by FC transport template) */ static int fcoe_reset(struct Scsi_Host *shost) { … } /** * fcoe_hostlist_lookup_port() - Find the FCoE interface associated with a net device * @netdev: The net device used as a key * * Locking: Must be called with the RNL mutex held. * * Returns: NULL or the FCoE interface */ static struct fcoe_interface * fcoe_hostlist_lookup_port(const struct net_device *netdev) { … } /** * fcoe_hostlist_lookup() - Find the local port associated with a * given net device * @netdev: The netdevice used as a key * * Locking: Must be called with the RTNL mutex held * * Returns: NULL or the local port */ static struct fc_lport *fcoe_hostlist_lookup(const struct net_device *netdev) { … } /** * fcoe_hostlist_add() - Add the FCoE interface identified by a local * port to the hostlist * @lport: The local port that identifies the FCoE interface to be added * * Locking: must be called with the RTNL mutex held * * Returns: 0 for success */ static int fcoe_hostlist_add(const struct fc_lport *lport) { … } /** * fcoe_hostlist_del() - Remove the FCoE interface identified by a local * port to the hostlist * @lport: The local port that identifies the FCoE interface to be added * * Locking: must be called with the RTNL mutex held * */ static void fcoe_hostlist_del(const struct fc_lport *lport) { … } static struct fcoe_transport fcoe_sw_transport = …; /** * fcoe_init() - Initialize fcoe.ko * * Returns: 0 on success, or a negative value on failure */ static int __init fcoe_init(void) { … } module_init(…) …; /** * fcoe_exit() - Clean up fcoe.ko * * Returns: 0 on success or a negative value on failure */ static void __exit fcoe_exit(void) { … } module_exit(fcoe_exit); /** * fcoe_flogi_resp() - FCoE specific FLOGI and FDISC response handler * @seq: active sequence in the FLOGI or FDISC exchange * @fp: response frame, or error encoded in a pointer (timeout) * @arg: pointer to the fcoe_ctlr structure * * This handles MAC address management for FCoE, then passes control on to * the libfc FLOGI response handler. */ static void fcoe_flogi_resp(struct fc_seq *seq, struct fc_frame *fp, void *arg) { … } /** * fcoe_logo_resp() - FCoE specific LOGO response handler * @seq: active sequence in the LOGO exchange * @fp: response frame, or error encoded in a pointer (timeout) * @arg: pointer to the fcoe_ctlr structure * * This handles MAC address management for FCoE, then passes control on to * the libfc LOGO response handler. */ static void fcoe_logo_resp(struct fc_seq *seq, struct fc_frame *fp, void *arg) { … } /* * fcoe_elsct_send - FCoE specific ELS handler * * This does special case handling of FIP encapsualted ELS exchanges for FCoE, * using FCoE specific response handlers and passing the FIP controller as * the argument (the lport is still available from the exchange). * * Most of the work here is just handed off to the libfc routine. */ static struct fc_seq *fcoe_elsct_send(struct fc_lport *lport, u32 did, struct fc_frame *fp, unsigned int op, void (*resp)(struct fc_seq *, struct fc_frame *, void *), void *arg, u32 timeout) { … } /** * fcoe_vport_create() - create an fc_host/scsi_host for a vport * @vport: fc_vport object to create a new fc_host for * @disabled: start the new fc_host in a disabled state by default? * * Returns: 0 for success */ static int fcoe_vport_create(struct fc_vport *vport, bool disabled) { … } /** * fcoe_vport_destroy() - destroy the fc_host/scsi_host for a vport * @vport: fc_vport object that is being destroyed * * Returns: 0 for success */ static int fcoe_vport_destroy(struct fc_vport *vport) { … } /** * fcoe_vport_remove() - remove attached vports * @lport: lport for which the vports should be removed */ static void fcoe_vport_remove(struct fc_lport *lport) { … } /** * fcoe_vport_disable() - change vport state * @vport: vport to bring online/offline * @disable: should the vport be disabled? */ static int fcoe_vport_disable(struct fc_vport *vport, bool disable) { … } /** * fcoe_set_vport_symbolic_name() - append vport string to symbolic name * @vport: fc_vport with a new symbolic name string * * After generating a new symbolic name string, a new RSPN_ID request is * sent to the name server. There is no response handler, so if it fails * for some reason it will not be retried. */ static void fcoe_set_vport_symbolic_name(struct fc_vport *vport) { … } static void fcoe_fcf_get_vlan_id(struct fcoe_fcf_device *fcf_dev) { … } /** * fcoe_set_port_id() - Callback from libfc when Port_ID is set. * @lport: the local port * @port_id: the port ID * @fp: the received frame, if any, that caused the port_id to be set. * * This routine handles the case where we received a FLOGI and are * entering point-to-point mode. We need to call fcoe_ctlr_recv_flogi() * so it can set the non-mapped mode and gateway address. * * The FLOGI LS_ACC is handled by fcoe_flogi_resp(). */ static void fcoe_set_port_id(struct fc_lport *lport, u32 port_id, struct fc_frame *fp) { … }