1fdecf31bSYi Zou /* 2fdecf31bSYi Zou * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. 3fdecf31bSYi Zou * 4fdecf31bSYi Zou * This program is free software; you can redistribute it and/or modify it 5fdecf31bSYi Zou * under the terms and conditions of the GNU General Public License, 6fdecf31bSYi Zou * version 2, as published by the Free Software Foundation. 7fdecf31bSYi Zou * 8fdecf31bSYi Zou * This program is distributed in the hope it will be useful, but WITHOUT 9fdecf31bSYi Zou * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10fdecf31bSYi Zou * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11fdecf31bSYi Zou * more details. 12fdecf31bSYi Zou * 13fdecf31bSYi Zou * You should have received a copy of the GNU General Public License along with 14fdecf31bSYi Zou * this program; if not, write to the Free Software Foundation, Inc., 15fdecf31bSYi Zou * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. 16fdecf31bSYi Zou * 17fdecf31bSYi Zou * Maintained at www.Open-FCoE.org 18fdecf31bSYi Zou */ 19fdecf31bSYi Zou 20fdecf31bSYi Zou #include <linux/types.h> 21fdecf31bSYi Zou #include <linux/module.h> 22fdecf31bSYi Zou #include <linux/kernel.h> 23fdecf31bSYi Zou #include <linux/list.h> 24fdecf31bSYi Zou #include <linux/netdevice.h> 25fdecf31bSYi Zou #include <linux/errno.h> 26fdecf31bSYi Zou #include <scsi/libfcoe.h> 27fdecf31bSYi Zou 28fdecf31bSYi Zou #include "libfcoe.h" 29fdecf31bSYi Zou 30fdecf31bSYi Zou static int fcoe_transport_create(const char *, struct kernel_param *); 31fdecf31bSYi Zou static int fcoe_transport_destroy(const char *, struct kernel_param *); 32fdecf31bSYi Zou static int fcoe_transport_show(char *buffer, const struct kernel_param *kp); 33fdecf31bSYi Zou static struct fcoe_transport *fcoe_transport_lookup(struct net_device *device); 34fdecf31bSYi Zou static struct fcoe_transport *fcoe_netdev_map_lookup(struct net_device *device); 35fdecf31bSYi Zou static int fcoe_transport_enable(const char *, struct kernel_param *); 36fdecf31bSYi Zou static int fcoe_transport_disable(const char *, struct kernel_param *); 37fdecf31bSYi Zou 38fdecf31bSYi Zou static LIST_HEAD(fcoe_transports); 39fdecf31bSYi Zou static LIST_HEAD(fcoe_netdevs); 40fdecf31bSYi Zou static DEFINE_MUTEX(ft_mutex); 41fdecf31bSYi Zou 42fdecf31bSYi Zou module_param_call(show, NULL, fcoe_transport_show, NULL, S_IRUSR); 43fdecf31bSYi Zou __MODULE_PARM_TYPE(show, "string"); 44fdecf31bSYi Zou MODULE_PARM_DESC(show, " Show attached FCoE transports"); 45fdecf31bSYi Zou 46fdecf31bSYi Zou module_param_call(create, fcoe_transport_create, NULL, 47fdecf31bSYi Zou (void *)FIP_MODE_FABRIC, S_IWUSR); 48fdecf31bSYi Zou __MODULE_PARM_TYPE(create, "string"); 49fdecf31bSYi Zou MODULE_PARM_DESC(create, " Creates fcoe instance on a ethernet interface"); 50fdecf31bSYi Zou 51fdecf31bSYi Zou module_param_call(create_vn2vn, fcoe_transport_create, NULL, 52fdecf31bSYi Zou (void *)FIP_MODE_VN2VN, S_IWUSR); 53fdecf31bSYi Zou __MODULE_PARM_TYPE(create_vn2vn, "string"); 54fdecf31bSYi Zou MODULE_PARM_DESC(create_vn2vn, " Creates a VN_node to VN_node FCoE instance " 55fdecf31bSYi Zou "on an Ethernet interface"); 56fdecf31bSYi Zou 57fdecf31bSYi Zou module_param_call(destroy, fcoe_transport_destroy, NULL, NULL, S_IWUSR); 58fdecf31bSYi Zou __MODULE_PARM_TYPE(destroy, "string"); 59fdecf31bSYi Zou MODULE_PARM_DESC(destroy, " Destroys fcoe instance on a ethernet interface"); 60fdecf31bSYi Zou 61fdecf31bSYi Zou module_param_call(enable, fcoe_transport_enable, NULL, NULL, S_IWUSR); 62fdecf31bSYi Zou __MODULE_PARM_TYPE(enable, "string"); 63fdecf31bSYi Zou MODULE_PARM_DESC(enable, " Enables fcoe on a ethernet interface."); 64fdecf31bSYi Zou 65fdecf31bSYi Zou module_param_call(disable, fcoe_transport_disable, NULL, NULL, S_IWUSR); 66fdecf31bSYi Zou __MODULE_PARM_TYPE(disable, "string"); 67fdecf31bSYi Zou MODULE_PARM_DESC(disable, " Disables fcoe on a ethernet interface."); 68fdecf31bSYi Zou 69fdecf31bSYi Zou /** 70fdecf31bSYi Zou * fcoe_transport_lookup - find an fcoe transport that matches a netdev 71fdecf31bSYi Zou * @netdev: The netdev to look for from all attached transports 72fdecf31bSYi Zou * 73fdecf31bSYi Zou * Returns : ptr to the fcoe transport that supports this netdev or NULL 74fdecf31bSYi Zou * if not found. 75fdecf31bSYi Zou * 76fdecf31bSYi Zou * The ft_mutex should be held when this is called 77fdecf31bSYi Zou */ 78fdecf31bSYi Zou static struct fcoe_transport *fcoe_transport_lookup(struct net_device *netdev) 79fdecf31bSYi Zou { 80fdecf31bSYi Zou struct fcoe_transport *ft = NULL; 81fdecf31bSYi Zou 82fdecf31bSYi Zou list_for_each_entry(ft, &fcoe_transports, list) 83fdecf31bSYi Zou if (ft->match && ft->match(netdev)) 84fdecf31bSYi Zou return ft; 85fdecf31bSYi Zou return NULL; 86fdecf31bSYi Zou } 87fdecf31bSYi Zou 88fdecf31bSYi Zou /** 89fdecf31bSYi Zou * fcoe_transport_attach - Attaches an FCoE transport 90fdecf31bSYi Zou * @ft: The fcoe transport to be attached 91fdecf31bSYi Zou * 92fdecf31bSYi Zou * Returns : 0 for success 93fdecf31bSYi Zou */ 94fdecf31bSYi Zou int fcoe_transport_attach(struct fcoe_transport *ft) 95fdecf31bSYi Zou { 96fdecf31bSYi Zou int rc = 0; 97fdecf31bSYi Zou 98fdecf31bSYi Zou mutex_lock(&ft_mutex); 99fdecf31bSYi Zou if (ft->attached) { 100fdecf31bSYi Zou LIBFCOE_TRANSPORT_DBG("transport %s already attached\n", 101fdecf31bSYi Zou ft->name); 102fdecf31bSYi Zou rc = -EEXIST; 103fdecf31bSYi Zou goto out_attach; 104fdecf31bSYi Zou } 105fdecf31bSYi Zou 106fdecf31bSYi Zou /* Add default transport to the tail */ 107fdecf31bSYi Zou if (strcmp(ft->name, FCOE_TRANSPORT_DEFAULT)) 108fdecf31bSYi Zou list_add(&ft->list, &fcoe_transports); 109fdecf31bSYi Zou else 110fdecf31bSYi Zou list_add_tail(&ft->list, &fcoe_transports); 111fdecf31bSYi Zou 112fdecf31bSYi Zou ft->attached = true; 113fdecf31bSYi Zou LIBFCOE_TRANSPORT_DBG("attaching transport %s\n", ft->name); 114fdecf31bSYi Zou 115fdecf31bSYi Zou out_attach: 116fdecf31bSYi Zou mutex_unlock(&ft_mutex); 117fdecf31bSYi Zou return rc; 118fdecf31bSYi Zou } 119fdecf31bSYi Zou EXPORT_SYMBOL(fcoe_transport_attach); 120fdecf31bSYi Zou 121fdecf31bSYi Zou /** 122fdecf31bSYi Zou * fcoe_transport_attach - Detaches an FCoE transport 123fdecf31bSYi Zou * @ft: The fcoe transport to be attached 124fdecf31bSYi Zou * 125fdecf31bSYi Zou * Returns : 0 for success 126fdecf31bSYi Zou */ 127fdecf31bSYi Zou int fcoe_transport_detach(struct fcoe_transport *ft) 128fdecf31bSYi Zou { 129fdecf31bSYi Zou int rc = 0; 130fdecf31bSYi Zou 131fdecf31bSYi Zou mutex_lock(&ft_mutex); 132fdecf31bSYi Zou if (!ft->attached) { 133fdecf31bSYi Zou LIBFCOE_TRANSPORT_DBG("transport %s already detached\n", 134fdecf31bSYi Zou ft->name); 135fdecf31bSYi Zou rc = -ENODEV; 136fdecf31bSYi Zou goto out_attach; 137fdecf31bSYi Zou } 138fdecf31bSYi Zou 139fdecf31bSYi Zou list_del(&ft->list); 140fdecf31bSYi Zou ft->attached = false; 141fdecf31bSYi Zou LIBFCOE_TRANSPORT_DBG("detaching transport %s\n", ft->name); 142fdecf31bSYi Zou 143fdecf31bSYi Zou out_attach: 144fdecf31bSYi Zou mutex_unlock(&ft_mutex); 145fdecf31bSYi Zou return rc; 146fdecf31bSYi Zou 147fdecf31bSYi Zou } 148fdecf31bSYi Zou EXPORT_SYMBOL(fcoe_transport_detach); 149fdecf31bSYi Zou 150fdecf31bSYi Zou static int fcoe_transport_show(char *buffer, const struct kernel_param *kp) 151fdecf31bSYi Zou { 152fdecf31bSYi Zou int i, j; 153fdecf31bSYi Zou struct fcoe_transport *ft = NULL; 154fdecf31bSYi Zou 155fdecf31bSYi Zou i = j = sprintf(buffer, "Attached FCoE transports:"); 156fdecf31bSYi Zou mutex_lock(&ft_mutex); 157fdecf31bSYi Zou list_for_each_entry(ft, &fcoe_transports, list) { 158fdecf31bSYi Zou i += snprintf(&buffer[i], IFNAMSIZ, "%s ", ft->name); 159fdecf31bSYi Zou if (i >= PAGE_SIZE) 160fdecf31bSYi Zou break; 161fdecf31bSYi Zou } 162fdecf31bSYi Zou mutex_unlock(&ft_mutex); 163fdecf31bSYi Zou if (i == j) 164fdecf31bSYi Zou i += snprintf(&buffer[i], IFNAMSIZ, "none"); 165fdecf31bSYi Zou return i; 166fdecf31bSYi Zou } 167fdecf31bSYi Zou 168fdecf31bSYi Zou static int __init fcoe_transport_init(void) 169fdecf31bSYi Zou { 170fdecf31bSYi Zou return 0; 171fdecf31bSYi Zou } 172fdecf31bSYi Zou 173fdecf31bSYi Zou static int __exit fcoe_transport_exit(void) 174fdecf31bSYi Zou { 175fdecf31bSYi Zou struct fcoe_transport *ft; 176fdecf31bSYi Zou 177fdecf31bSYi Zou mutex_lock(&ft_mutex); 178fdecf31bSYi Zou list_for_each_entry(ft, &fcoe_transports, list) 179fdecf31bSYi Zou printk(KERN_ERR "FCoE transport %s is still attached!\n", 180fdecf31bSYi Zou ft->name); 181fdecf31bSYi Zou mutex_unlock(&ft_mutex); 182fdecf31bSYi Zou return 0; 183fdecf31bSYi Zou } 184fdecf31bSYi Zou 185fdecf31bSYi Zou 186fdecf31bSYi Zou static int fcoe_add_netdev_mapping(struct net_device *netdev, 187fdecf31bSYi Zou struct fcoe_transport *ft) 188fdecf31bSYi Zou { 189fdecf31bSYi Zou struct fcoe_netdev_mapping *nm; 190fdecf31bSYi Zou 191fdecf31bSYi Zou nm = kmalloc(sizeof(*nm), GFP_KERNEL); 192fdecf31bSYi Zou if (!nm) { 193fdecf31bSYi Zou printk(KERN_ERR "Unable to allocate netdev_mapping"); 194fdecf31bSYi Zou return -ENOMEM; 195fdecf31bSYi Zou } 196fdecf31bSYi Zou 197fdecf31bSYi Zou nm->netdev = netdev; 198fdecf31bSYi Zou nm->ft = ft; 199fdecf31bSYi Zou 200fdecf31bSYi Zou list_add(&nm->list, &fcoe_netdevs); 201fdecf31bSYi Zou return 0; 202fdecf31bSYi Zou } 203fdecf31bSYi Zou 204fdecf31bSYi Zou 205fdecf31bSYi Zou static void fcoe_del_netdev_mapping(struct net_device *netdev) 206fdecf31bSYi Zou { 207fdecf31bSYi Zou struct fcoe_netdev_mapping *nm = NULL, *tmp; 208fdecf31bSYi Zou 209fdecf31bSYi Zou list_for_each_entry_safe(nm, tmp, &fcoe_netdevs, list) { 210fdecf31bSYi Zou if (nm->netdev == netdev) { 211fdecf31bSYi Zou list_del(&nm->list); 212fdecf31bSYi Zou kfree(nm); 213fdecf31bSYi Zou return; 214fdecf31bSYi Zou } 215fdecf31bSYi Zou } 216fdecf31bSYi Zou } 217fdecf31bSYi Zou 218fdecf31bSYi Zou 219fdecf31bSYi Zou /** 220fdecf31bSYi Zou * fcoe_netdev_map_lookup - find the fcoe transport that matches the netdev on which 221fdecf31bSYi Zou * it was created 222fdecf31bSYi Zou * 223fdecf31bSYi Zou * Returns : ptr to the fcoe transport that supports this netdev or NULL 224fdecf31bSYi Zou * if not found. 225fdecf31bSYi Zou * 226fdecf31bSYi Zou * The ft_mutex should be held when this is called 227fdecf31bSYi Zou */ 228fdecf31bSYi Zou static struct fcoe_transport *fcoe_netdev_map_lookup(struct net_device *netdev) 229fdecf31bSYi Zou { 230fdecf31bSYi Zou struct fcoe_transport *ft = NULL; 231fdecf31bSYi Zou struct fcoe_netdev_mapping *nm; 232fdecf31bSYi Zou 233fdecf31bSYi Zou list_for_each_entry(nm, &fcoe_netdevs, list) { 234fdecf31bSYi Zou if (netdev == nm->netdev) { 235fdecf31bSYi Zou ft = nm->ft; 236fdecf31bSYi Zou return ft; 237fdecf31bSYi Zou } 238fdecf31bSYi Zou } 239fdecf31bSYi Zou 240fdecf31bSYi Zou return NULL; 241fdecf31bSYi Zou } 242fdecf31bSYi Zou 243fdecf31bSYi Zou /** 244fdecf31bSYi Zou * fcoe_if_to_netdev() - Parse a name buffer to get a net device 245fdecf31bSYi Zou * @buffer: The name of the net device 246fdecf31bSYi Zou * 247fdecf31bSYi Zou * Returns: NULL or a ptr to net_device 248fdecf31bSYi Zou */ 249fdecf31bSYi Zou static struct net_device *fcoe_if_to_netdev(const char *buffer) 250fdecf31bSYi Zou { 251fdecf31bSYi Zou char *cp; 252fdecf31bSYi Zou char ifname[IFNAMSIZ + 2]; 253fdecf31bSYi Zou 254fdecf31bSYi Zou if (buffer) { 255fdecf31bSYi Zou strlcpy(ifname, buffer, IFNAMSIZ); 256fdecf31bSYi Zou cp = ifname + strlen(ifname); 257fdecf31bSYi Zou while (--cp >= ifname && *cp == '\n') 258fdecf31bSYi Zou *cp = '\0'; 259fdecf31bSYi Zou return dev_get_by_name(&init_net, ifname); 260fdecf31bSYi Zou } 261fdecf31bSYi Zou return NULL; 262fdecf31bSYi Zou } 263fdecf31bSYi Zou 264fdecf31bSYi Zou /** 265fdecf31bSYi Zou * fcoe_transport_create() - Create a fcoe interface 266fdecf31bSYi Zou * @buffer: The name of the Ethernet interface to create on 267fdecf31bSYi Zou * @kp: The associated kernel param 268fdecf31bSYi Zou * 269fdecf31bSYi Zou * Called from sysfs. This holds the ft_mutex while calling the 270fdecf31bSYi Zou * registered fcoe transport's create function. 271fdecf31bSYi Zou * 272fdecf31bSYi Zou * Returns: 0 for success 273fdecf31bSYi Zou */ 274fdecf31bSYi Zou static int fcoe_transport_create(const char *buffer, struct kernel_param *kp) 275fdecf31bSYi Zou { 276fdecf31bSYi Zou int rc = -ENODEV; 277fdecf31bSYi Zou struct net_device *netdev = NULL; 278fdecf31bSYi Zou struct fcoe_transport *ft = NULL; 279fdecf31bSYi Zou enum fip_state fip_mode = (enum fip_state)(long)kp->arg; 280fdecf31bSYi Zou 281fdecf31bSYi Zou if (!mutex_trylock(&ft_mutex)) 282fdecf31bSYi Zou return restart_syscall(); 283fdecf31bSYi Zou 284fdecf31bSYi Zou #ifdef CONFIG_LIBFCOE_MODULE 285fdecf31bSYi Zou /* 286fdecf31bSYi Zou * Make sure the module has been initialized, and is not about to be 287fdecf31bSYi Zou * removed. Module parameter sysfs files are writable before the 288fdecf31bSYi Zou * module_init function is called and after module_exit. 289fdecf31bSYi Zou */ 290fdecf31bSYi Zou if (THIS_MODULE->state != MODULE_STATE_LIVE) 291fdecf31bSYi Zou goto out_nodev; 292fdecf31bSYi Zou #endif 293fdecf31bSYi Zou 294fdecf31bSYi Zou netdev = fcoe_if_to_netdev(buffer); 295fdecf31bSYi Zou if (!netdev) { 296fdecf31bSYi Zou LIBFCOE_TRANSPORT_DBG("Invalid device %s.\n", buffer); 297fdecf31bSYi Zou goto out_nodev; 298fdecf31bSYi Zou } 299fdecf31bSYi Zou 300fdecf31bSYi Zou ft = fcoe_netdev_map_lookup(netdev); 301fdecf31bSYi Zou if (ft) { 302fdecf31bSYi Zou LIBFCOE_TRANSPORT_DBG("transport %s already has existing " 303fdecf31bSYi Zou "FCoE instance on %s.\n", 304fdecf31bSYi Zou ft->name, netdev->name); 305fdecf31bSYi Zou rc = -EEXIST; 306fdecf31bSYi Zou goto out_putdev; 307fdecf31bSYi Zou } 308fdecf31bSYi Zou 309fdecf31bSYi Zou ft = fcoe_transport_lookup(netdev); 310fdecf31bSYi Zou if (!ft) { 311fdecf31bSYi Zou LIBFCOE_TRANSPORT_DBG("no FCoE transport found for %s.\n", 312fdecf31bSYi Zou netdev->name); 313fdecf31bSYi Zou goto out_putdev; 314fdecf31bSYi Zou } 315fdecf31bSYi Zou 316fdecf31bSYi Zou rc = fcoe_add_netdev_mapping(netdev, ft); 317fdecf31bSYi Zou if (rc) { 318fdecf31bSYi Zou LIBFCOE_TRANSPORT_DBG("failed to add new netdev mapping " 319fdecf31bSYi Zou "for FCoE transport %s for %s.\n", 320fdecf31bSYi Zou ft->name, netdev->name); 321fdecf31bSYi Zou goto out_putdev; 322fdecf31bSYi Zou } 323fdecf31bSYi Zou 324fdecf31bSYi Zou /* pass to transport create */ 325fdecf31bSYi Zou rc = ft->create ? ft->create(netdev, fip_mode) : -ENODEV; 326fdecf31bSYi Zou if (rc) 327fdecf31bSYi Zou fcoe_del_netdev_mapping(netdev); 328fdecf31bSYi Zou 329fdecf31bSYi Zou LIBFCOE_TRANSPORT_DBG("transport %s %s to create fcoe on %s.\n", 330fdecf31bSYi Zou ft->name, (rc) ? "failed" : "succeeded", 331fdecf31bSYi Zou netdev->name); 332fdecf31bSYi Zou 333fdecf31bSYi Zou out_putdev: 334fdecf31bSYi Zou dev_put(netdev); 335fdecf31bSYi Zou out_nodev: 336fdecf31bSYi Zou mutex_unlock(&ft_mutex); 337fdecf31bSYi Zou if (rc == -ERESTARTSYS) 338fdecf31bSYi Zou return restart_syscall(); 339fdecf31bSYi Zou else 340fdecf31bSYi Zou return rc; 341fdecf31bSYi Zou } 342fdecf31bSYi Zou 343fdecf31bSYi Zou /** 344fdecf31bSYi Zou * fcoe_transport_destroy() - Destroy a FCoE interface 345fdecf31bSYi Zou * @buffer: The name of the Ethernet interface to be destroyed 346fdecf31bSYi Zou * @kp: The associated kernel parameter 347fdecf31bSYi Zou * 348fdecf31bSYi Zou * Called from sysfs. This holds the ft_mutex while calling the 349fdecf31bSYi Zou * registered fcoe transport's destroy function. 350fdecf31bSYi Zou * 351fdecf31bSYi Zou * Returns: 0 for success 352fdecf31bSYi Zou */ 353fdecf31bSYi Zou static int fcoe_transport_destroy(const char *buffer, struct kernel_param *kp) 354fdecf31bSYi Zou { 355fdecf31bSYi Zou int rc = -ENODEV; 356fdecf31bSYi Zou struct net_device *netdev = NULL; 357fdecf31bSYi Zou struct fcoe_transport *ft = NULL; 358fdecf31bSYi Zou 359fdecf31bSYi Zou if (!mutex_trylock(&ft_mutex)) 360fdecf31bSYi Zou return restart_syscall(); 361fdecf31bSYi Zou 362fdecf31bSYi Zou #ifdef CONFIG_LIBFCOE_MODULE 363fdecf31bSYi Zou /* 364fdecf31bSYi Zou * Make sure the module has been initialized, and is not about to be 365fdecf31bSYi Zou * removed. Module parameter sysfs files are writable before the 366fdecf31bSYi Zou * module_init function is called and after module_exit. 367fdecf31bSYi Zou */ 368fdecf31bSYi Zou if (THIS_MODULE->state != MODULE_STATE_LIVE) 369fdecf31bSYi Zou goto out_nodev; 370fdecf31bSYi Zou #endif 371fdecf31bSYi Zou 372fdecf31bSYi Zou netdev = fcoe_if_to_netdev(buffer); 373fdecf31bSYi Zou if (!netdev) { 374fdecf31bSYi Zou LIBFCOE_TRANSPORT_DBG("invalid device %s.\n", buffer); 375fdecf31bSYi Zou goto out_nodev; 376fdecf31bSYi Zou } 377fdecf31bSYi Zou 378fdecf31bSYi Zou ft = fcoe_netdev_map_lookup(netdev); 379fdecf31bSYi Zou if (!ft) { 380fdecf31bSYi Zou LIBFCOE_TRANSPORT_DBG("no FCoE transport found for %s.\n", 381fdecf31bSYi Zou netdev->name); 382fdecf31bSYi Zou goto out_putdev; 383fdecf31bSYi Zou } 384fdecf31bSYi Zou 385fdecf31bSYi Zou /* pass to transport destroy */ 386fdecf31bSYi Zou rc = ft->destroy ? ft->destroy(netdev) : -ENODEV; 387fdecf31bSYi Zou fcoe_del_netdev_mapping(netdev); 388fdecf31bSYi Zou LIBFCOE_TRANSPORT_DBG("transport %s %s to destroy fcoe on %s.\n", 389fdecf31bSYi Zou ft->name, (rc) ? "failed" : "succeeded", 390fdecf31bSYi Zou netdev->name); 391fdecf31bSYi Zou 392fdecf31bSYi Zou out_putdev: 393fdecf31bSYi Zou dev_put(netdev); 394fdecf31bSYi Zou out_nodev: 395fdecf31bSYi Zou mutex_unlock(&ft_mutex); 396fdecf31bSYi Zou 397fdecf31bSYi Zou if (rc == -ERESTARTSYS) 398fdecf31bSYi Zou return restart_syscall(); 399fdecf31bSYi Zou else 400fdecf31bSYi Zou return rc; 401fdecf31bSYi Zou } 402fdecf31bSYi Zou 403fdecf31bSYi Zou /** 404fdecf31bSYi Zou * fcoe_transport_disable() - Disables a FCoE interface 405fdecf31bSYi Zou * @buffer: The name of the Ethernet interface to be disabled 406fdecf31bSYi Zou * @kp: The associated kernel parameter 407fdecf31bSYi Zou * 408fdecf31bSYi Zou * Called from sysfs. 409fdecf31bSYi Zou * 410fdecf31bSYi Zou * Returns: 0 for success 411fdecf31bSYi Zou */ 412fdecf31bSYi Zou static int fcoe_transport_disable(const char *buffer, struct kernel_param *kp) 413fdecf31bSYi Zou { 414fdecf31bSYi Zou int rc = -ENODEV; 415fdecf31bSYi Zou struct net_device *netdev = NULL; 416fdecf31bSYi Zou struct fcoe_transport *ft = NULL; 417fdecf31bSYi Zou 418fdecf31bSYi Zou if (!mutex_trylock(&ft_mutex)) 419fdecf31bSYi Zou return restart_syscall(); 420fdecf31bSYi Zou 421fdecf31bSYi Zou #ifdef CONFIG_LIBFCOE_MODULE 422fdecf31bSYi Zou /* 423fdecf31bSYi Zou * Make sure the module has been initialized, and is not about to be 424fdecf31bSYi Zou * removed. Module parameter sysfs files are writable before the 425fdecf31bSYi Zou * module_init function is called and after module_exit. 426fdecf31bSYi Zou */ 427fdecf31bSYi Zou if (THIS_MODULE->state != MODULE_STATE_LIVE) 428fdecf31bSYi Zou goto out_nodev; 429fdecf31bSYi Zou #endif 430fdecf31bSYi Zou 431fdecf31bSYi Zou netdev = fcoe_if_to_netdev(buffer); 432fdecf31bSYi Zou if (!netdev) 433fdecf31bSYi Zou goto out_nodev; 434fdecf31bSYi Zou 435fdecf31bSYi Zou ft = fcoe_netdev_map_lookup(netdev); 436fdecf31bSYi Zou if (!ft) 437fdecf31bSYi Zou goto out_putdev; 438fdecf31bSYi Zou 439fdecf31bSYi Zou rc = ft->disable ? ft->disable(netdev) : -ENODEV; 440fdecf31bSYi Zou 441fdecf31bSYi Zou out_putdev: 442fdecf31bSYi Zou dev_put(netdev); 443fdecf31bSYi Zou out_nodev: 444fdecf31bSYi Zou mutex_unlock(&ft_mutex); 445fdecf31bSYi Zou 446fdecf31bSYi Zou if (rc == -ERESTARTSYS) 447fdecf31bSYi Zou return restart_syscall(); 448fdecf31bSYi Zou else 449fdecf31bSYi Zou return rc; 450fdecf31bSYi Zou } 451fdecf31bSYi Zou 452fdecf31bSYi Zou /** 453fdecf31bSYi Zou * fcoe_transport_enable() - Enables a FCoE interface 454fdecf31bSYi Zou * @buffer: The name of the Ethernet interface to be enabled 455fdecf31bSYi Zou * @kp: The associated kernel parameter 456fdecf31bSYi Zou * 457fdecf31bSYi Zou * Called from sysfs. 458fdecf31bSYi Zou * 459fdecf31bSYi Zou * Returns: 0 for success 460fdecf31bSYi Zou */ 461fdecf31bSYi Zou static int fcoe_transport_enable(const char *buffer, struct kernel_param *kp) 462fdecf31bSYi Zou { 463fdecf31bSYi Zou int rc = -ENODEV; 464fdecf31bSYi Zou struct net_device *netdev = NULL; 465fdecf31bSYi Zou struct fcoe_transport *ft = NULL; 466fdecf31bSYi Zou 467fdecf31bSYi Zou if (!mutex_trylock(&ft_mutex)) 468fdecf31bSYi Zou return restart_syscall(); 469fdecf31bSYi Zou 470fdecf31bSYi Zou #ifdef CONFIG_LIBFCOE_MODULE 471fdecf31bSYi Zou /* 472fdecf31bSYi Zou * Make sure the module has been initialized, and is not about to be 473fdecf31bSYi Zou * removed. Module parameter sysfs files are writable before the 474fdecf31bSYi Zou * module_init function is called and after module_exit. 475fdecf31bSYi Zou */ 476fdecf31bSYi Zou if (THIS_MODULE->state != MODULE_STATE_LIVE) 477fdecf31bSYi Zou goto out_nodev; 478fdecf31bSYi Zou #endif 479fdecf31bSYi Zou 480fdecf31bSYi Zou netdev = fcoe_if_to_netdev(buffer); 481fdecf31bSYi Zou if (!netdev) 482fdecf31bSYi Zou goto out_nodev; 483fdecf31bSYi Zou 484fdecf31bSYi Zou ft = fcoe_netdev_map_lookup(netdev); 485fdecf31bSYi Zou if (!ft) 486fdecf31bSYi Zou goto out_putdev; 487fdecf31bSYi Zou 488fdecf31bSYi Zou rc = ft->enable ? ft->enable(netdev) : -ENODEV; 489fdecf31bSYi Zou 490fdecf31bSYi Zou out_putdev: 491fdecf31bSYi Zou dev_put(netdev); 492fdecf31bSYi Zou out_nodev: 493fdecf31bSYi Zou mutex_unlock(&ft_mutex); 494fdecf31bSYi Zou if (rc == -ERESTARTSYS) 495fdecf31bSYi Zou return restart_syscall(); 496fdecf31bSYi Zou else 497fdecf31bSYi Zou return rc; 498fdecf31bSYi Zou } 499fdecf31bSYi Zou 500fdecf31bSYi Zou /** 501fdecf31bSYi Zou * libfcoe_init() - Initialization routine for libfcoe.ko 502fdecf31bSYi Zou */ 503fdecf31bSYi Zou static int __init libfcoe_init(void) 504fdecf31bSYi Zou { 505fdecf31bSYi Zou fcoe_transport_init(); 506fdecf31bSYi Zou 507fdecf31bSYi Zou return 0; 508fdecf31bSYi Zou } 509fdecf31bSYi Zou module_init(libfcoe_init); 510fdecf31bSYi Zou 511fdecf31bSYi Zou /** 512fdecf31bSYi Zou * libfcoe_exit() - Tear down libfcoe.ko 513fdecf31bSYi Zou */ 514fdecf31bSYi Zou static void __exit libfcoe_exit(void) 515fdecf31bSYi Zou { 516fdecf31bSYi Zou fcoe_transport_exit(); 517fdecf31bSYi Zou } 518fdecf31bSYi Zou module_exit(libfcoe_exit); 519