fc_transport_fcoe.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443
  1. /*
  2. * Copyright(c) 2007 - 2008 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/pci.h>
  20. #include <scsi/libfcoe.h>
  21. #include <scsi/fc_transport_fcoe.h>
  22. /* internal fcoe transport */
  23. struct fcoe_transport_internal {
  24. struct fcoe_transport *t;
  25. struct net_device *netdev;
  26. struct list_head list;
  27. };
  28. /* fcoe transports list and its lock */
  29. static LIST_HEAD(fcoe_transports);
  30. static DEFINE_MUTEX(fcoe_transports_lock);
  31. /**
  32. * fcoe_transport_default() - Returns ptr to the default transport fcoe_sw
  33. */
  34. struct fcoe_transport *fcoe_transport_default(void)
  35. {
  36. return &fcoe_sw_transport;
  37. }
  38. /**
  39. * fcoe_transport_to_pcidev() - get the pci dev from a netdev
  40. * @netdev: the netdev that pci dev will be retrived from
  41. *
  42. * Returns: NULL or the corrsponding pci_dev
  43. */
  44. struct pci_dev *fcoe_transport_pcidev(const struct net_device *netdev)
  45. {
  46. if (!netdev->dev.parent)
  47. return NULL;
  48. return to_pci_dev(netdev->dev.parent);
  49. }
  50. /**
  51. * fcoe_transport_device_lookup() - Lookup a transport
  52. * @netdev: the netdev the transport to be attached to
  53. *
  54. * This will look for existing offload driver, if not found, it falls back to
  55. * the default sw hba (fcoe_sw) as its fcoe transport.
  56. *
  57. * Returns: 0 for success
  58. */
  59. static struct fcoe_transport_internal *
  60. fcoe_transport_device_lookup(struct fcoe_transport *t,
  61. struct net_device *netdev)
  62. {
  63. struct fcoe_transport_internal *ti;
  64. /* assign the transpor to this device */
  65. mutex_lock(&t->devlock);
  66. list_for_each_entry(ti, &t->devlist, list) {
  67. if (ti->netdev == netdev) {
  68. mutex_unlock(&t->devlock);
  69. return ti;
  70. }
  71. }
  72. mutex_unlock(&t->devlock);
  73. return NULL;
  74. }
  75. /**
  76. * fcoe_transport_device_add() - Assign a transport to a device
  77. * @netdev: the netdev the transport to be attached to
  78. *
  79. * This will look for existing offload driver, if not found, it falls back to
  80. * the default sw hba (fcoe_sw) as its fcoe transport.
  81. *
  82. * Returns: 0 for success
  83. */
  84. static int fcoe_transport_device_add(struct fcoe_transport *t,
  85. struct net_device *netdev)
  86. {
  87. struct fcoe_transport_internal *ti;
  88. ti = fcoe_transport_device_lookup(t, netdev);
  89. if (ti) {
  90. printk(KERN_DEBUG "fcoe_transport_device_add:"
  91. "device %s is already added to transport %s\n",
  92. netdev->name, t->name);
  93. return -EEXIST;
  94. }
  95. /* allocate an internal struct to host the netdev and the list */
  96. ti = kzalloc(sizeof(*ti), GFP_KERNEL);
  97. if (!ti)
  98. return -ENOMEM;
  99. ti->t = t;
  100. ti->netdev = netdev;
  101. INIT_LIST_HEAD(&ti->list);
  102. dev_hold(ti->netdev);
  103. mutex_lock(&t->devlock);
  104. list_add(&ti->list, &t->devlist);
  105. mutex_unlock(&t->devlock);
  106. printk(KERN_DEBUG "fcoe_transport_device_add:"
  107. "device %s added to transport %s\n",
  108. netdev->name, t->name);
  109. return 0;
  110. }
  111. /**
  112. * fcoe_transport_device_remove() - Remove a device from its transport
  113. * @netdev: the netdev the transport to be attached to
  114. *
  115. * This removes the device from the transport so the given transport will
  116. * not manage this device any more
  117. *
  118. * Returns: 0 for success
  119. */
  120. static int fcoe_transport_device_remove(struct fcoe_transport *t,
  121. struct net_device *netdev)
  122. {
  123. struct fcoe_transport_internal *ti;
  124. ti = fcoe_transport_device_lookup(t, netdev);
  125. if (!ti) {
  126. printk(KERN_DEBUG "fcoe_transport_device_remove:"
  127. "device %s is not managed by transport %s\n",
  128. netdev->name, t->name);
  129. return -ENODEV;
  130. }
  131. mutex_lock(&t->devlock);
  132. list_del(&ti->list);
  133. mutex_unlock(&t->devlock);
  134. printk(KERN_DEBUG "fcoe_transport_device_remove:"
  135. "device %s removed from transport %s\n",
  136. netdev->name, t->name);
  137. dev_put(ti->netdev);
  138. kfree(ti);
  139. return 0;
  140. }
  141. /**
  142. * fcoe_transport_device_remove_all() - Remove all from transport devlist
  143. *
  144. * This removes the device from the transport so the given transport will
  145. * not manage this device any more
  146. *
  147. * Returns: 0 for success
  148. */
  149. static void fcoe_transport_device_remove_all(struct fcoe_transport *t)
  150. {
  151. struct fcoe_transport_internal *ti, *tmp;
  152. mutex_lock(&t->devlock);
  153. list_for_each_entry_safe(ti, tmp, &t->devlist, list) {
  154. list_del(&ti->list);
  155. kfree(ti);
  156. }
  157. mutex_unlock(&t->devlock);
  158. }
  159. /**
  160. * fcoe_transport_match() - Use the bus device match function to match the hw
  161. * @t: The fcoe transport to check
  162. * @netdev: The netdev to match against
  163. *
  164. * This function is used to check if the given transport wants to manage the
  165. * input netdev. if the transports implements the match function, it will be
  166. * called, o.w. we just compare the pci vendor and device id.
  167. *
  168. * Returns: true for match up
  169. */
  170. static bool fcoe_transport_match(struct fcoe_transport *t,
  171. struct net_device *netdev)
  172. {
  173. /* match transport by vendor and device id */
  174. struct pci_dev *pci;
  175. pci = fcoe_transport_pcidev(netdev);
  176. if (pci) {
  177. printk(KERN_DEBUG "fcoe_transport_match:"
  178. "%s:%x:%x -- %s:%x:%x\n",
  179. t->name, t->vendor, t->device,
  180. netdev->name, pci->vendor, pci->device);
  181. /* if transport supports match */
  182. if (t->match)
  183. return t->match(netdev);
  184. /* else just compare the vendor and device id: pci only */
  185. return (t->vendor == pci->vendor) && (t->device == pci->device);
  186. }
  187. return false;
  188. }
  189. /**
  190. * fcoe_transport_lookup() - Check if the transport is already registered
  191. * @t: the transport to be looked up
  192. *
  193. * This compares the parent device (pci) vendor and device id
  194. *
  195. * Returns: NULL if not found
  196. *
  197. * TODO: return default sw transport if no other transport is found
  198. */
  199. static struct fcoe_transport *
  200. fcoe_transport_lookup(struct net_device *netdev)
  201. {
  202. struct fcoe_transport *t;
  203. mutex_lock(&fcoe_transports_lock);
  204. list_for_each_entry(t, &fcoe_transports, list) {
  205. if (fcoe_transport_match(t, netdev)) {
  206. mutex_unlock(&fcoe_transports_lock);
  207. return t;
  208. }
  209. }
  210. mutex_unlock(&fcoe_transports_lock);
  211. printk(KERN_DEBUG "fcoe_transport_lookup:"
  212. "use default transport for %s\n", netdev->name);
  213. return fcoe_transport_default();
  214. }
  215. /**
  216. * fcoe_transport_register() - Adds a fcoe transport to the fcoe transports list
  217. * @t: ptr to the fcoe transport to be added
  218. *
  219. * Returns: 0 for success
  220. */
  221. int fcoe_transport_register(struct fcoe_transport *t)
  222. {
  223. struct fcoe_transport *tt;
  224. /* TODO - add fcoe_transport specific initialization here */
  225. mutex_lock(&fcoe_transports_lock);
  226. list_for_each_entry(tt, &fcoe_transports, list) {
  227. if (tt == t) {
  228. mutex_unlock(&fcoe_transports_lock);
  229. return -EEXIST;
  230. }
  231. }
  232. list_add_tail(&t->list, &fcoe_transports);
  233. mutex_unlock(&fcoe_transports_lock);
  234. printk(KERN_DEBUG "fcoe_transport_register:%s\n", t->name);
  235. return 0;
  236. }
  237. EXPORT_SYMBOL_GPL(fcoe_transport_register);
  238. /**
  239. * fcoe_transport_unregister() - Remove the tranport fro the fcoe transports list
  240. * @t: ptr to the fcoe transport to be removed
  241. *
  242. * Returns: 0 for success
  243. */
  244. int fcoe_transport_unregister(struct fcoe_transport *t)
  245. {
  246. struct fcoe_transport *tt, *tmp;
  247. mutex_lock(&fcoe_transports_lock);
  248. list_for_each_entry_safe(tt, tmp, &fcoe_transports, list) {
  249. if (tt == t) {
  250. list_del(&t->list);
  251. mutex_unlock(&fcoe_transports_lock);
  252. fcoe_transport_device_remove_all(t);
  253. printk(KERN_DEBUG "fcoe_transport_unregister:%s\n",
  254. t->name);
  255. return 0;
  256. }
  257. }
  258. mutex_unlock(&fcoe_transports_lock);
  259. return -ENODEV;
  260. }
  261. EXPORT_SYMBOL_GPL(fcoe_transport_unregister);
  262. /**
  263. * fcoe_load_transport_driver() - Load an offload driver by alias name
  264. * @netdev: the target net device
  265. *
  266. * Requests for an offload driver module as the fcoe transport, if fails, it
  267. * falls back to use the SW HBA (fcoe_sw) as its transport
  268. *
  269. * TODO -
  270. * 1. supports only PCI device
  271. * 2. needs fix for VLAn and bonding
  272. * 3. pure hw fcoe hba may not have netdev
  273. *
  274. * Returns: 0 for success
  275. */
  276. int fcoe_load_transport_driver(struct net_device *netdev)
  277. {
  278. struct pci_dev *pci;
  279. struct device *dev = netdev->dev.parent;
  280. if (fcoe_transport_lookup(netdev)) {
  281. /* load default transport */
  282. printk(KERN_DEBUG "fcoe: already loaded transport for %s\n",
  283. netdev->name);
  284. return -EEXIST;
  285. }
  286. pci = to_pci_dev(dev);
  287. if (dev->bus != &pci_bus_type) {
  288. printk(KERN_DEBUG "fcoe: support noly PCI device\n");
  289. return -ENODEV;
  290. }
  291. printk(KERN_DEBUG "fcoe: loading driver fcoe-pci-0x%04x-0x%04x\n",
  292. pci->vendor, pci->device);
  293. return request_module("fcoe-pci-0x%04x-0x%04x",
  294. pci->vendor, pci->device);
  295. }
  296. EXPORT_SYMBOL_GPL(fcoe_load_transport_driver);
  297. /**
  298. * fcoe_transport_attach() - Load transport to fcoe
  299. * @netdev: the netdev the transport to be attached to
  300. *
  301. * This will look for existing offload driver, if not found, it falls back to
  302. * the default sw hba (fcoe_sw) as its fcoe transport.
  303. *
  304. * Returns: 0 for success
  305. */
  306. int fcoe_transport_attach(struct net_device *netdev)
  307. {
  308. struct fcoe_transport *t;
  309. /* find the corresponding transport */
  310. t = fcoe_transport_lookup(netdev);
  311. if (!t) {
  312. printk(KERN_DEBUG "fcoe_transport_attach"
  313. ":no transport for %s:use %s\n",
  314. netdev->name, t->name);
  315. return -ENODEV;
  316. }
  317. /* add to the transport */
  318. if (fcoe_transport_device_add(t, netdev)) {
  319. printk(KERN_DEBUG "fcoe_transport_attach"
  320. ":failed to add %s to tramsport %s\n",
  321. netdev->name, t->name);
  322. return -EIO;
  323. }
  324. /* transport create function */
  325. if (t->create)
  326. t->create(netdev);
  327. printk(KERN_DEBUG "fcoe_transport_attach:transport %s for %s\n",
  328. t->name, netdev->name);
  329. return 0;
  330. }
  331. EXPORT_SYMBOL_GPL(fcoe_transport_attach);
  332. /**
  333. * fcoe_transport_release() - Unload transport from fcoe
  334. * @netdev: the net device on which fcoe is to be released
  335. *
  336. * Returns: 0 for success
  337. */
  338. int fcoe_transport_release(struct net_device *netdev)
  339. {
  340. struct fcoe_transport *t;
  341. /* find the corresponding transport */
  342. t = fcoe_transport_lookup(netdev);
  343. if (!t) {
  344. printk(KERN_DEBUG "fcoe_transport_release:"
  345. "no transport for %s:use %s\n",
  346. netdev->name, t->name);
  347. return -ENODEV;
  348. }
  349. /* remove the device from the transport */
  350. if (fcoe_transport_device_remove(t, netdev)) {
  351. printk(KERN_DEBUG "fcoe_transport_release:"
  352. "failed to add %s to tramsport %s\n",
  353. netdev->name, t->name);
  354. return -EIO;
  355. }
  356. /* transport destroy function */
  357. if (t->destroy)
  358. t->destroy(netdev);
  359. printk(KERN_DEBUG "fcoe_transport_release:"
  360. "device %s dettached from transport %s\n",
  361. netdev->name, t->name);
  362. return 0;
  363. }
  364. EXPORT_SYMBOL_GPL(fcoe_transport_release);
  365. /**
  366. * fcoe_transport_init() - Initializes fcoe transport layer
  367. *
  368. * This prepares for the fcoe transport layer
  369. *
  370. * Returns: none
  371. */
  372. int __init fcoe_transport_init(void)
  373. {
  374. INIT_LIST_HEAD(&fcoe_transports);
  375. mutex_init(&fcoe_transports_lock);
  376. return 0;
  377. }
  378. /**
  379. * fcoe_transport_exit() - Cleans up the fcoe transport layer
  380. *
  381. * This cleans up the fcoe transport layer. removing any transport on the list,
  382. * note that the transport destroy func is not called here.
  383. *
  384. * Returns: none
  385. */
  386. int __exit fcoe_transport_exit(void)
  387. {
  388. struct fcoe_transport *t, *tmp;
  389. mutex_lock(&fcoe_transports_lock);
  390. list_for_each_entry_safe(t, tmp, &fcoe_transports, list) {
  391. list_del(&t->list);
  392. mutex_unlock(&fcoe_transports_lock);
  393. fcoe_transport_device_remove_all(t);
  394. mutex_lock(&fcoe_transports_lock);
  395. }
  396. mutex_unlock(&fcoe_transports_lock);
  397. return 0;
  398. }