csio_attr.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797
  1. /*
  2. * This file is part of the Chelsio FCoE driver for Linux.
  3. *
  4. * Copyright (c) 2008-2012 Chelsio Communications, Inc. All rights reserved.
  5. *
  6. * This software is available to you under a choice of one of two
  7. * licenses. You may choose to be licensed under the terms of the GNU
  8. * General Public License (GPL) Version 2, available from the file
  9. * COPYING in the main directory of this source tree, or the
  10. * OpenIB.org BSD license below:
  11. *
  12. * Redistribution and use in source and binary forms, with or
  13. * without modification, are permitted provided that the following
  14. * conditions are met:
  15. *
  16. * - Redistributions of source code must retain the above
  17. * copyright notice, this list of conditions and the following
  18. * disclaimer.
  19. *
  20. * - Redistributions in binary form must reproduce the above
  21. * copyright notice, this list of conditions and the following
  22. * disclaimer in the documentation and/or other materials
  23. * provided with the distribution.
  24. *
  25. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  26. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  27. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  28. * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
  29. * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  30. * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  31. * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  32. * SOFTWARE.
  33. */
  34. #include <linux/kernel.h>
  35. #include <linux/string.h>
  36. #include <linux/delay.h>
  37. #include <linux/module.h>
  38. #include <linux/init.h>
  39. #include <linux/pci.h>
  40. #include <linux/mm.h>
  41. #include <linux/jiffies.h>
  42. #include <scsi/fc/fc_fs.h>
  43. #include "csio_init.h"
  44. static void
  45. csio_vport_set_state(struct csio_lnode *ln);
  46. /*
  47. * csio_reg_rnode - Register a remote port with FC transport.
  48. * @rn: Rnode representing remote port.
  49. *
  50. * Call fc_remote_port_add() to register this remote port with FC transport.
  51. * If remote port is Initiator OR Target OR both, change the role appropriately.
  52. *
  53. */
  54. void
  55. csio_reg_rnode(struct csio_rnode *rn)
  56. {
  57. struct csio_lnode *ln = csio_rnode_to_lnode(rn);
  58. struct Scsi_Host *shost = csio_ln_to_shost(ln);
  59. struct fc_rport_identifiers ids;
  60. struct fc_rport *rport;
  61. struct csio_service_parms *sp;
  62. ids.node_name = wwn_to_u64(csio_rn_wwnn(rn));
  63. ids.port_name = wwn_to_u64(csio_rn_wwpn(rn));
  64. ids.port_id = rn->nport_id;
  65. ids.roles = FC_RPORT_ROLE_UNKNOWN;
  66. if (rn->role & CSIO_RNFR_INITIATOR || rn->role & CSIO_RNFR_TARGET) {
  67. rport = rn->rport;
  68. CSIO_ASSERT(rport != NULL);
  69. goto update_role;
  70. }
  71. rn->rport = fc_remote_port_add(shost, 0, &ids);
  72. if (!rn->rport) {
  73. csio_ln_err(ln, "Failed to register rport = 0x%x.\n",
  74. rn->nport_id);
  75. return;
  76. }
  77. ln->num_reg_rnodes++;
  78. rport = rn->rport;
  79. spin_lock_irq(shost->host_lock);
  80. *((struct csio_rnode **)rport->dd_data) = rn;
  81. spin_unlock_irq(shost->host_lock);
  82. sp = &rn->rn_sparm;
  83. rport->maxframe_size = ntohs(sp->csp.sp_bb_data);
  84. if (ntohs(sp->clsp[2].cp_class) & FC_CPC_VALID)
  85. rport->supported_classes = FC_COS_CLASS3;
  86. else
  87. rport->supported_classes = FC_COS_UNSPECIFIED;
  88. update_role:
  89. if (rn->role & CSIO_RNFR_INITIATOR)
  90. ids.roles |= FC_RPORT_ROLE_FCP_INITIATOR;
  91. if (rn->role & CSIO_RNFR_TARGET)
  92. ids.roles |= FC_RPORT_ROLE_FCP_TARGET;
  93. if (ids.roles != FC_RPORT_ROLE_UNKNOWN)
  94. fc_remote_port_rolechg(rport, ids.roles);
  95. rn->scsi_id = rport->scsi_target_id;
  96. csio_ln_dbg(ln, "Remote port x%x role 0x%x registered\n",
  97. rn->nport_id, ids.roles);
  98. }
  99. /*
  100. * csio_unreg_rnode - Unregister a remote port with FC transport.
  101. * @rn: Rnode representing remote port.
  102. *
  103. * Call fc_remote_port_delete() to unregister this remote port with FC
  104. * transport.
  105. *
  106. */
  107. void
  108. csio_unreg_rnode(struct csio_rnode *rn)
  109. {
  110. struct csio_lnode *ln = csio_rnode_to_lnode(rn);
  111. struct fc_rport *rport = rn->rport;
  112. rn->role &= ~(CSIO_RNFR_INITIATOR | CSIO_RNFR_TARGET);
  113. fc_remote_port_delete(rport);
  114. ln->num_reg_rnodes--;
  115. csio_ln_dbg(ln, "Remote port x%x un-registered\n", rn->nport_id);
  116. }
  117. /*
  118. * csio_lnode_async_event - Async events from local port.
  119. * @ln: lnode representing local port.
  120. *
  121. * Async events from local node that FC transport/SCSI ML
  122. * should be made aware of (Eg: RSCN).
  123. */
  124. void
  125. csio_lnode_async_event(struct csio_lnode *ln, enum csio_ln_fc_evt fc_evt)
  126. {
  127. switch (fc_evt) {
  128. case CSIO_LN_FC_RSCN:
  129. /* Get payload of rscn from ln */
  130. /* For each RSCN entry */
  131. /*
  132. * fc_host_post_event(shost,
  133. * fc_get_event_number(),
  134. * FCH_EVT_RSCN,
  135. * rscn_entry);
  136. */
  137. break;
  138. case CSIO_LN_FC_LINKUP:
  139. /* send fc_host_post_event */
  140. /* set vport state */
  141. if (csio_is_npiv_ln(ln))
  142. csio_vport_set_state(ln);
  143. break;
  144. case CSIO_LN_FC_LINKDOWN:
  145. /* send fc_host_post_event */
  146. /* set vport state */
  147. if (csio_is_npiv_ln(ln))
  148. csio_vport_set_state(ln);
  149. break;
  150. case CSIO_LN_FC_ATTRIB_UPDATE:
  151. csio_fchost_attr_init(ln);
  152. break;
  153. default:
  154. break;
  155. }
  156. }
  157. /*
  158. * csio_fchost_attr_init - Initialize FC transport attributes
  159. * @ln: Lnode.
  160. *
  161. */
  162. void
  163. csio_fchost_attr_init(struct csio_lnode *ln)
  164. {
  165. struct Scsi_Host *shost = csio_ln_to_shost(ln);
  166. fc_host_node_name(shost) = wwn_to_u64(csio_ln_wwnn(ln));
  167. fc_host_port_name(shost) = wwn_to_u64(csio_ln_wwpn(ln));
  168. fc_host_supported_classes(shost) = FC_COS_CLASS3;
  169. fc_host_max_npiv_vports(shost) =
  170. (csio_lnode_to_hw(ln))->fres_info.max_vnps;
  171. fc_host_supported_speeds(shost) = FC_PORTSPEED_10GBIT |
  172. FC_PORTSPEED_1GBIT;
  173. fc_host_maxframe_size(shost) = ntohs(ln->ln_sparm.csp.sp_bb_data);
  174. memset(fc_host_supported_fc4s(shost), 0,
  175. sizeof(fc_host_supported_fc4s(shost)));
  176. fc_host_supported_fc4s(shost)[7] = 1;
  177. memset(fc_host_active_fc4s(shost), 0,
  178. sizeof(fc_host_active_fc4s(shost)));
  179. fc_host_active_fc4s(shost)[7] = 1;
  180. }
  181. /*
  182. * csio_get_host_port_id - sysfs entries for nport_id is
  183. * populated/cached from this function
  184. */
  185. static void
  186. csio_get_host_port_id(struct Scsi_Host *shost)
  187. {
  188. struct csio_lnode *ln = shost_priv(shost);
  189. struct csio_hw *hw = csio_lnode_to_hw(ln);
  190. spin_lock_irq(&hw->lock);
  191. fc_host_port_id(shost) = ln->nport_id;
  192. spin_unlock_irq(&hw->lock);
  193. }
  194. /*
  195. * csio_get_port_type - Return FC local port type.
  196. * @shost: scsi host.
  197. *
  198. */
  199. static void
  200. csio_get_host_port_type(struct Scsi_Host *shost)
  201. {
  202. struct csio_lnode *ln = shost_priv(shost);
  203. struct csio_hw *hw = csio_lnode_to_hw(ln);
  204. spin_lock_irq(&hw->lock);
  205. if (csio_is_npiv_ln(ln))
  206. fc_host_port_type(shost) = FC_PORTTYPE_NPIV;
  207. else
  208. fc_host_port_type(shost) = FC_PORTTYPE_NPORT;
  209. spin_unlock_irq(&hw->lock);
  210. }
  211. /*
  212. * csio_get_port_state - Return FC local port state.
  213. * @shost: scsi host.
  214. *
  215. */
  216. static void
  217. csio_get_host_port_state(struct Scsi_Host *shost)
  218. {
  219. struct csio_lnode *ln = shost_priv(shost);
  220. struct csio_hw *hw = csio_lnode_to_hw(ln);
  221. char state[16];
  222. spin_lock_irq(&hw->lock);
  223. csio_lnode_state_to_str(ln, state);
  224. if (!strcmp(state, "READY"))
  225. fc_host_port_state(shost) = FC_PORTSTATE_ONLINE;
  226. else if (!strcmp(state, "OFFLINE"))
  227. fc_host_port_state(shost) = FC_PORTSTATE_LINKDOWN;
  228. else
  229. fc_host_port_state(shost) = FC_PORTSTATE_UNKNOWN;
  230. spin_unlock_irq(&hw->lock);
  231. }
  232. /*
  233. * csio_get_host_speed - Return link speed to FC transport.
  234. * @shost: scsi host.
  235. *
  236. */
  237. static void
  238. csio_get_host_speed(struct Scsi_Host *shost)
  239. {
  240. struct csio_lnode *ln = shost_priv(shost);
  241. struct csio_hw *hw = csio_lnode_to_hw(ln);
  242. spin_lock_irq(&hw->lock);
  243. switch (hw->pport[ln->portid].link_speed) {
  244. case FW_PORT_CAP_SPEED_1G:
  245. fc_host_speed(shost) = FC_PORTSPEED_1GBIT;
  246. break;
  247. case FW_PORT_CAP_SPEED_10G:
  248. fc_host_speed(shost) = FC_PORTSPEED_10GBIT;
  249. break;
  250. default:
  251. fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN;
  252. break;
  253. }
  254. spin_unlock_irq(&hw->lock);
  255. }
  256. /*
  257. * csio_get_host_fabric_name - Return fabric name
  258. * @shost: scsi host.
  259. *
  260. */
  261. static void
  262. csio_get_host_fabric_name(struct Scsi_Host *shost)
  263. {
  264. struct csio_lnode *ln = shost_priv(shost);
  265. struct csio_rnode *rn = NULL;
  266. struct csio_hw *hw = csio_lnode_to_hw(ln);
  267. spin_lock_irq(&hw->lock);
  268. rn = csio_rnode_lookup_portid(ln, FC_FID_FLOGI);
  269. if (rn)
  270. fc_host_fabric_name(shost) = wwn_to_u64(csio_rn_wwnn(rn));
  271. else
  272. fc_host_fabric_name(shost) = 0;
  273. spin_unlock_irq(&hw->lock);
  274. }
  275. /*
  276. * csio_get_host_speed - Return FC transport statistics.
  277. * @ln: Lnode.
  278. *
  279. */
  280. static struct fc_host_statistics *
  281. csio_get_stats(struct Scsi_Host *shost)
  282. {
  283. struct csio_lnode *ln = shost_priv(shost);
  284. struct csio_hw *hw = csio_lnode_to_hw(ln);
  285. struct fc_host_statistics *fhs = &ln->fch_stats;
  286. struct fw_fcoe_port_stats fcoe_port_stats;
  287. uint64_t seconds;
  288. memset(&fcoe_port_stats, 0, sizeof(struct fw_fcoe_port_stats));
  289. csio_get_phy_port_stats(hw, ln->portid, &fcoe_port_stats);
  290. fhs->tx_frames += (be64_to_cpu(fcoe_port_stats.tx_bcast_frames) +
  291. be64_to_cpu(fcoe_port_stats.tx_mcast_frames) +
  292. be64_to_cpu(fcoe_port_stats.tx_ucast_frames) +
  293. be64_to_cpu(fcoe_port_stats.tx_offload_frames));
  294. fhs->tx_words += (be64_to_cpu(fcoe_port_stats.tx_bcast_bytes) +
  295. be64_to_cpu(fcoe_port_stats.tx_mcast_bytes) +
  296. be64_to_cpu(fcoe_port_stats.tx_ucast_bytes) +
  297. be64_to_cpu(fcoe_port_stats.tx_offload_bytes)) /
  298. CSIO_WORD_TO_BYTE;
  299. fhs->rx_frames += (be64_to_cpu(fcoe_port_stats.rx_bcast_frames) +
  300. be64_to_cpu(fcoe_port_stats.rx_mcast_frames) +
  301. be64_to_cpu(fcoe_port_stats.rx_ucast_frames));
  302. fhs->rx_words += (be64_to_cpu(fcoe_port_stats.rx_bcast_bytes) +
  303. be64_to_cpu(fcoe_port_stats.rx_mcast_bytes) +
  304. be64_to_cpu(fcoe_port_stats.rx_ucast_bytes)) /
  305. CSIO_WORD_TO_BYTE;
  306. fhs->error_frames += be64_to_cpu(fcoe_port_stats.rx_err_frames);
  307. fhs->fcp_input_requests += ln->stats.n_input_requests;
  308. fhs->fcp_output_requests += ln->stats.n_output_requests;
  309. fhs->fcp_control_requests += ln->stats.n_control_requests;
  310. fhs->fcp_input_megabytes += ln->stats.n_input_bytes >> 20;
  311. fhs->fcp_output_megabytes += ln->stats.n_output_bytes >> 20;
  312. fhs->link_failure_count = ln->stats.n_link_down;
  313. /* Reset stats for the device */
  314. seconds = jiffies_to_msecs(jiffies) - hw->stats.n_reset_start;
  315. do_div(seconds, 1000);
  316. fhs->seconds_since_last_reset = seconds;
  317. return fhs;
  318. }
  319. /*
  320. * csio_set_rport_loss_tmo - Set the rport dev loss timeout
  321. * @rport: fc rport.
  322. * @timeout: new value for dev loss tmo.
  323. *
  324. * If timeout is non zero set the dev_loss_tmo to timeout, else set
  325. * dev_loss_tmo to one.
  326. */
  327. static void
  328. csio_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout)
  329. {
  330. if (timeout)
  331. rport->dev_loss_tmo = timeout;
  332. else
  333. rport->dev_loss_tmo = 1;
  334. }
  335. static void
  336. csio_vport_set_state(struct csio_lnode *ln)
  337. {
  338. struct fc_vport *fc_vport = ln->fc_vport;
  339. struct csio_lnode *pln = ln->pln;
  340. char state[16];
  341. /* Set fc vport state based on phyiscal lnode */
  342. csio_lnode_state_to_str(pln, state);
  343. if (strcmp(state, "READY")) {
  344. fc_vport_set_state(fc_vport, FC_VPORT_LINKDOWN);
  345. return;
  346. }
  347. if (!(pln->flags & CSIO_LNF_NPIVSUPP)) {
  348. fc_vport_set_state(fc_vport, FC_VPORT_NO_FABRIC_SUPP);
  349. return;
  350. }
  351. /* Set fc vport state based on virtual lnode */
  352. csio_lnode_state_to_str(ln, state);
  353. if (strcmp(state, "READY")) {
  354. fc_vport_set_state(fc_vport, FC_VPORT_LINKDOWN);
  355. return;
  356. }
  357. fc_vport_set_state(fc_vport, FC_VPORT_ACTIVE);
  358. }
  359. static int
  360. csio_fcoe_alloc_vnp(struct csio_hw *hw, struct csio_lnode *ln)
  361. {
  362. struct csio_lnode *pln;
  363. struct csio_mb *mbp;
  364. struct fw_fcoe_vnp_cmd *rsp;
  365. int ret = 0;
  366. int retry = 0;
  367. /* Issue VNP cmd to alloc vport */
  368. /* Allocate Mbox request */
  369. spin_lock_irq(&hw->lock);
  370. mbp = mempool_alloc(hw->mb_mempool, GFP_ATOMIC);
  371. if (!mbp) {
  372. CSIO_INC_STATS(hw, n_err_nomem);
  373. ret = -ENOMEM;
  374. goto out;
  375. }
  376. pln = ln->pln;
  377. ln->fcf_flowid = pln->fcf_flowid;
  378. ln->portid = pln->portid;
  379. csio_fcoe_vnp_alloc_init_mb(ln, mbp, CSIO_MB_DEFAULT_TMO,
  380. pln->fcf_flowid, pln->vnp_flowid, 0,
  381. csio_ln_wwnn(ln), csio_ln_wwpn(ln), NULL);
  382. for (retry = 0; retry < 3; retry++) {
  383. /* FW is expected to complete vnp cmd in immediate mode
  384. * without much delay.
  385. * Otherwise, there will be increase in IO latency since HW
  386. * lock is held till completion of vnp mbox cmd.
  387. */
  388. ret = csio_mb_issue(hw, mbp);
  389. if (ret != -EBUSY)
  390. break;
  391. /* Retry if mbox returns busy */
  392. spin_unlock_irq(&hw->lock);
  393. msleep(2000);
  394. spin_lock_irq(&hw->lock);
  395. }
  396. if (ret) {
  397. csio_ln_err(ln, "Failed to issue mbox FCoE VNP command\n");
  398. goto out_free;
  399. }
  400. /* Process Mbox response of VNP command */
  401. rsp = (struct fw_fcoe_vnp_cmd *)(mbp->mb);
  402. if (FW_CMD_RETVAL_G(ntohl(rsp->alloc_to_len16)) != FW_SUCCESS) {
  403. csio_ln_err(ln, "FCOE VNP ALLOC cmd returned 0x%x!\n",
  404. FW_CMD_RETVAL_G(ntohl(rsp->alloc_to_len16)));
  405. ret = -EINVAL;
  406. goto out_free;
  407. }
  408. ln->vnp_flowid = FW_FCOE_VNP_CMD_VNPI_GET(
  409. ntohl(rsp->gen_wwn_to_vnpi));
  410. memcpy(csio_ln_wwnn(ln), rsp->vnport_wwnn, 8);
  411. memcpy(csio_ln_wwpn(ln), rsp->vnport_wwpn, 8);
  412. csio_ln_dbg(ln, "FCOE VNPI: 0x%x\n", ln->vnp_flowid);
  413. csio_ln_dbg(ln, "\tWWNN: %x%x%x%x%x%x%x%x\n",
  414. ln->ln_sparm.wwnn[0], ln->ln_sparm.wwnn[1],
  415. ln->ln_sparm.wwnn[2], ln->ln_sparm.wwnn[3],
  416. ln->ln_sparm.wwnn[4], ln->ln_sparm.wwnn[5],
  417. ln->ln_sparm.wwnn[6], ln->ln_sparm.wwnn[7]);
  418. csio_ln_dbg(ln, "\tWWPN: %x%x%x%x%x%x%x%x\n",
  419. ln->ln_sparm.wwpn[0], ln->ln_sparm.wwpn[1],
  420. ln->ln_sparm.wwpn[2], ln->ln_sparm.wwpn[3],
  421. ln->ln_sparm.wwpn[4], ln->ln_sparm.wwpn[5],
  422. ln->ln_sparm.wwpn[6], ln->ln_sparm.wwpn[7]);
  423. out_free:
  424. mempool_free(mbp, hw->mb_mempool);
  425. out:
  426. spin_unlock_irq(&hw->lock);
  427. return ret;
  428. }
  429. static int
  430. csio_fcoe_free_vnp(struct csio_hw *hw, struct csio_lnode *ln)
  431. {
  432. struct csio_lnode *pln;
  433. struct csio_mb *mbp;
  434. struct fw_fcoe_vnp_cmd *rsp;
  435. int ret = 0;
  436. int retry = 0;
  437. /* Issue VNP cmd to free vport */
  438. /* Allocate Mbox request */
  439. spin_lock_irq(&hw->lock);
  440. mbp = mempool_alloc(hw->mb_mempool, GFP_ATOMIC);
  441. if (!mbp) {
  442. CSIO_INC_STATS(hw, n_err_nomem);
  443. ret = -ENOMEM;
  444. goto out;
  445. }
  446. pln = ln->pln;
  447. csio_fcoe_vnp_free_init_mb(ln, mbp, CSIO_MB_DEFAULT_TMO,
  448. ln->fcf_flowid, ln->vnp_flowid,
  449. NULL);
  450. for (retry = 0; retry < 3; retry++) {
  451. ret = csio_mb_issue(hw, mbp);
  452. if (ret != -EBUSY)
  453. break;
  454. /* Retry if mbox returns busy */
  455. spin_unlock_irq(&hw->lock);
  456. msleep(2000);
  457. spin_lock_irq(&hw->lock);
  458. }
  459. if (ret) {
  460. csio_ln_err(ln, "Failed to issue mbox FCoE VNP command\n");
  461. goto out_free;
  462. }
  463. /* Process Mbox response of VNP command */
  464. rsp = (struct fw_fcoe_vnp_cmd *)(mbp->mb);
  465. if (FW_CMD_RETVAL_G(ntohl(rsp->alloc_to_len16)) != FW_SUCCESS) {
  466. csio_ln_err(ln, "FCOE VNP FREE cmd returned 0x%x!\n",
  467. FW_CMD_RETVAL_G(ntohl(rsp->alloc_to_len16)));
  468. ret = -EINVAL;
  469. }
  470. out_free:
  471. mempool_free(mbp, hw->mb_mempool);
  472. out:
  473. spin_unlock_irq(&hw->lock);
  474. return ret;
  475. }
  476. static int
  477. csio_vport_create(struct fc_vport *fc_vport, bool disable)
  478. {
  479. struct Scsi_Host *shost = fc_vport->shost;
  480. struct csio_lnode *pln = shost_priv(shost);
  481. struct csio_lnode *ln = NULL;
  482. struct csio_hw *hw = csio_lnode_to_hw(pln);
  483. uint8_t wwn[8];
  484. int ret = -1;
  485. ln = csio_shost_init(hw, &fc_vport->dev, false, pln);
  486. if (!ln)
  487. goto error;
  488. if (fc_vport->node_name != 0) {
  489. u64_to_wwn(fc_vport->node_name, wwn);
  490. if (!CSIO_VALID_WWN(wwn)) {
  491. csio_ln_err(ln,
  492. "vport create failed. Invalid wwnn\n");
  493. goto error;
  494. }
  495. memcpy(csio_ln_wwnn(ln), wwn, 8);
  496. }
  497. if (fc_vport->port_name != 0) {
  498. u64_to_wwn(fc_vport->port_name, wwn);
  499. if (!CSIO_VALID_WWN(wwn)) {
  500. csio_ln_err(ln,
  501. "vport create failed. Invalid wwpn\n");
  502. goto error;
  503. }
  504. if (csio_lnode_lookup_by_wwpn(hw, wwn)) {
  505. csio_ln_err(ln,
  506. "vport create failed. wwpn already exists\n");
  507. goto error;
  508. }
  509. memcpy(csio_ln_wwpn(ln), wwn, 8);
  510. }
  511. fc_vport_set_state(fc_vport, FC_VPORT_INITIALIZING);
  512. if (csio_fcoe_alloc_vnp(hw, ln))
  513. goto error;
  514. *(struct csio_lnode **)fc_vport->dd_data = ln;
  515. ln->fc_vport = fc_vport;
  516. if (!fc_vport->node_name)
  517. fc_vport->node_name = wwn_to_u64(csio_ln_wwnn(ln));
  518. if (!fc_vport->port_name)
  519. fc_vport->port_name = wwn_to_u64(csio_ln_wwpn(ln));
  520. csio_fchost_attr_init(ln);
  521. return 0;
  522. error:
  523. if (ln)
  524. csio_shost_exit(ln);
  525. return ret;
  526. }
  527. static int
  528. csio_vport_delete(struct fc_vport *fc_vport)
  529. {
  530. struct csio_lnode *ln = *(struct csio_lnode **)fc_vport->dd_data;
  531. struct Scsi_Host *shost = csio_ln_to_shost(ln);
  532. struct csio_hw *hw = csio_lnode_to_hw(ln);
  533. int rmv;
  534. spin_lock_irq(&hw->lock);
  535. rmv = csio_is_hw_removing(hw);
  536. spin_unlock_irq(&hw->lock);
  537. if (rmv) {
  538. csio_shost_exit(ln);
  539. return 0;
  540. }
  541. /* Quiesce ios and send remove event to lnode */
  542. scsi_block_requests(shost);
  543. spin_lock_irq(&hw->lock);
  544. csio_scsim_cleanup_io_lnode(csio_hw_to_scsim(hw), ln);
  545. csio_lnode_close(ln);
  546. spin_unlock_irq(&hw->lock);
  547. scsi_unblock_requests(shost);
  548. /* Free vnp */
  549. if (fc_vport->vport_state != FC_VPORT_DISABLED)
  550. csio_fcoe_free_vnp(hw, ln);
  551. csio_shost_exit(ln);
  552. return 0;
  553. }
  554. static int
  555. csio_vport_disable(struct fc_vport *fc_vport, bool disable)
  556. {
  557. struct csio_lnode *ln = *(struct csio_lnode **)fc_vport->dd_data;
  558. struct Scsi_Host *shost = csio_ln_to_shost(ln);
  559. struct csio_hw *hw = csio_lnode_to_hw(ln);
  560. /* disable vport */
  561. if (disable) {
  562. /* Quiesce ios and send stop event to lnode */
  563. scsi_block_requests(shost);
  564. spin_lock_irq(&hw->lock);
  565. csio_scsim_cleanup_io_lnode(csio_hw_to_scsim(hw), ln);
  566. csio_lnode_stop(ln);
  567. spin_unlock_irq(&hw->lock);
  568. scsi_unblock_requests(shost);
  569. /* Free vnp */
  570. csio_fcoe_free_vnp(hw, ln);
  571. fc_vport_set_state(fc_vport, FC_VPORT_DISABLED);
  572. csio_ln_err(ln, "vport disabled\n");
  573. return 0;
  574. } else {
  575. /* enable vport */
  576. fc_vport_set_state(fc_vport, FC_VPORT_INITIALIZING);
  577. if (csio_fcoe_alloc_vnp(hw, ln)) {
  578. csio_ln_err(ln, "vport enabled failed.\n");
  579. return -1;
  580. }
  581. csio_ln_err(ln, "vport enabled\n");
  582. return 0;
  583. }
  584. }
  585. static void
  586. csio_dev_loss_tmo_callbk(struct fc_rport *rport)
  587. {
  588. struct csio_rnode *rn;
  589. struct csio_hw *hw;
  590. struct csio_lnode *ln;
  591. rn = *((struct csio_rnode **)rport->dd_data);
  592. ln = csio_rnode_to_lnode(rn);
  593. hw = csio_lnode_to_hw(ln);
  594. spin_lock_irq(&hw->lock);
  595. /* return if driver is being removed or same rnode comes back online */
  596. if (csio_is_hw_removing(hw) || csio_is_rnode_ready(rn))
  597. goto out;
  598. csio_ln_dbg(ln, "devloss timeout on rnode:%p portid:x%x flowid:x%x\n",
  599. rn, rn->nport_id, csio_rn_flowid(rn));
  600. CSIO_INC_STATS(ln, n_dev_loss_tmo);
  601. /*
  602. * enqueue devloss event to event worker thread to serialize all
  603. * rnode events.
  604. */
  605. if (csio_enqueue_evt(hw, CSIO_EVT_DEV_LOSS, &rn, sizeof(rn))) {
  606. CSIO_INC_STATS(hw, n_evt_drop);
  607. goto out;
  608. }
  609. if (!(hw->flags & CSIO_HWF_FWEVT_PENDING)) {
  610. hw->flags |= CSIO_HWF_FWEVT_PENDING;
  611. spin_unlock_irq(&hw->lock);
  612. schedule_work(&hw->evtq_work);
  613. return;
  614. }
  615. out:
  616. spin_unlock_irq(&hw->lock);
  617. }
  618. /* FC transport functions template - Physical port */
  619. struct fc_function_template csio_fc_transport_funcs = {
  620. .show_host_node_name = 1,
  621. .show_host_port_name = 1,
  622. .show_host_supported_classes = 1,
  623. .show_host_supported_fc4s = 1,
  624. .show_host_maxframe_size = 1,
  625. .get_host_port_id = csio_get_host_port_id,
  626. .show_host_port_id = 1,
  627. .get_host_port_type = csio_get_host_port_type,
  628. .show_host_port_type = 1,
  629. .get_host_port_state = csio_get_host_port_state,
  630. .show_host_port_state = 1,
  631. .show_host_active_fc4s = 1,
  632. .get_host_speed = csio_get_host_speed,
  633. .show_host_speed = 1,
  634. .get_host_fabric_name = csio_get_host_fabric_name,
  635. .show_host_fabric_name = 1,
  636. .get_fc_host_stats = csio_get_stats,
  637. .dd_fcrport_size = sizeof(struct csio_rnode *),
  638. .show_rport_maxframe_size = 1,
  639. .show_rport_supported_classes = 1,
  640. .set_rport_dev_loss_tmo = csio_set_rport_loss_tmo,
  641. .show_rport_dev_loss_tmo = 1,
  642. .show_starget_port_id = 1,
  643. .show_starget_node_name = 1,
  644. .show_starget_port_name = 1,
  645. .dev_loss_tmo_callbk = csio_dev_loss_tmo_callbk,
  646. .dd_fcvport_size = sizeof(struct csio_lnode *),
  647. .vport_create = csio_vport_create,
  648. .vport_disable = csio_vport_disable,
  649. .vport_delete = csio_vport_delete,
  650. };
  651. /* FC transport functions template - Virtual port */
  652. struct fc_function_template csio_fc_transport_vport_funcs = {
  653. .show_host_node_name = 1,
  654. .show_host_port_name = 1,
  655. .show_host_supported_classes = 1,
  656. .show_host_supported_fc4s = 1,
  657. .show_host_maxframe_size = 1,
  658. .get_host_port_id = csio_get_host_port_id,
  659. .show_host_port_id = 1,
  660. .get_host_port_type = csio_get_host_port_type,
  661. .show_host_port_type = 1,
  662. .get_host_port_state = csio_get_host_port_state,
  663. .show_host_port_state = 1,
  664. .show_host_active_fc4s = 1,
  665. .get_host_speed = csio_get_host_speed,
  666. .show_host_speed = 1,
  667. .get_host_fabric_name = csio_get_host_fabric_name,
  668. .show_host_fabric_name = 1,
  669. .get_fc_host_stats = csio_get_stats,
  670. .dd_fcrport_size = sizeof(struct csio_rnode *),
  671. .show_rport_maxframe_size = 1,
  672. .show_rport_supported_classes = 1,
  673. .set_rport_dev_loss_tmo = csio_set_rport_loss_tmo,
  674. .show_rport_dev_loss_tmo = 1,
  675. .show_starget_port_id = 1,
  676. .show_starget_node_name = 1,
  677. .show_starget_port_name = 1,
  678. .dev_loss_tmo_callbk = csio_dev_loss_tmo_callbk,
  679. };