fcoe_sw.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494
  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/module.h>
  20. #include <linux/version.h>
  21. #include <linux/kernel.h>
  22. #include <linux/pci.h>
  23. #include <linux/init.h>
  24. #include <linux/spinlock.h>
  25. #include <linux/netdevice.h>
  26. #include <linux/etherdevice.h>
  27. #include <linux/if_vlan.h>
  28. #include <net/rtnetlink.h>
  29. #include <scsi/fc/fc_els.h>
  30. #include <scsi/fc/fc_encaps.h>
  31. #include <scsi/fc/fc_fs.h>
  32. #include <scsi/scsi_transport.h>
  33. #include <scsi/scsi_transport_fc.h>
  34. #include <scsi/libfc.h>
  35. #include <scsi/libfcoe.h>
  36. #include <scsi/fc_transport_fcoe.h>
  37. #define FCOE_SW_VERSION "0.1"
  38. #define FCOE_SW_NAME "fcoesw"
  39. #define FCOE_SW_VENDOR "Open-FCoE.org"
  40. #define FCOE_MAX_LUN 255
  41. #define FCOE_MAX_FCP_TARGET 256
  42. #define FCOE_MAX_OUTSTANDING_COMMANDS 1024
  43. #define FCOE_MIN_XID 0x0001 /* the min xid supported by fcoe_sw */
  44. #define FCOE_MAX_XID 0x07ef /* the max xid supported by fcoe_sw */
  45. static struct scsi_transport_template *scsi_transport_fcoe_sw;
  46. struct fc_function_template fcoe_sw_transport_function = {
  47. .show_host_node_name = 1,
  48. .show_host_port_name = 1,
  49. .show_host_supported_classes = 1,
  50. .show_host_supported_fc4s = 1,
  51. .show_host_active_fc4s = 1,
  52. .show_host_maxframe_size = 1,
  53. .show_host_port_id = 1,
  54. .show_host_supported_speeds = 1,
  55. .get_host_speed = fc_get_host_speed,
  56. .show_host_speed = 1,
  57. .show_host_port_type = 1,
  58. .get_host_port_state = fc_get_host_port_state,
  59. .show_host_port_state = 1,
  60. .show_host_symbolic_name = 1,
  61. .dd_fcrport_size = sizeof(struct fc_rport_libfc_priv),
  62. .show_rport_maxframe_size = 1,
  63. .show_rport_supported_classes = 1,
  64. .show_host_fabric_name = 1,
  65. .show_starget_node_name = 1,
  66. .show_starget_port_name = 1,
  67. .show_starget_port_id = 1,
  68. .set_rport_dev_loss_tmo = fc_set_rport_loss_tmo,
  69. .show_rport_dev_loss_tmo = 1,
  70. .get_fc_host_stats = fc_get_host_stats,
  71. .issue_fc_host_lip = fcoe_reset,
  72. .terminate_rport_io = fc_rport_terminate_io,
  73. };
  74. static struct scsi_host_template fcoe_sw_shost_template = {
  75. .module = THIS_MODULE,
  76. .name = "FCoE Driver",
  77. .proc_name = FCOE_SW_NAME,
  78. .queuecommand = fc_queuecommand,
  79. .eh_abort_handler = fc_eh_abort,
  80. .eh_device_reset_handler = fc_eh_device_reset,
  81. .eh_host_reset_handler = fc_eh_host_reset,
  82. .slave_alloc = fc_slave_alloc,
  83. .change_queue_depth = fc_change_queue_depth,
  84. .change_queue_type = fc_change_queue_type,
  85. .this_id = -1,
  86. .cmd_per_lun = 32,
  87. .can_queue = FCOE_MAX_OUTSTANDING_COMMANDS,
  88. .use_clustering = ENABLE_CLUSTERING,
  89. .sg_tablesize = SG_ALL,
  90. .max_sectors = 0xffff,
  91. };
  92. /*
  93. * fcoe_sw_lport_config - sets up the fc_lport
  94. * @lp: ptr to the fc_lport
  95. * @shost: ptr to the parent scsi host
  96. *
  97. * Returns: 0 for success
  98. *
  99. */
  100. static int fcoe_sw_lport_config(struct fc_lport *lp)
  101. {
  102. int i = 0;
  103. lp->link_status = 0;
  104. lp->max_retry_count = 3;
  105. lp->e_d_tov = 2 * 1000; /* FC-FS default */
  106. lp->r_a_tov = 2 * 2 * 1000;
  107. lp->service_params = (FCP_SPPF_INIT_FCN | FCP_SPPF_RD_XRDY_DIS |
  108. FCP_SPPF_RETRY | FCP_SPPF_CONF_COMPL);
  109. /*
  110. * allocate per cpu stats block
  111. */
  112. for_each_online_cpu(i)
  113. lp->dev_stats[i] = kzalloc(sizeof(struct fcoe_dev_stats),
  114. GFP_KERNEL);
  115. /* lport fc_lport related configuration */
  116. fc_lport_config(lp);
  117. return 0;
  118. }
  119. /*
  120. * fcoe_sw_netdev_config - sets up fcoe_softc for lport and network
  121. * related properties
  122. * @lp : ptr to the fc_lport
  123. * @netdev : ptr to the associated netdevice struct
  124. *
  125. * Must be called after fcoe_sw_lport_config() as it will use lport mutex
  126. *
  127. * Returns : 0 for success
  128. *
  129. */
  130. static int fcoe_sw_netdev_config(struct fc_lport *lp, struct net_device *netdev)
  131. {
  132. u32 mfs;
  133. u64 wwnn, wwpn;
  134. struct fcoe_softc *fc;
  135. u8 flogi_maddr[ETH_ALEN];
  136. /* Setup lport private data to point to fcoe softc */
  137. fc = lport_priv(lp);
  138. fc->lp = lp;
  139. fc->real_dev = netdev;
  140. fc->phys_dev = netdev;
  141. /* Require support for get_pauseparam ethtool op. */
  142. if (netdev->priv_flags & IFF_802_1Q_VLAN)
  143. fc->phys_dev = vlan_dev_real_dev(netdev);
  144. /* Do not support for bonding device */
  145. if ((fc->real_dev->priv_flags & IFF_MASTER_ALB) ||
  146. (fc->real_dev->priv_flags & IFF_SLAVE_INACTIVE) ||
  147. (fc->real_dev->priv_flags & IFF_MASTER_8023AD)) {
  148. return -EOPNOTSUPP;
  149. }
  150. /*
  151. * Determine max frame size based on underlying device and optional
  152. * user-configured limit. If the MFS is too low, fcoe_link_ok()
  153. * will return 0, so do this first.
  154. */
  155. mfs = fc->real_dev->mtu - (sizeof(struct fcoe_hdr) +
  156. sizeof(struct fcoe_crc_eof));
  157. if (fc_set_mfs(lp, mfs))
  158. return -EINVAL;
  159. lp->link_status = ~FC_PAUSE & ~FC_LINK_UP;
  160. if (!fcoe_link_ok(lp))
  161. lp->link_status |= FC_LINK_UP;
  162. /* offload features support */
  163. if (fc->real_dev->features & NETIF_F_SG)
  164. lp->sg_supp = 1;
  165. skb_queue_head_init(&fc->fcoe_pending_queue);
  166. /* setup Source Mac Address */
  167. memcpy(fc->ctl_src_addr, fc->real_dev->dev_addr,
  168. fc->real_dev->addr_len);
  169. wwnn = fcoe_wwn_from_mac(fc->real_dev->dev_addr, 1, 0);
  170. fc_set_wwnn(lp, wwnn);
  171. /* XXX - 3rd arg needs to be vlan id */
  172. wwpn = fcoe_wwn_from_mac(fc->real_dev->dev_addr, 2, 0);
  173. fc_set_wwpn(lp, wwpn);
  174. /*
  175. * Add FCoE MAC address as second unicast MAC address
  176. * or enter promiscuous mode if not capable of listening
  177. * for multiple unicast MACs.
  178. */
  179. rtnl_lock();
  180. memcpy(flogi_maddr, (u8[6]) FC_FCOE_FLOGI_MAC, ETH_ALEN);
  181. dev_unicast_add(fc->real_dev, flogi_maddr, ETH_ALEN);
  182. rtnl_unlock();
  183. /*
  184. * setup the receive function from ethernet driver
  185. * on the ethertype for the given device
  186. */
  187. fc->fcoe_packet_type.func = fcoe_rcv;
  188. fc->fcoe_packet_type.type = __constant_htons(ETH_P_FCOE);
  189. fc->fcoe_packet_type.dev = fc->real_dev;
  190. dev_add_pack(&fc->fcoe_packet_type);
  191. return 0;
  192. }
  193. /*
  194. * fcoe_sw_shost_config - sets up fc_lport->host
  195. * @lp : ptr to the fc_lport
  196. * @shost : ptr to the associated scsi host
  197. * @dev : device associated to scsi host
  198. *
  199. * Must be called after fcoe_sw_lport_config) and fcoe_sw_netdev_config()
  200. *
  201. * Returns : 0 for success
  202. *
  203. */
  204. static int fcoe_sw_shost_config(struct fc_lport *lp, struct Scsi_Host *shost,
  205. struct device *dev)
  206. {
  207. int rc = 0;
  208. /* lport scsi host config */
  209. lp->host = shost;
  210. lp->host->max_lun = FCOE_MAX_LUN;
  211. lp->host->max_id = FCOE_MAX_FCP_TARGET;
  212. lp->host->max_channel = 0;
  213. lp->host->transportt = scsi_transport_fcoe_sw;
  214. /* add the new host to the SCSI-ml */
  215. rc = scsi_add_host(lp->host, dev);
  216. if (rc) {
  217. FC_DBG("fcoe_sw_shost_config:error on scsi_add_host\n");
  218. return rc;
  219. }
  220. sprintf(fc_host_symbolic_name(lp->host), "%s v%s over %s",
  221. FCOE_SW_NAME, FCOE_SW_VERSION,
  222. fcoe_netdev(lp)->name);
  223. return 0;
  224. }
  225. /*
  226. * fcoe_sw_em_config - allocates em for this lport
  227. * @lp: the port that em is to allocated for
  228. *
  229. * Returns : 0 on success
  230. */
  231. static inline int fcoe_sw_em_config(struct fc_lport *lp)
  232. {
  233. BUG_ON(lp->emp);
  234. lp->emp = fc_exch_mgr_alloc(lp, FC_CLASS_3,
  235. FCOE_MIN_XID, FCOE_MAX_XID);
  236. if (!lp->emp)
  237. return -ENOMEM;
  238. return 0;
  239. }
  240. /*
  241. * fcoe_sw_destroy - FCoE software HBA tear-down function
  242. * @netdev: ptr to the associated net_device
  243. *
  244. * Returns: 0 if link is OK for use by FCoE.
  245. */
  246. static int fcoe_sw_destroy(struct net_device *netdev)
  247. {
  248. int cpu;
  249. struct fc_lport *lp = NULL;
  250. struct fcoe_softc *fc;
  251. u8 flogi_maddr[ETH_ALEN];
  252. BUG_ON(!netdev);
  253. printk(KERN_DEBUG "fcoe_sw_destroy:interface on %s\n",
  254. netdev->name);
  255. lp = fcoe_hostlist_lookup(netdev);
  256. if (!lp)
  257. return -ENODEV;
  258. fc = fcoe_softc(lp);
  259. /* Logout of the fabric */
  260. fc_fabric_logoff(lp);
  261. /* Remove the instance from fcoe's list */
  262. fcoe_hostlist_remove(lp);
  263. /* Don't listen for Ethernet packets anymore */
  264. dev_remove_pack(&fc->fcoe_packet_type);
  265. /* Cleanup the fc_lport */
  266. fc_lport_destroy(lp);
  267. fc_fcp_destroy(lp);
  268. /* Detach from the scsi-ml */
  269. fc_remove_host(lp->host);
  270. scsi_remove_host(lp->host);
  271. /* There are no more rports or I/O, free the EM */
  272. if (lp->emp)
  273. fc_exch_mgr_free(lp->emp);
  274. /* Delete secondary MAC addresses */
  275. rtnl_lock();
  276. memcpy(flogi_maddr, (u8[6]) FC_FCOE_FLOGI_MAC, ETH_ALEN);
  277. dev_unicast_delete(fc->real_dev, flogi_maddr, ETH_ALEN);
  278. if (compare_ether_addr(fc->data_src_addr, (u8[6]) { 0 }))
  279. dev_unicast_delete(fc->real_dev, fc->data_src_addr, ETH_ALEN);
  280. rtnl_unlock();
  281. /* Free the per-CPU revieve threads */
  282. fcoe_percpu_clean(lp);
  283. /* Free existing skbs */
  284. fcoe_clean_pending_queue(lp);
  285. /* Free memory used by statistical counters */
  286. for_each_online_cpu(cpu)
  287. kfree(lp->dev_stats[cpu]);
  288. /* Release the net_device and Scsi_Host */
  289. dev_put(fc->real_dev);
  290. scsi_host_put(lp->host);
  291. return 0;
  292. }
  293. static struct libfc_function_template fcoe_sw_libfc_fcn_templ = {
  294. .frame_send = fcoe_xmit,
  295. };
  296. /*
  297. * fcoe_sw_create - this function creates the fcoe interface
  298. * @netdev: pointer the associated netdevice
  299. *
  300. * Creates fc_lport struct and scsi_host for lport, configures lport
  301. * and starts fabric login.
  302. *
  303. * Returns : 0 on success
  304. */
  305. static int fcoe_sw_create(struct net_device *netdev)
  306. {
  307. int rc;
  308. struct fc_lport *lp = NULL;
  309. struct fcoe_softc *fc;
  310. struct Scsi_Host *shost;
  311. BUG_ON(!netdev);
  312. printk(KERN_DEBUG "fcoe_sw_create:interface on %s\n",
  313. netdev->name);
  314. lp = fcoe_hostlist_lookup(netdev);
  315. if (lp)
  316. return -EEXIST;
  317. shost = fcoe_host_alloc(&fcoe_sw_shost_template,
  318. sizeof(struct fcoe_softc));
  319. if (!shost) {
  320. FC_DBG("Could not allocate host structure\n");
  321. return -ENOMEM;
  322. }
  323. lp = shost_priv(shost);
  324. fc = lport_priv(lp);
  325. /* configure fc_lport, e.g., em */
  326. rc = fcoe_sw_lport_config(lp);
  327. if (rc) {
  328. FC_DBG("Could not configure lport\n");
  329. goto out_host_put;
  330. }
  331. /* configure lport network properties */
  332. rc = fcoe_sw_netdev_config(lp, netdev);
  333. if (rc) {
  334. FC_DBG("Could not configure netdev for lport\n");
  335. goto out_host_put;
  336. }
  337. /* configure lport scsi host properties */
  338. rc = fcoe_sw_shost_config(lp, shost, &netdev->dev);
  339. if (rc) {
  340. FC_DBG("Could not configure shost for lport\n");
  341. goto out_host_put;
  342. }
  343. /* lport exch manager allocation */
  344. rc = fcoe_sw_em_config(lp);
  345. if (rc) {
  346. FC_DBG("Could not configure em for lport\n");
  347. goto out_host_put;
  348. }
  349. /* Initialize the library */
  350. rc = fcoe_libfc_config(lp, &fcoe_sw_libfc_fcn_templ);
  351. if (rc) {
  352. FC_DBG("Could not configure libfc for lport!\n");
  353. goto out_lp_destroy;
  354. }
  355. /* add to lports list */
  356. fcoe_hostlist_add(lp);
  357. lp->boot_time = jiffies;
  358. fc_fabric_login(lp);
  359. dev_hold(netdev);
  360. return rc;
  361. out_lp_destroy:
  362. fc_exch_mgr_free(lp->emp); /* Free the EM */
  363. out_host_put:
  364. scsi_host_put(lp->host);
  365. return rc;
  366. }
  367. /*
  368. * fcoe_sw_match - the fcoe sw transport match function
  369. *
  370. * Returns : false always
  371. */
  372. static bool fcoe_sw_match(struct net_device *netdev)
  373. {
  374. /* FIXME - for sw transport, always return false */
  375. return false;
  376. }
  377. /* the sw hba fcoe transport */
  378. struct fcoe_transport fcoe_sw_transport = {
  379. .name = "fcoesw",
  380. .create = fcoe_sw_create,
  381. .destroy = fcoe_sw_destroy,
  382. .match = fcoe_sw_match,
  383. .vendor = 0x0,
  384. .device = 0xffff,
  385. };
  386. /*
  387. * fcoe_sw_init - registers fcoe_sw_transport
  388. *
  389. * Returns : 0 on success
  390. */
  391. int __init fcoe_sw_init(void)
  392. {
  393. /* attach to scsi transport */
  394. scsi_transport_fcoe_sw =
  395. fc_attach_transport(&fcoe_sw_transport_function);
  396. if (!scsi_transport_fcoe_sw) {
  397. printk(KERN_ERR "fcoe_sw_init:fc_attach_transport() failed\n");
  398. return -ENODEV;
  399. }
  400. /* register sw transport */
  401. fcoe_transport_register(&fcoe_sw_transport);
  402. return 0;
  403. }
  404. /*
  405. * fcoe_sw_exit - unregisters fcoe_sw_transport
  406. *
  407. * Returns : 0 on success
  408. */
  409. int __exit fcoe_sw_exit(void)
  410. {
  411. /* dettach the transport */
  412. fc_release_transport(scsi_transport_fcoe_sw);
  413. fcoe_transport_unregister(&fcoe_sw_transport);
  414. return 0;
  415. }