// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
*
* Maintained at www.Open-FCoE.org
*/
#include <linux/types.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/netdevice.h>
#include <linux/errno.h>
#include <linux/crc32.h>
#include <scsi/libfcoe.h>
#include "libfcoe.h"
MODULE_AUTHOR("Open-FCoE.org");
MODULE_DESCRIPTION("FIP discovery protocol and FCoE transport for FCoE HBAs");
MODULE_LICENSE("GPL v2");
static int fcoe_transport_create(const char *, const struct kernel_param *);
static int fcoe_transport_destroy(const char *, const struct kernel_param *);
static int fcoe_transport_show(char *buffer, const struct kernel_param *kp);
static struct fcoe_transport *fcoe_transport_lookup(struct net_device *device);
static struct fcoe_transport *fcoe_netdev_map_lookup(struct net_device *device);
static int fcoe_transport_enable(const char *, const struct kernel_param *);
static int fcoe_transport_disable(const char *, const struct kernel_param *);
static int libfcoe_device_notification(struct notifier_block *notifier,
ulong event, void *ptr);
static LIST_HEAD(fcoe_transports);
static DEFINE_MUTEX(ft_mutex);
static LIST_HEAD(fcoe_netdevs);
static DEFINE_MUTEX(fn_mutex);
unsigned int libfcoe_debug_logging;
module_param_named(debug_logging, libfcoe_debug_logging, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(debug_logging, "a bit mask of logging levels");
module_param_call(show, NULL, fcoe_transport_show, NULL, S_IRUSR);
__MODULE_PARM_TYPE(show, "string");
MODULE_PARM_DESC(show, " Show attached FCoE transports");
module_param_call(create, fcoe_transport_create, NULL,
(void *)FIP_MODE_FABRIC, S_IWUSR);
__MODULE_PARM_TYPE(create, "string");
MODULE_PARM_DESC(create, " Creates fcoe instance on an ethernet interface");
module_param_call(create_vn2vn, fcoe_transport_create, NULL,
(void *)FIP_MODE_VN2VN, S_IWUSR);
__MODULE_PARM_TYPE(create_vn2vn, "string");
MODULE_PARM_DESC(create_vn2vn, " Creates a VN_node to VN_node FCoE instance "
"on an Ethernet interface");
module_param_call(destroy, fcoe_transport_destroy, NULL, NULL, S_IWUSR);
__MODULE_PARM_TYPE(destroy, "string");
MODULE_PARM_DESC(destroy, " Destroys fcoe instance on an ethernet interface");
module_param_call(enable, fcoe_transport_enable, NULL, NULL, S_IWUSR);
__MODULE_PARM_TYPE(enable, "string");
MODULE_PARM_DESC(enable, " Enables fcoe on an ethernet interface.");
module_param_call(disable, fcoe_transport_disable, NULL, NULL, S_IWUSR);
__MODULE_PARM_TYPE(disable, "string");
MODULE_PARM_DESC(disable, " Disables fcoe on an ethernet interface.");
/* notification function for packets from net device */
static struct notifier_block libfcoe_notifier = {
.notifier_call = libfcoe_device_notification,
};
static const struct {
u32 fc_port_speed;
#define SPEED_2000 2000
#define SPEED_4000 4000
#define SPEED_8000 8000
#define SPEED_16000 16000
#define SPEED_32000 32000
u32 eth_port_speed;
} fcoe_port_speed_mapping[] = {
{ FC_PORTSPEED_1GBIT, SPEED_1000 },
{ FC_PORTSPEED_2GBIT, SPEED_2000 },
{ FC_PORTSPEED_4GBIT, SPEED_4000 },
{ FC_PORTSPEED_8GBIT, SPEED_8000 },
{ FC_PORTSPEED_10GBIT, SPEED_10000 },
{ FC_PORTSPEED_16GBIT, SPEED_16000 },
{ FC_PORTSPEED_20GBIT, SPEED_20000 },
{ FC_PORTSPEED_25GBIT, SPEED_25000 },
{ FC_PORTSPEED_32GBIT, SPEED_32000 },
{ FC_PORTSPEED_40GBIT, SPEED_40000 },
{ FC_PORTSPEED_50GBIT, SPEED_50000 },
{ FC_PORTSPEED_100GBIT, SPEED_100000 },
};
static inline u32 eth2fc_speed(u32 eth_port_speed)
{
int i;
for (i = 0; i < ARRAY_SIZE(fcoe_port_speed_mapping); i++) {
if (fcoe_port_speed_mapping[i].eth_port_speed == eth_port_speed)
return fcoe_port_speed_mapping[i].fc_port_speed;
}
return FC_PORTSPEED_UNKNOWN;
}
/**
* fcoe_link_speed_update() - Update the supported and actual link speeds
* @lport: The local port to update speeds for
*
* Returns: 0 if the ethtool query was successful
* -1 if the ethtool query failed
*/
int fcoe_link_speed_update(struct