csio_rnode.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913
  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/string.h>
  35. #include <scsi/scsi_device.h>
  36. #include <scsi/scsi_transport_fc.h>
  37. #include <scsi/fc/fc_els.h>
  38. #include <scsi/fc/fc_fs.h>
  39. #include "csio_hw.h"
  40. #include "csio_lnode.h"
  41. #include "csio_rnode.h"
  42. static int csio_rnode_init(struct csio_rnode *, struct csio_lnode *);
  43. static void csio_rnode_exit(struct csio_rnode *);
  44. /* Static machine forward declarations */
  45. static void csio_rns_uninit(struct csio_rnode *, enum csio_rn_ev);
  46. static void csio_rns_ready(struct csio_rnode *, enum csio_rn_ev);
  47. static void csio_rns_offline(struct csio_rnode *, enum csio_rn_ev);
  48. static void csio_rns_disappeared(struct csio_rnode *, enum csio_rn_ev);
  49. /* RNF event mapping */
  50. static enum csio_rn_ev fwevt_to_rnevt[] = {
  51. CSIO_RNFE_NONE, /* None */
  52. CSIO_RNFE_LOGGED_IN, /* PLOGI_ACC_RCVD */
  53. CSIO_RNFE_NONE, /* PLOGI_RJT_RCVD */
  54. CSIO_RNFE_PLOGI_RECV, /* PLOGI_RCVD */
  55. CSIO_RNFE_LOGO_RECV, /* PLOGO_RCVD */
  56. CSIO_RNFE_PRLI_DONE, /* PRLI_ACC_RCVD */
  57. CSIO_RNFE_NONE, /* PRLI_RJT_RCVD */
  58. CSIO_RNFE_PRLI_RECV, /* PRLI_RCVD */
  59. CSIO_RNFE_PRLO_RECV, /* PRLO_RCVD */
  60. CSIO_RNFE_NONE, /* NPORT_ID_CHGD */
  61. CSIO_RNFE_LOGO_RECV, /* FLOGO_RCVD */
  62. CSIO_RNFE_NONE, /* CLR_VIRT_LNK_RCVD */
  63. CSIO_RNFE_LOGGED_IN, /* FLOGI_ACC_RCVD */
  64. CSIO_RNFE_NONE, /* FLOGI_RJT_RCVD */
  65. CSIO_RNFE_LOGGED_IN, /* FDISC_ACC_RCVD */
  66. CSIO_RNFE_NONE, /* FDISC_RJT_RCVD */
  67. CSIO_RNFE_NONE, /* FLOGI_TMO_MAX_RETRY */
  68. CSIO_RNFE_NONE, /* IMPL_LOGO_ADISC_ACC */
  69. CSIO_RNFE_NONE, /* IMPL_LOGO_ADISC_RJT */
  70. CSIO_RNFE_NONE, /* IMPL_LOGO_ADISC_CNFLT */
  71. CSIO_RNFE_NONE, /* PRLI_TMO */
  72. CSIO_RNFE_NONE, /* ADISC_TMO */
  73. CSIO_RNFE_NAME_MISSING, /* RSCN_DEV_LOST */
  74. CSIO_RNFE_NONE, /* SCR_ACC_RCVD */
  75. CSIO_RNFE_NONE, /* ADISC_RJT_RCVD */
  76. CSIO_RNFE_NONE, /* LOGO_SNT */
  77. CSIO_RNFE_LOGO_RECV, /* PROTO_ERR_IMPL_LOGO */
  78. };
  79. #define CSIO_FWE_TO_RNFE(_evt) ((_evt > PROTO_ERR_IMPL_LOGO) ? \
  80. CSIO_RNFE_NONE : \
  81. fwevt_to_rnevt[_evt])
  82. int
  83. csio_is_rnode_ready(struct csio_rnode *rn)
  84. {
  85. return csio_match_state(rn, csio_rns_ready);
  86. }
  87. static int
  88. csio_is_rnode_uninit(struct csio_rnode *rn)
  89. {
  90. return csio_match_state(rn, csio_rns_uninit);
  91. }
  92. static int
  93. csio_is_rnode_wka(uint8_t rport_type)
  94. {
  95. if ((rport_type == FLOGI_VFPORT) ||
  96. (rport_type == FDISC_VFPORT) ||
  97. (rport_type == NS_VNPORT) ||
  98. (rport_type == FDMI_VNPORT))
  99. return 1;
  100. return 0;
  101. }
  102. /*
  103. * csio_rn_lookup - Finds the rnode with the given flowid
  104. * @ln - lnode
  105. * @flowid - flowid.
  106. *
  107. * Does the rnode lookup on the given lnode and flowid.If no matching entry
  108. * found, NULL is returned.
  109. */
  110. static struct csio_rnode *
  111. csio_rn_lookup(struct csio_lnode *ln, uint32_t flowid)
  112. {
  113. struct csio_rnode *rnhead = (struct csio_rnode *) &ln->rnhead;
  114. struct list_head *tmp;
  115. struct csio_rnode *rn;
  116. list_for_each(tmp, &rnhead->sm.sm_list) {
  117. rn = (struct csio_rnode *) tmp;
  118. if (rn->flowid == flowid)
  119. return rn;
  120. }
  121. return NULL;
  122. }
  123. /*
  124. * csio_rn_lookup_wwpn - Finds the rnode with the given wwpn
  125. * @ln: lnode
  126. * @wwpn: wwpn
  127. *
  128. * Does the rnode lookup on the given lnode and wwpn. If no matching entry
  129. * found, NULL is returned.
  130. */
  131. static struct csio_rnode *
  132. csio_rn_lookup_wwpn(struct csio_lnode *ln, uint8_t *wwpn)
  133. {
  134. struct csio_rnode *rnhead = (struct csio_rnode *) &ln->rnhead;
  135. struct list_head *tmp;
  136. struct csio_rnode *rn;
  137. list_for_each(tmp, &rnhead->sm.sm_list) {
  138. rn = (struct csio_rnode *) tmp;
  139. if (!memcmp(csio_rn_wwpn(rn), wwpn, 8))
  140. return rn;
  141. }
  142. return NULL;
  143. }
  144. /**
  145. * csio_rnode_lookup_portid - Finds the rnode with the given portid
  146. * @ln: lnode
  147. * @portid: port id
  148. *
  149. * Lookup the rnode list for a given portid. If no matching entry
  150. * found, NULL is returned.
  151. */
  152. struct csio_rnode *
  153. csio_rnode_lookup_portid(struct csio_lnode *ln, uint32_t portid)
  154. {
  155. struct csio_rnode *rnhead = (struct csio_rnode *) &ln->rnhead;
  156. struct list_head *tmp;
  157. struct csio_rnode *rn;
  158. list_for_each(tmp, &rnhead->sm.sm_list) {
  159. rn = (struct csio_rnode *) tmp;
  160. if (rn->nport_id == portid)
  161. return rn;
  162. }
  163. return NULL;
  164. }
  165. static int
  166. csio_rn_dup_flowid(struct csio_lnode *ln, uint32_t rdev_flowid,
  167. uint32_t *vnp_flowid)
  168. {
  169. struct csio_rnode *rnhead;
  170. struct list_head *tmp, *tmp1;
  171. struct csio_rnode *rn;
  172. struct csio_lnode *ln_tmp;
  173. struct csio_hw *hw = csio_lnode_to_hw(ln);
  174. list_for_each(tmp1, &hw->sln_head) {
  175. ln_tmp = (struct csio_lnode *) tmp1;
  176. if (ln_tmp == ln)
  177. continue;
  178. rnhead = (struct csio_rnode *)&ln_tmp->rnhead;
  179. list_for_each(tmp, &rnhead->sm.sm_list) {
  180. rn = (struct csio_rnode *) tmp;
  181. if (csio_is_rnode_ready(rn)) {
  182. if (rn->flowid == rdev_flowid) {
  183. *vnp_flowid = csio_ln_flowid(ln_tmp);
  184. return 1;
  185. }
  186. }
  187. }
  188. }
  189. return 0;
  190. }
  191. static struct csio_rnode *
  192. csio_alloc_rnode(struct csio_lnode *ln)
  193. {
  194. struct csio_hw *hw = csio_lnode_to_hw(ln);
  195. struct csio_rnode *rn = mempool_alloc(hw->rnode_mempool, GFP_ATOMIC);
  196. if (!rn)
  197. goto err;
  198. memset(rn, 0, sizeof(struct csio_rnode));
  199. if (csio_rnode_init(rn, ln))
  200. goto err_free;
  201. CSIO_INC_STATS(ln, n_rnode_alloc);
  202. return rn;
  203. err_free:
  204. mempool_free(rn, hw->rnode_mempool);
  205. err:
  206. CSIO_INC_STATS(ln, n_rnode_nomem);
  207. return NULL;
  208. }
  209. static void
  210. csio_free_rnode(struct csio_rnode *rn)
  211. {
  212. struct csio_hw *hw = csio_lnode_to_hw(csio_rnode_to_lnode(rn));
  213. csio_rnode_exit(rn);
  214. CSIO_INC_STATS(rn->lnp, n_rnode_free);
  215. mempool_free(rn, hw->rnode_mempool);
  216. }
  217. /*
  218. * csio_get_rnode - Gets rnode with the given flowid
  219. * @ln - lnode
  220. * @flowid - flow id.
  221. *
  222. * Does the rnode lookup on the given lnode and flowid. If no matching
  223. * rnode found, then new rnode with given npid is allocated and returned.
  224. */
  225. static struct csio_rnode *
  226. csio_get_rnode(struct csio_lnode *ln, uint32_t flowid)
  227. {
  228. struct csio_rnode *rn;
  229. rn = csio_rn_lookup(ln, flowid);
  230. if (!rn) {
  231. rn = csio_alloc_rnode(ln);
  232. if (!rn)
  233. return NULL;
  234. rn->flowid = flowid;
  235. }
  236. return rn;
  237. }
  238. /*
  239. * csio_put_rnode - Frees the given rnode
  240. * @ln - lnode
  241. * @flowid - flow id.
  242. *
  243. * Does the rnode lookup on the given lnode and flowid. If no matching
  244. * rnode found, then new rnode with given npid is allocated and returned.
  245. */
  246. void
  247. csio_put_rnode(struct csio_lnode *ln, struct csio_rnode *rn)
  248. {
  249. CSIO_DB_ASSERT(csio_is_rnode_uninit(rn) != 0);
  250. csio_free_rnode(rn);
  251. }
  252. /*
  253. * csio_confirm_rnode - confirms rnode based on wwpn.
  254. * @ln: lnode
  255. * @rdev_flowid: remote device flowid
  256. * @rdevp: remote device params
  257. * This routines searches other rnode in list having same wwpn of new rnode.
  258. * If there is a match, then matched rnode is returned and otherwise new rnode
  259. * is returned.
  260. * returns rnode.
  261. */
  262. struct csio_rnode *
  263. csio_confirm_rnode(struct csio_lnode *ln, uint32_t rdev_flowid,
  264. struct fcoe_rdev_entry *rdevp)
  265. {
  266. uint8_t rport_type;
  267. struct csio_rnode *rn, *match_rn;
  268. uint32_t vnp_flowid;
  269. __be32 *port_id;
  270. port_id = (__be32 *)&rdevp->r_id[0];
  271. rport_type =
  272. FW_RDEV_WR_RPORT_TYPE_GET(rdevp->rd_xfer_rdy_to_rport_type);
  273. /* Drop rdev event for cntrl port */
  274. if (rport_type == FAB_CTLR_VNPORT) {
  275. csio_ln_dbg(ln,
  276. "Unhandled rport_type:%d recv in rdev evt "
  277. "ssni:x%x\n", rport_type, rdev_flowid);
  278. return NULL;
  279. }
  280. /* Lookup on flowid */
  281. rn = csio_rn_lookup(ln, rdev_flowid);
  282. if (!rn) {
  283. /* Drop events with duplicate flowid */
  284. if (csio_rn_dup_flowid(ln, rdev_flowid, &vnp_flowid)) {
  285. csio_ln_warn(ln,
  286. "ssni:%x already active on vnpi:%x",
  287. rdev_flowid, vnp_flowid);
  288. return NULL;
  289. }
  290. /* Lookup on wwpn for NPORTs */
  291. rn = csio_rn_lookup_wwpn(ln, rdevp->wwpn);
  292. if (!rn)
  293. goto alloc_rnode;
  294. } else {
  295. /* Lookup well-known ports with nport id */
  296. if (csio_is_rnode_wka(rport_type)) {
  297. match_rn = csio_rnode_lookup_portid(ln,
  298. ((ntohl(*port_id) >> 8) & CSIO_DID_MASK));
  299. if (match_rn == NULL) {
  300. csio_rn_flowid(rn) = CSIO_INVALID_IDX;
  301. goto alloc_rnode;
  302. }
  303. /*
  304. * Now compare the wwpn to confirm that
  305. * same port relogged in. If so update the matched rn.
  306. * Else, go ahead and alloc a new rnode.
  307. */
  308. if (!memcmp(csio_rn_wwpn(match_rn), rdevp->wwpn, 8)) {
  309. if (csio_is_rnode_ready(rn)) {
  310. csio_ln_warn(ln,
  311. "rnode is already"
  312. "active ssni:x%x\n",
  313. rdev_flowid);
  314. CSIO_ASSERT(0);
  315. }
  316. csio_rn_flowid(rn) = CSIO_INVALID_IDX;
  317. rn = match_rn;
  318. /* Update rn */
  319. goto found_rnode;
  320. }
  321. csio_rn_flowid(rn) = CSIO_INVALID_IDX;
  322. goto alloc_rnode;
  323. }
  324. /* wwpn match */
  325. if (!memcmp(csio_rn_wwpn(rn), rdevp->wwpn, 8))
  326. goto found_rnode;
  327. /* Search for rnode that have same wwpn */
  328. match_rn = csio_rn_lookup_wwpn(ln, rdevp->wwpn);
  329. if (match_rn != NULL) {
  330. csio_ln_dbg(ln,
  331. "ssni:x%x changed for rport name(wwpn):%llx "
  332. "did:x%x\n", rdev_flowid,
  333. wwn_to_u64(rdevp->wwpn),
  334. match_rn->nport_id);
  335. csio_rn_flowid(rn) = CSIO_INVALID_IDX;
  336. rn = match_rn;
  337. } else {
  338. csio_ln_dbg(ln,
  339. "rnode wwpn mismatch found ssni:x%x "
  340. "name(wwpn):%llx\n",
  341. rdev_flowid,
  342. wwn_to_u64(csio_rn_wwpn(rn)));
  343. if (csio_is_rnode_ready(rn)) {
  344. csio_ln_warn(ln,
  345. "rnode is already active "
  346. "wwpn:%llx ssni:x%x\n",
  347. wwn_to_u64(csio_rn_wwpn(rn)),
  348. rdev_flowid);
  349. CSIO_ASSERT(0);
  350. }
  351. csio_rn_flowid(rn) = CSIO_INVALID_IDX;
  352. goto alloc_rnode;
  353. }
  354. }
  355. found_rnode:
  356. csio_ln_dbg(ln, "found rnode:%p ssni:x%x name(wwpn):%llx\n",
  357. rn, rdev_flowid, wwn_to_u64(rdevp->wwpn));
  358. /* Update flowid */
  359. csio_rn_flowid(rn) = rdev_flowid;
  360. /* update rdev entry */
  361. rn->rdev_entry = rdevp;
  362. CSIO_INC_STATS(ln, n_rnode_match);
  363. return rn;
  364. alloc_rnode:
  365. rn = csio_get_rnode(ln, rdev_flowid);
  366. if (!rn)
  367. return NULL;
  368. csio_ln_dbg(ln, "alloc rnode:%p ssni:x%x name(wwpn):%llx\n",
  369. rn, rdev_flowid, wwn_to_u64(rdevp->wwpn));
  370. /* update rdev entry */
  371. rn->rdev_entry = rdevp;
  372. return rn;
  373. }
  374. /*
  375. * csio_rn_verify_rparams - verify rparams.
  376. * @ln: lnode
  377. * @rn: rnode
  378. * @rdevp: remote device params
  379. * returns success if rparams are verified.
  380. */
  381. static int
  382. csio_rn_verify_rparams(struct csio_lnode *ln, struct csio_rnode *rn,
  383. struct fcoe_rdev_entry *rdevp)
  384. {
  385. uint8_t null[8];
  386. uint8_t rport_type;
  387. uint8_t fc_class;
  388. __be32 *did;
  389. did = (__be32 *) &rdevp->r_id[0];
  390. rport_type =
  391. FW_RDEV_WR_RPORT_TYPE_GET(rdevp->rd_xfer_rdy_to_rport_type);
  392. switch (rport_type) {
  393. case FLOGI_VFPORT:
  394. rn->role = CSIO_RNFR_FABRIC;
  395. if (((ntohl(*did) >> 8) & CSIO_DID_MASK) != FC_FID_FLOGI) {
  396. csio_ln_err(ln, "ssni:x%x invalid fabric portid\n",
  397. csio_rn_flowid(rn));
  398. return -EINVAL;
  399. }
  400. /* NPIV support */
  401. if (FW_RDEV_WR_NPIV_GET(rdevp->vft_to_qos))
  402. ln->flags |= CSIO_LNF_NPIVSUPP;
  403. break;
  404. case NS_VNPORT:
  405. rn->role = CSIO_RNFR_NS;
  406. if (((ntohl(*did) >> 8) & CSIO_DID_MASK) != FC_FID_DIR_SERV) {
  407. csio_ln_err(ln, "ssni:x%x invalid fabric portid\n",
  408. csio_rn_flowid(rn));
  409. return -EINVAL;
  410. }
  411. break;
  412. case REG_FC4_VNPORT:
  413. case REG_VNPORT:
  414. rn->role = CSIO_RNFR_NPORT;
  415. if (rdevp->event_cause == PRLI_ACC_RCVD ||
  416. rdevp->event_cause == PRLI_RCVD) {
  417. if (FW_RDEV_WR_TASK_RETRY_ID_GET(
  418. rdevp->enh_disc_to_tgt))
  419. rn->fcp_flags |= FCP_SPPF_OVLY_ALLOW;
  420. if (FW_RDEV_WR_RETRY_GET(rdevp->enh_disc_to_tgt))
  421. rn->fcp_flags |= FCP_SPPF_RETRY;
  422. if (FW_RDEV_WR_CONF_CMPL_GET(rdevp->enh_disc_to_tgt))
  423. rn->fcp_flags |= FCP_SPPF_CONF_COMPL;
  424. if (FW_RDEV_WR_TGT_GET(rdevp->enh_disc_to_tgt))
  425. rn->role |= CSIO_RNFR_TARGET;
  426. if (FW_RDEV_WR_INI_GET(rdevp->enh_disc_to_tgt))
  427. rn->role |= CSIO_RNFR_INITIATOR;
  428. }
  429. break;
  430. case FDMI_VNPORT:
  431. case FAB_CTLR_VNPORT:
  432. rn->role = 0;
  433. break;
  434. default:
  435. csio_ln_err(ln, "ssni:x%x invalid rport type recv x%x\n",
  436. csio_rn_flowid(rn), rport_type);
  437. return -EINVAL;
  438. }
  439. /* validate wwpn/wwnn for Name server/remote port */
  440. if (rport_type == REG_VNPORT || rport_type == NS_VNPORT) {
  441. memset(null, 0, 8);
  442. if (!memcmp(rdevp->wwnn, null, 8)) {
  443. csio_ln_err(ln,
  444. "ssni:x%x invalid wwnn received from"
  445. " rport did:x%x\n",
  446. csio_rn_flowid(rn),
  447. (ntohl(*did) & CSIO_DID_MASK));
  448. return -EINVAL;
  449. }
  450. if (!memcmp(rdevp->wwpn, null, 8)) {
  451. csio_ln_err(ln,
  452. "ssni:x%x invalid wwpn received from"
  453. " rport did:x%x\n",
  454. csio_rn_flowid(rn),
  455. (ntohl(*did) & CSIO_DID_MASK));
  456. return -EINVAL;
  457. }
  458. }
  459. /* Copy wwnn, wwpn and nport id */
  460. rn->nport_id = (ntohl(*did) >> 8) & CSIO_DID_MASK;
  461. memcpy(csio_rn_wwnn(rn), rdevp->wwnn, 8);
  462. memcpy(csio_rn_wwpn(rn), rdevp->wwpn, 8);
  463. rn->rn_sparm.csp.sp_bb_data = rdevp->rcv_fr_sz;
  464. fc_class = FW_RDEV_WR_CLASS_GET(rdevp->vft_to_qos);
  465. rn->rn_sparm.clsp[fc_class - 1].cp_class = htons(FC_CPC_VALID);
  466. return 0;
  467. }
  468. static void
  469. __csio_reg_rnode(struct csio_rnode *rn)
  470. {
  471. struct csio_lnode *ln = csio_rnode_to_lnode(rn);
  472. struct csio_hw *hw = csio_lnode_to_hw(ln);
  473. spin_unlock_irq(&hw->lock);
  474. csio_reg_rnode(rn);
  475. spin_lock_irq(&hw->lock);
  476. if (rn->role & CSIO_RNFR_TARGET)
  477. ln->n_scsi_tgts++;
  478. if (rn->nport_id == FC_FID_MGMT_SERV)
  479. csio_ln_fdmi_start(ln, (void *) rn);
  480. }
  481. static void
  482. __csio_unreg_rnode(struct csio_rnode *rn)
  483. {
  484. struct csio_lnode *ln = csio_rnode_to_lnode(rn);
  485. struct csio_hw *hw = csio_lnode_to_hw(ln);
  486. LIST_HEAD(tmp_q);
  487. int cmpl = 0;
  488. if (!list_empty(&rn->host_cmpl_q)) {
  489. csio_dbg(hw, "Returning completion queue I/Os\n");
  490. list_splice_tail_init(&rn->host_cmpl_q, &tmp_q);
  491. cmpl = 1;
  492. }
  493. if (rn->role & CSIO_RNFR_TARGET) {
  494. ln->n_scsi_tgts--;
  495. ln->last_scan_ntgts--;
  496. }
  497. spin_unlock_irq(&hw->lock);
  498. csio_unreg_rnode(rn);
  499. spin_lock_irq(&hw->lock);
  500. /* Cleanup I/Os that were waiting for rnode to unregister */
  501. if (cmpl)
  502. csio_scsi_cleanup_io_q(csio_hw_to_scsim(hw), &tmp_q);
  503. }
  504. /*****************************************************************************/
  505. /* START: Rnode SM */
  506. /*****************************************************************************/
  507. /*
  508. * csio_rns_uninit -
  509. * @rn - rnode
  510. * @evt - SM event.
  511. *
  512. */
  513. static void
  514. csio_rns_uninit(struct csio_rnode *rn, enum csio_rn_ev evt)
  515. {
  516. struct csio_lnode *ln = csio_rnode_to_lnode(rn);
  517. int ret = 0;
  518. CSIO_INC_STATS(rn, n_evt_sm[evt]);
  519. switch (evt) {
  520. case CSIO_RNFE_LOGGED_IN:
  521. case CSIO_RNFE_PLOGI_RECV:
  522. ret = csio_rn_verify_rparams(ln, rn, rn->rdev_entry);
  523. if (!ret) {
  524. csio_set_state(&rn->sm, csio_rns_ready);
  525. __csio_reg_rnode(rn);
  526. } else {
  527. CSIO_INC_STATS(rn, n_err_inval);
  528. }
  529. break;
  530. case CSIO_RNFE_LOGO_RECV:
  531. csio_ln_dbg(ln,
  532. "ssni:x%x Ignoring event %d recv "
  533. "in rn state[uninit]\n", csio_rn_flowid(rn), evt);
  534. CSIO_INC_STATS(rn, n_evt_drop);
  535. break;
  536. default:
  537. csio_ln_dbg(ln,
  538. "ssni:x%x unexp event %d recv "
  539. "in rn state[uninit]\n", csio_rn_flowid(rn), evt);
  540. CSIO_INC_STATS(rn, n_evt_unexp);
  541. break;
  542. }
  543. }
  544. /*
  545. * csio_rns_ready -
  546. * @rn - rnode
  547. * @evt - SM event.
  548. *
  549. */
  550. static void
  551. csio_rns_ready(struct csio_rnode *rn, enum csio_rn_ev evt)
  552. {
  553. struct csio_lnode *ln = csio_rnode_to_lnode(rn);
  554. int ret = 0;
  555. CSIO_INC_STATS(rn, n_evt_sm[evt]);
  556. switch (evt) {
  557. case CSIO_RNFE_LOGGED_IN:
  558. case CSIO_RNFE_PLOGI_RECV:
  559. csio_ln_dbg(ln,
  560. "ssni:x%x Ignoring event %d recv from did:x%x "
  561. "in rn state[ready]\n", csio_rn_flowid(rn), evt,
  562. rn->nport_id);
  563. CSIO_INC_STATS(rn, n_evt_drop);
  564. break;
  565. case CSIO_RNFE_PRLI_DONE:
  566. case CSIO_RNFE_PRLI_RECV:
  567. ret = csio_rn_verify_rparams(ln, rn, rn->rdev_entry);
  568. if (!ret)
  569. __csio_reg_rnode(rn);
  570. else
  571. CSIO_INC_STATS(rn, n_err_inval);
  572. break;
  573. case CSIO_RNFE_DOWN:
  574. csio_set_state(&rn->sm, csio_rns_offline);
  575. __csio_unreg_rnode(rn);
  576. /* FW expected to internally aborted outstanding SCSI WRs
  577. * and return all SCSI WRs to host with status "ABORTED".
  578. */
  579. break;
  580. case CSIO_RNFE_LOGO_RECV:
  581. csio_set_state(&rn->sm, csio_rns_offline);
  582. __csio_unreg_rnode(rn);
  583. /* FW expected to internally aborted outstanding SCSI WRs
  584. * and return all SCSI WRs to host with status "ABORTED".
  585. */
  586. break;
  587. case CSIO_RNFE_CLOSE:
  588. /*
  589. * Each rnode receives CLOSE event when driver is removed or
  590. * device is reset
  591. * Note: All outstanding IOs on remote port need to returned
  592. * to uppper layer with appropriate error before sending
  593. * CLOSE event
  594. */
  595. csio_set_state(&rn->sm, csio_rns_uninit);
  596. __csio_unreg_rnode(rn);
  597. break;
  598. case CSIO_RNFE_NAME_MISSING:
  599. csio_set_state(&rn->sm, csio_rns_disappeared);
  600. __csio_unreg_rnode(rn);
  601. /*
  602. * FW expected to internally aborted outstanding SCSI WRs
  603. * and return all SCSI WRs to host with status "ABORTED".
  604. */
  605. break;
  606. default:
  607. csio_ln_dbg(ln,
  608. "ssni:x%x unexp event %d recv from did:x%x "
  609. "in rn state[uninit]\n", csio_rn_flowid(rn), evt,
  610. rn->nport_id);
  611. CSIO_INC_STATS(rn, n_evt_unexp);
  612. break;
  613. }
  614. }
  615. /*
  616. * csio_rns_offline -
  617. * @rn - rnode
  618. * @evt - SM event.
  619. *
  620. */
  621. static void
  622. csio_rns_offline(struct csio_rnode *rn, enum csio_rn_ev evt)
  623. {
  624. struct csio_lnode *ln = csio_rnode_to_lnode(rn);
  625. int ret = 0;
  626. CSIO_INC_STATS(rn, n_evt_sm[evt]);
  627. switch (evt) {
  628. case CSIO_RNFE_LOGGED_IN:
  629. case CSIO_RNFE_PLOGI_RECV:
  630. ret = csio_rn_verify_rparams(ln, rn, rn->rdev_entry);
  631. if (!ret) {
  632. csio_set_state(&rn->sm, csio_rns_ready);
  633. __csio_reg_rnode(rn);
  634. } else {
  635. CSIO_INC_STATS(rn, n_err_inval);
  636. csio_post_event(&rn->sm, CSIO_RNFE_CLOSE);
  637. }
  638. break;
  639. case CSIO_RNFE_DOWN:
  640. csio_ln_dbg(ln,
  641. "ssni:x%x Ignoring event %d recv from did:x%x "
  642. "in rn state[offline]\n", csio_rn_flowid(rn), evt,
  643. rn->nport_id);
  644. CSIO_INC_STATS(rn, n_evt_drop);
  645. break;
  646. case CSIO_RNFE_CLOSE:
  647. /* Each rnode receives CLOSE event when driver is removed or
  648. * device is reset
  649. * Note: All outstanding IOs on remote port need to returned
  650. * to uppper layer with appropriate error before sending
  651. * CLOSE event
  652. */
  653. csio_set_state(&rn->sm, csio_rns_uninit);
  654. break;
  655. case CSIO_RNFE_NAME_MISSING:
  656. csio_set_state(&rn->sm, csio_rns_disappeared);
  657. break;
  658. default:
  659. csio_ln_dbg(ln,
  660. "ssni:x%x unexp event %d recv from did:x%x "
  661. "in rn state[offline]\n", csio_rn_flowid(rn), evt,
  662. rn->nport_id);
  663. CSIO_INC_STATS(rn, n_evt_unexp);
  664. break;
  665. }
  666. }
  667. /*
  668. * csio_rns_disappeared -
  669. * @rn - rnode
  670. * @evt - SM event.
  671. *
  672. */
  673. static void
  674. csio_rns_disappeared(struct csio_rnode *rn, enum csio_rn_ev evt)
  675. {
  676. struct csio_lnode *ln = csio_rnode_to_lnode(rn);
  677. int ret = 0;
  678. CSIO_INC_STATS(rn, n_evt_sm[evt]);
  679. switch (evt) {
  680. case CSIO_RNFE_LOGGED_IN:
  681. case CSIO_RNFE_PLOGI_RECV:
  682. ret = csio_rn_verify_rparams(ln, rn, rn->rdev_entry);
  683. if (!ret) {
  684. csio_set_state(&rn->sm, csio_rns_ready);
  685. __csio_reg_rnode(rn);
  686. } else {
  687. CSIO_INC_STATS(rn, n_err_inval);
  688. csio_post_event(&rn->sm, CSIO_RNFE_CLOSE);
  689. }
  690. break;
  691. case CSIO_RNFE_CLOSE:
  692. /* Each rnode receives CLOSE event when driver is removed or
  693. * device is reset.
  694. * Note: All outstanding IOs on remote port need to returned
  695. * to uppper layer with appropriate error before sending
  696. * CLOSE event
  697. */
  698. csio_set_state(&rn->sm, csio_rns_uninit);
  699. break;
  700. case CSIO_RNFE_DOWN:
  701. case CSIO_RNFE_NAME_MISSING:
  702. csio_ln_dbg(ln,
  703. "ssni:x%x Ignoring event %d recv from did x%x"
  704. "in rn state[disappeared]\n", csio_rn_flowid(rn),
  705. evt, rn->nport_id);
  706. break;
  707. default:
  708. csio_ln_dbg(ln,
  709. "ssni:x%x unexp event %d recv from did x%x"
  710. "in rn state[disappeared]\n", csio_rn_flowid(rn),
  711. evt, rn->nport_id);
  712. CSIO_INC_STATS(rn, n_evt_unexp);
  713. break;
  714. }
  715. }
  716. /*****************************************************************************/
  717. /* END: Rnode SM */
  718. /*****************************************************************************/
  719. /*
  720. * csio_rnode_devloss_handler - Device loss event handler
  721. * @rn: rnode
  722. *
  723. * Post event to close rnode SM and free rnode.
  724. */
  725. void
  726. csio_rnode_devloss_handler(struct csio_rnode *rn)
  727. {
  728. struct csio_lnode *ln = csio_rnode_to_lnode(rn);
  729. /* ignore if same rnode came back as online */
  730. if (csio_is_rnode_ready(rn))
  731. return;
  732. csio_post_event(&rn->sm, CSIO_RNFE_CLOSE);
  733. /* Free rn if in uninit state */
  734. if (csio_is_rnode_uninit(rn))
  735. csio_put_rnode(ln, rn);
  736. }
  737. /**
  738. * csio_rnode_fwevt_handler - Event handler for firmware rnode events.
  739. * @rn: rnode
  740. *
  741. */
  742. void
  743. csio_rnode_fwevt_handler(struct csio_rnode *rn, uint8_t fwevt)
  744. {
  745. struct csio_lnode *ln = csio_rnode_to_lnode(rn);
  746. enum csio_rn_ev evt;
  747. evt = CSIO_FWE_TO_RNFE(fwevt);
  748. if (!evt) {
  749. csio_ln_err(ln, "ssni:x%x Unhandled FW Rdev event: %d\n",
  750. csio_rn_flowid(rn), fwevt);
  751. CSIO_INC_STATS(rn, n_evt_unexp);
  752. return;
  753. }
  754. CSIO_INC_STATS(rn, n_evt_fw[fwevt]);
  755. /* Track previous & current events for debugging */
  756. rn->prev_evt = rn->cur_evt;
  757. rn->cur_evt = fwevt;
  758. /* Post event to rnode SM */
  759. csio_post_event(&rn->sm, evt);
  760. /* Free rn if in uninit state */
  761. if (csio_is_rnode_uninit(rn))
  762. csio_put_rnode(ln, rn);
  763. }
  764. /*
  765. * csio_rnode_init - Initialize rnode.
  766. * @rn: RNode
  767. * @ln: Associated lnode
  768. *
  769. * Caller is responsible for holding the lock. The lock is required
  770. * to be held for inserting the rnode in ln->rnhead list.
  771. */
  772. static int
  773. csio_rnode_init(struct csio_rnode *rn, struct csio_lnode *ln)
  774. {
  775. csio_rnode_to_lnode(rn) = ln;
  776. csio_init_state(&rn->sm, csio_rns_uninit);
  777. INIT_LIST_HEAD(&rn->host_cmpl_q);
  778. csio_rn_flowid(rn) = CSIO_INVALID_IDX;
  779. /* Add rnode to list of lnodes->rnhead */
  780. list_add_tail(&rn->sm.sm_list, &ln->rnhead);
  781. return 0;
  782. }
  783. static void
  784. csio_rnode_exit(struct csio_rnode *rn)
  785. {
  786. list_del_init(&rn->sm.sm_list);
  787. CSIO_DB_ASSERT(list_empty(&rn->host_cmpl_q));
  788. }