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
					
				
			
		
					 19 changed files with 821 additions and 297 deletions
				
			
		|  | @ -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 | Date:		March 2012 | ||||||
| KernelVersion:	TBD | KernelVersion:	TBD | ||||||
| Contact:	Robert Love <robert.w.love@intel.com>, devel@open-fcoe.org | 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: | Attributes: | ||||||
| 
 | 
 | ||||||
| 	fcf_dev_loss_tmo: Device loss timeout peroid (see below). Changing | 	fcf_dev_loss_tmo: Device loss timeout peroid (see below). Changing | ||||||
| 			  this value will change the dev_loss_tmo for all | 			  this value will change the dev_loss_tmo for all | ||||||
| 			  FCFs discovered by this controller. | 			  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/link_fail:   Link Error Status Block (LESB) link failure count. | ||||||
| 
 | 
 | ||||||
| 	lesb/vlink_fail:  Link Error Status Block (LESB) virtual link | 	lesb/vlink_fail:  Link Error Status Block (LESB) virtual link | ||||||
|  | @ -26,7 +65,7 @@ Attributes: | ||||||
| 
 | 
 | ||||||
| Notes: ctlr_X (global increment starting at 0) | Notes: ctlr_X (global increment starting at 0) | ||||||
| 
 | 
 | ||||||
| What:		/sys/bus/fcoe/fcf_X | What:		/sys/bus/fcoe/devices/fcf_X | ||||||
| Date:		March 2012 | Date:		March 2012 | ||||||
| KernelVersion:	TBD | KernelVersion:	TBD | ||||||
| Contact:	Robert Love <robert.w.love@intel.com>, devel@open-fcoe.org | 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_enable(struct net_device *netdev); | ||||||
| static int bnx2fc_disable(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_recv_frame(struct sk_buff *skb); | ||||||
| 
 | 
 | ||||||
| static void bnx2fc_start_disc(struct bnx2fc_interface *interface); | 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 void bnx2fc_stop(struct bnx2fc_interface *interface); | ||||||
| static int __init bnx2fc_mod_init(void); | static int __init bnx2fc_mod_init(void); | ||||||
| static void __exit bnx2fc_mod_exit(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; | unsigned int bnx2fc_debug_level; | ||||||
| module_param_named(debug_logging, bnx2fc_debug_level, int, S_IRUGO|S_IWUSR); | 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; | 		((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) | static void bnx2fc_fcf_get_vlan_id(struct fcoe_fcf_device *fcf_dev) | ||||||
| { | { | ||||||
| 	struct fcoe_ctlr_device *ctlr_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; | 	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) | static int bnx2fc_link_ok(struct fc_lport *lport) | ||||||
| { | { | ||||||
| 	struct fcoe_port *port = lport_priv(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; | 	port->fcoe_pending_queue_active = 0; | ||||||
| 	setup_timer(&port->timer, fcoe_queue_timer, (unsigned long) lport); | 	setup_timer(&port->timer, fcoe_queue_timer, (unsigned long) lport); | ||||||
| 
 | 
 | ||||||
| 	bnx2fc_link_speed_update(lport); | 	fcoe_link_speed_update(lport); | ||||||
| 
 | 
 | ||||||
| 	if (!lport->vport) { | 	if (!lport->vport) { | ||||||
| 		if (fcoe_get_wwn(netdev, &wwnn, NETDEV_FCOE_WWNN)) | 		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) | 				     u16 vlan_id) | ||||||
| { | { | ||||||
| 	struct bnx2fc_hba *hba = (struct bnx2fc_hba *)context; | 	struct bnx2fc_hba *hba = (struct bnx2fc_hba *)context; | ||||||
|  | 	struct fcoe_ctlr_device *cdev; | ||||||
| 	struct fc_lport *lport; | 	struct fc_lport *lport; | ||||||
| 	struct fc_lport *vport; | 	struct fc_lport *vport; | ||||||
| 	struct bnx2fc_interface *interface, *tmp; | 	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", | 		BNX2FC_HBA_DBG(lport, "netevent handler - event=%s %ld\n", | ||||||
| 				interface->netdev->name, event); | 				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)) { | 		if (link_possible && !bnx2fc_link_ok(lport)) { | ||||||
| 			/* Reset max recv frame size to default */ | 			switch (cdev->enabled) { | ||||||
| 			fc_set_mfs(lport, BNX2FC_MFS); | 			case FCOE_CTLR_DISABLED: | ||||||
| 			/*
 | 				pr_info("Link up while interface is disabled.\n"); | ||||||
| 			 * ctlr link up will only be handled during | 				break; | ||||||
| 			 * enable to avoid sending discovery solicitation | 			case FCOE_CTLR_ENABLED: | ||||||
| 			 * on a stale vlan | 			case FCOE_CTLR_UNUSED: | ||||||
| 			 */ | 				/* Reset max recv frame size to default */ | ||||||
| 			if (interface->enabled) | 				fc_set_mfs(lport, BNX2FC_MFS); | ||||||
| 				fcoe_ctlr_link_up(ctlr); | 				/*
 | ||||||
|  | 				 * 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)) { | 		} else if (fcoe_ctlr_link_down(ctlr)) { | ||||||
| 			mutex_lock(&lport->lp_mutex); | 			switch (cdev->enabled) { | ||||||
| 			list_for_each_entry(vport, &lport->vports, list) | 			case FCOE_CTLR_DISABLED: | ||||||
| 				fc_host_port_type(vport->host) = | 				pr_info("Link down while interface is disabled.\n"); | ||||||
| 							FC_PORTTYPE_UNKNOWN; | 				break; | ||||||
| 			mutex_unlock(&lport->lp_mutex); | 			case FCOE_CTLR_ENABLED: | ||||||
| 			fc_host_port_type(lport->host) = FC_PORTTYPE_UNKNOWN; | 			case FCOE_CTLR_UNUSED: | ||||||
| 			per_cpu_ptr(lport->stats, | 				mutex_lock(&lport->lp_mutex); | ||||||
| 				    get_cpu())->LinkFailureCount++; | 				list_for_each_entry(vport, &lport->vports, list) | ||||||
| 			put_cpu(); | 					fc_host_port_type(vport->host) = | ||||||
| 			fcoe_clean_pending_queue(lport); | 					FC_PORTTYPE_UNKNOWN; | ||||||
| 			wait_for_upload = 1; | 				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); | 	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_priv(lport); | ||||||
| 	port->lport = lport; | 	port->lport = lport; | ||||||
| 	port->priv = interface; | 	port->priv = interface; | ||||||
|  | 	port->get_netdev = bnx2fc_netdev; | ||||||
| 	INIT_WORK(&port->destroy_work, bnx2fc_destroy_work); | 	INIT_WORK(&port->destroy_work, bnx2fc_destroy_work); | ||||||
| 
 | 
 | ||||||
| 	/* Configure fcoe_port */ | 	/* 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); | 		set_bit(BNX2FC_CNIC_REGISTERED, &hba->reg_with_cnic); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | /**
 | ||||||
|  |  * Deperecated: Use bnx2fc_enabled() | ||||||
|  |  */ | ||||||
| static int bnx2fc_disable(struct net_device *netdev) | static int bnx2fc_disable(struct net_device *netdev) | ||||||
| { | { | ||||||
| 	struct bnx2fc_interface *interface; | 	struct bnx2fc_interface *interface; | ||||||
|  | @ -2029,7 +1986,9 @@ static int bnx2fc_disable(struct net_device *netdev) | ||||||
| 	return rc; | 	return rc; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | /**
 | ||||||
|  |  * Deprecated: Use bnx2fc_enabled() | ||||||
|  |  */ | ||||||
| static int bnx2fc_enable(struct net_device *netdev) | static int bnx2fc_enable(struct net_device *netdev) | ||||||
| { | { | ||||||
| 	struct bnx2fc_interface *interface; | 	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 |  * fcoe_sysfs will ensure that the state of 'enabled' has | ||||||
|  * @kp:     The associated kernel param |  * 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 |  * 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 fcoe_ctlr *ctlr; | ||||||
| 	struct bnx2fc_interface *interface; | 	struct bnx2fc_interface *interface; | ||||||
| 	struct bnx2fc_hba *hba; | 	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 */ | 	/* Make this master N_port */ | ||||||
| 	ctlr->lp = lport; | 	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); | 		fcoe_ctlr_link_up(ctlr); | ||||||
| 		fc_host_port_type(lport->host) = FC_PORTTYPE_NPORT; | 		fc_host_port_type(lport->host) = FC_PORTTYPE_NPORT; | ||||||
| 		set_bit(ADAPTER_STATE_READY, &interface->hba->adapter_state); | 		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_HBA_DBG(lport, "create: START DISC\n"); | ||||||
| 	bnx2fc_start_disc(interface); | 	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 | 	 * Release from kref_init in bnx2fc_interface_setup, on success | ||||||
| 	 * lport should be holding a reference taken in bnx2fc_if_create | 	 * lport should be holding a reference taken in bnx2fc_if_create | ||||||
|  | @ -2193,6 +2203,37 @@ mod_err: | ||||||
| 	return rc; | 	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 |  * bnx2fc_find_hba_for_cnic - maps cnic instance to bnx2fc hba instance | ||||||
|  * |  * | ||||||
|  | @ -2318,6 +2359,7 @@ static struct fcoe_transport bnx2fc_transport = { | ||||||
| 	.name = {"bnx2fc"}, | 	.name = {"bnx2fc"}, | ||||||
| 	.attached = false, | 	.attached = false, | ||||||
| 	.list = LIST_HEAD_INIT(bnx2fc_transport.list), | 	.list = LIST_HEAD_INIT(bnx2fc_transport.list), | ||||||
|  | 	.alloc = bnx2fc_ctlr_alloc, | ||||||
| 	.match = bnx2fc_match, | 	.match = bnx2fc_match, | ||||||
| 	.create = bnx2fc_create, | 	.create = bnx2fc_create, | ||||||
| 	.destroy = bnx2fc_destroy, | 	.destroy = bnx2fc_destroy, | ||||||
|  | @ -2562,13 +2604,13 @@ module_init(bnx2fc_mod_init); | ||||||
| module_exit(bnx2fc_mod_exit); | module_exit(bnx2fc_mod_exit); | ||||||
| 
 | 
 | ||||||
| static struct fcoe_sysfs_function_template bnx2fc_fcoe_sysfs_templ = { | static struct fcoe_sysfs_function_template bnx2fc_fcoe_sysfs_templ = { | ||||||
| 	.get_fcoe_ctlr_mode = fcoe_ctlr_get_fip_mode, | 	.set_fcoe_ctlr_enabled = bnx2fc_ctlr_enabled, | ||||||
| 	.get_fcoe_ctlr_link_fail = bnx2fc_ctlr_get_lesb, | 	.get_fcoe_ctlr_link_fail = fcoe_ctlr_get_lesb, | ||||||
| 	.get_fcoe_ctlr_vlink_fail = bnx2fc_ctlr_get_lesb, | 	.get_fcoe_ctlr_vlink_fail = fcoe_ctlr_get_lesb, | ||||||
| 	.get_fcoe_ctlr_miss_fka = bnx2fc_ctlr_get_lesb, | 	.get_fcoe_ctlr_miss_fka = fcoe_ctlr_get_lesb, | ||||||
| 	.get_fcoe_ctlr_symb_err = bnx2fc_ctlr_get_lesb, | 	.get_fcoe_ctlr_symb_err = fcoe_ctlr_get_lesb, | ||||||
| 	.get_fcoe_ctlr_err_block = bnx2fc_ctlr_get_lesb, | 	.get_fcoe_ctlr_err_block = fcoe_ctlr_get_lesb, | ||||||
| 	.get_fcoe_ctlr_fcs_error = bnx2fc_ctlr_get_lesb, | 	.get_fcoe_ctlr_fcs_error = fcoe_ctlr_get_lesb, | ||||||
| 
 | 
 | ||||||
| 	.get_fcoe_fcf_selected = fcoe_fcf_get_selected, | 	.get_fcoe_fcf_selected = fcoe_fcf_get_selected, | ||||||
| 	.get_fcoe_fcf_vlan_id = bnx2fc_fcf_get_vlan_id, | 	.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, | 	.elsct_send		= bnx2fc_elsct_send, | ||||||
| 	.fcp_abort_io		= bnx2fc_abort_io, | 	.fcp_abort_io		= bnx2fc_abort_io, | ||||||
| 	.fcp_cleanup		= bnx2fc_cleanup, | 	.fcp_cleanup		= bnx2fc_cleanup, | ||||||
| 	.get_lesb		= bnx2fc_get_lesb, | 	.get_lesb		= fcoe_get_lesb, | ||||||
| 	.rport_event_callback	= bnx2fc_rport_event_handler, | 	.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 *); | 		    struct packet_type *, struct net_device *); | ||||||
| static int fcoe_percpu_receive_thread(void *); | static int fcoe_percpu_receive_thread(void *); | ||||||
| static void fcoe_percpu_clean(struct fc_lport *); | 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 int fcoe_link_ok(struct fc_lport *); | ||||||
| 
 | 
 | ||||||
| static struct fc_lport *fcoe_hostlist_lookup(const struct net_device *); | static struct fc_lport *fcoe_hostlist_lookup(const struct net_device *); | ||||||
| static int fcoe_hostlist_add(const struct fc_lport *); | 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 int fcoe_device_notification(struct notifier_block *, ulong, void *); | ||||||
| static void fcoe_dev_setup(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_enable(struct net_device *netdev); | ||||||
| static int fcoe_disable(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 *, | static struct fc_seq *fcoe_elsct_send(struct fc_lport *, | ||||||
| 				      u32 did, struct fc_frame *, | 				      u32 did, struct fc_frame *, | ||||||
| 				      unsigned int op, | 				      unsigned int op, | ||||||
|  | @ -126,8 +131,6 @@ static struct fc_seq *fcoe_elsct_send(struct fc_lport *, | ||||||
| 				      void *, u32 timeout); | 				      void *, u32 timeout); | ||||||
| static void fcoe_recv_frame(struct sk_buff *skb); | 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 */ | /* notification function for packets from net device */ | ||||||
| static struct notifier_block fcoe_notifier = { | static struct notifier_block fcoe_notifier = { | ||||||
| 	.notifier_call = fcoe_device_notification, | 	.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 int fcoe_vport_disable(struct fc_vport *, bool disable); | ||||||
| static void fcoe_set_vport_symbolic_name(struct fc_vport *); | 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_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 void fcoe_fcf_get_vlan_id(struct fcoe_fcf_device *); | ||||||
| 
 | 
 | ||||||
| static struct fcoe_sysfs_function_template fcoe_sysfs_templ = { | 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_link_fail = fcoe_ctlr_get_lesb, | ||||||
| 	.get_fcoe_ctlr_vlink_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_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_priv(lport); | ||||||
| 	port->lport = lport; | 	port->lport = lport; | ||||||
| 	port->priv = fcoe; | 	port->priv = fcoe; | ||||||
|  | 	port->get_netdev = fcoe_netdev; | ||||||
| 	port->max_queue_depth = FCOE_MAX_QUEUE_DEPTH; | 	port->max_queue_depth = FCOE_MAX_QUEUE_DEPTH; | ||||||
| 	port->min_queue_depth = FCOE_MIN_QUEUE_DEPTH; | 	port->min_queue_depth = FCOE_MIN_QUEUE_DEPTH; | ||||||
| 	INIT_WORK(&port->destroy_work, fcoe_destroy_work); | 	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 */ | 	/* configure a fc_lport including the exchange manager */ | ||||||
| 	rc = fcoe_lport_config(lport); | 	rc = fcoe_lport_config(lport); | ||||||
| 	if (rc) { | 	if (rc) { | ||||||
|  | @ -1187,6 +1197,7 @@ static struct fc_lport *fcoe_if_create(struct fcoe_interface *fcoe, | ||||||
| out_lp_destroy: | out_lp_destroy: | ||||||
| 	fc_exch_mgr_free(lport); | 	fc_exch_mgr_free(lport); | ||||||
| out_host_put: | out_host_put: | ||||||
|  | 	fcoe_hostlist_del(lport); | ||||||
| 	scsi_host_put(lport->host); | 	scsi_host_put(lport->host); | ||||||
| out: | out: | ||||||
| 	return ERR_PTR(rc); | 	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, | static int fcoe_device_notification(struct notifier_block *notifier, | ||||||
| 				    ulong event, void *ptr) | 				    ulong event, void *ptr) | ||||||
| { | { | ||||||
|  | 	struct fcoe_ctlr_device *cdev; | ||||||
| 	struct fc_lport *lport = NULL; | 	struct fc_lport *lport = NULL; | ||||||
| 	struct net_device *netdev = ptr; | 	struct net_device *netdev = ptr; | ||||||
| 	struct fcoe_ctlr *ctlr; | 	struct fcoe_ctlr *ctlr; | ||||||
|  | @ -2020,13 +2032,29 @@ static int fcoe_device_notification(struct notifier_block *notifier, | ||||||
| 
 | 
 | ||||||
| 	fcoe_link_speed_update(lport); | 	fcoe_link_speed_update(lport); | ||||||
| 
 | 
 | ||||||
| 	if (link_possible && !fcoe_link_ok(lport)) | 	cdev = fcoe_ctlr_to_ctlr_dev(ctlr); | ||||||
| 		fcoe_ctlr_link_up(ctlr); | 
 | ||||||
| 	else if (fcoe_ctlr_link_down(ctlr)) { | 	if (link_possible && !fcoe_link_ok(lport)) { | ||||||
| 		stats = per_cpu_ptr(lport->stats, get_cpu()); | 		switch (cdev->enabled) { | ||||||
| 		stats->LinkFailureCount++; | 		case FCOE_CTLR_DISABLED: | ||||||
| 		put_cpu(); | 			pr_info("Link up while interface is disabled.\n"); | ||||||
| 		fcoe_clean_pending_queue(lport); | 			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: | out: | ||||||
| 	return rc; | 	return rc; | ||||||
|  | @ -2039,6 +2067,8 @@ out: | ||||||
|  * Called from fcoe transport. |  * Called from fcoe transport. | ||||||
|  * |  * | ||||||
|  * Returns: 0 for success |  * Returns: 0 for success | ||||||
|  |  * | ||||||
|  |  * Deprecated: use fcoe_ctlr_enabled() | ||||||
|  */ |  */ | ||||||
| static int fcoe_disable(struct net_device *netdev) | static int fcoe_disable(struct net_device *netdev) | ||||||
| { | { | ||||||
|  | @ -2097,6 +2127,33 @@ out: | ||||||
| 	return rc; | 	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 |  * fcoe_destroy() - Destroy a FCoE interface | ||||||
|  * @netdev  : The net_device object the Ethernet interface to create on |  * @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_port *port; | ||||||
| 	struct fcoe_interface *fcoe; | 	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); | 	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); | 	mutex_lock(&fcoe_config_mutex); | ||||||
| 
 | 
 | ||||||
| 	fcoe = port->priv; | 	fcoe = port->priv; | ||||||
|  | @ -2204,16 +2284,26 @@ static void fcoe_dcb_create(struct fcoe_interface *fcoe) | ||||||
| #endif | #endif | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | enum fcoe_create_link_state { | ||||||
|  | 	FCOE_CREATE_LINK_DOWN, | ||||||
|  | 	FCOE_CREATE_LINK_UP, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| /**
 | /**
 | ||||||
|  * fcoe_create() - Create a fcoe interface |  * _fcoe_create() - (internal) Create a fcoe interface | ||||||
|  * @netdev  : The net_device object the Ethernet interface to create on |  * @netdev  :   The net_device object the Ethernet interface to create on | ||||||
|  * @fip_mode: The FIP mode for this creation |  * @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; | 	int rc = 0; | ||||||
| 	struct fcoe_ctlr_device *ctlr_dev; | 	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. */ | 	/* setup DCB priority attributes. */ | ||||||
| 	fcoe_dcb_create(fcoe); | 	fcoe_dcb_create(fcoe); | ||||||
| 
 | 
 | ||||||
| 	/* add to lports list */ |  | ||||||
| 	fcoe_hostlist_add(lport); |  | ||||||
| 
 |  | ||||||
| 	/* start FIP Discovery and FLOGI */ | 	/* start FIP Discovery and FLOGI */ | ||||||
| 	lport->boot_time = jiffies; | 	lport->boot_time = jiffies; | ||||||
| 	fc_fabric_login(lport); | 	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(); | 		rtnl_unlock(); | ||||||
| 		fcoe_ctlr_link_up(ctlr); | 		fcoe_ctlr_link_up(ctlr); | ||||||
| 		mutex_unlock(&fcoe_config_mutex); | 		mutex_unlock(&fcoe_config_mutex); | ||||||
|  | @ -2275,37 +2381,34 @@ out_nortnl: | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  * fcoe_link_speed_update() - Update the supported and actual link speeds |  * fcoe_create() - Create a fcoe interface | ||||||
|  * @lport: The local port to update speeds for |  * @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 |  * Called from fcoe transport | ||||||
|  *          -1 if the ethtool query failed |  * | ||||||
|  |  * 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); | 	return _fcoe_create(netdev, fip_mode, FCOE_CREATE_LINK_UP); | ||||||
| 	struct ethtool_cmd ecmd; | } | ||||||
| 
 | 
 | ||||||
| 	if (!__ethtool_get_settings(netdev, &ecmd)) { | /**
 | ||||||
| 		lport->link_supported_speeds &= |  * fcoe_ctlr_alloc() - Allocate a fcoe interface from fcoe_sysfs | ||||||
| 			~(FC_PORTSPEED_1GBIT | FC_PORTSPEED_10GBIT); |  * @netdev: The net_device to be used by the allocated FCoE Controller | ||||||
| 		if (ecmd.supported & (SUPPORTED_1000baseT_Half | |  * | ||||||
| 				      SUPPORTED_1000baseT_Full)) |  * This routine is called from fcoe_sysfs. It will start the fcoe_ctlr | ||||||
| 			lport->link_supported_speeds |= FC_PORTSPEED_1GBIT; |  * in a link_down state. The allows the user an opportunity to configure | ||||||
| 		if (ecmd.supported & SUPPORTED_10000baseT_Full) |  * the FCoE Controller from sysfs before enabling the FCoE Controller. | ||||||
| 			lport->link_supported_speeds |= |  * | ||||||
| 				FC_PORTSPEED_10GBIT; |  * Creating in with this routine starts the FCoE Controller in Fabric | ||||||
| 		switch (ethtool_cmd_speed(&ecmd)) { |  * mode. The user can change to VN2VN or another mode before enabling. | ||||||
| 		case SPEED_1000: |  */ | ||||||
| 			lport->link_speed = FC_PORTSPEED_1GBIT; | static int fcoe_ctlr_alloc(struct net_device *netdev) | ||||||
| 			break; | { | ||||||
| 		case SPEED_10000: | 	return _fcoe_create(netdev, FIP_MODE_FABRIC, | ||||||
| 			lport->link_speed = FC_PORTSPEED_10GBIT; | 			    FCOE_CREATE_LINK_DOWN); | ||||||
| 			break; |  | ||||||
| 		} |  | ||||||
| 		return 0; |  | ||||||
| 	} |  | ||||||
| 	return -1; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  | @ -2375,10 +2478,13 @@ static int fcoe_reset(struct Scsi_Host *shost) | ||||||
| 	struct fcoe_port *port = lport_priv(lport); | 	struct fcoe_port *port = lport_priv(lport); | ||||||
| 	struct fcoe_interface *fcoe = port->priv; | 	struct fcoe_interface *fcoe = port->priv; | ||||||
| 	struct fcoe_ctlr *ctlr = fcoe_to_ctlr(fcoe); | 	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_ctlr_link_down(ctlr); | ||||||
| 	fcoe_clean_pending_queue(ctlr->lp); | 	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); | 		fcoe_ctlr_link_up(ctlr); | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
|  | @ -2445,12 +2551,31 @@ static int fcoe_hostlist_add(const struct fc_lport *lport) | ||||||
| 	return 0; | 	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 = { | static struct fcoe_transport fcoe_sw_transport = { | ||||||
| 	.name = {FCOE_TRANSPORT_DEFAULT}, | 	.name = {FCOE_TRANSPORT_DEFAULT}, | ||||||
| 	.attached = false, | 	.attached = false, | ||||||
| 	.list = LIST_HEAD_INIT(fcoe_sw_transport.list), | 	.list = LIST_HEAD_INIT(fcoe_sw_transport.list), | ||||||
| 	.match = fcoe_match, | 	.match = fcoe_match, | ||||||
|  | 	.alloc = fcoe_ctlr_alloc, | ||||||
| 	.create = fcoe_create, | 	.create = fcoe_create, | ||||||
| 	.destroy = fcoe_destroy, | 	.destroy = fcoe_destroy, | ||||||
| 	.enable = fcoe_enable, | 	.enable = fcoe_enable, | ||||||
|  | @ -2534,9 +2659,9 @@ static void __exit fcoe_exit(void) | ||||||
| 	/* releases the associated fcoe hosts */ | 	/* releases the associated fcoe hosts */ | ||||||
| 	rtnl_lock(); | 	rtnl_lock(); | ||||||
| 	list_for_each_entry_safe(fcoe, tmp, &fcoe_hostlist, list) { | 	list_for_each_entry_safe(fcoe, tmp, &fcoe_hostlist, list) { | ||||||
| 		list_del(&fcoe->list); |  | ||||||
| 		ctlr = fcoe_to_ctlr(fcoe); | 		ctlr = fcoe_to_ctlr(fcoe); | ||||||
| 		port = lport_priv(ctlr->lp); | 		port = lport_priv(ctlr->lp); | ||||||
|  | 		fcoe_hostlist_del(port->lport); | ||||||
| 		queue_work(fcoe_wq, &port->destroy_work); | 		queue_work(fcoe_wq, &port->destroy_work); | ||||||
| 	} | 	} | ||||||
| 	rtnl_unlock(); | 	rtnl_unlock(); | ||||||
|  | @ -2776,43 +2901,6 @@ static void fcoe_set_vport_symbolic_name(struct fc_vport *vport) | ||||||
| 			     NULL, NULL, 3 * lport->r_a_tov); | 			     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) | static void fcoe_fcf_get_vlan_id(struct fcoe_fcf_device *fcf_dev) | ||||||
| { | { | ||||||
| 	struct fcoe_ctlr_device *ctlr_dev = | 	struct fcoe_ctlr_device *ctlr_dev = | ||||||
|  |  | ||||||
|  | @ -55,12 +55,12 @@ do {                                                            	\ | ||||||
| 
 | 
 | ||||||
| #define FCOE_DBG(fmt, args...)						\ | #define FCOE_DBG(fmt, args...)						\ | ||||||
| 	FCOE_CHECK_LOGGING(FCOE_LOGGING,				\ | 	FCOE_CHECK_LOGGING(FCOE_LOGGING,				\ | ||||||
| 			   printk(KERN_INFO "fcoe: " fmt, ##args);) | 			   pr_info("fcoe: " fmt, ##args);) | ||||||
| 
 | 
 | ||||||
| #define FCOE_NETDEV_DBG(netdev, fmt, args...)			\ | #define FCOE_NETDEV_DBG(netdev, fmt, args...)			\ | ||||||
| 	FCOE_CHECK_LOGGING(FCOE_NETDEV_LOGGING,			\ | 	FCOE_CHECK_LOGGING(FCOE_NETDEV_LOGGING,			\ | ||||||
| 			   printk(KERN_INFO "fcoe: %s: " fmt,	\ | 			   pr_info("fcoe: %s: " fmt,		\ | ||||||
| 				  netdev->name, ##args);) | 				   netdev->name, ##args);) | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  * struct fcoe_interface - A FCoE interface |  * 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"); | 	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; | 		return; | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| 	/*
 | 	/*
 | ||||||
| 	 * mask of required descriptors.  Validating each one clears its bit. | 	 * 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->fabric_name, fcf->vfid, fcf->fcf_mac, | ||||||
| 				fcf->fc_map, fcoe_ctlr_mtu_valid(fcf), | 				fcf->fc_map, fcoe_ctlr_mtu_valid(fcf), | ||||||
| 				fcf->flogi_sent, fcf->pri); | 				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)) { | 		if (!fcoe_ctlr_fcf_usable(fcf)) { | ||||||
| 			LIBFCOE_FIP_DBG(fip, "FCF for fab %16.16llx " | 			LIBFCOE_FIP_DBG(fip, "FCF for fab %16.16llx " | ||||||
| 					"map %x %svalid %savailable\n", | 					"map %x %svalid %savailable\n", | ||||||
|  | @ -1569,6 +1568,15 @@ static struct fcoe_fcf *fcoe_ctlr_select(struct fcoe_ctlr *fip) | ||||||
| 					"" : "un"); | 					"" : "un"); | ||||||
| 			continue; | 			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) | 		if (!best || fcf->pri < best->pri || best->flogi_sent) | ||||||
| 			best = fcf; | 			best = fcf; | ||||||
| 	} | 	} | ||||||
|  | @ -2864,22 +2872,21 @@ void fcoe_fcf_get_selected(struct fcoe_fcf_device *fcf_dev) | ||||||
| } | } | ||||||
| EXPORT_SYMBOL(fcoe_fcf_get_selected); | 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); | 	struct fcoe_ctlr *ctlr = fcoe_ctlr_device_priv(ctlr_dev); | ||||||
| 
 | 
 | ||||||
| 	mutex_lock(&ctlr->ctlr_mutex); | 	mutex_lock(&ctlr->ctlr_mutex); | ||||||
| 	switch (ctlr->mode) { | 	switch (ctlr_dev->mode) { | ||||||
| 	case FIP_MODE_FABRIC: | 	case FIP_CONN_TYPE_VN2VN: | ||||||
| 		ctlr_dev->mode = FIP_CONN_TYPE_FABRIC; | 		ctlr->mode = FIP_MODE_VN2VN; | ||||||
| 		break; |  | ||||||
| 	case FIP_MODE_VN2VN: |  | ||||||
| 		ctlr_dev->mode = FIP_CONN_TYPE_VN2VN; |  | ||||||
| 		break; | 		break; | ||||||
|  | 	case FIP_CONN_TYPE_FABRIC: | ||||||
| 	default: | 	default: | ||||||
| 		ctlr_dev->mode = FIP_CONN_TYPE_UNKNOWN; | 		ctlr->mode = FIP_MODE_FABRIC; | ||||||
| 		break; | 		break; | ||||||
| 	} | 	} | ||||||
|  | 
 | ||||||
| 	mutex_unlock(&ctlr->ctlr_mutex); | 	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/types.h> | ||||||
| #include <linux/kernel.h> | #include <linux/kernel.h> | ||||||
| #include <linux/etherdevice.h> | #include <linux/etherdevice.h> | ||||||
|  | #include <linux/ctype.h> | ||||||
| 
 | 
 | ||||||
| #include <scsi/fcoe_sysfs.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 ctlr_num; | ||||||
| static atomic_t fcf_num; | static atomic_t fcf_num; | ||||||
|  | @ -71,6 +80,8 @@ MODULE_PARM_DESC(fcf_dev_loss_tmo, | ||||||
| 	((x)->lesb.lesb_err_block) | 	((x)->lesb.lesb_err_block) | ||||||
| #define fcoe_ctlr_fcs_error(x)			\ | #define fcoe_ctlr_fcs_error(x)			\ | ||||||
| 	((x)->lesb.lesb_fcs_error) | 	((x)->lesb.lesb_fcs_error) | ||||||
|  | #define fcoe_ctlr_enabled(x)			\ | ||||||
|  | 	((x)->enabled) | ||||||
| #define fcoe_fcf_state(x)			\ | #define fcoe_fcf_state(x)			\ | ||||||
| 	((x)->state) | 	((x)->state) | ||||||
| #define fcoe_fcf_fabric_name(x)			\ | #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)			\ | #define fcoe_enum_name_search(title, table_type, table)			\ | ||||||
| static const char *get_fcoe_##title##_name(enum table_type table_key)	\ | static const char *get_fcoe_##title##_name(enum table_type table_key)	\ | ||||||
| {									\ | {									\ | ||||||
| 	int i;								\ | 	if (table_key < 0 || table_key >= ARRAY_SIZE(table))		\ | ||||||
| 	char *name = NULL;						\ | 		return NULL;						\ | ||||||
| 									\ | 	return table[table_key];					\ | ||||||
| 	for (i = 0; i < ARRAY_SIZE(table); i++) {			\ |  | ||||||
| 		if (table[i].value == table_key) {			\ |  | ||||||
| 			name = table[i].name;				\ |  | ||||||
| 			break;						\ |  | ||||||
| 		}							\ |  | ||||||
| 	}								\ |  | ||||||
| 	return name;							\ |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static struct { | static char *fip_conn_type_names[] = { | ||||||
| 	enum fcf_state value; | 	[ FIP_CONN_TYPE_UNKNOWN ] = "Unknown", | ||||||
| 	char           *name; | 	[ FIP_CONN_TYPE_FABRIC ]  = "Fabric", | ||||||
| } fcf_state_names[] = { | 	[ FIP_CONN_TYPE_VN2VN ]   = "VN2VN", | ||||||
| 	{ FCOE_FCF_STATE_UNKNOWN,      "Unknown" }, | }; | ||||||
| 	{ FCOE_FCF_STATE_DISCONNECTED, "Disconnected" }, | fcoe_enum_name_search(ctlr_mode, fip_conn_type, fip_conn_type_names) | ||||||
| 	{ FCOE_FCF_STATE_CONNECTED,    "Connected" }, | 
 | ||||||
|  | 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) | fcoe_enum_name_search(fcf_state, fcf_state, fcf_state_names) | ||||||
| #define FCOE_FCF_STATE_MAX_NAMELEN 50 | #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 FCOE_DEVICE_ATTR(fcf, state, S_IRUGO, show_fcf_state, NULL); | ||||||
| 
 | 
 | ||||||
| static struct { | #define FCOE_MAX_MODENAME_LEN 20 | ||||||
| 	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 |  | ||||||
| 
 |  | ||||||
| static ssize_t show_ctlr_mode(struct device *dev, | static ssize_t show_ctlr_mode(struct device *dev, | ||||||
| 			      struct device_attribute *attr, | 			      struct device_attribute *attr, | ||||||
| 			      char *buf) | 			      char *buf) | ||||||
|  | @ -264,17 +274,116 @@ static ssize_t show_ctlr_mode(struct device *dev, | ||||||
| 	struct fcoe_ctlr_device *ctlr = dev_to_ctlr(dev); | 	struct fcoe_ctlr_device *ctlr = dev_to_ctlr(dev); | ||||||
| 	const char *name; | 	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); | 	name = get_fcoe_ctlr_mode_name(ctlr->mode); | ||||||
| 	if (!name) | 	if (!name) | ||||||
| 		return -EINVAL; | 		return -EINVAL; | ||||||
| 	return snprintf(buf, FCOE_CTLR_MODE_MAX_NAMELEN, | 	return snprintf(buf, FCOE_MAX_MODENAME_LEN, | ||||||
| 			"%s\n", name); | 			"%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 | static ssize_t | ||||||
| store_private_fcoe_ctlr_fcf_dev_loss_tmo(struct device *dev, | 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[] = { | static struct attribute *fcoe_ctlr_attrs[] = { | ||||||
| 	&device_attr_fcoe_ctlr_fcf_dev_loss_tmo.attr, | 	&device_attr_fcoe_ctlr_fcf_dev_loss_tmo.attr, | ||||||
|  | 	&device_attr_fcoe_ctlr_enabled.attr, | ||||||
| 	&device_attr_fcoe_ctlr_mode.attr, | 	&device_attr_fcoe_ctlr_mode.attr, | ||||||
| 	NULL, | 	NULL, | ||||||
| }; | }; | ||||||
|  | @ -443,9 +553,16 @@ struct device_type fcoe_fcf_device_type = { | ||||||
| 	.release = fcoe_fcf_device_release, | 	.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 = { | struct bus_type fcoe_bus_type = { | ||||||
| 	.name = "fcoe", | 	.name = "fcoe", | ||||||
| 	.match = &fcoe_bus_match, | 	.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->id = atomic_inc_return(&ctlr_num) - 1; | ||||||
| 	ctlr->f = f; | 	ctlr->f = f; | ||||||
|  | 	ctlr->mode = FIP_CONN_TYPE_FABRIC; | ||||||
| 	INIT_LIST_HEAD(&ctlr->fcfs); | 	INIT_LIST_HEAD(&ctlr->fcfs); | ||||||
| 	mutex_init(&ctlr->lock); | 	mutex_init(&ctlr->lock); | ||||||
| 	ctlr->dev.parent = parent; | 	ctlr->dev.parent = parent; | ||||||
|  |  | ||||||
|  | @ -83,6 +83,50 @@ static struct notifier_block libfcoe_notifier = { | ||||||
| 	.notifier_call = libfcoe_device_notification, | 	.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, | void __fcoe_get_lesb(struct fc_lport *lport, | ||||||
| 		     struct fc_els_lesb *fc_lesb, | 		     struct fc_els_lesb *fc_lesb, | ||||||
| 		     struct net_device *netdev) | 		     struct net_device *netdev) | ||||||
|  | @ -112,6 +156,51 @@ void __fcoe_get_lesb(struct fc_lport *lport, | ||||||
| } | } | ||||||
| EXPORT_SYMBOL_GPL(__fcoe_get_lesb); | 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) | void fcoe_wwn_to_str(u64 wwn, char *buf, int len) | ||||||
| { | { | ||||||
| 	u8 wwpn[8]; | 	u8 wwpn[8]; | ||||||
|  | @ -627,6 +716,110 @@ static int libfcoe_device_notification(struct notifier_block *notifier, | ||||||
| 	return NOTIFY_OK; | 	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 |  * fcoe_transport_create() - Create a fcoe interface | ||||||
|  | @ -769,11 +962,7 @@ out_putdev: | ||||||
| 	dev_put(netdev); | 	dev_put(netdev); | ||||||
| out_nodev: | out_nodev: | ||||||
| 	mutex_unlock(&ft_mutex); | 	mutex_unlock(&ft_mutex); | ||||||
| 
 | 	return rc; | ||||||
| 	if (rc == -ERESTARTSYS) |  | ||||||
| 		return restart_syscall(); |  | ||||||
| 	else |  | ||||||
| 		return rc; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  |  | ||||||
|  | @ -2,9 +2,10 @@ | ||||||
| #define _FCOE_LIBFCOE_H_ | #define _FCOE_LIBFCOE_H_ | ||||||
| 
 | 
 | ||||||
| extern unsigned int libfcoe_debug_logging; | extern unsigned int libfcoe_debug_logging; | ||||||
| #define LIBFCOE_LOGGING	    0x01 /* General logging, not categorized */ | #define LIBFCOE_LOGGING	          0x01 /* General logging, not categorized */ | ||||||
| #define LIBFCOE_FIP_LOGGING 0x02 /* FIP logging */ | #define LIBFCOE_FIP_LOGGING       0x02 /* FIP logging */ | ||||||
| #define LIBFCOE_TRANSPORT_LOGGING	0x04 /* FCoE transport logging */ | #define LIBFCOE_TRANSPORT_LOGGING 0x04 /* FCoE transport logging */ | ||||||
|  | #define LIBFCOE_SYSFS_LOGGING     0x08 /* fcoe_sysfs logging */ | ||||||
| 
 | 
 | ||||||
| #define LIBFCOE_CHECK_LOGGING(LEVEL, CMD)		\ | #define LIBFCOE_CHECK_LOGGING(LEVEL, CMD)		\ | ||||||
| do {							\ | do {							\ | ||||||
|  | @ -16,16 +17,19 @@ do {							\ | ||||||
| 
 | 
 | ||||||
| #define LIBFCOE_DBG(fmt, args...)					\ | #define LIBFCOE_DBG(fmt, args...)					\ | ||||||
| 	LIBFCOE_CHECK_LOGGING(LIBFCOE_LOGGING,				\ | 	LIBFCOE_CHECK_LOGGING(LIBFCOE_LOGGING,				\ | ||||||
| 			      printk(KERN_INFO "libfcoe: " fmt, ##args);) | 			      pr_info("libfcoe: " fmt, ##args);) | ||||||
| 
 | 
 | ||||||
| #define LIBFCOE_FIP_DBG(fip, fmt, args...)				\ | #define LIBFCOE_FIP_DBG(fip, fmt, args...)				\ | ||||||
| 	LIBFCOE_CHECK_LOGGING(LIBFCOE_FIP_LOGGING,			\ | 	LIBFCOE_CHECK_LOGGING(LIBFCOE_FIP_LOGGING,			\ | ||||||
| 			      printk(KERN_INFO "host%d: fip: " fmt,	\ | 			      pr_info("host%d: fip: " fmt,		\ | ||||||
| 				     (fip)->lp->host->host_no, ##args);) | 				      (fip)->lp->host->host_no, ##args);) | ||||||
| 
 | 
 | ||||||
| #define LIBFCOE_TRANSPORT_DBG(fmt, args...)				\ | #define LIBFCOE_TRANSPORT_DBG(fmt, args...)				\ | ||||||
| 	LIBFCOE_CHECK_LOGGING(LIBFCOE_TRANSPORT_LOGGING,		\ | 	LIBFCOE_CHECK_LOGGING(LIBFCOE_TRANSPORT_LOGGING,		\ | ||||||
| 			      printk(KERN_INFO "%s: " fmt,		\ | 			      pr_info("%s: " fmt, __func__, ##args);) | ||||||
| 				     __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_ */ | #endif /* _FCOE_LIBFCOE_H_ */ | ||||||
|  |  | ||||||
|  | @ -1381,10 +1381,10 @@ static void fc_fcp_timeout(unsigned long data) | ||||||
| 
 | 
 | ||||||
| 	fsp->state |= FC_SRB_FCP_PROCESSING_TMO; | 	fsp->state |= FC_SRB_FCP_PROCESSING_TMO; | ||||||
| 
 | 
 | ||||||
| 	if (fsp->state & FC_SRB_RCV_STATUS) | 	if (rpriv->flags & FC_RP_FLAGS_REC_SUPPORTED) | ||||||
| 		fc_fcp_complete_locked(fsp); |  | ||||||
| 	else if (rpriv->flags & FC_RP_FLAGS_REC_SUPPORTED) |  | ||||||
| 		fc_fcp_rec(fsp); | 		fc_fcp_rec(fsp); | ||||||
|  | 	else if (fsp->state & FC_SRB_RCV_STATUS) | ||||||
|  | 		fc_fcp_complete_locked(fsp); | ||||||
| 	else | 	else | ||||||
| 		fc_fcp_recovery(fsp, FC_TIMED_OUT); | 		fc_fcp_recovery(fsp, FC_TIMED_OUT); | ||||||
| 	fsp->state &= ~FC_SRB_FCP_PROCESSING_TMO; | 	fsp->state &= ~FC_SRB_FCP_PROCESSING_TMO; | ||||||
|  |  | ||||||
|  | @ -41,25 +41,25 @@ extern unsigned int fc_debug_logging; | ||||||
| 
 | 
 | ||||||
| #define FC_LIBFC_DBG(fmt, args...)					\ | #define FC_LIBFC_DBG(fmt, args...)					\ | ||||||
| 	FC_CHECK_LOGGING(FC_LIBFC_LOGGING,				\ | 	FC_CHECK_LOGGING(FC_LIBFC_LOGGING,				\ | ||||||
| 			 printk(KERN_INFO "libfc: " fmt, ##args)) | 			 pr_info("libfc: " fmt, ##args)) | ||||||
| 
 | 
 | ||||||
| #define FC_LPORT_DBG(lport, fmt, args...)				\ | #define FC_LPORT_DBG(lport, fmt, args...)				\ | ||||||
| 	FC_CHECK_LOGGING(FC_LPORT_LOGGING,				\ | 	FC_CHECK_LOGGING(FC_LPORT_LOGGING,				\ | ||||||
| 			 printk(KERN_INFO "host%u: lport %6.6x: " fmt,	\ | 			 pr_info("host%u: lport %6.6x: " fmt,		\ | ||||||
| 				(lport)->host->host_no,			\ | 				 (lport)->host->host_no,		\ | ||||||
| 				(lport)->port_id, ##args)) | 				 (lport)->port_id, ##args)) | ||||||
| 
 | 
 | ||||||
| #define FC_DISC_DBG(disc, fmt, args...)				\ | #define FC_DISC_DBG(disc, fmt, args...)					\ | ||||||
| 	FC_CHECK_LOGGING(FC_DISC_LOGGING,			\ | 	FC_CHECK_LOGGING(FC_DISC_LOGGING,				\ | ||||||
| 			 printk(KERN_INFO "host%u: disc: " fmt,	\ | 			 pr_info("host%u: disc: " fmt,			\ | ||||||
| 				fc_disc_lport(disc)->host->host_no,	\ | 				 fc_disc_lport(disc)->host->host_no,	\ | ||||||
| 				##args)) | 				 ##args)) | ||||||
| 
 | 
 | ||||||
| #define FC_RPORT_ID_DBG(lport, port_id, fmt, args...)			\ | #define FC_RPORT_ID_DBG(lport, port_id, fmt, args...)			\ | ||||||
| 	FC_CHECK_LOGGING(FC_RPORT_LOGGING,				\ | 	FC_CHECK_LOGGING(FC_RPORT_LOGGING,				\ | ||||||
| 			 printk(KERN_INFO "host%u: rport %6.6x: " fmt,	\ | 			 pr_info("host%u: rport %6.6x: " fmt,		\ | ||||||
| 				(lport)->host->host_no,			\ | 				 (lport)->host->host_no,		\ | ||||||
| 				(port_id), ##args)) | 				 (port_id), ##args)) | ||||||
| 
 | 
 | ||||||
| #define FC_RPORT_DBG(rdata, fmt, args...)				\ | #define FC_RPORT_DBG(rdata, fmt, args...)				\ | ||||||
| 	FC_RPORT_ID_DBG((rdata)->local_port, (rdata)->ids.port_id, 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) {					\ | 		if ((pkt)->seq_ptr) {					\ | ||||||
| 			struct fc_exch *_ep = NULL;			\ | 			struct fc_exch *_ep = NULL;			\ | ||||||
| 			_ep = fc_seq_exch((pkt)->seq_ptr);		\ | 			_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,			\ | 				"xid %04x-%04x: " fmt,			\ | ||||||
| 				(pkt)->lp->host->host_no,		\ | 				(pkt)->lp->host->host_no,		\ | ||||||
| 				(pkt)->rport->port_id,			\ | 				(pkt)->rport->port_id,			\ | ||||||
| 				(_ep)->oxid, (_ep)->rxid, ##args);	\ | 				(_ep)->oxid, (_ep)->rxid, ##args);	\ | ||||||
| 		} else {						\ | 		} else {						\ | ||||||
| 			printk(KERN_INFO "host%u: fcp: %6.6x: " fmt,	\ | 			pr_info("host%u: fcp: %6.6x: " fmt,		\ | ||||||
| 				(pkt)->lp->host->host_no,		\ | 				(pkt)->lp->host->host_no,		\ | ||||||
| 				(pkt)->rport->port_id, ##args);		\ | 				(pkt)->rport->port_id, ##args);		\ | ||||||
| 		}							\ | 		}							\ | ||||||
|  | @ -84,14 +84,14 @@ extern unsigned int fc_debug_logging; | ||||||
| 
 | 
 | ||||||
| #define FC_EXCH_DBG(exch, fmt, args...)					\ | #define FC_EXCH_DBG(exch, fmt, args...)					\ | ||||||
| 	FC_CHECK_LOGGING(FC_EXCH_LOGGING,				\ | 	FC_CHECK_LOGGING(FC_EXCH_LOGGING,				\ | ||||||
| 			 printk(KERN_INFO "host%u: xid %4x: " fmt,	\ | 			 pr_info("host%u: xid %4x: " fmt,		\ | ||||||
| 				(exch)->lp->host->host_no,		\ | 				 (exch)->lp->host->host_no,		\ | ||||||
| 				exch->xid, ##args)) | 				 exch->xid, ##args)) | ||||||
| 
 | 
 | ||||||
| #define FC_SCSI_DBG(lport, fmt, args...)				\ | #define FC_SCSI_DBG(lport, fmt, args...)				\ | ||||||
| 	FC_CHECK_LOGGING(FC_SCSI_LOGGING,				\ | 	FC_CHECK_LOGGING(FC_SCSI_LOGGING,				\ | ||||||
| 			 printk(KERN_INFO "host%u: scsi: " fmt,		\ | 			 pr_info("host%u: scsi: " fmt,			\ | ||||||
| 				(lport)->host->host_no,	##args)) | 				 (lport)->host->host_no, ##args)) | ||||||
| 
 | 
 | ||||||
| /*
 | /*
 | ||||||
|  * FC-4 Providers. |  * 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, | static void fc_rport_error_retry(struct fc_rport_priv *rdata, | ||||||
| 				 struct fc_frame *fp) | 				 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 */ | 	/* make sure this isn't an FC_EX_CLOSED error, never retry those */ | ||||||
| 	if (PTR_ERR(fp) == -FC_EX_CLOSED) | 	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_symb_err)(struct fcoe_ctlr_device *); | ||||||
| 	void (*get_fcoe_ctlr_err_block)(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_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_selected)(struct fcoe_fcf_device *); | ||||||
| 	void (*get_fcoe_fcf_vlan_id)(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, | 	FIP_CONN_TYPE_VN2VN, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | enum ctlr_enabled_state { | ||||||
|  | 	FCOE_CTLR_ENABLED, | ||||||
|  | 	FCOE_CTLR_DISABLED, | ||||||
|  | 	FCOE_CTLR_UNUSED, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| struct fcoe_ctlr_device { | struct fcoe_ctlr_device { | ||||||
| 	u32				id; | 	u32				id; | ||||||
| 
 | 
 | ||||||
|  | @ -64,6 +71,8 @@ struct fcoe_ctlr_device { | ||||||
| 	int                             fcf_dev_loss_tmo; | 	int                             fcf_dev_loss_tmo; | ||||||
| 	enum fip_conn_type              mode; | 	enum fip_conn_type              mode; | ||||||
| 
 | 
 | ||||||
|  | 	enum ctlr_enabled_state         enabled; | ||||||
|  | 
 | ||||||
| 	/* expected in host order for displaying */ | 	/* expected in host order for displaying */ | ||||||
| 	struct fcoe_fc_els_lesb         lesb; | 	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); | 		     struct net_device *netdev); | ||||||
| void fcoe_wwn_to_str(u64 wwn, char *buf, int len); | void fcoe_wwn_to_str(u64 wwn, char *buf, int len); | ||||||
| int fcoe_validate_vport_create(struct fc_vport *vport); | 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. |  * 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 |  * @attached:	whether this transport is already attached | ||||||
|  * @list:	list linkage to all attached transports |  * @list:	list linkage to all attached transports | ||||||
|  * @match:	handler to allow the transport driver to match up a given netdev |  * @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 |  * @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 |  * @enable:	handler to sysfs entry of enable for FCoE instances | ||||||
|  * @disable:	handler to sysfs entry of disable for FCoE instances |  * @disable:	handler to sysfs entry of disable for FCoE instances | ||||||
|  */ |  */ | ||||||
|  | @ -299,6 +305,7 @@ struct fcoe_transport { | ||||||
| 	bool attached; | 	bool attached; | ||||||
| 	struct list_head list; | 	struct list_head list; | ||||||
| 	bool (*match) (struct net_device *device); | 	bool (*match) (struct net_device *device); | ||||||
|  | 	int (*alloc) (struct net_device *device); | ||||||
| 	int (*create) (struct net_device *device, enum fip_state fip_mode); | 	int (*create) (struct net_device *device, enum fip_state fip_mode); | ||||||
| 	int (*destroy) (struct net_device *device); | 	int (*destroy) (struct net_device *device); | ||||||
| 	int (*enable) (struct net_device *device); | 	int (*enable) (struct net_device *device); | ||||||
|  | @ -347,7 +354,20 @@ struct fcoe_port { | ||||||
| 	struct timer_list     timer; | 	struct timer_list     timer; | ||||||
| 	struct work_struct    destroy_work; | 	struct work_struct    destroy_work; | ||||||
| 	u8		      data_src_addr[ETH_ALEN]; | 	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_clean_pending_queue(struct fc_lport *); | ||||||
| void fcoe_check_wait_queue(struct fc_lport *lport, struct sk_buff *skb); | void fcoe_check_wait_queue(struct fc_lport *lport, struct sk_buff *skb); | ||||||
| void fcoe_queue_timer(ulong lport); | 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 */ | /* FCoE Sysfs helpers */ | ||||||
| void fcoe_fcf_get_selected(struct fcoe_fcf_device *); | 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 |  * struct netdev_list | ||||||
|  | @ -372,4 +392,12 @@ struct fcoe_netdev_mapping { | ||||||
| int fcoe_transport_attach(struct fcoe_transport *ft); | int fcoe_transport_attach(struct fcoe_transport *ft); | ||||||
| int fcoe_transport_detach(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 */ | #endif /* _LIBFCOE_H */ | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |  | ||||||
|  | @ -1 +1,5 @@ | ||||||
| # UAPI Header export list | # 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…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 James Bottomley
				James Bottomley