diff options
| author | Robert Love <robert.w.love@intel.com> | 2012-05-22 19:06:26 -0700 | 
|---|---|---|
| committer | James Bottomley <JBottomley@Parallels.com> | 2012-05-23 09:43:13 +0100 | 
| commit | 8d55e507d24c6db7eb012c379c62912e642eb75e (patch) | |
| tree | 5118b221cf9eab4ad040c9e1bcabb794e57dc906 | |
| parent | 9a74e884ee71dbf3d0967b0321d7b4529a04826c (diff) | |
[SCSI] fcoe, bnx2fc, libfcoe: SW FCoE and bnx2fc use FCoE Syfs
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>
| -rw-r--r-- | drivers/scsi/bnx2fc/bnx2fc_fcoe.c | 63 | ||||
| -rw-r--r-- | drivers/scsi/fcoe/fcoe.c | 71 | ||||
| -rw-r--r-- | drivers/scsi/fcoe/fcoe_ctlr.c | 159 | ||||
| -rw-r--r-- | include/scsi/libfcoe.h | 17 | 
4 files changed, 285 insertions, 25 deletions
| diff --git a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c index cb9bf364170b..f52f668fd247 100644 --- a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c +++ b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c @@ -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); @@ -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); @@ -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; @@ -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; @@ -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); @@ -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); @@ -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;  } @@ -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, diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c index 4bb42e19d537..fe30b1b65e1d 100644 --- a/drivers/scsi/fcoe/fcoe.c +++ b/drivers/scsi/fcoe/fcoe.c @@ -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> @@ -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, @@ -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; @@ -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);  	/* @@ -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; @@ -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) @@ -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);  } @@ -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; @@ -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); @@ -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 diff --git a/drivers/scsi/fcoe/fcoe_ctlr.c b/drivers/scsi/fcoe/fcoe_ctlr.c index 5a4c7250aa77..d68d57241ee6 100644 --- a/drivers/scsi/fcoe/fcoe_ctlr.c +++ b/drivers/scsi/fcoe/fcoe_ctlr.c @@ -160,6 +160,76 @@ void fcoe_ctlr_init(struct fcoe_ctlr *fip, enum fip_state mode)  }  EXPORT_SYMBOL(fcoe_ctlr_init); +static int fcoe_sysfs_fcf_add(struct fcoe_fcf *new) +{ +	struct fcoe_ctlr *fip = new->fip; +	struct fcoe_ctlr_device *ctlr_dev = fcoe_ctlr_to_ctlr_dev(fip); +	struct fcoe_fcf_device temp, *fcf_dev; +	int rc = 0; + +	LIBFCOE_FIP_DBG(fip, "New FCF fab %16.16llx mac %pM\n", +			new->fabric_name, new->fcf_mac); + +	mutex_lock(&ctlr_dev->lock); + +	temp.fabric_name = new->fabric_name; +	temp.switch_name = new->switch_name; +	temp.fc_map = new->fc_map; +	temp.vfid = new->vfid; +	memcpy(temp.mac, new->fcf_mac, ETH_ALEN); +	temp.priority = new->pri; +	temp.fka_period = new->fka_period; +	temp.selected = 0; /* default to unselected */ + +	fcf_dev = fcoe_fcf_device_add(ctlr_dev, &temp); +	if (unlikely(!fcf_dev)) { +		rc = -ENOMEM; +		goto out; +	} + +	/* +	 * The fcoe_sysfs layer can return a CONNECTED fcf that +	 * has a priv (fcf was never deleted) or a CONNECTED fcf +	 * that doesn't have a priv (fcf was deleted). However, +	 * libfcoe will always delete FCFs before trying to add +	 * them. This is ensured because both recv_adv and +	 * age_fcfs are protected by the the fcoe_ctlr's mutex. +	 * This means that we should never get a FCF with a +	 * non-NULL priv pointer. +	 */ +	BUG_ON(fcf_dev->priv); + +	fcf_dev->priv = new; +	new->fcf_dev = fcf_dev; + +	list_add(&new->list, &fip->fcfs); +	fip->fcf_count++; + +out: +	mutex_unlock(&ctlr_dev->lock); +	return rc; +} + +static void fcoe_sysfs_fcf_del(struct fcoe_fcf *new) +{ +	struct fcoe_ctlr *fip = new->fip; +	struct fcoe_ctlr_device *ctlr_dev = fcoe_ctlr_to_ctlr_dev(fip); +	struct fcoe_fcf_device *fcf_dev; + +	list_del(&new->list); +	fip->fcf_count--; + +	mutex_lock(&ctlr_dev->lock); + +	fcf_dev = fcoe_fcf_to_fcf_dev(new); +	WARN_ON(!fcf_dev); +	new->fcf_dev = NULL; +	fcoe_fcf_device_delete(fcf_dev); +	kfree(new); + +	mutex_unlock(&ctlr_dev->lock); +} +  /**   * fcoe_ctlr_reset_fcfs() - Reset and free all FCFs for a controller   * @fip: The FCoE controller whose FCFs are to be reset @@ -173,10 +243,10 @@ static void fcoe_ctlr_reset_fcfs(struct fcoe_ctlr *fip)  	fip->sel_fcf = NULL;  	list_for_each_entry_safe(fcf, next, &fip->fcfs, list) { -		list_del(&fcf->list); -		kfree(fcf); +		fcoe_sysfs_fcf_del(fcf);  	} -	fip->fcf_count = 0; +	WARN_ON(fip->fcf_count); +  	fip->sel_time = 0;  } @@ -717,8 +787,11 @@ static unsigned long fcoe_ctlr_age_fcfs(struct fcoe_ctlr *fip)  	unsigned long next_timer = jiffies + msecs_to_jiffies(FIP_VN_KA_PERIOD);  	unsigned long deadline;  	unsigned long sel_time = 0; +	struct list_head del_list;  	struct fcoe_dev_stats *stats; +	INIT_LIST_HEAD(&del_list); +  	stats = per_cpu_ptr(fip->lp->dev_stats, get_cpu());  	list_for_each_entry_safe(fcf, next, &fip->fcfs, list) { @@ -739,10 +812,13 @@ static unsigned long fcoe_ctlr_age_fcfs(struct fcoe_ctlr *fip)  		if (time_after_eq(jiffies, deadline)) {  			if (fip->sel_fcf == fcf)  				fip->sel_fcf = NULL; +			/* +			 * Move to delete list so we can call +			 * fcoe_sysfs_fcf_del (which can sleep) +			 * after the put_cpu(). +			 */  			list_del(&fcf->list); -			WARN_ON(!fip->fcf_count); -			fip->fcf_count--; -			kfree(fcf); +			list_add(&fcf->list, &del_list);  			stats->VLinkFailureCount++;  		} else {  			if (time_after(next_timer, deadline)) @@ -753,6 +829,12 @@ static unsigned long fcoe_ctlr_age_fcfs(struct fcoe_ctlr *fip)  		}  	}  	put_cpu(); + +	list_for_each_entry_safe(fcf, next, &del_list, list) { +		/* Removes fcf from current list */ +		fcoe_sysfs_fcf_del(fcf); +	} +  	if (sel_time && !fip->sel_fcf && !fip->sel_time) {  		sel_time += msecs_to_jiffies(FCOE_CTLR_START_DELAY);  		fip->sel_time = sel_time; @@ -903,23 +985,23 @@ static void fcoe_ctlr_recv_adv(struct fcoe_ctlr *fip, struct sk_buff *skb)  {  	struct fcoe_fcf *fcf;  	struct fcoe_fcf new; -	struct fcoe_fcf *found;  	unsigned long sol_tov = msecs_to_jiffies(FCOE_CTRL_SOL_TOV);  	int first = 0;  	int mtu_valid; +	int found = 0; +	int rc = 0;  	if (fcoe_ctlr_parse_adv(fip, skb, &new))  		return;  	mutex_lock(&fip->ctlr_mutex);  	first = list_empty(&fip->fcfs); -	found = NULL;  	list_for_each_entry(fcf, &fip->fcfs, list) {  		if (fcf->switch_name == new.switch_name &&  		    fcf->fabric_name == new.fabric_name &&  		    fcf->fc_map == new.fc_map &&  		    compare_ether_addr(fcf->fcf_mac, new.fcf_mac) == 0) { -			found = fcf; +			found = 1;  			break;  		}  	} @@ -931,9 +1013,16 @@ static void fcoe_ctlr_recv_adv(struct fcoe_ctlr *fip, struct sk_buff *skb)  		if (!fcf)  			goto out; -		fip->fcf_count++;  		memcpy(fcf, &new, sizeof(new)); -		list_add(&fcf->list, &fip->fcfs); +		fcf->fip = fip; +		rc = fcoe_sysfs_fcf_add(fcf); +		if (rc) { +			printk(KERN_ERR "Failed to allocate sysfs instance " +			       "for FCF, fab %16.16llx mac %pM\n", +			       new.fabric_name, new.fcf_mac); +			kfree(fcf); +			goto out; +		}  	} else {  		/*  		 * Update the FCF's keep-alive descriptor flags. @@ -954,6 +1043,7 @@ static void fcoe_ctlr_recv_adv(struct fcoe_ctlr *fip, struct sk_buff *skb)  		fcf->fka_period = new.fka_period;  		memcpy(fcf->fcf_mac, new.fcf_mac, ETH_ALEN);  	} +  	mtu_valid = fcoe_ctlr_mtu_valid(fcf);  	fcf->time = jiffies;  	if (!found) @@ -996,6 +1086,7 @@ static void fcoe_ctlr_recv_adv(struct fcoe_ctlr *fip, struct sk_buff *skb)  		    time_before(fip->sel_time, fip->timer.expires))  			mod_timer(&fip->timer, fip->sel_time);  	} +  out:  	mutex_unlock(&fip->ctlr_mutex);  } @@ -2718,9 +2809,9 @@ unlock:  /**   * fcoe_libfc_config() - Sets up libfc related properties for local port - * @lp: The local port to configure libfc for - * @fip: The FCoE controller in use by the local port - * @tt: The libfc function template + * @lport:    The local port to configure libfc for + * @fip:      The FCoE controller in use by the local port + * @tt:       The libfc function template   * @init_fcp: If non-zero, the FCP portion of libfc should be initialized   *   * Returns : 0 for success @@ -2753,3 +2844,43 @@ int fcoe_libfc_config(struct fc_lport *lport, struct fcoe_ctlr *fip,  	return 0;  }  EXPORT_SYMBOL_GPL(fcoe_libfc_config); + +void fcoe_fcf_get_selected(struct fcoe_fcf_device *fcf_dev) +{ +	struct fcoe_ctlr_device *ctlr_dev = fcoe_fcf_dev_to_ctlr_dev(fcf_dev); +	struct fcoe_ctlr *fip = fcoe_ctlr_device_priv(ctlr_dev); +	struct fcoe_fcf *fcf; + +	mutex_lock(&fip->ctlr_mutex); +	mutex_lock(&ctlr_dev->lock); + +	fcf = fcoe_fcf_device_priv(fcf_dev); +	if (fcf) +		fcf_dev->selected = (fcf == fip->sel_fcf) ? 1 : 0; +	else +		fcf_dev->selected = 0; + +	mutex_unlock(&ctlr_dev->lock); +	mutex_unlock(&fip->ctlr_mutex); +} +EXPORT_SYMBOL(fcoe_fcf_get_selected); + +void fcoe_ctlr_get_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; +		break; +	default: +		ctlr_dev->mode = FIP_CONN_TYPE_UNKNOWN; +		break; +	} +	mutex_unlock(&ctlr->ctlr_mutex); +} +EXPORT_SYMBOL(fcoe_ctlr_get_fip_mode); diff --git a/include/scsi/libfcoe.h b/include/scsi/libfcoe.h index 7b93f211b935..22b07cc99808 100644 --- a/include/scsi/libfcoe.h +++ b/include/scsi/libfcoe.h @@ -168,9 +168,16 @@ static inline void *fcoe_ctlr_priv(const struct fcoe_ctlr *ctlr)  	return (void *)(ctlr + 1);  } +#define fcoe_ctlr_to_ctlr_dev(x)					\ +	(struct fcoe_ctlr_device *)(((struct fcoe_ctlr_device *)(x)) - 1) +  /**   * struct fcoe_fcf - Fibre-Channel Forwarder   * @list:	 list linkage + * @event_work:  Work for FC Transport actions queue + * @event:       The event to be processed + * @fip:         The controller that the FCF was discovered on + * @fcf_dev:     The associated fcoe_fcf_device instance   * @time:	 system time (jiffies) when an advertisement was last received   * @switch_name: WWN of switch from advertisement   * @fabric_name: WWN of fabric from advertisement @@ -192,6 +199,9 @@ static inline void *fcoe_ctlr_priv(const struct fcoe_ctlr *ctlr)   */  struct fcoe_fcf {  	struct list_head list; +	struct work_struct event_work; +	struct fcoe_ctlr *fip; +	struct fcoe_fcf_device *fcf_dev;  	unsigned long time;  	u64 switch_name; @@ -208,6 +218,9 @@ struct fcoe_fcf {  	u8 fd_flags:1;  }; +#define fcoe_fcf_to_fcf_dev(x)			\ +	((x)->fcf_dev) +  /**   * struct fcoe_rport - VN2VN remote port   * @time:	time of create or last beacon packet received from node @@ -343,6 +356,10 @@ void fcoe_queue_timer(ulong lport);  int fcoe_get_paged_crc_eof(struct sk_buff *skb, int tlen,  			   struct fcoe_percpu_s *fps); +/* FCoE Sysfs helpers */ +void fcoe_fcf_get_selected(struct fcoe_fcf_device *); +void fcoe_ctlr_get_fip_mode(struct fcoe_ctlr_device *); +  /**   * struct netdev_list   * A mapping from netdevice to fcoe_transport | 
