linux/drivers/scsi/bnx2fc/bnx2fc_fcoe.c

/* bnx2fc_fcoe.c: QLogic Linux FCoE offload driver.
 * This file contains the code that interacts with libfc, libfcoe,
 * cnic modules to create FCoE instances, send/receive non-offloaded
 * FIP/FCoE packets, listen to link events etc.
 *
 * Copyright (c) 2008-2013 Broadcom Corporation
 * Copyright (c) 2014-2016 QLogic Corporation
 * Copyright (c) 2016-2017 Cavium Inc.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation.
 *
 * Written by: Bhanu Prakash Gollapudi ([email protected])
 */

#include "bnx2fc.h"

#include <linux/ethtool.h>

static struct list_head adapter_list;
static struct list_head if_list;
static u32 adapter_count;
static DEFINE_MUTEX(bnx2fc_dev_lock);
DEFINE_PER_CPU(struct bnx2fc_percpu_s, bnx2fc_percpu);

#define DRV_MODULE_NAME
#define DRV_MODULE_VERSION
#define DRV_MODULE_RELDATE


static char version[] =;


MODULE_AUTHOR();
MODULE_DESCRIPTION();
MODULE_LICENSE();
MODULE_VERSION();

#define BNX2FC_MAX_QUEUE_DEPTH
#define BNX2FC_MIN_QUEUE_DEPTH
#define FCOE_WORD_TO_BYTE

static struct scsi_transport_template	*bnx2fc_transport_template;
static struct scsi_transport_template	*bnx2fc_vport_xport_template;

struct workqueue_struct *bnx2fc_wq;

/* bnx2fc structure needs only one instance of the fcoe_percpu_s structure.
 * Here the io threads are per cpu but the l2 thread is just one
 */
struct fcoe_percpu_s bnx2fc_global;
static DEFINE_SPINLOCK(bnx2fc_global_lock);

static struct cnic_ulp_ops bnx2fc_cnic_cb;
static struct libfc_function_template bnx2fc_libfc_fcn_templ;
static struct scsi_host_template bnx2fc_shost_template;
static struct fc_function_template bnx2fc_transport_function;
static struct fcoe_sysfs_function_template bnx2fc_fcoe_sysfs_templ;
static struct fc_function_template bnx2fc_vport_xport_function;
static int bnx2fc_create(struct net_device *netdev, enum fip_mode fip_mode);
static void __bnx2fc_destroy(struct bnx2fc_interface *interface);
static int bnx2fc_destroy(struct net_device *net_device);
static int bnx2fc_enable(struct net_device *netdev);
static int bnx2fc_disable(struct net_device *netdev);

/* fcoe_syfs control interface handlers */
static int bnx2fc_ctlr_alloc(struct net_device *netdev);
static int bnx2fc_ctlr_enabled(struct fcoe_ctlr_device *cdev);

static void bnx2fc_recv_frame(struct sk_buff *skb);

static void bnx2fc_start_disc(struct bnx2fc_interface *interface);
static int bnx2fc_shost_config(struct fc_lport *lport, struct device *dev);
static int bnx2fc_lport_config(struct fc_lport *lport);
static int bnx2fc_em_config(struct fc_lport *lport, struct bnx2fc_hba *hba);
static int bnx2fc_bind_adapter_devices(struct bnx2fc_hba *hba);
static void bnx2fc_unbind_adapter_devices(struct bnx2fc_hba *hba);
static int bnx2fc_bind_pcidev(struct bnx2fc_hba *hba);
static void bnx2fc_unbind_pcidev(struct bnx2fc_hba *hba);
static struct fc_lport *bnx2fc_if_create(struct bnx2fc_interface *interface,
				  struct device *parent, int npiv);
static void bnx2fc_port_destroy(struct fcoe_port *port);

static struct bnx2fc_hba *bnx2fc_hba_lookup(struct net_device *phys_dev);
static struct bnx2fc_interface *bnx2fc_interface_lookup(struct net_device
							*phys_dev);
static inline void bnx2fc_interface_put(struct bnx2fc_interface *interface);
static struct bnx2fc_hba *bnx2fc_find_hba_for_cnic(struct cnic_dev *cnic);

static int bnx2fc_fw_init(struct bnx2fc_hba *hba);
static void bnx2fc_fw_destroy(struct bnx2fc_hba *hba);

static void bnx2fc_port_shutdown(struct fc_lport *lport);
static void bnx2fc_stop(struct bnx2fc_interface *interface);
static int __init bnx2fc_mod_init(void);
static void __exit bnx2fc_mod_exit(void);

unsigned int bnx2fc_debug_level;
module_param_named(debug_logging, bnx2fc_debug_level, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC();

static uint bnx2fc_devloss_tmo;
module_param_named(devloss_tmo, bnx2fc_devloss_tmo, uint, S_IRUGO);
MODULE_PARM_DESC();

static uint bnx2fc_max_luns =;
module_param_named(max_luns, bnx2fc_max_luns, uint, S_IRUGO);
MODULE_PARM_DESC();

static uint bnx2fc_queue_depth;
module_param_named(queue_depth, bnx2fc_queue_depth, uint, S_IRUGO);
MODULE_PARM_DESC();

static uint bnx2fc_log_fka;
module_param_named(log_fka, bnx2fc_log_fka, uint, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC();

static inline struct net_device *bnx2fc_netdev(const struct fc_lport *lport)
{}

static void bnx2fc_fcf_get_vlan_id(struct fcoe_fcf_device *fcf_dev)
{}

static void bnx2fc_clean_rx_queue(struct fc_lport *lp)
{}

int bnx2fc_get_paged_crc_eof(struct sk_buff *skb, int tlen)
{}

static void bnx2fc_abort_io(struct fc_lport *lport)
{}

static void bnx2fc_cleanup(struct fc_lport *lport)
{}

static int bnx2fc_xmit_l2_frame(struct bnx2fc_rport *tgt,
			     struct fc_frame *fp)
{}

/**
 * bnx2fc_xmit - bnx2fc's FCoE frame transmit function
 *
 * @lport:	the associated local port
 * @fp:	the fc_frame to be transmitted
 */
static int bnx2fc_xmit(struct fc_lport *lport, struct fc_frame *fp)
{}

/**
 * bnx2fc_rcv - This is bnx2fc's receive function called by NET_RX_SOFTIRQ
 *
 * @skb:	the receive socket buffer
 * @dev:	associated net device
 * @ptype:	context
 * @olddev:	last device
 *
 * This function receives the packet and builds FC frame and passes it up
 */
static int bnx2fc_rcv(struct sk_buff *skb, struct net_device *dev,
		struct packet_type *ptype, struct net_device *olddev)
{}

static int bnx2fc_l2_rcv_thread(void *arg)
{}


static void bnx2fc_recv_frame(struct sk_buff *skb)
{}

/**
 * bnx2fc_percpu_io_thread - thread per cpu for ios
 *
 * @arg:	ptr to bnx2fc_percpu_info structure
 */
static int bnx2fc_percpu_io_thread(void *arg)
{}

static struct fc_host_statistics *bnx2fc_get_host_stats(struct Scsi_Host *shost)
{}

static int bnx2fc_shost_config(struct fc_lport *lport, struct device *dev)
{}

static int bnx2fc_link_ok(struct fc_lport *lport)
{}

/**
 * bnx2fc_get_link_state - get network link state
 *
 * @hba:	adapter instance pointer
 *
 * updates adapter structure flag based on netdev state
 */
void bnx2fc_get_link_state(struct bnx2fc_hba *hba)
{}

static int bnx2fc_net_config(struct fc_lport *lport, struct net_device *netdev)
{}

static void bnx2fc_destroy_timer(struct timer_list *t)
{}

/**
 * bnx2fc_indicate_netevent - Generic netdev event handler
 *
 * @context:	adapter structure pointer
 * @event:	event type
 * @vlan_id:	vlan id - associated vlan id with this event
 *
 * Handles NETDEV_UP, NETDEV_DOWN, NETDEV_GOING_DOWN,NETDEV_CHANGE and
 * NETDEV_CHANGE_MTU events. Handle NETDEV_UNREGISTER only for vlans.
 */
static void bnx2fc_indicate_netevent(void *context, unsigned long event,
				     u16 vlan_id)
{}

static int bnx2fc_libfc_config(struct fc_lport *lport)
{}

static int bnx2fc_em_config(struct fc_lport *lport, struct bnx2fc_hba *hba)
{}

static int bnx2fc_lport_config(struct fc_lport *lport)
{}

/**
 * bnx2fc_fip_recv - handle a received FIP frame.
 *
 * @skb: the received skb
 * @dev: associated &net_device
 * @ptype: the &packet_type structure which was used to register this handler.
 * @orig_dev: original receive &net_device, in case @ dev is a bond.
 *
 * Returns: 0 for success
 */
static int bnx2fc_fip_recv(struct sk_buff *skb, struct net_device *dev,
			   struct packet_type *ptype,
			   struct net_device *orig_dev)
{}

/**
 * bnx2fc_update_src_mac - Update Ethernet MAC filters.
 *
 * @lport: The local port
 * @addr: Location of data to copy
 *
 * Remove any previously-set unicast MAC filter.
 * Add secondary FCoE MAC address filter for our OUI.
 */
static void bnx2fc_update_src_mac(struct fc_lport *lport, u8 *addr)
{}

/**
 * bnx2fc_get_src_mac - return the ethernet source address for an lport
 *
 * @lport: libfc port
 */
static u8 *bnx2fc_get_src_mac(struct fc_lport *lport)
{}

/**
 * bnx2fc_fip_send - send an Ethernet-encapsulated FIP frame.
 *
 * @fip: FCoE controller.
 * @skb: FIP Packet.
 */
static void bnx2fc_fip_send(struct fcoe_ctlr *fip, struct sk_buff *skb)
{}

static int bnx2fc_vport_create(struct fc_vport *vport, bool disabled)
{}

static void bnx2fc_free_vport(struct bnx2fc_hba *hba, struct fc_lport *lport)
{}

static int bnx2fc_vport_destroy(struct fc_vport *vport)
{}

static int bnx2fc_vport_disable(struct fc_vport *vport, bool disable)
{}


static int bnx2fc_interface_setup(struct bnx2fc_interface *interface)
{}

static int bnx2fc_attach_transport(void)
{}
static void bnx2fc_release_transport(void)
{}

static void bnx2fc_interface_release(struct kref *kref)
{}

static inline void bnx2fc_interface_get(struct bnx2fc_interface *interface)
{}

static inline void bnx2fc_interface_put(struct bnx2fc_interface *interface)
{}
static void bnx2fc_hba_destroy(struct bnx2fc_hba *hba)
{}

/**
 * bnx2fc_hba_create - create a new bnx2fc hba
 *
 * @cnic:	pointer to cnic device
 *
 * Creates a new FCoE hba on the given device.
 *
 */
static struct bnx2fc_hba *bnx2fc_hba_create(struct cnic_dev *cnic)
{}

static struct bnx2fc_interface *
bnx2fc_interface_create(struct bnx2fc_hba *hba,
			struct net_device *netdev,
			enum fip_mode fip_mode)
{}

/**
 * bnx2fc_if_create - Create FCoE instance on a given interface
 *
 * @interface:	FCoE interface to create a local port on
 * @parent:	Device pointer to be the parent in sysfs for the SCSI host
 * @npiv:	Indicates if the port is vport or not
 *
 * Creates a fc_lport instance and a Scsi_Host instance and configure them.
 *
 * Returns:	Allocated fc_lport or an error pointer
 */
static struct fc_lport *bnx2fc_if_create(struct bnx2fc_interface *interface,
				  struct device *parent, int npiv)
{}

static void bnx2fc_net_cleanup(struct bnx2fc_interface *interface)
{}

static void bnx2fc_interface_cleanup(struct bnx2fc_interface *interface)
{}

static void bnx2fc_if_destroy(struct fc_lport *lport)
{}

static void __bnx2fc_destroy(struct bnx2fc_interface *interface)
{}

/**
 * bnx2fc_destroy - Destroy a bnx2fc FCoE interface
 *
 * @netdev: The net device that the FCoE interface is on
 *
 * Called from sysfs.
 *
 * Returns: 0 for success
 */
static int bnx2fc_destroy(struct net_device *netdev)
{}

static void bnx2fc_port_destroy(struct fcoe_port *port)
{}

static void bnx2fc_unbind_adapter_devices(struct bnx2fc_hba *hba)
{}

/**
 * bnx2fc_bind_adapter_devices - binds bnx2fc adapter with the associated
 *			pci structure
 *
 * @hba:		Adapter instance
 */
static int bnx2fc_bind_adapter_devices(struct bnx2fc_hba *hba)
{}

static int bnx2fc_bind_pcidev(struct bnx2fc_hba *hba)
{}

static void bnx2fc_unbind_pcidev(struct bnx2fc_hba *hba)
{}

/**
 * bnx2fc_ulp_get_stats - cnic callback to populate FCoE stats
 *
 * @handle:    transport handle pointing to adapter structure
 */
static int bnx2fc_ulp_get_stats(void *handle)
{}


/**
 * bnx2fc_ulp_start - cnic callback to initialize & start adapter instance
 *
 * @handle:	transport handle pointing to adapter structure
 *
 * This function maps adapter structure to pcidev structure and initiates
 *	firmware handshake to enable/initialize on-chip FCoE components.
 *	This bnx2fc - cnic interface api callback is used after following
 *	conditions are met -
 *	a) underlying network interface is up (marked by event NETDEV_UP
 *		from netdev
 *	b) bnx2fc adatper structure is registered.
 */
static void bnx2fc_ulp_start(void *handle)
{}

static void bnx2fc_port_shutdown(struct fc_lport *lport)
{}

static void bnx2fc_stop(struct bnx2fc_interface *interface)
{}

static int bnx2fc_fw_init(struct bnx2fc_hba *hba)
{}

static void bnx2fc_fw_destroy(struct bnx2fc_hba *hba)
{}

/**
 * bnx2fc_ulp_stop - cnic callback to shutdown adapter instance
 *
 * @handle:	transport handle pointing to adapter structure
 *
 * Driver checks if adapter is already in shutdown mode, if not start
 *	the shutdown process.
 */
static void bnx2fc_ulp_stop(void *handle)
{}

static void bnx2fc_start_disc(struct bnx2fc_interface *interface)
{}


/**
 * bnx2fc_ulp_init - Initialize an adapter instance
 *
 * @dev :	cnic device handle
 * Called from cnic_register_driver() context to initialize all
 *	enumerated cnic devices. This routine allocates adapter structure
 *	and other device specific resources.
 */
static void bnx2fc_ulp_init(struct cnic_dev *dev)
{}

/* Assumes rtnl_lock and the bnx2fc_dev_lock are already taken */
static int __bnx2fc_disable(struct fcoe_ctlr *ctlr)
{}

/*
 * Deperecated: Use bnx2fc_enabled()
 */
static int bnx2fc_disable(struct net_device *netdev)
{}

static uint bnx2fc_npiv_create_vports(struct fc_lport *lport,
				      struct cnic_fc_npiv_tbl *npiv_tbl)
{}

static int __bnx2fc_enable(struct fcoe_ctlr *ctlr)
{}

/*
 * Deprecated: Use bnx2fc_enabled()
 */
static int bnx2fc_enable(struct net_device *netdev)
{}

/**
 * bnx2fc_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 bnx2fc_ctlr_enabled(struct fcoe_ctlr_device *cdev)
{}

enum bnx2fc_create_link_state {};

/**
 * _bnx2fc_create() - Create bnx2fc 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.
 *
 * Returns: 0 for success
 */
static int _bnx2fc_create(struct net_device *netdev,
			  enum fip_mode fip_mode,
			  enum bnx2fc_create_link_state link_state)
{}

/**
 * bnx2fc_create() - Create a bnx2fc 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 bnx2fc_create(struct net_device *netdev, enum fip_mode fip_mode)
{}

/**
 * bnx2fc_ctlr_alloc() - Allocate a bnx2fc 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 bnx2fc_ctlr_alloc(struct net_device *netdev)
{}

/**
 * bnx2fc_find_hba_for_cnic - maps cnic instance to bnx2fc hba instance
 *
 * @cnic:	Pointer to cnic device instance
 *
 **/
static struct bnx2fc_hba *bnx2fc_find_hba_for_cnic(struct cnic_dev *cnic)
{}

static struct bnx2fc_interface *bnx2fc_interface_lookup(struct net_device
							*netdev)
{}

static struct bnx2fc_hba *bnx2fc_hba_lookup(struct net_device
						      *phys_dev)
{}

/**
 * bnx2fc_ulp_exit - shuts down adapter instance and frees all resources
 *
 * @dev:	cnic device handle
 */
static void bnx2fc_ulp_exit(struct cnic_dev *dev)
{}

static void bnx2fc_rport_terminate_io(struct fc_rport *rport)
{}

/**
 * bnx2fc_fcoe_reset - Resets the fcoe
 *
 * @shost: shost the reset is from
 *
 * Returns: always 0
 */
static int bnx2fc_fcoe_reset(struct Scsi_Host *shost)
{}


static bool bnx2fc_match(struct net_device *netdev)
{}


static struct fcoe_transport bnx2fc_transport =;

/**
 * bnx2fc_cpu_online - Create a receive thread for an  online CPU
 *
 * @cpu: cpu index for the online cpu
 */
static int bnx2fc_cpu_online(unsigned int cpu)
{}

static int bnx2fc_cpu_offline(unsigned int cpu)
{}

static int bnx2fc_slave_configure(struct scsi_device *sdev)
{}

static enum cpuhp_state bnx2fc_online_state;

/**
 * bnx2fc_mod_init - module init entry point
 *
 * Initialize driver wide global data structures, and register
 * with cnic module
 **/
static int __init bnx2fc_mod_init(void)
{}

static void __exit bnx2fc_mod_exit(void)
{}

module_init();
module_exit(bnx2fc_mod_exit);

static struct fcoe_sysfs_function_template bnx2fc_fcoe_sysfs_templ =;

static struct fc_function_template bnx2fc_transport_function =;

static struct fc_function_template bnx2fc_vport_xport_function =;

/*
 * Additional scsi_host attributes.
 */
static ssize_t
bnx2fc_tm_timeout_show(struct device *dev, struct device_attribute *attr,
	char *buf)
{}

static ssize_t
bnx2fc_tm_timeout_store(struct device *dev,
	struct device_attribute *attr, const char *buf, size_t count)
{}

static DEVICE_ATTR(tm_timeout, S_IRUGO|S_IWUSR, bnx2fc_tm_timeout_show,
	bnx2fc_tm_timeout_store);

static struct attribute *bnx2fc_host_attrs[] =;

ATTRIBUTE_GROUPS();

/*
 * scsi_host_template structure used while registering with SCSI-ml
 */
static struct scsi_host_template bnx2fc_shost_template =;

static struct libfc_function_template bnx2fc_libfc_fcn_templ =;

/*
 * bnx2fc_cnic_cb - global template of bnx2fc - cnic driver interface
 *			structure carrying callback function pointers
 */
static struct cnic_ulp_ops bnx2fc_cnic_cb =;