fcoe_transport.c 13 KB

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