[SCSI] fcoe: convert fcoe.ko to become an fcoe transport provider driver

Remove the existing sysfs entry points of the fcoe.ko module parameters that
are used to create/destroy/enable/disable an FCoE instance, rather, use the
newly added fcoe transport code to attach itself as an FCoE transport provider
when fcoe.ko gets loaded. There is no functionality change on the logic of
fcoe interacts with upper libfc and lower netdev. The fcoe transport only acts
as thin layer to provide a unified interface for all fcoe transport providers
so all FCoE instances on any network interfaces from all vendors can be
managed through the same Open-FCoE.org's user space tool package, which also
has full DCB support.

Signed-off-by: Yi Zou <yi.zou@intel.com>
Signed-off-by: Bhanu Prakash Gollapudi <bprakash@broadcom.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
This commit is contained in:
Yi Zou 2011-01-28 16:05:16 -08:00 committed by James Bottomley
parent 8ca86f84dd
commit 78a582463c

View File

@ -101,10 +101,11 @@ static int fcoe_ddp_done(struct fc_lport *, u16);
static int fcoe_cpu_callback(struct notifier_block *, unsigned long, void *); static int fcoe_cpu_callback(struct notifier_block *, unsigned long, void *);
static int fcoe_create(const char *, struct kernel_param *); static bool fcoe_match(struct net_device *netdev);
static int fcoe_destroy(const char *, struct kernel_param *); static int fcoe_create(struct net_device *netdev, enum fip_state fip_mode);
static int fcoe_enable(const char *, struct kernel_param *); static int fcoe_destroy(struct net_device *netdev);
static int fcoe_disable(const char *, struct kernel_param *); static int fcoe_enable(struct net_device *netdev);
static int fcoe_disable(struct net_device *netdev);
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 *,
@ -117,24 +118,6 @@ static void fcoe_recv_frame(struct sk_buff *skb);
static void fcoe_get_lesb(struct fc_lport *, struct fc_els_lesb *); static void fcoe_get_lesb(struct fc_lport *, struct fc_els_lesb *);
module_param_call(create, fcoe_create, NULL, (void *)FIP_MODE_FABRIC, S_IWUSR);
__MODULE_PARM_TYPE(create, "string");
MODULE_PARM_DESC(create, " Creates fcoe instance on a ethernet interface");
module_param_call(create_vn2vn, fcoe_create, NULL,
(void *)FIP_MODE_VN2VN, S_IWUSR);
__MODULE_PARM_TYPE(create_vn2vn, "string");
MODULE_PARM_DESC(create_vn2vn, " Creates a VN_node to VN_node FCoE instance "
"on an Ethernet interface");
module_param_call(destroy, fcoe_destroy, NULL, NULL, S_IWUSR);
__MODULE_PARM_TYPE(destroy, "string");
MODULE_PARM_DESC(destroy, " Destroys fcoe instance on a ethernet interface");
module_param_call(enable, fcoe_enable, NULL, NULL, S_IWUSR);
__MODULE_PARM_TYPE(enable, "string");
MODULE_PARM_DESC(enable, " Enables fcoe on a ethernet interface.");
module_param_call(disable, fcoe_disable, NULL, NULL, S_IWUSR);
__MODULE_PARM_TYPE(disable, "string");
MODULE_PARM_DESC(disable, " Disables fcoe on a ethernet interface.");
/* 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,
@ -1938,40 +1921,17 @@ out:
return rc; return rc;
} }
/**
* fcoe_if_to_netdev() - Parse a name buffer to get a net device
* @buffer: The name of the net device
*
* Returns: NULL or a ptr to net_device
*/
static struct net_device *fcoe_if_to_netdev(const char *buffer)
{
char *cp;
char ifname[IFNAMSIZ + 2];
if (buffer) {
strlcpy(ifname, buffer, IFNAMSIZ);
cp = ifname + strlen(ifname);
while (--cp >= ifname && *cp == '\n')
*cp = '\0';
return dev_get_by_name(&init_net, ifname);
}
return NULL;
}
/** /**
* fcoe_disable() - Disables a FCoE interface * fcoe_disable() - Disables a FCoE interface
* @buffer: The name of the Ethernet interface to be disabled * @netdev : The net_device object the Ethernet interface to create on
* @kp: The associated kernel parameter
* *
* Called from sysfs. * Called from fcoe transport.
* *
* Returns: 0 for success * Returns: 0 for success
*/ */
static int fcoe_disable(const char *buffer, struct kernel_param *kp) static int fcoe_disable(struct net_device *netdev)
{ {
struct fcoe_interface *fcoe; struct fcoe_interface *fcoe;
struct net_device *netdev;
int rc = 0; int rc = 0;
mutex_lock(&fcoe_config_mutex); mutex_lock(&fcoe_config_mutex);
@ -1987,16 +1947,9 @@ static int fcoe_disable(const char *buffer, struct kernel_param *kp)
} }
#endif #endif
netdev = fcoe_if_to_netdev(buffer);
if (!netdev) {
rc = -ENODEV;
goto out_nodev;
}
if (!rtnl_trylock()) { if (!rtnl_trylock()) {
dev_put(netdev);
mutex_unlock(&fcoe_config_mutex); mutex_unlock(&fcoe_config_mutex);
return restart_syscall(); return -ERESTARTSYS;
} }
fcoe = fcoe_hostlist_lookup_port(netdev); fcoe = fcoe_hostlist_lookup_port(netdev);
@ -2008,7 +1961,6 @@ static int fcoe_disable(const char *buffer, struct kernel_param *kp)
} else } else
rc = -ENODEV; rc = -ENODEV;
dev_put(netdev);
out_nodev: out_nodev:
mutex_unlock(&fcoe_config_mutex); mutex_unlock(&fcoe_config_mutex);
return rc; return rc;
@ -2016,17 +1968,15 @@ out_nodev:
/** /**
* fcoe_enable() - Enables a FCoE interface * fcoe_enable() - Enables a FCoE interface
* @buffer: The name of the Ethernet interface to be enabled * @netdev : The net_device object the Ethernet interface to create on
* @kp: The associated kernel parameter
* *
* Called from sysfs. * Called from fcoe transport.
* *
* Returns: 0 for success * Returns: 0 for success
*/ */
static int fcoe_enable(const char *buffer, struct kernel_param *kp) static int fcoe_enable(struct net_device *netdev)
{ {
struct fcoe_interface *fcoe; struct fcoe_interface *fcoe;
struct net_device *netdev;
int rc = 0; int rc = 0;
mutex_lock(&fcoe_config_mutex); mutex_lock(&fcoe_config_mutex);
@ -2041,17 +1991,9 @@ static int fcoe_enable(const char *buffer, struct kernel_param *kp)
goto out_nodev; goto out_nodev;
} }
#endif #endif
netdev = fcoe_if_to_netdev(buffer);
if (!netdev) {
rc = -ENODEV;
goto out_nodev;
}
if (!rtnl_trylock()) { if (!rtnl_trylock()) {
dev_put(netdev);
mutex_unlock(&fcoe_config_mutex); mutex_unlock(&fcoe_config_mutex);
return restart_syscall(); return -ERESTARTSYS;
} }
fcoe = fcoe_hostlist_lookup_port(netdev); fcoe = fcoe_hostlist_lookup_port(netdev);
@ -2062,7 +2004,6 @@ static int fcoe_enable(const char *buffer, struct kernel_param *kp)
else if (!fcoe_link_ok(fcoe->ctlr.lp)) else if (!fcoe_link_ok(fcoe->ctlr.lp))
fcoe_ctlr_link_up(&fcoe->ctlr); fcoe_ctlr_link_up(&fcoe->ctlr);
dev_put(netdev);
out_nodev: out_nodev:
mutex_unlock(&fcoe_config_mutex); mutex_unlock(&fcoe_config_mutex);
return rc; return rc;
@ -2070,17 +2011,15 @@ out_nodev:
/** /**
* fcoe_destroy() - Destroy a FCoE interface * fcoe_destroy() - Destroy a FCoE interface
* @buffer: The name of the Ethernet interface to be destroyed * @netdev : The net_device object the Ethernet interface to create on
* @kp: The associated kernel parameter
* *
* Called from sysfs. * Called from fcoe transport
* *
* Returns: 0 for success * Returns: 0 for success
*/ */
static int fcoe_destroy(const char *buffer, struct kernel_param *kp) static int fcoe_destroy(struct net_device *netdev)
{ {
struct fcoe_interface *fcoe; struct fcoe_interface *fcoe;
struct net_device *netdev;
int rc = 0; int rc = 0;
mutex_lock(&fcoe_config_mutex); mutex_lock(&fcoe_config_mutex);
@ -2095,32 +2034,21 @@ static int fcoe_destroy(const char *buffer, struct kernel_param *kp)
goto out_nodev; goto out_nodev;
} }
#endif #endif
netdev = fcoe_if_to_netdev(buffer);
if (!netdev) {
rc = -ENODEV;
goto out_nodev;
}
if (!rtnl_trylock()) { if (!rtnl_trylock()) {
dev_put(netdev);
mutex_unlock(&fcoe_config_mutex); mutex_unlock(&fcoe_config_mutex);
return restart_syscall(); return -ERESTARTSYS;
} }
fcoe = fcoe_hostlist_lookup_port(netdev); fcoe = fcoe_hostlist_lookup_port(netdev);
if (!fcoe) { if (!fcoe) {
rtnl_unlock(); rtnl_unlock();
rc = -ENODEV; rc = -ENODEV;
goto out_putdev; goto out_nodev;
} }
fcoe_interface_cleanup(fcoe); fcoe_interface_cleanup(fcoe);
list_del(&fcoe->list); list_del(&fcoe->list);
/* RTNL mutex is dropped by fcoe_if_destroy */ /* RTNL mutex is dropped by fcoe_if_destroy */
fcoe_if_destroy(fcoe->ctlr.lp); fcoe_if_destroy(fcoe->ctlr.lp);
out_putdev:
dev_put(netdev);
out_nodev: out_nodev:
mutex_unlock(&fcoe_config_mutex); mutex_unlock(&fcoe_config_mutex);
return rc; return rc;
@ -2143,27 +2071,39 @@ static void fcoe_destroy_work(struct work_struct *work)
} }
/** /**
* fcoe_create() - Create a fcoe interface * fcoe_match() - Check if the FCoE is supported on the given netdevice
* @buffer: The name of the Ethernet interface to create on * @netdev : The net_device object the Ethernet interface to create on
* @kp: The associated kernel param
* *
* Called from sysfs. * Called from fcoe transport.
*
* Returns: always returns true as this is the default FCoE transport,
* i.e., support all netdevs.
*/
static bool fcoe_match(struct net_device *netdev)
{
return true;
}
/**
* fcoe_create() - Create a fcoe interface
* @netdev : The net_device object the Ethernet interface to create on
* @fip_mode: The FIP mode for this creation
*
* Called from fcoe transport
* *
* Returns: 0 for success * Returns: 0 for success
*/ */
static int fcoe_create(const char *buffer, struct kernel_param *kp) static int fcoe_create(struct net_device *netdev, enum fip_state fip_mode)
{ {
enum fip_state fip_mode = (enum fip_state)(long)kp->arg;
int rc; int rc;
struct fcoe_interface *fcoe; struct fcoe_interface *fcoe;
struct fc_lport *lport; struct fc_lport *lport;
struct net_device *netdev;
mutex_lock(&fcoe_config_mutex); mutex_lock(&fcoe_config_mutex);
if (!rtnl_trylock()) { if (!rtnl_trylock()) {
mutex_unlock(&fcoe_config_mutex); mutex_unlock(&fcoe_config_mutex);
return restart_syscall(); return -ERESTARTSYS;
} }
#ifdef CONFIG_FCOE_MODULE #ifdef CONFIG_FCOE_MODULE
@ -2178,22 +2118,16 @@ static int fcoe_create(const char *buffer, struct kernel_param *kp)
} }
#endif #endif
netdev = fcoe_if_to_netdev(buffer);
if (!netdev) {
rc = -ENODEV;
goto out_nodev;
}
/* look for existing lport */ /* look for existing lport */
if (fcoe_hostlist_lookup(netdev)) { if (fcoe_hostlist_lookup(netdev)) {
rc = -EEXIST; rc = -EEXIST;
goto out_putdev; goto out_nodev;
} }
fcoe = fcoe_interface_create(netdev, fip_mode); fcoe = fcoe_interface_create(netdev, fip_mode);
if (IS_ERR(fcoe)) { if (IS_ERR(fcoe)) {
rc = PTR_ERR(fcoe); rc = PTR_ERR(fcoe);
goto out_putdev; goto out_nodev;
} }
lport = fcoe_if_create(fcoe, &netdev->dev, 0); lport = fcoe_if_create(fcoe, &netdev->dev, 0);
@ -2222,15 +2156,12 @@ static int fcoe_create(const char *buffer, struct kernel_param *kp)
* should be holding a reference taken in fcoe_if_create(). * should be holding a reference taken in fcoe_if_create().
*/ */
fcoe_interface_put(fcoe); fcoe_interface_put(fcoe);
dev_put(netdev);
rtnl_unlock(); rtnl_unlock();
mutex_unlock(&fcoe_config_mutex); mutex_unlock(&fcoe_config_mutex);
return 0; return 0;
out_free: out_free:
fcoe_interface_put(fcoe); fcoe_interface_put(fcoe);
out_putdev:
dev_put(netdev);
out_nodev: out_nodev:
rtnl_unlock(); rtnl_unlock();
mutex_unlock(&fcoe_config_mutex); mutex_unlock(&fcoe_config_mutex);
@ -2433,6 +2364,18 @@ static int fcoe_hostlist_add(const struct fc_lport *lport)
return 0; return 0;
} }
static struct fcoe_transport fcoe_sw_transport = {
.name = {FCOE_TRANSPORT_DEFAULT},
.attached = false,
.list = LIST_HEAD_INIT(fcoe_sw_transport.list),
.match = fcoe_match,
.create = fcoe_create,
.destroy = fcoe_destroy,
.enable = fcoe_enable,
.disable = fcoe_disable,
};
/** /**
* fcoe_init() - Initialize fcoe.ko * fcoe_init() - Initialize fcoe.ko
* *
@ -2444,6 +2387,14 @@ static int __init fcoe_init(void)
unsigned int cpu; unsigned int cpu;
int rc = 0; int rc = 0;
/* register as a fcoe transport */
rc = fcoe_transport_attach(&fcoe_sw_transport);
if (rc) {
printk(KERN_ERR "failed to register an fcoe transport, check "
"if libfcoe is loaded\n");
return rc;
}
mutex_lock(&fcoe_config_mutex); mutex_lock(&fcoe_config_mutex);
for_each_possible_cpu(cpu) { for_each_possible_cpu(cpu) {
@ -2520,6 +2471,9 @@ static void __exit fcoe_exit(void)
/* detach from scsi transport /* detach from scsi transport
* must happen after all destroys are done, therefor after the flush */ * must happen after all destroys are done, therefor after the flush */
fcoe_if_exit(); fcoe_if_exit();
/* detach from fcoe transport */
fcoe_transport_detach(&fcoe_sw_transport);
} }
module_exit(fcoe_exit); module_exit(fcoe_exit);