mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-11 12:28:41 +08:00
FCoE Updates for 3.9
-----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.11 (GNU/Linux) iQIcBAABAgAGBQJRI992AAoJEEajxTw9cn4HCAcQAI0yWjsDYkTZUAN3vcU7Xh83 e1Qt1dAWjY+sFspo54p4ndK7gkBQzBlzIPf1MdcTQOSBWSA2QYnvukpZuRm99OjH /60xky0TgGtvGUbNgCRG9zhrPQ+/rTvuenZrZa9ibWeIMM8RgyWBV76REDyetd3b K6q2Cz75MKDZwgwJpp7FPF7SJYQVgVbhbVJFIvN5rtS2xEUZI7Ltj/stW0QoJfkD R1XAlGCJETV+pzG0VY7aycxCGhN3HM7QYiA1EiKCfBkLzfFosf+oozWTgIkLm1PE UKO8b6RNR0d7BHXBkIgP0C18Wx9BrLWS5woNoiDANBK3FTJIgL/D32tiJJXhLFGP zzY4OXDT0OEUsn1oc8ldI5/LqALdvDJGzUBbiA1wTiXsJyHVAsBajJc3pP9btnom Z91xB4nRLQx/doJqaKOZiQJRCSeG7b/lQM06jOEHFAO7Ah9sRSqbelHd1+tmSV6J NfDhkZsi5rPZ9My23J5Nkcfy4Vi8hpyqNC0KZR7PTUYJwi1LrTKRSTkek53b5K3O Ee7ZtQ1cY3v90QuG2bNieWaLUKINX/nTKF5DIKH1l9dfxmcpHystPpjRZ06D5wUY vsH+9wNAq0v6+tAT8yvoc5qrZb2OEO/xkgCNIN8c5pNGiw0hjeXzhg5bZBGjNmGK ixtSPIR5QoaU1XFq62JH =r8PC -----END PGP SIGNATURE----- [SCSI] Merge tag 'fcoe-02-19-13' into for-linus FCoE Updates for 3.9 Signed-off-by: James Bottomley <JBottomley@Parallels.com>
This commit is contained in:
commit
3e34c1fc2b
@ -1,14 +1,53 @@
|
||||
What: /sys/bus/fcoe/ctlr_X
|
||||
What: /sys/bus/fcoe/
|
||||
Date: August 2012
|
||||
KernelVersion: TBD
|
||||
Contact: Robert Love <robert.w.love@intel.com>, devel@open-fcoe.org
|
||||
Description: The FCoE bus. Attributes in this directory are control interfaces.
|
||||
Attributes:
|
||||
|
||||
ctlr_create: 'FCoE Controller' instance creation interface. Writing an
|
||||
<ifname> to this file will allocate and populate sysfs with a
|
||||
fcoe_ctlr_device (ctlr_X). The user can then configure any
|
||||
per-port settings and finally write to the fcoe_ctlr_device's
|
||||
'start' attribute to begin the kernel's discovery and login
|
||||
process.
|
||||
|
||||
ctlr_destroy: 'FCoE Controller' instance removal interface. Writing a
|
||||
fcoe_ctlr_device's sysfs name to this file will log the
|
||||
fcoe_ctlr_device out of the fabric or otherwise connected
|
||||
FCoE devices. It will also free all kernel memory allocated
|
||||
for this fcoe_ctlr_device and any structures associated
|
||||
with it, this includes the scsi_host.
|
||||
|
||||
What: /sys/bus/fcoe/devices/ctlr_X
|
||||
Date: March 2012
|
||||
KernelVersion: TBD
|
||||
Contact: Robert Love <robert.w.love@intel.com>, devel@open-fcoe.org
|
||||
Description: 'FCoE Controller' instances on the fcoe bus
|
||||
Description: 'FCoE Controller' instances on the fcoe bus.
|
||||
The FCoE Controller now has a three stage creation process.
|
||||
1) Write interface name to ctlr_create 2) Configure the FCoE
|
||||
Controller (ctlr_X) 3) Enable the FCoE Controller to begin
|
||||
discovery and login. The FCoE Controller is destroyed by
|
||||
writing it's name, i.e. ctlr_X to the ctlr_delete file.
|
||||
|
||||
Attributes:
|
||||
|
||||
fcf_dev_loss_tmo: Device loss timeout peroid (see below). Changing
|
||||
this value will change the dev_loss_tmo for all
|
||||
FCFs discovered by this controller.
|
||||
|
||||
mode: Display or change the FCoE Controller's mode. Possible
|
||||
modes are 'Fabric' and 'VN2VN'. If a FCoE Controller
|
||||
is started in 'Fabric' mode then FIP FCF discovery is
|
||||
initiated and ultimately a fabric login is attempted.
|
||||
If a FCoE Controller is started in 'VN2VN' mode then
|
||||
FIP VN2VN discovery and login is performed. A FCoE
|
||||
Controller only supports one mode at a time.
|
||||
|
||||
enabled: Whether an FCoE controller is enabled or disabled.
|
||||
0 if disabled, 1 if enabled. Writing either 0 or 1
|
||||
to this file will enable or disable the FCoE controller.
|
||||
|
||||
lesb/link_fail: Link Error Status Block (LESB) link failure count.
|
||||
|
||||
lesb/vlink_fail: Link Error Status Block (LESB) virtual link
|
||||
@ -26,7 +65,7 @@ Attributes:
|
||||
|
||||
Notes: ctlr_X (global increment starting at 0)
|
||||
|
||||
What: /sys/bus/fcoe/fcf_X
|
||||
What: /sys/bus/fcoe/devices/fcf_X
|
||||
Date: March 2012
|
||||
KernelVersion: TBD
|
||||
Contact: Robert Love <robert.w.love@intel.com>, devel@open-fcoe.org
|
||||
|
@ -62,6 +62,10 @@ 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);
|
||||
@ -89,7 +93,6 @@ 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);
|
||||
static void bnx2fc_ctlr_get_lesb(struct fcoe_ctlr_device *ctlr_dev);
|
||||
|
||||
unsigned int bnx2fc_debug_level;
|
||||
module_param_named(debug_logging, bnx2fc_debug_level, int, S_IRUGO|S_IWUSR);
|
||||
@ -107,44 +110,6 @@ static inline struct net_device *bnx2fc_netdev(const struct fc_lport *lport)
|
||||
((struct fcoe_port *)lport_priv(lport))->priv)->netdev;
|
||||
}
|
||||
|
||||
/**
|
||||
* bnx2fc_get_lesb() - Fill the FCoE Link Error Status Block
|
||||
* @lport: the local port
|
||||
* @fc_lesb: the link error status block
|
||||
*/
|
||||
static void bnx2fc_get_lesb(struct fc_lport *lport,
|
||||
struct fc_els_lesb *fc_lesb)
|
||||
{
|
||||
struct net_device *netdev = bnx2fc_netdev(lport);
|
||||
|
||||
__fcoe_get_lesb(lport, fc_lesb, netdev);
|
||||
}
|
||||
|
||||
static void bnx2fc_ctlr_get_lesb(struct fcoe_ctlr_device *ctlr_dev)
|
||||
{
|
||||
struct fcoe_ctlr *fip = fcoe_ctlr_device_priv(ctlr_dev);
|
||||
struct net_device *netdev = bnx2fc_netdev(fip->lp);
|
||||
struct fcoe_fc_els_lesb *fcoe_lesb;
|
||||
struct fc_els_lesb fc_lesb;
|
||||
|
||||
__fcoe_get_lesb(fip->lp, &fc_lesb, netdev);
|
||||
fcoe_lesb = (struct fcoe_fc_els_lesb *)(&fc_lesb);
|
||||
|
||||
ctlr_dev->lesb.lesb_link_fail =
|
||||
ntohl(fcoe_lesb->lesb_link_fail);
|
||||
ctlr_dev->lesb.lesb_vlink_fail =
|
||||
ntohl(fcoe_lesb->lesb_vlink_fail);
|
||||
ctlr_dev->lesb.lesb_miss_fka =
|
||||
ntohl(fcoe_lesb->lesb_miss_fka);
|
||||
ctlr_dev->lesb.lesb_symb_err =
|
||||
ntohl(fcoe_lesb->lesb_symb_err);
|
||||
ctlr_dev->lesb.lesb_err_block =
|
||||
ntohl(fcoe_lesb->lesb_err_block);
|
||||
ctlr_dev->lesb.lesb_fcs_error =
|
||||
ntohl(fcoe_lesb->lesb_fcs_error);
|
||||
}
|
||||
EXPORT_SYMBOL(bnx2fc_ctlr_get_lesb);
|
||||
|
||||
static void bnx2fc_fcf_get_vlan_id(struct fcoe_fcf_device *fcf_dev)
|
||||
{
|
||||
struct fcoe_ctlr_device *ctlr_dev =
|
||||
@ -741,35 +706,6 @@ static int bnx2fc_shost_config(struct fc_lport *lport, struct device *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void bnx2fc_link_speed_update(struct fc_lport *lport)
|
||||
{
|
||||
struct fcoe_port *port = lport_priv(lport);
|
||||
struct bnx2fc_interface *interface = port->priv;
|
||||
struct net_device *netdev = interface->netdev;
|
||||
struct ethtool_cmd ecmd;
|
||||
|
||||
if (!__ethtool_get_settings(netdev, &ecmd)) {
|
||||
lport->link_supported_speeds &=
|
||||
~(FC_PORTSPEED_1GBIT | FC_PORTSPEED_10GBIT);
|
||||
if (ecmd.supported & (SUPPORTED_1000baseT_Half |
|
||||
SUPPORTED_1000baseT_Full))
|
||||
lport->link_supported_speeds |= FC_PORTSPEED_1GBIT;
|
||||
if (ecmd.supported & SUPPORTED_10000baseT_Full)
|
||||
lport->link_supported_speeds |= FC_PORTSPEED_10GBIT;
|
||||
|
||||
switch (ethtool_cmd_speed(&ecmd)) {
|
||||
case SPEED_1000:
|
||||
lport->link_speed = FC_PORTSPEED_1GBIT;
|
||||
break;
|
||||
case SPEED_2500:
|
||||
lport->link_speed = FC_PORTSPEED_2GBIT;
|
||||
break;
|
||||
case SPEED_10000:
|
||||
lport->link_speed = FC_PORTSPEED_10GBIT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
static int bnx2fc_link_ok(struct fc_lport *lport)
|
||||
{
|
||||
struct fcoe_port *port = lport_priv(lport);
|
||||
@ -827,7 +763,7 @@ static int bnx2fc_net_config(struct fc_lport *lport, struct net_device *netdev)
|
||||
port->fcoe_pending_queue_active = 0;
|
||||
setup_timer(&port->timer, fcoe_queue_timer, (unsigned long) lport);
|
||||
|
||||
bnx2fc_link_speed_update(lport);
|
||||
fcoe_link_speed_update(lport);
|
||||
|
||||
if (!lport->vport) {
|
||||
if (fcoe_get_wwn(netdev, &wwnn, NETDEV_FCOE_WWNN))
|
||||
@ -871,6 +807,7 @@ static void bnx2fc_indicate_netevent(void *context, unsigned long event,
|
||||
u16 vlan_id)
|
||||
{
|
||||
struct bnx2fc_hba *hba = (struct bnx2fc_hba *)context;
|
||||
struct fcoe_ctlr_device *cdev;
|
||||
struct fc_lport *lport;
|
||||
struct fc_lport *vport;
|
||||
struct bnx2fc_interface *interface, *tmp;
|
||||
@ -930,30 +867,47 @@ static void bnx2fc_indicate_netevent(void *context, unsigned long event,
|
||||
BNX2FC_HBA_DBG(lport, "netevent handler - event=%s %ld\n",
|
||||
interface->netdev->name, event);
|
||||
|
||||
bnx2fc_link_speed_update(lport);
|
||||
fcoe_link_speed_update(lport);
|
||||
|
||||
cdev = fcoe_ctlr_to_ctlr_dev(ctlr);
|
||||
|
||||
if (link_possible && !bnx2fc_link_ok(lport)) {
|
||||
/* Reset max recv frame size to default */
|
||||
fc_set_mfs(lport, BNX2FC_MFS);
|
||||
/*
|
||||
* ctlr link up will only be handled during
|
||||
* enable to avoid sending discovery solicitation
|
||||
* on a stale vlan
|
||||
*/
|
||||
if (interface->enabled)
|
||||
fcoe_ctlr_link_up(ctlr);
|
||||
switch (cdev->enabled) {
|
||||
case FCOE_CTLR_DISABLED:
|
||||
pr_info("Link up while interface is disabled.\n");
|
||||
break;
|
||||
case FCOE_CTLR_ENABLED:
|
||||
case FCOE_CTLR_UNUSED:
|
||||
/* Reset max recv frame size to default */
|
||||
fc_set_mfs(lport, BNX2FC_MFS);
|
||||
/*
|
||||
* ctlr link up will only be handled during
|
||||
* enable to avoid sending discovery
|
||||
* solicitation on a stale vlan
|
||||
*/
|
||||
if (interface->enabled)
|
||||
fcoe_ctlr_link_up(ctlr);
|
||||
};
|
||||
} else if (fcoe_ctlr_link_down(ctlr)) {
|
||||
mutex_lock(&lport->lp_mutex);
|
||||
list_for_each_entry(vport, &lport->vports, list)
|
||||
fc_host_port_type(vport->host) =
|
||||
FC_PORTTYPE_UNKNOWN;
|
||||
mutex_unlock(&lport->lp_mutex);
|
||||
fc_host_port_type(lport->host) = FC_PORTTYPE_UNKNOWN;
|
||||
per_cpu_ptr(lport->stats,
|
||||
get_cpu())->LinkFailureCount++;
|
||||
put_cpu();
|
||||
fcoe_clean_pending_queue(lport);
|
||||
wait_for_upload = 1;
|
||||
switch (cdev->enabled) {
|
||||
case FCOE_CTLR_DISABLED:
|
||||
pr_info("Link down while interface is disabled.\n");
|
||||
break;
|
||||
case FCOE_CTLR_ENABLED:
|
||||
case FCOE_CTLR_UNUSED:
|
||||
mutex_lock(&lport->lp_mutex);
|
||||
list_for_each_entry(vport, &lport->vports, list)
|
||||
fc_host_port_type(vport->host) =
|
||||
FC_PORTTYPE_UNKNOWN;
|
||||
mutex_unlock(&lport->lp_mutex);
|
||||
fc_host_port_type(lport->host) =
|
||||
FC_PORTTYPE_UNKNOWN;
|
||||
per_cpu_ptr(lport->stats,
|
||||
get_cpu())->LinkFailureCount++;
|
||||
put_cpu();
|
||||
fcoe_clean_pending_queue(lport);
|
||||
wait_for_upload = 1;
|
||||
};
|
||||
}
|
||||
}
|
||||
mutex_unlock(&bnx2fc_dev_lock);
|
||||
@ -1484,6 +1438,7 @@ static struct fc_lport *bnx2fc_if_create(struct bnx2fc_interface *interface,
|
||||
port = lport_priv(lport);
|
||||
port->lport = lport;
|
||||
port->priv = interface;
|
||||
port->get_netdev = bnx2fc_netdev;
|
||||
INIT_WORK(&port->destroy_work, bnx2fc_destroy_work);
|
||||
|
||||
/* Configure fcoe_port */
|
||||
@ -2003,7 +1958,9 @@ static void bnx2fc_ulp_init(struct cnic_dev *dev)
|
||||
set_bit(BNX2FC_CNIC_REGISTERED, &hba->reg_with_cnic);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Deperecated: Use bnx2fc_enabled()
|
||||
*/
|
||||
static int bnx2fc_disable(struct net_device *netdev)
|
||||
{
|
||||
struct bnx2fc_interface *interface;
|
||||
@ -2029,7 +1986,9 @@ static int bnx2fc_disable(struct net_device *netdev)
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Deprecated: Use bnx2fc_enabled()
|
||||
*/
|
||||
static int bnx2fc_enable(struct net_device *netdev)
|
||||
{
|
||||
struct bnx2fc_interface *interface;
|
||||
@ -2055,17 +2014,57 @@ static int bnx2fc_enable(struct net_device *netdev)
|
||||
}
|
||||
|
||||
/**
|
||||
* bnx2fc_create - Create bnx2fc FCoE interface
|
||||
* bnx2fc_ctlr_enabled() - Enable or disable an FCoE Controller
|
||||
* @cdev: The FCoE Controller that is being enabled or disabled
|
||||
*
|
||||
* @buffer: The name of Ethernet interface to create on
|
||||
* @kp: The associated kernel param
|
||||
* 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)
|
||||
{
|
||||
struct fcoe_ctlr *ctlr = fcoe_ctlr_device_priv(cdev);
|
||||
struct fc_lport *lport = ctlr->lp;
|
||||
struct net_device *netdev = bnx2fc_netdev(lport);
|
||||
|
||||
switch (cdev->enabled) {
|
||||
case FCOE_CTLR_ENABLED:
|
||||
return bnx2fc_enable(netdev);
|
||||
case FCOE_CTLR_DISABLED:
|
||||
return bnx2fc_disable(netdev);
|
||||
case FCOE_CTLR_UNUSED:
|
||||
default:
|
||||
return -ENOTSUPP;
|
||||
};
|
||||
}
|
||||
|
||||
enum bnx2fc_create_link_state {
|
||||
BNX2FC_CREATE_LINK_DOWN,
|
||||
BNX2FC_CREATE_LINK_UP,
|
||||
};
|
||||
|
||||
/**
|
||||
* _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 sysfs.
|
||||
* 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_state fip_mode)
|
||||
static int _bnx2fc_create(struct net_device *netdev,
|
||||
enum fip_state fip_mode,
|
||||
enum bnx2fc_create_link_state link_state)
|
||||
{
|
||||
struct fcoe_ctlr_device *cdev;
|
||||
struct fcoe_ctlr *ctlr;
|
||||
struct bnx2fc_interface *interface;
|
||||
struct bnx2fc_hba *hba;
|
||||
@ -2160,7 +2159,15 @@ static int bnx2fc_create(struct net_device *netdev, enum fip_state fip_mode)
|
||||
/* Make this master N_port */
|
||||
ctlr->lp = lport;
|
||||
|
||||
if (!bnx2fc_link_ok(lport)) {
|
||||
cdev = fcoe_ctlr_to_ctlr_dev(ctlr);
|
||||
|
||||
if (link_state == BNX2FC_CREATE_LINK_UP)
|
||||
cdev->enabled = FCOE_CTLR_ENABLED;
|
||||
else
|
||||
cdev->enabled = FCOE_CTLR_DISABLED;
|
||||
|
||||
if (link_state == BNX2FC_CREATE_LINK_UP &&
|
||||
!bnx2fc_link_ok(lport)) {
|
||||
fcoe_ctlr_link_up(ctlr);
|
||||
fc_host_port_type(lport->host) = FC_PORTTYPE_NPORT;
|
||||
set_bit(ADAPTER_STATE_READY, &interface->hba->adapter_state);
|
||||
@ -2168,7 +2175,10 @@ static int bnx2fc_create(struct net_device *netdev, enum fip_state fip_mode)
|
||||
|
||||
BNX2FC_HBA_DBG(lport, "create: START DISC\n");
|
||||
bnx2fc_start_disc(interface);
|
||||
interface->enabled = true;
|
||||
|
||||
if (link_state == BNX2FC_CREATE_LINK_UP)
|
||||
interface->enabled = true;
|
||||
|
||||
/*
|
||||
* Release from kref_init in bnx2fc_interface_setup, on success
|
||||
* lport should be holding a reference taken in bnx2fc_if_create
|
||||
@ -2193,6 +2203,37 @@ mod_err:
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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_state fip_mode)
|
||||
{
|
||||
return _bnx2fc_create(netdev, fip_mode, BNX2FC_CREATE_LINK_UP);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
return _bnx2fc_create(netdev, FIP_MODE_FABRIC,
|
||||
BNX2FC_CREATE_LINK_DOWN);
|
||||
}
|
||||
|
||||
/**
|
||||
* bnx2fc_find_hba_for_cnic - maps cnic instance to bnx2fc hba instance
|
||||
*
|
||||
@ -2318,6 +2359,7 @@ static struct fcoe_transport bnx2fc_transport = {
|
||||
.name = {"bnx2fc"},
|
||||
.attached = false,
|
||||
.list = LIST_HEAD_INIT(bnx2fc_transport.list),
|
||||
.alloc = bnx2fc_ctlr_alloc,
|
||||
.match = bnx2fc_match,
|
||||
.create = bnx2fc_create,
|
||||
.destroy = bnx2fc_destroy,
|
||||
@ -2562,13 +2604,13 @@ module_init(bnx2fc_mod_init);
|
||||
module_exit(bnx2fc_mod_exit);
|
||||
|
||||
static struct fcoe_sysfs_function_template bnx2fc_fcoe_sysfs_templ = {
|
||||
.get_fcoe_ctlr_mode = fcoe_ctlr_get_fip_mode,
|
||||
.get_fcoe_ctlr_link_fail = bnx2fc_ctlr_get_lesb,
|
||||
.get_fcoe_ctlr_vlink_fail = bnx2fc_ctlr_get_lesb,
|
||||
.get_fcoe_ctlr_miss_fka = bnx2fc_ctlr_get_lesb,
|
||||
.get_fcoe_ctlr_symb_err = bnx2fc_ctlr_get_lesb,
|
||||
.get_fcoe_ctlr_err_block = bnx2fc_ctlr_get_lesb,
|
||||
.get_fcoe_ctlr_fcs_error = bnx2fc_ctlr_get_lesb,
|
||||
.set_fcoe_ctlr_enabled = bnx2fc_ctlr_enabled,
|
||||
.get_fcoe_ctlr_link_fail = fcoe_ctlr_get_lesb,
|
||||
.get_fcoe_ctlr_vlink_fail = fcoe_ctlr_get_lesb,
|
||||
.get_fcoe_ctlr_miss_fka = fcoe_ctlr_get_lesb,
|
||||
.get_fcoe_ctlr_symb_err = fcoe_ctlr_get_lesb,
|
||||
.get_fcoe_ctlr_err_block = fcoe_ctlr_get_lesb,
|
||||
.get_fcoe_ctlr_fcs_error = fcoe_ctlr_get_lesb,
|
||||
|
||||
.get_fcoe_fcf_selected = fcoe_fcf_get_selected,
|
||||
.get_fcoe_fcf_vlan_id = bnx2fc_fcf_get_vlan_id,
|
||||
@ -2675,7 +2717,7 @@ static struct libfc_function_template bnx2fc_libfc_fcn_templ = {
|
||||
.elsct_send = bnx2fc_elsct_send,
|
||||
.fcp_abort_io = bnx2fc_abort_io,
|
||||
.fcp_cleanup = bnx2fc_cleanup,
|
||||
.get_lesb = bnx2fc_get_lesb,
|
||||
.get_lesb = fcoe_get_lesb,
|
||||
.rport_event_callback = bnx2fc_rport_event_handler,
|
||||
};
|
||||
|
||||
|
@ -82,11 +82,11 @@ static int fcoe_rcv(struct sk_buff *, struct net_device *,
|
||||
struct packet_type *, struct net_device *);
|
||||
static int fcoe_percpu_receive_thread(void *);
|
||||
static void fcoe_percpu_clean(struct fc_lport *);
|
||||
static int fcoe_link_speed_update(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);
|
||||
@ -117,6 +117,11 @@ 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 struct fc_seq *fcoe_elsct_send(struct fc_lport *,
|
||||
u32 did, struct fc_frame *,
|
||||
unsigned int op,
|
||||
@ -126,8 +131,6 @@ static struct fc_seq *fcoe_elsct_send(struct fc_lport *,
|
||||
void *, u32 timeout);
|
||||
static void fcoe_recv_frame(struct sk_buff *skb);
|
||||
|
||||
static void fcoe_get_lesb(struct fc_lport *, struct fc_els_lesb *);
|
||||
|
||||
/* notification function for packets from net device */
|
||||
static struct notifier_block fcoe_notifier = {
|
||||
.notifier_call = fcoe_device_notification,
|
||||
@ -151,11 +154,11 @@ 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_ctlr_get_lesb(struct fcoe_ctlr_device *);
|
||||
static void fcoe_fcf_get_vlan_id(struct fcoe_fcf_device *);
|
||||
|
||||
static struct fcoe_sysfs_function_template fcoe_sysfs_templ = {
|
||||
.get_fcoe_ctlr_mode = fcoe_ctlr_get_fip_mode,
|
||||
.set_fcoe_ctlr_mode = fcoe_ctlr_set_fip_mode,
|
||||
.set_fcoe_ctlr_enabled = fcoe_ctlr_enabled,
|
||||
.get_fcoe_ctlr_link_fail = fcoe_ctlr_get_lesb,
|
||||
.get_fcoe_ctlr_vlink_fail = fcoe_ctlr_get_lesb,
|
||||
.get_fcoe_ctlr_miss_fka = fcoe_ctlr_get_lesb,
|
||||
@ -1112,10 +1115,17 @@ static struct fc_lport *fcoe_if_create(struct fcoe_interface *fcoe,
|
||||
port = lport_priv(lport);
|
||||
port->lport = lport;
|
||||
port->priv = fcoe;
|
||||
port->get_netdev = fcoe_netdev;
|
||||
port->max_queue_depth = FCOE_MAX_QUEUE_DEPTH;
|
||||
port->min_queue_depth = FCOE_MIN_QUEUE_DEPTH;
|
||||
INIT_WORK(&port->destroy_work, fcoe_destroy_work);
|
||||
|
||||
/*
|
||||
* Need to add the lport to the hostlist
|
||||
* so we catch NETDEV_CHANGE events.
|
||||
*/
|
||||
fcoe_hostlist_add(lport);
|
||||
|
||||
/* configure a fc_lport including the exchange manager */
|
||||
rc = fcoe_lport_config(lport);
|
||||
if (rc) {
|
||||
@ -1187,6 +1197,7 @@ static struct fc_lport *fcoe_if_create(struct fcoe_interface *fcoe,
|
||||
out_lp_destroy:
|
||||
fc_exch_mgr_free(lport);
|
||||
out_host_put:
|
||||
fcoe_hostlist_del(lport);
|
||||
scsi_host_put(lport->host);
|
||||
out:
|
||||
return ERR_PTR(rc);
|
||||
@ -1964,6 +1975,7 @@ static int fcoe_dcb_app_notification(struct notifier_block *notifier,
|
||||
static int fcoe_device_notification(struct notifier_block *notifier,
|
||||
ulong event, void *ptr)
|
||||
{
|
||||
struct fcoe_ctlr_device *cdev;
|
||||
struct fc_lport *lport = NULL;
|
||||
struct net_device *netdev = ptr;
|
||||
struct fcoe_ctlr *ctlr;
|
||||
@ -2020,13 +2032,29 @@ static int fcoe_device_notification(struct notifier_block *notifier,
|
||||
|
||||
fcoe_link_speed_update(lport);
|
||||
|
||||
if (link_possible && !fcoe_link_ok(lport))
|
||||
fcoe_ctlr_link_up(ctlr);
|
||||
else if (fcoe_ctlr_link_down(ctlr)) {
|
||||
stats = per_cpu_ptr(lport->stats, get_cpu());
|
||||
stats->LinkFailureCount++;
|
||||
put_cpu();
|
||||
fcoe_clean_pending_queue(lport);
|
||||
cdev = fcoe_ctlr_to_ctlr_dev(ctlr);
|
||||
|
||||
if (link_possible && !fcoe_link_ok(lport)) {
|
||||
switch (cdev->enabled) {
|
||||
case FCOE_CTLR_DISABLED:
|
||||
pr_info("Link up while interface is disabled.\n");
|
||||
break;
|
||||
case FCOE_CTLR_ENABLED:
|
||||
case FCOE_CTLR_UNUSED:
|
||||
fcoe_ctlr_link_up(ctlr);
|
||||
};
|
||||
} else if (fcoe_ctlr_link_down(ctlr)) {
|
||||
switch (cdev->enabled) {
|
||||
case FCOE_CTLR_DISABLED:
|
||||
pr_info("Link down while interface is disabled.\n");
|
||||
break;
|
||||
case FCOE_CTLR_ENABLED:
|
||||
case FCOE_CTLR_UNUSED:
|
||||
stats = per_cpu_ptr(lport->stats, get_cpu());
|
||||
stats->LinkFailureCount++;
|
||||
put_cpu();
|
||||
fcoe_clean_pending_queue(lport);
|
||||
};
|
||||
}
|
||||
out:
|
||||
return rc;
|
||||
@ -2039,6 +2067,8 @@ out:
|
||||
* Called from fcoe transport.
|
||||
*
|
||||
* Returns: 0 for success
|
||||
*
|
||||
* Deprecated: use fcoe_ctlr_enabled()
|
||||
*/
|
||||
static int fcoe_disable(struct net_device *netdev)
|
||||
{
|
||||
@ -2097,6 +2127,33 @@ out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
struct fcoe_ctlr *ctlr = fcoe_ctlr_device_priv(cdev);
|
||||
struct fc_lport *lport = ctlr->lp;
|
||||
struct net_device *netdev = fcoe_netdev(lport);
|
||||
|
||||
switch (cdev->enabled) {
|
||||
case FCOE_CTLR_ENABLED:
|
||||
return fcoe_enable(netdev);
|
||||
case FCOE_CTLR_DISABLED:
|
||||
return fcoe_disable(netdev);
|
||||
case FCOE_CTLR_UNUSED:
|
||||
default:
|
||||
return -ENOTSUPP;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* fcoe_destroy() - Destroy a FCoE interface
|
||||
* @netdev : The net_device object the Ethernet interface to create on
|
||||
@ -2139,8 +2196,31 @@ static void fcoe_destroy_work(struct work_struct *work)
|
||||
{
|
||||
struct fcoe_port *port;
|
||||
struct fcoe_interface *fcoe;
|
||||
struct Scsi_Host *shost;
|
||||
struct fc_host_attrs *fc_host;
|
||||
unsigned long flags;
|
||||
struct fc_vport *vport;
|
||||
struct fc_vport *next_vport;
|
||||
|
||||
port = container_of(work, struct fcoe_port, destroy_work);
|
||||
shost = port->lport->host;
|
||||
fc_host = shost_to_fc_host(shost);
|
||||
|
||||
/* Loop through all the vports and mark them for deletion */
|
||||
spin_lock_irqsave(shost->host_lock, flags);
|
||||
list_for_each_entry_safe(vport, next_vport, &fc_host->vports, peers) {
|
||||
if (vport->flags & (FC_VPORT_DEL | FC_VPORT_CREATING)) {
|
||||
continue;
|
||||
} else {
|
||||
vport->flags |= FC_VPORT_DELETING;
|
||||
queue_work(fc_host_work_q(shost),
|
||||
&vport->vport_delete_work);
|
||||
}
|
||||
}
|
||||
spin_unlock_irqrestore(shost->host_lock, flags);
|
||||
|
||||
flush_workqueue(fc_host_work_q(shost));
|
||||
|
||||
mutex_lock(&fcoe_config_mutex);
|
||||
|
||||
fcoe = port->priv;
|
||||
@ -2204,16 +2284,26 @@ static void fcoe_dcb_create(struct fcoe_interface *fcoe)
|
||||
#endif
|
||||
}
|
||||
|
||||
enum fcoe_create_link_state {
|
||||
FCOE_CREATE_LINK_DOWN,
|
||||
FCOE_CREATE_LINK_UP,
|
||||
};
|
||||
|
||||
/**
|
||||
* 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
|
||||
* _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 fcoe transport
|
||||
* Called from either the libfcoe 'create' module parameter
|
||||
* via fcoe_create or from fcoe_syfs's ctlr_create file.
|
||||
*
|
||||
* Returns: 0 for success
|
||||
* 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_state fip_mode)
|
||||
static int _fcoe_create(struct net_device *netdev, enum fip_state fip_mode,
|
||||
enum fcoe_create_link_state link_state)
|
||||
{
|
||||
int rc = 0;
|
||||
struct fcoe_ctlr_device *ctlr_dev;
|
||||
@ -2254,13 +2344,29 @@ static int fcoe_create(struct net_device *netdev, enum fip_state fip_mode)
|
||||
/* setup DCB priority attributes. */
|
||||
fcoe_dcb_create(fcoe);
|
||||
|
||||
/* add to lports list */
|
||||
fcoe_hostlist_add(lport);
|
||||
|
||||
/* start FIP Discovery and FLOGI */
|
||||
lport->boot_time = jiffies;
|
||||
fc_fabric_login(lport);
|
||||
if (!fcoe_link_ok(lport)) {
|
||||
|
||||
/*
|
||||
* If the fcoe_ctlr_device is to be set to DISABLED
|
||||
* it must be done after the lport is added to the
|
||||
* hostlist, but before the rtnl_lock is released.
|
||||
* This is because the rtnl_lock protects the
|
||||
* hostlist that fcoe_device_notification uses. If
|
||||
* the FCoE Controller is intended to be created
|
||||
* DISABLED then 'enabled' needs to be considered
|
||||
* handling link events. 'enabled' must be set
|
||||
* before the lport can be found in the hostlist
|
||||
* when a link up event is received.
|
||||
*/
|
||||
if (link_state == FCOE_CREATE_LINK_UP)
|
||||
ctlr_dev->enabled = FCOE_CTLR_ENABLED;
|
||||
else
|
||||
ctlr_dev->enabled = FCOE_CTLR_DISABLED;
|
||||
|
||||
if (link_state == FCOE_CREATE_LINK_UP &&
|
||||
!fcoe_link_ok(lport)) {
|
||||
rtnl_unlock();
|
||||
fcoe_ctlr_link_up(ctlr);
|
||||
mutex_unlock(&fcoe_config_mutex);
|
||||
@ -2275,37 +2381,34 @@ out_nortnl:
|
||||
}
|
||||
|
||||
/**
|
||||
* fcoe_link_speed_update() - Update the supported and actual link speeds
|
||||
* @lport: The local port to update speeds for
|
||||
* 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
|
||||
*
|
||||
* Returns: 0 if the ethtool query was successful
|
||||
* -1 if the ethtool query failed
|
||||
* Called from fcoe transport
|
||||
*
|
||||
* Returns: 0 for success
|
||||
*/
|
||||
static int fcoe_link_speed_update(struct fc_lport *lport)
|
||||
static int fcoe_create(struct net_device *netdev, enum fip_state fip_mode)
|
||||
{
|
||||
struct net_device *netdev = fcoe_netdev(lport);
|
||||
struct ethtool_cmd ecmd;
|
||||
return _fcoe_create(netdev, fip_mode, FCOE_CREATE_LINK_UP);
|
||||
}
|
||||
|
||||
if (!__ethtool_get_settings(netdev, &ecmd)) {
|
||||
lport->link_supported_speeds &=
|
||||
~(FC_PORTSPEED_1GBIT | FC_PORTSPEED_10GBIT);
|
||||
if (ecmd.supported & (SUPPORTED_1000baseT_Half |
|
||||
SUPPORTED_1000baseT_Full))
|
||||
lport->link_supported_speeds |= FC_PORTSPEED_1GBIT;
|
||||
if (ecmd.supported & SUPPORTED_10000baseT_Full)
|
||||
lport->link_supported_speeds |=
|
||||
FC_PORTSPEED_10GBIT;
|
||||
switch (ethtool_cmd_speed(&ecmd)) {
|
||||
case SPEED_1000:
|
||||
lport->link_speed = FC_PORTSPEED_1GBIT;
|
||||
break;
|
||||
case SPEED_10000:
|
||||
lport->link_speed = FC_PORTSPEED_10GBIT;
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
return _fcoe_create(netdev, FIP_MODE_FABRIC,
|
||||
FCOE_CREATE_LINK_DOWN);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2375,10 +2478,13 @@ static int fcoe_reset(struct Scsi_Host *shost)
|
||||
struct fcoe_port *port = lport_priv(lport);
|
||||
struct fcoe_interface *fcoe = port->priv;
|
||||
struct fcoe_ctlr *ctlr = fcoe_to_ctlr(fcoe);
|
||||
struct fcoe_ctlr_device *cdev = fcoe_ctlr_to_ctlr_dev(ctlr);
|
||||
|
||||
fcoe_ctlr_link_down(ctlr);
|
||||
fcoe_clean_pending_queue(ctlr->lp);
|
||||
if (!fcoe_link_ok(ctlr->lp))
|
||||
|
||||
if (cdev->enabled != FCOE_CTLR_DISABLED &&
|
||||
!fcoe_link_ok(ctlr->lp))
|
||||
fcoe_ctlr_link_up(ctlr);
|
||||
return 0;
|
||||
}
|
||||
@ -2445,12 +2551,31 @@ static int fcoe_hostlist_add(const struct fc_lport *lport)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
struct fcoe_interface *fcoe;
|
||||
struct fcoe_port *port;
|
||||
|
||||
port = lport_priv(lport);
|
||||
fcoe = port->priv;
|
||||
list_del(&fcoe->list);
|
||||
return;
|
||||
}
|
||||
|
||||
static struct fcoe_transport fcoe_sw_transport = {
|
||||
.name = {FCOE_TRANSPORT_DEFAULT},
|
||||
.attached = false,
|
||||
.list = LIST_HEAD_INIT(fcoe_sw_transport.list),
|
||||
.match = fcoe_match,
|
||||
.alloc = fcoe_ctlr_alloc,
|
||||
.create = fcoe_create,
|
||||
.destroy = fcoe_destroy,
|
||||
.enable = fcoe_enable,
|
||||
@ -2534,9 +2659,9 @@ static void __exit fcoe_exit(void)
|
||||
/* releases the associated fcoe hosts */
|
||||
rtnl_lock();
|
||||
list_for_each_entry_safe(fcoe, tmp, &fcoe_hostlist, list) {
|
||||
list_del(&fcoe->list);
|
||||
ctlr = fcoe_to_ctlr(fcoe);
|
||||
port = lport_priv(ctlr->lp);
|
||||
fcoe_hostlist_del(port->lport);
|
||||
queue_work(fcoe_wq, &port->destroy_work);
|
||||
}
|
||||
rtnl_unlock();
|
||||
@ -2776,43 +2901,6 @@ static void fcoe_set_vport_symbolic_name(struct fc_vport *vport)
|
||||
NULL, NULL, 3 * lport->r_a_tov);
|
||||
}
|
||||
|
||||
/**
|
||||
* fcoe_get_lesb() - Fill the FCoE Link Error Status Block
|
||||
* @lport: the local port
|
||||
* @fc_lesb: the link error status block
|
||||
*/
|
||||
static void fcoe_get_lesb(struct fc_lport *lport,
|
||||
struct fc_els_lesb *fc_lesb)
|
||||
{
|
||||
struct net_device *netdev = fcoe_netdev(lport);
|
||||
|
||||
__fcoe_get_lesb(lport, fc_lesb, netdev);
|
||||
}
|
||||
|
||||
static void fcoe_ctlr_get_lesb(struct fcoe_ctlr_device *ctlr_dev)
|
||||
{
|
||||
struct fcoe_ctlr *fip = fcoe_ctlr_device_priv(ctlr_dev);
|
||||
struct net_device *netdev = fcoe_netdev(fip->lp);
|
||||
struct fcoe_fc_els_lesb *fcoe_lesb;
|
||||
struct fc_els_lesb fc_lesb;
|
||||
|
||||
__fcoe_get_lesb(fip->lp, &fc_lesb, netdev);
|
||||
fcoe_lesb = (struct fcoe_fc_els_lesb *)(&fc_lesb);
|
||||
|
||||
ctlr_dev->lesb.lesb_link_fail =
|
||||
ntohl(fcoe_lesb->lesb_link_fail);
|
||||
ctlr_dev->lesb.lesb_vlink_fail =
|
||||
ntohl(fcoe_lesb->lesb_vlink_fail);
|
||||
ctlr_dev->lesb.lesb_miss_fka =
|
||||
ntohl(fcoe_lesb->lesb_miss_fka);
|
||||
ctlr_dev->lesb.lesb_symb_err =
|
||||
ntohl(fcoe_lesb->lesb_symb_err);
|
||||
ctlr_dev->lesb.lesb_err_block =
|
||||
ntohl(fcoe_lesb->lesb_err_block);
|
||||
ctlr_dev->lesb.lesb_fcs_error =
|
||||
ntohl(fcoe_lesb->lesb_fcs_error);
|
||||
}
|
||||
|
||||
static void fcoe_fcf_get_vlan_id(struct fcoe_fcf_device *fcf_dev)
|
||||
{
|
||||
struct fcoe_ctlr_device *ctlr_dev =
|
||||
|
@ -55,12 +55,12 @@ do { \
|
||||
|
||||
#define FCOE_DBG(fmt, args...) \
|
||||
FCOE_CHECK_LOGGING(FCOE_LOGGING, \
|
||||
printk(KERN_INFO "fcoe: " fmt, ##args);)
|
||||
pr_info("fcoe: " fmt, ##args);)
|
||||
|
||||
#define FCOE_NETDEV_DBG(netdev, fmt, args...) \
|
||||
FCOE_CHECK_LOGGING(FCOE_NETDEV_LOGGING, \
|
||||
printk(KERN_INFO "fcoe: %s: " fmt, \
|
||||
netdev->name, ##args);)
|
||||
pr_info("fcoe: %s: " fmt, \
|
||||
netdev->name, ##args);)
|
||||
|
||||
/**
|
||||
* struct fcoe_interface - A FCoE interface
|
||||
|
@ -1291,8 +1291,16 @@ static void fcoe_ctlr_recv_clr_vlink(struct fcoe_ctlr *fip,
|
||||
|
||||
LIBFCOE_FIP_DBG(fip, "Clear Virtual Link received\n");
|
||||
|
||||
if (!fcf || !lport->port_id)
|
||||
if (!fcf || !lport->port_id) {
|
||||
/*
|
||||
* We are yet to select best FCF, but we got CVL in the
|
||||
* meantime. reset the ctlr and let it rediscover the FCF
|
||||
*/
|
||||
mutex_lock(&fip->ctlr_mutex);
|
||||
fcoe_ctlr_reset(fip);
|
||||
mutex_unlock(&fip->ctlr_mutex);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* mask of required descriptors. Validating each one clears its bit.
|
||||
@ -1551,15 +1559,6 @@ static struct fcoe_fcf *fcoe_ctlr_select(struct fcoe_ctlr *fip)
|
||||
fcf->fabric_name, fcf->vfid, fcf->fcf_mac,
|
||||
fcf->fc_map, fcoe_ctlr_mtu_valid(fcf),
|
||||
fcf->flogi_sent, fcf->pri);
|
||||
if (fcf->fabric_name != first->fabric_name ||
|
||||
fcf->vfid != first->vfid ||
|
||||
fcf->fc_map != first->fc_map) {
|
||||
LIBFCOE_FIP_DBG(fip, "Conflicting fabric, VFID, "
|
||||
"or FC-MAP\n");
|
||||
return NULL;
|
||||
}
|
||||
if (fcf->flogi_sent)
|
||||
continue;
|
||||
if (!fcoe_ctlr_fcf_usable(fcf)) {
|
||||
LIBFCOE_FIP_DBG(fip, "FCF for fab %16.16llx "
|
||||
"map %x %svalid %savailable\n",
|
||||
@ -1569,6 +1568,15 @@ static struct fcoe_fcf *fcoe_ctlr_select(struct fcoe_ctlr *fip)
|
||||
"" : "un");
|
||||
continue;
|
||||
}
|
||||
if (fcf->fabric_name != first->fabric_name ||
|
||||
fcf->vfid != first->vfid ||
|
||||
fcf->fc_map != first->fc_map) {
|
||||
LIBFCOE_FIP_DBG(fip, "Conflicting fabric, VFID, "
|
||||
"or FC-MAP\n");
|
||||
return NULL;
|
||||
}
|
||||
if (fcf->flogi_sent)
|
||||
continue;
|
||||
if (!best || fcf->pri < best->pri || best->flogi_sent)
|
||||
best = fcf;
|
||||
}
|
||||
@ -2864,22 +2872,21 @@ void fcoe_fcf_get_selected(struct fcoe_fcf_device *fcf_dev)
|
||||
}
|
||||
EXPORT_SYMBOL(fcoe_fcf_get_selected);
|
||||
|
||||
void fcoe_ctlr_get_fip_mode(struct fcoe_ctlr_device *ctlr_dev)
|
||||
void fcoe_ctlr_set_fip_mode(struct fcoe_ctlr_device *ctlr_dev)
|
||||
{
|
||||
struct fcoe_ctlr *ctlr = fcoe_ctlr_device_priv(ctlr_dev);
|
||||
|
||||
mutex_lock(&ctlr->ctlr_mutex);
|
||||
switch (ctlr->mode) {
|
||||
case FIP_MODE_FABRIC:
|
||||
ctlr_dev->mode = FIP_CONN_TYPE_FABRIC;
|
||||
break;
|
||||
case FIP_MODE_VN2VN:
|
||||
ctlr_dev->mode = FIP_CONN_TYPE_VN2VN;
|
||||
switch (ctlr_dev->mode) {
|
||||
case FIP_CONN_TYPE_VN2VN:
|
||||
ctlr->mode = FIP_MODE_VN2VN;
|
||||
break;
|
||||
case FIP_CONN_TYPE_FABRIC:
|
||||
default:
|
||||
ctlr_dev->mode = FIP_CONN_TYPE_UNKNOWN;
|
||||
ctlr->mode = FIP_MODE_FABRIC;
|
||||
break;
|
||||
}
|
||||
|
||||
mutex_unlock(&ctlr->ctlr_mutex);
|
||||
}
|
||||
EXPORT_SYMBOL(fcoe_ctlr_get_fip_mode);
|
||||
EXPORT_SYMBOL(fcoe_ctlr_set_fip_mode);
|
||||
|
@ -21,8 +21,17 @@
|
||||
#include <linux/types.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/ctype.h>
|
||||
|
||||
#include <scsi/fcoe_sysfs.h>
|
||||
#include <scsi/libfcoe.h>
|
||||
|
||||
/*
|
||||
* OK to include local libfcoe.h for debug_logging, but cannot include
|
||||
* <scsi/libfcoe.h> otherwise non-netdev based fcoe solutions would have
|
||||
* have to include more than fcoe_sysfs.h.
|
||||
*/
|
||||
#include "libfcoe.h"
|
||||
|
||||
static atomic_t ctlr_num;
|
||||
static atomic_t fcf_num;
|
||||
@ -71,6 +80,8 @@ MODULE_PARM_DESC(fcf_dev_loss_tmo,
|
||||
((x)->lesb.lesb_err_block)
|
||||
#define fcoe_ctlr_fcs_error(x) \
|
||||
((x)->lesb.lesb_fcs_error)
|
||||
#define fcoe_ctlr_enabled(x) \
|
||||
((x)->enabled)
|
||||
#define fcoe_fcf_state(x) \
|
||||
((x)->state)
|
||||
#define fcoe_fcf_fabric_name(x) \
|
||||
@ -210,25 +221,34 @@ static ssize_t show_fcoe_fcf_device_##field(struct device *dev, \
|
||||
#define fcoe_enum_name_search(title, table_type, table) \
|
||||
static const char *get_fcoe_##title##_name(enum table_type table_key) \
|
||||
{ \
|
||||
int i; \
|
||||
char *name = NULL; \
|
||||
\
|
||||
for (i = 0; i < ARRAY_SIZE(table); i++) { \
|
||||
if (table[i].value == table_key) { \
|
||||
name = table[i].name; \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
return name; \
|
||||
if (table_key < 0 || table_key >= ARRAY_SIZE(table)) \
|
||||
return NULL; \
|
||||
return table[table_key]; \
|
||||
}
|
||||
|
||||
static struct {
|
||||
enum fcf_state value;
|
||||
char *name;
|
||||
} fcf_state_names[] = {
|
||||
{ FCOE_FCF_STATE_UNKNOWN, "Unknown" },
|
||||
{ FCOE_FCF_STATE_DISCONNECTED, "Disconnected" },
|
||||
{ FCOE_FCF_STATE_CONNECTED, "Connected" },
|
||||
static char *fip_conn_type_names[] = {
|
||||
[ FIP_CONN_TYPE_UNKNOWN ] = "Unknown",
|
||||
[ FIP_CONN_TYPE_FABRIC ] = "Fabric",
|
||||
[ FIP_CONN_TYPE_VN2VN ] = "VN2VN",
|
||||
};
|
||||
fcoe_enum_name_search(ctlr_mode, fip_conn_type, fip_conn_type_names)
|
||||
|
||||
static enum fip_conn_type fcoe_parse_mode(const char *buf)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(fip_conn_type_names); i++) {
|
||||
if (strcasecmp(buf, fip_conn_type_names[i]) == 0)
|
||||
return i;
|
||||
}
|
||||
|
||||
return FIP_CONN_TYPE_UNKNOWN;
|
||||
}
|
||||
|
||||
static char *fcf_state_names[] = {
|
||||
[ FCOE_FCF_STATE_UNKNOWN ] = "Unknown",
|
||||
[ FCOE_FCF_STATE_DISCONNECTED ] = "Disconnected",
|
||||
[ FCOE_FCF_STATE_CONNECTED ] = "Connected",
|
||||
};
|
||||
fcoe_enum_name_search(fcf_state, fcf_state, fcf_state_names)
|
||||
#define FCOE_FCF_STATE_MAX_NAMELEN 50
|
||||
@ -246,17 +266,7 @@ static ssize_t show_fcf_state(struct device *dev,
|
||||
}
|
||||
static FCOE_DEVICE_ATTR(fcf, state, S_IRUGO, show_fcf_state, NULL);
|
||||
|
||||
static struct {
|
||||
enum fip_conn_type value;
|
||||
char *name;
|
||||
} fip_conn_type_names[] = {
|
||||
{ FIP_CONN_TYPE_UNKNOWN, "Unknown" },
|
||||
{ FIP_CONN_TYPE_FABRIC, "Fabric" },
|
||||
{ FIP_CONN_TYPE_VN2VN, "VN2VN" },
|
||||
};
|
||||
fcoe_enum_name_search(ctlr_mode, fip_conn_type, fip_conn_type_names)
|
||||
#define FCOE_CTLR_MODE_MAX_NAMELEN 50
|
||||
|
||||
#define FCOE_MAX_MODENAME_LEN 20
|
||||
static ssize_t show_ctlr_mode(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
@ -264,17 +274,116 @@ static ssize_t show_ctlr_mode(struct device *dev,
|
||||
struct fcoe_ctlr_device *ctlr = dev_to_ctlr(dev);
|
||||
const char *name;
|
||||
|
||||
if (ctlr->f->get_fcoe_ctlr_mode)
|
||||
ctlr->f->get_fcoe_ctlr_mode(ctlr);
|
||||
|
||||
name = get_fcoe_ctlr_mode_name(ctlr->mode);
|
||||
if (!name)
|
||||
return -EINVAL;
|
||||
return snprintf(buf, FCOE_CTLR_MODE_MAX_NAMELEN,
|
||||
return snprintf(buf, FCOE_MAX_MODENAME_LEN,
|
||||
"%s\n", name);
|
||||
}
|
||||
static FCOE_DEVICE_ATTR(ctlr, mode, S_IRUGO,
|
||||
show_ctlr_mode, NULL);
|
||||
|
||||
static ssize_t store_ctlr_mode(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct fcoe_ctlr_device *ctlr = dev_to_ctlr(dev);
|
||||
char mode[FCOE_MAX_MODENAME_LEN + 1];
|
||||
|
||||
if (count > FCOE_MAX_MODENAME_LEN)
|
||||
return -EINVAL;
|
||||
|
||||
strncpy(mode, buf, count);
|
||||
|
||||
if (mode[count - 1] == '\n')
|
||||
mode[count - 1] = '\0';
|
||||
else
|
||||
mode[count] = '\0';
|
||||
|
||||
switch (ctlr->enabled) {
|
||||
case FCOE_CTLR_ENABLED:
|
||||
LIBFCOE_SYSFS_DBG(ctlr, "Cannot change mode when enabled.");
|
||||
return -EBUSY;
|
||||
case FCOE_CTLR_DISABLED:
|
||||
if (!ctlr->f->set_fcoe_ctlr_mode) {
|
||||
LIBFCOE_SYSFS_DBG(ctlr,
|
||||
"Mode change not supported by LLD.");
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
ctlr->mode = fcoe_parse_mode(mode);
|
||||
if (ctlr->mode == FIP_CONN_TYPE_UNKNOWN) {
|
||||
LIBFCOE_SYSFS_DBG(ctlr,
|
||||
"Unknown mode %s provided.", buf);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ctlr->f->set_fcoe_ctlr_mode(ctlr);
|
||||
LIBFCOE_SYSFS_DBG(ctlr, "Mode changed to %s.", buf);
|
||||
|
||||
return count;
|
||||
case FCOE_CTLR_UNUSED:
|
||||
default:
|
||||
LIBFCOE_SYSFS_DBG(ctlr, "Mode change not supported.");
|
||||
return -ENOTSUPP;
|
||||
};
|
||||
}
|
||||
|
||||
static FCOE_DEVICE_ATTR(ctlr, mode, S_IRUGO | S_IWUSR,
|
||||
show_ctlr_mode, store_ctlr_mode);
|
||||
|
||||
static ssize_t store_ctlr_enabled(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct fcoe_ctlr_device *ctlr = dev_to_ctlr(dev);
|
||||
int rc;
|
||||
|
||||
switch (ctlr->enabled) {
|
||||
case FCOE_CTLR_ENABLED:
|
||||
if (*buf == '1')
|
||||
return count;
|
||||
ctlr->enabled = FCOE_CTLR_DISABLED;
|
||||
break;
|
||||
case FCOE_CTLR_DISABLED:
|
||||
if (*buf == '0')
|
||||
return count;
|
||||
ctlr->enabled = FCOE_CTLR_ENABLED;
|
||||
break;
|
||||
case FCOE_CTLR_UNUSED:
|
||||
return -ENOTSUPP;
|
||||
};
|
||||
|
||||
rc = ctlr->f->set_fcoe_ctlr_enabled(ctlr);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static char *ctlr_enabled_state_names[] = {
|
||||
[ FCOE_CTLR_ENABLED ] = "1",
|
||||
[ FCOE_CTLR_DISABLED ] = "0",
|
||||
};
|
||||
fcoe_enum_name_search(ctlr_enabled_state, ctlr_enabled_state,
|
||||
ctlr_enabled_state_names)
|
||||
#define FCOE_CTLR_ENABLED_MAX_NAMELEN 50
|
||||
|
||||
static ssize_t show_ctlr_enabled_state(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct fcoe_ctlr_device *ctlr = dev_to_ctlr(dev);
|
||||
const char *name;
|
||||
|
||||
name = get_fcoe_ctlr_enabled_state_name(ctlr->enabled);
|
||||
if (!name)
|
||||
return -EINVAL;
|
||||
return snprintf(buf, FCOE_CTLR_ENABLED_MAX_NAMELEN,
|
||||
"%s\n", name);
|
||||
}
|
||||
|
||||
static FCOE_DEVICE_ATTR(ctlr, enabled, S_IRUGO | S_IWUSR,
|
||||
show_ctlr_enabled_state,
|
||||
store_ctlr_enabled);
|
||||
|
||||
static ssize_t
|
||||
store_private_fcoe_ctlr_fcf_dev_loss_tmo(struct device *dev,
|
||||
@ -359,6 +468,7 @@ static struct attribute_group fcoe_ctlr_lesb_attr_group = {
|
||||
|
||||
static struct attribute *fcoe_ctlr_attrs[] = {
|
||||
&device_attr_fcoe_ctlr_fcf_dev_loss_tmo.attr,
|
||||
&device_attr_fcoe_ctlr_enabled.attr,
|
||||
&device_attr_fcoe_ctlr_mode.attr,
|
||||
NULL,
|
||||
};
|
||||
@ -443,9 +553,16 @@ struct device_type fcoe_fcf_device_type = {
|
||||
.release = fcoe_fcf_device_release,
|
||||
};
|
||||
|
||||
struct bus_attribute fcoe_bus_attr_group[] = {
|
||||
__ATTR(ctlr_create, S_IWUSR, NULL, fcoe_ctlr_create_store),
|
||||
__ATTR(ctlr_destroy, S_IWUSR, NULL, fcoe_ctlr_destroy_store),
|
||||
__ATTR_NULL
|
||||
};
|
||||
|
||||
struct bus_type fcoe_bus_type = {
|
||||
.name = "fcoe",
|
||||
.match = &fcoe_bus_match,
|
||||
.bus_attrs = fcoe_bus_attr_group,
|
||||
};
|
||||
|
||||
/**
|
||||
@ -566,6 +683,7 @@ struct fcoe_ctlr_device *fcoe_ctlr_device_add(struct device *parent,
|
||||
|
||||
ctlr->id = atomic_inc_return(&ctlr_num) - 1;
|
||||
ctlr->f = f;
|
||||
ctlr->mode = FIP_CONN_TYPE_FABRIC;
|
||||
INIT_LIST_HEAD(&ctlr->fcfs);
|
||||
mutex_init(&ctlr->lock);
|
||||
ctlr->dev.parent = parent;
|
||||
|
@ -83,6 +83,50 @@ static struct notifier_block libfcoe_notifier = {
|
||||
.notifier_call = libfcoe_device_notification,
|
||||
};
|
||||
|
||||
/**
|
||||
* 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 fc_lport *lport)
|
||||
{
|
||||
struct net_device *netdev = fcoe_get_netdev(lport);
|
||||
struct ethtool_cmd ecmd;
|
||||
|
||||
if (!__ethtool_get_settings(netdev, &ecmd)) {
|
||||
lport->link_supported_speeds &=
|
||||
~(FC_PORTSPEED_1GBIT | FC_PORTSPEED_10GBIT);
|
||||
if (ecmd.supported & (SUPPORTED_1000baseT_Half |
|
||||
SUPPORTED_1000baseT_Full))
|
||||
lport->link_supported_speeds |= FC_PORTSPEED_1GBIT;
|
||||
if (ecmd.supported & SUPPORTED_10000baseT_Full)
|
||||
lport->link_supported_speeds |=
|
||||
FC_PORTSPEED_10GBIT;
|
||||
switch (ethtool_cmd_speed(&ecmd)) {
|
||||
case SPEED_1000:
|
||||
lport->link_speed = FC_PORTSPEED_1GBIT;
|
||||
break;
|
||||
case SPEED_10000:
|
||||
lport->link_speed = FC_PORTSPEED_10GBIT;
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(fcoe_link_speed_update);
|
||||
|
||||
/**
|
||||
* __fcoe_get_lesb() - Get the Link Error Status Block (LESB) for a given lport
|
||||
* @lport: The local port to update speeds for
|
||||
* @fc_lesb: Pointer to the LESB to be filled up
|
||||
* @netdev: Pointer to the netdev that is associated with the lport
|
||||
*
|
||||
* Note, the Link Error Status Block (LESB) for FCoE is defined in FC-BB-6
|
||||
* Clause 7.11 in v1.04.
|
||||
*/
|
||||
void __fcoe_get_lesb(struct fc_lport *lport,
|
||||
struct fc_els_lesb *fc_lesb,
|
||||
struct net_device *netdev)
|
||||
@ -112,6 +156,51 @@ void __fcoe_get_lesb(struct fc_lport *lport,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(__fcoe_get_lesb);
|
||||
|
||||
/**
|
||||
* fcoe_get_lesb() - Fill the FCoE Link Error Status Block
|
||||
* @lport: the local port
|
||||
* @fc_lesb: the link error status block
|
||||
*/
|
||||
void fcoe_get_lesb(struct fc_lport *lport,
|
||||
struct fc_els_lesb *fc_lesb)
|
||||
{
|
||||
struct net_device *netdev = fcoe_get_netdev(lport);
|
||||
|
||||
__fcoe_get_lesb(lport, fc_lesb, netdev);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(fcoe_get_lesb);
|
||||
|
||||
/**
|
||||
* fcoe_ctlr_get_lesb() - Get the Link Error Status Block (LESB) for a given
|
||||
* fcoe controller device
|
||||
* @ctlr_dev: The given fcoe controller device
|
||||
*
|
||||
*/
|
||||
void fcoe_ctlr_get_lesb(struct fcoe_ctlr_device *ctlr_dev)
|
||||
{
|
||||
struct fcoe_ctlr *fip = fcoe_ctlr_device_priv(ctlr_dev);
|
||||
struct net_device *netdev = fcoe_get_netdev(fip->lp);
|
||||
struct fcoe_fc_els_lesb *fcoe_lesb;
|
||||
struct fc_els_lesb fc_lesb;
|
||||
|
||||
__fcoe_get_lesb(fip->lp, &fc_lesb, netdev);
|
||||
fcoe_lesb = (struct fcoe_fc_els_lesb *)(&fc_lesb);
|
||||
|
||||
ctlr_dev->lesb.lesb_link_fail =
|
||||
ntohl(fcoe_lesb->lesb_link_fail);
|
||||
ctlr_dev->lesb.lesb_vlink_fail =
|
||||
ntohl(fcoe_lesb->lesb_vlink_fail);
|
||||
ctlr_dev->lesb.lesb_miss_fka =
|
||||
ntohl(fcoe_lesb->lesb_miss_fka);
|
||||
ctlr_dev->lesb.lesb_symb_err =
|
||||
ntohl(fcoe_lesb->lesb_symb_err);
|
||||
ctlr_dev->lesb.lesb_err_block =
|
||||
ntohl(fcoe_lesb->lesb_err_block);
|
||||
ctlr_dev->lesb.lesb_fcs_error =
|
||||
ntohl(fcoe_lesb->lesb_fcs_error);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(fcoe_ctlr_get_lesb);
|
||||
|
||||
void fcoe_wwn_to_str(u64 wwn, char *buf, int len)
|
||||
{
|
||||
u8 wwpn[8];
|
||||
@ -627,6 +716,110 @@ static int libfcoe_device_notification(struct notifier_block *notifier,
|
||||
return NOTIFY_OK;
|
||||
}
|
||||
|
||||
ssize_t fcoe_ctlr_create_store(struct bus_type *bus,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct net_device *netdev = NULL;
|
||||
struct fcoe_transport *ft = NULL;
|
||||
struct fcoe_ctlr_device *ctlr_dev = NULL;
|
||||
int rc = 0;
|
||||
int err;
|
||||
|
||||
mutex_lock(&ft_mutex);
|
||||
|
||||
netdev = fcoe_if_to_netdev(buf);
|
||||
if (!netdev) {
|
||||
LIBFCOE_TRANSPORT_DBG("Invalid device %s.\n", buf);
|
||||
rc = -ENODEV;
|
||||
goto out_nodev;
|
||||
}
|
||||
|
||||
ft = fcoe_netdev_map_lookup(netdev);
|
||||
if (ft) {
|
||||
LIBFCOE_TRANSPORT_DBG("transport %s already has existing "
|
||||
"FCoE instance on %s.\n",
|
||||
ft->name, netdev->name);
|
||||
rc = -EEXIST;
|
||||
goto out_putdev;
|
||||
}
|
||||
|
||||
ft = fcoe_transport_lookup(netdev);
|
||||
if (!ft) {
|
||||
LIBFCOE_TRANSPORT_DBG("no FCoE transport found for %s.\n",
|
||||
netdev->name);
|
||||
rc = -ENODEV;
|
||||
goto out_putdev;
|
||||
}
|
||||
|
||||
/* pass to transport create */
|
||||
err = ft->alloc ? ft->alloc(netdev) : -ENODEV;
|
||||
if (err) {
|
||||
fcoe_del_netdev_mapping(netdev);
|
||||
rc = -ENOMEM;
|
||||
goto out_putdev;
|
||||
}
|
||||
|
||||
err = fcoe_add_netdev_mapping(netdev, ft);
|
||||
if (err) {
|
||||
LIBFCOE_TRANSPORT_DBG("failed to add new netdev mapping "
|
||||
"for FCoE transport %s for %s.\n",
|
||||
ft->name, netdev->name);
|
||||
rc = -ENODEV;
|
||||
goto out_putdev;
|
||||
}
|
||||
|
||||
LIBFCOE_TRANSPORT_DBG("transport %s %s to create fcoe on %s.\n",
|
||||
ft->name, (ctlr_dev) ? "succeeded" : "failed",
|
||||
netdev->name);
|
||||
|
||||
out_putdev:
|
||||
dev_put(netdev);
|
||||
out_nodev:
|
||||
mutex_unlock(&ft_mutex);
|
||||
if (rc)
|
||||
return rc;
|
||||
return count;
|
||||
}
|
||||
|
||||
ssize_t fcoe_ctlr_destroy_store(struct bus_type *bus,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
int rc = -ENODEV;
|
||||
struct net_device *netdev = NULL;
|
||||
struct fcoe_transport *ft = NULL;
|
||||
|
||||
mutex_lock(&ft_mutex);
|
||||
|
||||
netdev = fcoe_if_to_netdev(buf);
|
||||
if (!netdev) {
|
||||
LIBFCOE_TRANSPORT_DBG("invalid device %s.\n", buf);
|
||||
goto out_nodev;
|
||||
}
|
||||
|
||||
ft = fcoe_netdev_map_lookup(netdev);
|
||||
if (!ft) {
|
||||
LIBFCOE_TRANSPORT_DBG("no FCoE transport found for %s.\n",
|
||||
netdev->name);
|
||||
goto out_putdev;
|
||||
}
|
||||
|
||||
/* pass to transport destroy */
|
||||
rc = ft->destroy(netdev);
|
||||
if (rc)
|
||||
goto out_putdev;
|
||||
|
||||
fcoe_del_netdev_mapping(netdev);
|
||||
LIBFCOE_TRANSPORT_DBG("transport %s %s to destroy fcoe on %s.\n",
|
||||
ft->name, (rc) ? "failed" : "succeeded",
|
||||
netdev->name);
|
||||
rc = count; /* required for successful return */
|
||||
out_putdev:
|
||||
dev_put(netdev);
|
||||
out_nodev:
|
||||
mutex_unlock(&ft_mutex);
|
||||
return rc;
|
||||
}
|
||||
EXPORT_SYMBOL(fcoe_ctlr_destroy_store);
|
||||
|
||||
/**
|
||||
* fcoe_transport_create() - Create a fcoe interface
|
||||
@ -769,11 +962,7 @@ out_putdev:
|
||||
dev_put(netdev);
|
||||
out_nodev:
|
||||
mutex_unlock(&ft_mutex);
|
||||
|
||||
if (rc == -ERESTARTSYS)
|
||||
return restart_syscall();
|
||||
else
|
||||
return rc;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2,9 +2,10 @@
|
||||
#define _FCOE_LIBFCOE_H_
|
||||
|
||||
extern unsigned int libfcoe_debug_logging;
|
||||
#define LIBFCOE_LOGGING 0x01 /* General logging, not categorized */
|
||||
#define LIBFCOE_FIP_LOGGING 0x02 /* FIP logging */
|
||||
#define LIBFCOE_TRANSPORT_LOGGING 0x04 /* FCoE transport logging */
|
||||
#define LIBFCOE_LOGGING 0x01 /* General logging, not categorized */
|
||||
#define LIBFCOE_FIP_LOGGING 0x02 /* FIP logging */
|
||||
#define LIBFCOE_TRANSPORT_LOGGING 0x04 /* FCoE transport logging */
|
||||
#define LIBFCOE_SYSFS_LOGGING 0x08 /* fcoe_sysfs logging */
|
||||
|
||||
#define LIBFCOE_CHECK_LOGGING(LEVEL, CMD) \
|
||||
do { \
|
||||
@ -16,16 +17,19 @@ do { \
|
||||
|
||||
#define LIBFCOE_DBG(fmt, args...) \
|
||||
LIBFCOE_CHECK_LOGGING(LIBFCOE_LOGGING, \
|
||||
printk(KERN_INFO "libfcoe: " fmt, ##args);)
|
||||
pr_info("libfcoe: " fmt, ##args);)
|
||||
|
||||
#define LIBFCOE_FIP_DBG(fip, fmt, args...) \
|
||||
LIBFCOE_CHECK_LOGGING(LIBFCOE_FIP_LOGGING, \
|
||||
printk(KERN_INFO "host%d: fip: " fmt, \
|
||||
(fip)->lp->host->host_no, ##args);)
|
||||
pr_info("host%d: fip: " fmt, \
|
||||
(fip)->lp->host->host_no, ##args);)
|
||||
|
||||
#define LIBFCOE_TRANSPORT_DBG(fmt, args...) \
|
||||
LIBFCOE_CHECK_LOGGING(LIBFCOE_TRANSPORT_LOGGING, \
|
||||
printk(KERN_INFO "%s: " fmt, \
|
||||
__func__, ##args);)
|
||||
pr_info("%s: " fmt, __func__, ##args);)
|
||||
|
||||
#define LIBFCOE_SYSFS_DBG(cdev, fmt, args...) \
|
||||
LIBFCOE_CHECK_LOGGING(LIBFCOE_SYSFS_LOGGING, \
|
||||
pr_info("ctlr_%d: " fmt, cdev->id, ##args);)
|
||||
|
||||
#endif /* _FCOE_LIBFCOE_H_ */
|
||||
|
@ -1381,10 +1381,10 @@ static void fc_fcp_timeout(unsigned long data)
|
||||
|
||||
fsp->state |= FC_SRB_FCP_PROCESSING_TMO;
|
||||
|
||||
if (fsp->state & FC_SRB_RCV_STATUS)
|
||||
fc_fcp_complete_locked(fsp);
|
||||
else if (rpriv->flags & FC_RP_FLAGS_REC_SUPPORTED)
|
||||
if (rpriv->flags & FC_RP_FLAGS_REC_SUPPORTED)
|
||||
fc_fcp_rec(fsp);
|
||||
else if (fsp->state & FC_SRB_RCV_STATUS)
|
||||
fc_fcp_complete_locked(fsp);
|
||||
else
|
||||
fc_fcp_recovery(fsp, FC_TIMED_OUT);
|
||||
fsp->state &= ~FC_SRB_FCP_PROCESSING_TMO;
|
||||
|
@ -41,25 +41,25 @@ extern unsigned int fc_debug_logging;
|
||||
|
||||
#define FC_LIBFC_DBG(fmt, args...) \
|
||||
FC_CHECK_LOGGING(FC_LIBFC_LOGGING, \
|
||||
printk(KERN_INFO "libfc: " fmt, ##args))
|
||||
pr_info("libfc: " fmt, ##args))
|
||||
|
||||
#define FC_LPORT_DBG(lport, fmt, args...) \
|
||||
FC_CHECK_LOGGING(FC_LPORT_LOGGING, \
|
||||
printk(KERN_INFO "host%u: lport %6.6x: " fmt, \
|
||||
(lport)->host->host_no, \
|
||||
(lport)->port_id, ##args))
|
||||
pr_info("host%u: lport %6.6x: " fmt, \
|
||||
(lport)->host->host_no, \
|
||||
(lport)->port_id, ##args))
|
||||
|
||||
#define FC_DISC_DBG(disc, fmt, args...) \
|
||||
FC_CHECK_LOGGING(FC_DISC_LOGGING, \
|
||||
printk(KERN_INFO "host%u: disc: " fmt, \
|
||||
fc_disc_lport(disc)->host->host_no, \
|
||||
##args))
|
||||
#define FC_DISC_DBG(disc, fmt, args...) \
|
||||
FC_CHECK_LOGGING(FC_DISC_LOGGING, \
|
||||
pr_info("host%u: disc: " fmt, \
|
||||
fc_disc_lport(disc)->host->host_no, \
|
||||
##args))
|
||||
|
||||
#define FC_RPORT_ID_DBG(lport, port_id, fmt, args...) \
|
||||
FC_CHECK_LOGGING(FC_RPORT_LOGGING, \
|
||||
printk(KERN_INFO "host%u: rport %6.6x: " fmt, \
|
||||
(lport)->host->host_no, \
|
||||
(port_id), ##args))
|
||||
pr_info("host%u: rport %6.6x: " fmt, \
|
||||
(lport)->host->host_no, \
|
||||
(port_id), ##args))
|
||||
|
||||
#define FC_RPORT_DBG(rdata, fmt, args...) \
|
||||
FC_RPORT_ID_DBG((rdata)->local_port, (rdata)->ids.port_id, fmt, ##args)
|
||||
@ -70,13 +70,13 @@ extern unsigned int fc_debug_logging;
|
||||
if ((pkt)->seq_ptr) { \
|
||||
struct fc_exch *_ep = NULL; \
|
||||
_ep = fc_seq_exch((pkt)->seq_ptr); \
|
||||
printk(KERN_INFO "host%u: fcp: %6.6x: " \
|
||||
pr_info("host%u: fcp: %6.6x: " \
|
||||
"xid %04x-%04x: " fmt, \
|
||||
(pkt)->lp->host->host_no, \
|
||||
(pkt)->rport->port_id, \
|
||||
(_ep)->oxid, (_ep)->rxid, ##args); \
|
||||
} else { \
|
||||
printk(KERN_INFO "host%u: fcp: %6.6x: " fmt, \
|
||||
pr_info("host%u: fcp: %6.6x: " fmt, \
|
||||
(pkt)->lp->host->host_no, \
|
||||
(pkt)->rport->port_id, ##args); \
|
||||
} \
|
||||
@ -84,14 +84,14 @@ extern unsigned int fc_debug_logging;
|
||||
|
||||
#define FC_EXCH_DBG(exch, fmt, args...) \
|
||||
FC_CHECK_LOGGING(FC_EXCH_LOGGING, \
|
||||
printk(KERN_INFO "host%u: xid %4x: " fmt, \
|
||||
(exch)->lp->host->host_no, \
|
||||
exch->xid, ##args))
|
||||
pr_info("host%u: xid %4x: " fmt, \
|
||||
(exch)->lp->host->host_no, \
|
||||
exch->xid, ##args))
|
||||
|
||||
#define FC_SCSI_DBG(lport, fmt, args...) \
|
||||
FC_CHECK_LOGGING(FC_SCSI_LOGGING, \
|
||||
printk(KERN_INFO "host%u: scsi: " fmt, \
|
||||
(lport)->host->host_no, ##args))
|
||||
pr_info("host%u: scsi: " fmt, \
|
||||
(lport)->host->host_no, ##args))
|
||||
|
||||
/*
|
||||
* FC-4 Providers.
|
||||
|
@ -582,7 +582,7 @@ static void fc_rport_error(struct fc_rport_priv *rdata, struct fc_frame *fp)
|
||||
static void fc_rport_error_retry(struct fc_rport_priv *rdata,
|
||||
struct fc_frame *fp)
|
||||
{
|
||||
unsigned long delay = FC_DEF_E_D_TOV;
|
||||
unsigned long delay = msecs_to_jiffies(FC_DEF_E_D_TOV);
|
||||
|
||||
/* make sure this isn't an FC_EX_CLOSED error, never retry those */
|
||||
if (PTR_ERR(fp) == -FC_EX_CLOSED)
|
||||
|
@ -1,4 +0,0 @@
|
||||
header-y += fc_els.h
|
||||
header-y += fc_fs.h
|
||||
header-y += fc_gs.h
|
||||
header-y += fc_ns.h
|
@ -34,7 +34,8 @@ struct fcoe_sysfs_function_template {
|
||||
void (*get_fcoe_ctlr_symb_err)(struct fcoe_ctlr_device *);
|
||||
void (*get_fcoe_ctlr_err_block)(struct fcoe_ctlr_device *);
|
||||
void (*get_fcoe_ctlr_fcs_error)(struct fcoe_ctlr_device *);
|
||||
void (*get_fcoe_ctlr_mode)(struct fcoe_ctlr_device *);
|
||||
void (*set_fcoe_ctlr_mode)(struct fcoe_ctlr_device *);
|
||||
int (*set_fcoe_ctlr_enabled)(struct fcoe_ctlr_device *);
|
||||
void (*get_fcoe_fcf_selected)(struct fcoe_fcf_device *);
|
||||
void (*get_fcoe_fcf_vlan_id)(struct fcoe_fcf_device *);
|
||||
};
|
||||
@ -48,6 +49,12 @@ enum fip_conn_type {
|
||||
FIP_CONN_TYPE_VN2VN,
|
||||
};
|
||||
|
||||
enum ctlr_enabled_state {
|
||||
FCOE_CTLR_ENABLED,
|
||||
FCOE_CTLR_DISABLED,
|
||||
FCOE_CTLR_UNUSED,
|
||||
};
|
||||
|
||||
struct fcoe_ctlr_device {
|
||||
u32 id;
|
||||
|
||||
@ -64,6 +71,8 @@ struct fcoe_ctlr_device {
|
||||
int fcf_dev_loss_tmo;
|
||||
enum fip_conn_type mode;
|
||||
|
||||
enum ctlr_enabled_state enabled;
|
||||
|
||||
/* expected in host order for displaying */
|
||||
struct fcoe_fc_els_lesb lesb;
|
||||
};
|
||||
|
@ -260,6 +260,9 @@ void __fcoe_get_lesb(struct fc_lport *lport, struct fc_els_lesb *fc_lesb,
|
||||
struct net_device *netdev);
|
||||
void fcoe_wwn_to_str(u64 wwn, char *buf, int len);
|
||||
int fcoe_validate_vport_create(struct fc_vport *vport);
|
||||
int fcoe_link_speed_update(struct fc_lport *);
|
||||
void fcoe_get_lesb(struct fc_lport *, struct fc_els_lesb *);
|
||||
void fcoe_ctlr_get_lesb(struct fcoe_ctlr_device *ctlr_dev);
|
||||
|
||||
/**
|
||||
* is_fip_mode() - returns true if FIP mode selected.
|
||||
@ -289,8 +292,11 @@ static inline bool is_fip_mode(struct fcoe_ctlr *fip)
|
||||
* @attached: whether this transport is already attached
|
||||
* @list: list linkage to all attached transports
|
||||
* @match: handler to allow the transport driver to match up a given netdev
|
||||
* @alloc: handler to allocate per-instance FCoE structures
|
||||
* (no discovery or login)
|
||||
* @create: handler to sysfs entry of create for FCoE instances
|
||||
* @destroy: handler to sysfs entry of destroy for FCoE instances
|
||||
* @destroy: handler to delete per-instance FCoE structures
|
||||
* (frees all memory)
|
||||
* @enable: handler to sysfs entry of enable for FCoE instances
|
||||
* @disable: handler to sysfs entry of disable for FCoE instances
|
||||
*/
|
||||
@ -299,6 +305,7 @@ struct fcoe_transport {
|
||||
bool attached;
|
||||
struct list_head list;
|
||||
bool (*match) (struct net_device *device);
|
||||
int (*alloc) (struct net_device *device);
|
||||
int (*create) (struct net_device *device, enum fip_state fip_mode);
|
||||
int (*destroy) (struct net_device *device);
|
||||
int (*enable) (struct net_device *device);
|
||||
@ -347,7 +354,20 @@ struct fcoe_port {
|
||||
struct timer_list timer;
|
||||
struct work_struct destroy_work;
|
||||
u8 data_src_addr[ETH_ALEN];
|
||||
struct net_device * (*get_netdev)(const struct fc_lport *lport);
|
||||
};
|
||||
|
||||
/**
|
||||
* fcoe_get_netdev() - Return the net device associated with a local port
|
||||
* @lport: The local port to get the net device from
|
||||
*/
|
||||
static inline struct net_device *fcoe_get_netdev(const struct fc_lport *lport)
|
||||
{
|
||||
struct fcoe_port *port = ((struct fcoe_port *)lport_priv(lport));
|
||||
|
||||
return (port->get_netdev) ? port->get_netdev(lport) : NULL;
|
||||
}
|
||||
|
||||
void fcoe_clean_pending_queue(struct fc_lport *);
|
||||
void fcoe_check_wait_queue(struct fc_lport *lport, struct sk_buff *skb);
|
||||
void fcoe_queue_timer(ulong lport);
|
||||
@ -356,7 +376,7 @@ int fcoe_get_paged_crc_eof(struct sk_buff *skb, int tlen,
|
||||
|
||||
/* FCoE Sysfs helpers */
|
||||
void fcoe_fcf_get_selected(struct fcoe_fcf_device *);
|
||||
void fcoe_ctlr_get_fip_mode(struct fcoe_ctlr_device *);
|
||||
void fcoe_ctlr_set_fip_mode(struct fcoe_ctlr_device *);
|
||||
|
||||
/**
|
||||
* struct netdev_list
|
||||
@ -372,4 +392,12 @@ struct fcoe_netdev_mapping {
|
||||
int fcoe_transport_attach(struct fcoe_transport *ft);
|
||||
int fcoe_transport_detach(struct fcoe_transport *ft);
|
||||
|
||||
/* sysfs store handler for ctrl_control interface */
|
||||
ssize_t fcoe_ctlr_create_store(struct bus_type *bus,
|
||||
const char *buf, size_t count);
|
||||
ssize_t fcoe_ctlr_destroy_store(struct bus_type *bus,
|
||||
const char *buf, size_t count);
|
||||
|
||||
#endif /* _LIBFCOE_H */
|
||||
|
||||
|
||||
|
@ -1 +1,5 @@
|
||||
# UAPI Header export list
|
||||
header-y += fc_els.h
|
||||
header-y += fc_fs.h
|
||||
header-y += fc_gs.h
|
||||
header-y += fc_ns.h
|
||||
|
Loading…
Reference in New Issue
Block a user