Skip to content

Commit

Permalink
[SCSI] fcoe, bnx2fc, libfcoe: SW FCoE and bnx2fc use FCoE Syfs
Browse files Browse the repository at this point in the history
This patch has the SW FCoE driver and the bnx2fc
driver make use of the new fcoe_sysfs API added
earlier in this patch series.

After this patch a fcoe_ctlr_device is allocated with
private data in this order.

+------------------+   +------------------+
| fcoe_ctlr_device |   | fcoe_ctlr_device |
+------------------+   +------------------+
| fcoe_ctlr        |   | fcoe_ctlr        |
+------------------+   +------------------+
| fcoe_interface   |   | bnx2fc_interface |
+------------------+   +------------------+

libfcoe also takes part in this new model since it
discovers and manages fcoe_fcf instances. The memory
allocation is different for FCFs. I didn't want to
impact libfcoe's fcoe_fcf processing, so this patch
creates fcoe_fcf_device instances for each discovered
fcoe_fcf. The two are paired using a (void * priv)
member of the fcoe_ctlr_device. This allows libfcoe
to continue maintaining its list of fcoe_fcf instances
and simply attaches and detaches them from existing
or new fcoe_fcf_device instances.

Signed-off-by: Robert Love <robert.w.love@intel.com>
Tested-by: Ross Brattain <ross.b.brattain@intel.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
  • Loading branch information
Robert Love authored and James Bottomley committed May 23, 2012
1 parent 9a74e88 commit 8d55e50
Show file tree
Hide file tree
Showing 4 changed files with 285 additions and 25 deletions.
63 changes: 59 additions & 4 deletions drivers/scsi/bnx2fc/bnx2fc_fcoe.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ 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_state fip_mode);
static void __bnx2fc_destroy(struct bnx2fc_interface *interface);
Expand Down Expand Up @@ -88,6 +89,7 @@ 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);
Expand Down Expand Up @@ -118,6 +120,41 @@ static void bnx2fc_get_lesb(struct fc_lport *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 =
fcoe_fcf_dev_to_ctlr_dev(fcf_dev);
struct fcoe_ctlr *ctlr = fcoe_ctlr_device_priv(ctlr_dev);
struct bnx2fc_interface *fcoe = fcoe_ctlr_priv(ctlr);

fcf_dev->vlan_id = fcoe->vlan_id;
}

static void bnx2fc_clean_rx_queue(struct fc_lport *lp)
{
struct fcoe_percpu_s *bg;
Expand Down Expand Up @@ -1235,6 +1272,7 @@ static void bnx2fc_release_transport(void)

static void bnx2fc_interface_release(struct kref *kref)
{
struct fcoe_ctlr_device *ctlr_dev;
struct bnx2fc_interface *interface;
struct fcoe_ctlr *ctlr;
struct net_device *netdev;
Expand All @@ -1243,13 +1281,14 @@ static void bnx2fc_interface_release(struct kref *kref)
BNX2FC_MISC_DBG("Interface is being released\n");

ctlr = bnx2fc_to_ctlr(interface);
ctlr_dev = fcoe_ctlr_to_ctlr_dev(ctlr);
netdev = interface->netdev;

/* tear-down FIP controller */
if (test_and_clear_bit(BNX2FC_CTLR_INIT_DONE, &interface->if_flags))
fcoe_ctlr_destroy(ctlr);

kfree(ctlr);
fcoe_ctlr_device_delete(ctlr_dev);

dev_put(netdev);
module_put(THIS_MODULE);
Expand Down Expand Up @@ -1342,17 +1381,20 @@ struct bnx2fc_interface *bnx2fc_interface_create(struct bnx2fc_hba *hba,
struct net_device *netdev,
enum fip_state fip_mode)
{
struct fcoe_ctlr_device *ctlr_dev;
struct bnx2fc_interface *interface;
struct fcoe_ctlr *ctlr;
int size;
int rc = 0;

size = (sizeof(*interface) + sizeof(struct fcoe_ctlr));
ctlr = kzalloc(size, GFP_KERNEL);
if (!ctlr) {
ctlr_dev = fcoe_ctlr_device_add(&netdev->dev, &bnx2fc_fcoe_sysfs_templ,
size);
if (!ctlr_dev) {
printk(KERN_ERR PFX "Unable to allocate interface structure\n");
return NULL;
}
ctlr = fcoe_ctlr_device_priv(ctlr_dev);
interface = fcoe_ctlr_priv(ctlr);
dev_hold(netdev);
kref_init(&interface->kref);
Expand All @@ -1372,7 +1414,7 @@ struct bnx2fc_interface *bnx2fc_interface_create(struct bnx2fc_hba *hba,

fcoe_ctlr_destroy(ctlr);
dev_put(netdev);
kfree(ctlr);
fcoe_ctlr_device_delete(ctlr_dev);
return NULL;
}

Expand Down Expand Up @@ -2471,6 +2513,19 @@ static void __exit bnx2fc_mod_exit(void)
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,

.get_fcoe_fcf_selected = fcoe_fcf_get_selected,
.get_fcoe_fcf_vlan_id = bnx2fc_fcf_get_vlan_id,
};

static struct fc_function_template bnx2fc_transport_function = {
.show_host_node_name = 1,
.show_host_port_name = 1,
Expand Down
71 changes: 64 additions & 7 deletions drivers/scsi/fcoe/fcoe.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@

#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>
Expand Down Expand Up @@ -150,6 +151,21 @@ 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,
.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 = fcoe_fcf_get_vlan_id,
};

static struct libfc_function_template fcoe_libfc_fcn_templ = {
.frame_send = fcoe_xmit,
Expand Down Expand Up @@ -366,6 +382,7 @@ static int fcoe_interface_setup(struct fcoe_interface *fcoe,
static struct fcoe_interface *fcoe_interface_create(struct net_device *netdev,
enum fip_state fip_mode)
{
struct fcoe_ctlr_device *ctlr_dev;
struct fcoe_ctlr *ctlr;
struct fcoe_interface *fcoe;
int size;
Expand All @@ -379,14 +396,17 @@ static struct fcoe_interface *fcoe_interface_create(struct net_device *netdev,
}

size = sizeof(struct fcoe_ctlr) + sizeof(struct fcoe_interface);
ctlr = kzalloc(size, GFP_KERNEL);
fcoe = fcoe_ctlr_priv(ctlr);
if (!fcoe) {
FCOE_NETDEV_DBG(netdev, "Could not allocate fcoe structure\n");
ctlr_dev = fcoe_ctlr_device_add(&netdev->dev, &fcoe_sysfs_templ,
size);
if (!ctlr_dev) {
FCOE_DBG("Failed to add fcoe_ctlr_device\n");
fcoe = ERR_PTR(-ENOMEM);
goto out_putmod;
}

ctlr = fcoe_ctlr_device_priv(ctlr_dev);
fcoe = fcoe_ctlr_priv(ctlr);

dev_hold(netdev);

/*
Expand All @@ -400,6 +420,7 @@ static struct fcoe_interface *fcoe_interface_create(struct net_device *netdev,
err = fcoe_interface_setup(fcoe, netdev);
if (err) {
fcoe_ctlr_destroy(ctlr);
fcoe_ctlr_device_delete(ctlr_dev);
dev_put(netdev);
fcoe = ERR_PTR(err);
goto out_putmod;
Expand Down Expand Up @@ -466,6 +487,7 @@ static void fcoe_interface_cleanup(struct fcoe_interface *fcoe)
{
struct net_device *netdev = fcoe->netdev;
struct fcoe_ctlr *fip = fcoe_to_ctlr(fcoe);
struct fcoe_ctlr_device *ctlr_dev = fcoe_ctlr_to_ctlr_dev(fip);

rtnl_lock();
if (!fcoe->removed)
Expand All @@ -476,7 +498,7 @@ static void fcoe_interface_cleanup(struct fcoe_interface *fcoe)
/* tear-down the FCoE controller */
fcoe_ctlr_destroy(fip);
scsi_host_put(fip->lp->host);
kfree(fip);
fcoe_ctlr_device_delete(ctlr_dev);
dev_put(netdev);
module_put(THIS_MODULE);
}
Expand Down Expand Up @@ -2196,6 +2218,7 @@ static void fcoe_dcb_create(struct fcoe_interface *fcoe)
static int fcoe_create(struct net_device *netdev, enum fip_state fip_mode)
{
int rc = 0;
struct fcoe_ctlr_device *ctlr_dev;
struct fcoe_ctlr *ctlr;
struct fcoe_interface *fcoe;
struct fc_lport *lport;
Expand All @@ -2216,8 +2239,8 @@ static int fcoe_create(struct net_device *netdev, enum fip_state fip_mode)
}

ctlr = fcoe_to_ctlr(fcoe);

lport = fcoe_if_create(fcoe, &netdev->dev, 0);
ctlr_dev = fcoe_ctlr_to_ctlr_dev(ctlr);
lport = fcoe_if_create(fcoe, &ctlr_dev->dev, 0);
if (IS_ERR(lport)) {
printk(KERN_ERR "fcoe: Failed to create interface (%s)\n",
netdev->name);
Expand Down Expand Up @@ -2768,6 +2791,40 @@ static void fcoe_get_lesb(struct fc_lport *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 =
fcoe_fcf_dev_to_ctlr_dev(fcf_dev);
struct fcoe_ctlr *ctlr = fcoe_ctlr_device_priv(ctlr_dev);
struct fcoe_interface *fcoe = fcoe_ctlr_priv(ctlr);

fcf_dev->vlan_id = vlan_dev_vlan_id(fcoe->netdev);
}

/**
* fcoe_set_port_id() - Callback from libfc when Port_ID is set.
* @lport: the local port
Expand Down
Loading

0 comments on commit 8d55e50

Please sign in to comment.