bfa_fcs_fcpim.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793
  1. /*
  2. * Copyright (c) 2005-2010 Brocade Communications Systems, Inc.
  3. * All rights reserved
  4. * www.brocade.com
  5. *
  6. * Linux driver for Brocade Fibre Channel Host Bus Adapter.
  7. *
  8. * This program is free software; you can redistribute it and/or modify it
  9. * under the terms of the GNU General Public License (GPL) Version 2 as
  10. * published by the Free Software Foundation
  11. *
  12. * This program is distributed in the hope that it will be useful, but
  13. * WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * General Public License for more details.
  16. */
  17. /*
  18. * fcpim.c - FCP initiator mode i-t nexus state machine
  19. */
  20. #include "bfad_drv.h"
  21. #include "bfa_fcs.h"
  22. #include "bfa_fcbuild.h"
  23. #include "bfad_im.h"
  24. BFA_TRC_FILE(FCS, FCPIM);
  25. /*
  26. * forward declarations
  27. */
  28. static void bfa_fcs_itnim_timeout(void *arg);
  29. static void bfa_fcs_itnim_free(struct bfa_fcs_itnim_s *itnim);
  30. static void bfa_fcs_itnim_send_prli(void *itnim_cbarg,
  31. struct bfa_fcxp_s *fcxp_alloced);
  32. static void bfa_fcs_itnim_prli_response(void *fcsarg,
  33. struct bfa_fcxp_s *fcxp, void *cbarg,
  34. bfa_status_t req_status, u32 rsp_len,
  35. u32 resid_len, struct fchs_s *rsp_fchs);
  36. /*
  37. * fcs_itnim_sm FCS itnim state machine events
  38. */
  39. enum bfa_fcs_itnim_event {
  40. BFA_FCS_ITNIM_SM_ONLINE = 1, /* rport online event */
  41. BFA_FCS_ITNIM_SM_OFFLINE = 2, /* rport offline */
  42. BFA_FCS_ITNIM_SM_FRMSENT = 3, /* prli frame is sent */
  43. BFA_FCS_ITNIM_SM_RSP_OK = 4, /* good response */
  44. BFA_FCS_ITNIM_SM_RSP_ERROR = 5, /* error response */
  45. BFA_FCS_ITNIM_SM_TIMEOUT = 6, /* delay timeout */
  46. BFA_FCS_ITNIM_SM_HCB_OFFLINE = 7, /* BFA online callback */
  47. BFA_FCS_ITNIM_SM_HCB_ONLINE = 8, /* BFA offline callback */
  48. BFA_FCS_ITNIM_SM_INITIATOR = 9, /* rport is initiator */
  49. BFA_FCS_ITNIM_SM_DELETE = 10, /* delete event from rport */
  50. BFA_FCS_ITNIM_SM_PRLO = 11, /* delete event from rport */
  51. BFA_FCS_ITNIM_SM_RSP_NOT_SUPP = 12, /* cmd not supported rsp */
  52. };
  53. static void bfa_fcs_itnim_sm_offline(struct bfa_fcs_itnim_s *itnim,
  54. enum bfa_fcs_itnim_event event);
  55. static void bfa_fcs_itnim_sm_prli_send(struct bfa_fcs_itnim_s *itnim,
  56. enum bfa_fcs_itnim_event event);
  57. static void bfa_fcs_itnim_sm_prli(struct bfa_fcs_itnim_s *itnim,
  58. enum bfa_fcs_itnim_event event);
  59. static void bfa_fcs_itnim_sm_prli_retry(struct bfa_fcs_itnim_s *itnim,
  60. enum bfa_fcs_itnim_event event);
  61. static void bfa_fcs_itnim_sm_hcb_online(struct bfa_fcs_itnim_s *itnim,
  62. enum bfa_fcs_itnim_event event);
  63. static void bfa_fcs_itnim_sm_online(struct bfa_fcs_itnim_s *itnim,
  64. enum bfa_fcs_itnim_event event);
  65. static void bfa_fcs_itnim_sm_hcb_offline(struct bfa_fcs_itnim_s *itnim,
  66. enum bfa_fcs_itnim_event event);
  67. static void bfa_fcs_itnim_sm_initiator(struct bfa_fcs_itnim_s *itnim,
  68. enum bfa_fcs_itnim_event event);
  69. static struct bfa_sm_table_s itnim_sm_table[] = {
  70. {BFA_SM(bfa_fcs_itnim_sm_offline), BFA_ITNIM_OFFLINE},
  71. {BFA_SM(bfa_fcs_itnim_sm_prli_send), BFA_ITNIM_PRLI_SEND},
  72. {BFA_SM(bfa_fcs_itnim_sm_prli), BFA_ITNIM_PRLI_SENT},
  73. {BFA_SM(bfa_fcs_itnim_sm_prli_retry), BFA_ITNIM_PRLI_RETRY},
  74. {BFA_SM(bfa_fcs_itnim_sm_hcb_online), BFA_ITNIM_HCB_ONLINE},
  75. {BFA_SM(bfa_fcs_itnim_sm_online), BFA_ITNIM_ONLINE},
  76. {BFA_SM(bfa_fcs_itnim_sm_hcb_offline), BFA_ITNIM_HCB_OFFLINE},
  77. {BFA_SM(bfa_fcs_itnim_sm_initiator), BFA_ITNIM_INITIATIOR},
  78. };
  79. /*
  80. * fcs_itnim_sm FCS itnim state machine
  81. */
  82. static void
  83. bfa_fcs_itnim_sm_offline(struct bfa_fcs_itnim_s *itnim,
  84. enum bfa_fcs_itnim_event event)
  85. {
  86. bfa_trc(itnim->fcs, itnim->rport->pwwn);
  87. bfa_trc(itnim->fcs, event);
  88. switch (event) {
  89. case BFA_FCS_ITNIM_SM_ONLINE:
  90. bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_prli_send);
  91. itnim->prli_retries = 0;
  92. bfa_fcs_itnim_send_prli(itnim, NULL);
  93. break;
  94. case BFA_FCS_ITNIM_SM_OFFLINE:
  95. bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_OFFLINE);
  96. break;
  97. case BFA_FCS_ITNIM_SM_INITIATOR:
  98. bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_initiator);
  99. break;
  100. case BFA_FCS_ITNIM_SM_DELETE:
  101. bfa_fcs_itnim_free(itnim);
  102. break;
  103. default:
  104. bfa_sm_fault(itnim->fcs, event);
  105. }
  106. }
  107. static void
  108. bfa_fcs_itnim_sm_prli_send(struct bfa_fcs_itnim_s *itnim,
  109. enum bfa_fcs_itnim_event event)
  110. {
  111. bfa_trc(itnim->fcs, itnim->rport->pwwn);
  112. bfa_trc(itnim->fcs, event);
  113. switch (event) {
  114. case BFA_FCS_ITNIM_SM_FRMSENT:
  115. bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_prli);
  116. break;
  117. case BFA_FCS_ITNIM_SM_INITIATOR:
  118. bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_initiator);
  119. bfa_fcxp_walloc_cancel(itnim->fcs->bfa, &itnim->fcxp_wqe);
  120. break;
  121. case BFA_FCS_ITNIM_SM_OFFLINE:
  122. bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
  123. bfa_fcxp_walloc_cancel(itnim->fcs->bfa, &itnim->fcxp_wqe);
  124. bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_OFFLINE);
  125. break;
  126. case BFA_FCS_ITNIM_SM_DELETE:
  127. bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
  128. bfa_fcxp_walloc_cancel(itnim->fcs->bfa, &itnim->fcxp_wqe);
  129. bfa_fcs_itnim_free(itnim);
  130. break;
  131. default:
  132. bfa_sm_fault(itnim->fcs, event);
  133. }
  134. }
  135. static void
  136. bfa_fcs_itnim_sm_prli(struct bfa_fcs_itnim_s *itnim,
  137. enum bfa_fcs_itnim_event event)
  138. {
  139. bfa_trc(itnim->fcs, itnim->rport->pwwn);
  140. bfa_trc(itnim->fcs, event);
  141. switch (event) {
  142. case BFA_FCS_ITNIM_SM_RSP_OK:
  143. if (itnim->rport->scsi_function == BFA_RPORT_INITIATOR) {
  144. bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_initiator);
  145. } else {
  146. bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_hcb_online);
  147. bfa_itnim_online(itnim->bfa_itnim, itnim->seq_rec);
  148. }
  149. break;
  150. case BFA_FCS_ITNIM_SM_RSP_ERROR:
  151. bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_prli_retry);
  152. bfa_timer_start(itnim->fcs->bfa, &itnim->timer,
  153. bfa_fcs_itnim_timeout, itnim,
  154. BFA_FCS_RETRY_TIMEOUT);
  155. break;
  156. case BFA_FCS_ITNIM_SM_RSP_NOT_SUPP:
  157. bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
  158. break;
  159. case BFA_FCS_ITNIM_SM_OFFLINE:
  160. bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
  161. bfa_fcxp_discard(itnim->fcxp);
  162. bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_OFFLINE);
  163. break;
  164. case BFA_FCS_ITNIM_SM_INITIATOR:
  165. bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_initiator);
  166. bfa_fcxp_discard(itnim->fcxp);
  167. break;
  168. case BFA_FCS_ITNIM_SM_DELETE:
  169. bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
  170. bfa_fcxp_discard(itnim->fcxp);
  171. bfa_fcs_itnim_free(itnim);
  172. break;
  173. default:
  174. bfa_sm_fault(itnim->fcs, event);
  175. }
  176. }
  177. static void
  178. bfa_fcs_itnim_sm_prli_retry(struct bfa_fcs_itnim_s *itnim,
  179. enum bfa_fcs_itnim_event event)
  180. {
  181. bfa_trc(itnim->fcs, itnim->rport->pwwn);
  182. bfa_trc(itnim->fcs, event);
  183. switch (event) {
  184. case BFA_FCS_ITNIM_SM_TIMEOUT:
  185. if (itnim->prli_retries < BFA_FCS_RPORT_MAX_RETRIES) {
  186. itnim->prli_retries++;
  187. bfa_trc(itnim->fcs, itnim->prli_retries);
  188. bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_prli_send);
  189. bfa_fcs_itnim_send_prli(itnim, NULL);
  190. } else {
  191. /* invoke target offline */
  192. bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
  193. bfa_sm_send_event(itnim->rport, RPSM_EVENT_LOGO_IMP);
  194. }
  195. break;
  196. case BFA_FCS_ITNIM_SM_OFFLINE:
  197. bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
  198. bfa_timer_stop(&itnim->timer);
  199. bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_OFFLINE);
  200. break;
  201. case BFA_FCS_ITNIM_SM_INITIATOR:
  202. bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_initiator);
  203. bfa_timer_stop(&itnim->timer);
  204. break;
  205. case BFA_FCS_ITNIM_SM_DELETE:
  206. bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
  207. bfa_timer_stop(&itnim->timer);
  208. bfa_fcs_itnim_free(itnim);
  209. break;
  210. default:
  211. bfa_sm_fault(itnim->fcs, event);
  212. }
  213. }
  214. static void
  215. bfa_fcs_itnim_sm_hcb_online(struct bfa_fcs_itnim_s *itnim,
  216. enum bfa_fcs_itnim_event event)
  217. {
  218. struct bfad_s *bfad = (struct bfad_s *)itnim->fcs->bfad;
  219. char lpwwn_buf[BFA_STRING_32];
  220. char rpwwn_buf[BFA_STRING_32];
  221. bfa_trc(itnim->fcs, itnim->rport->pwwn);
  222. bfa_trc(itnim->fcs, event);
  223. switch (event) {
  224. case BFA_FCS_ITNIM_SM_HCB_ONLINE:
  225. bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_online);
  226. bfa_fcb_itnim_online(itnim->itnim_drv);
  227. wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(itnim->rport->port));
  228. wwn2str(rpwwn_buf, itnim->rport->pwwn);
  229. BFA_LOG(KERN_INFO, bfad, bfa_log_level,
  230. "Target (WWN = %s) is online for initiator (WWN = %s)\n",
  231. rpwwn_buf, lpwwn_buf);
  232. break;
  233. case BFA_FCS_ITNIM_SM_OFFLINE:
  234. bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
  235. bfa_itnim_offline(itnim->bfa_itnim);
  236. bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_OFFLINE);
  237. break;
  238. case BFA_FCS_ITNIM_SM_DELETE:
  239. bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
  240. bfa_fcs_itnim_free(itnim);
  241. break;
  242. default:
  243. bfa_sm_fault(itnim->fcs, event);
  244. }
  245. }
  246. static void
  247. bfa_fcs_itnim_sm_online(struct bfa_fcs_itnim_s *itnim,
  248. enum bfa_fcs_itnim_event event)
  249. {
  250. struct bfad_s *bfad = (struct bfad_s *)itnim->fcs->bfad;
  251. char lpwwn_buf[BFA_STRING_32];
  252. char rpwwn_buf[BFA_STRING_32];
  253. bfa_trc(itnim->fcs, itnim->rport->pwwn);
  254. bfa_trc(itnim->fcs, event);
  255. switch (event) {
  256. case BFA_FCS_ITNIM_SM_OFFLINE:
  257. bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_hcb_offline);
  258. bfa_fcb_itnim_offline(itnim->itnim_drv);
  259. bfa_itnim_offline(itnim->bfa_itnim);
  260. wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(itnim->rport->port));
  261. wwn2str(rpwwn_buf, itnim->rport->pwwn);
  262. if (bfa_fcs_lport_is_online(itnim->rport->port) == BFA_TRUE)
  263. BFA_LOG(KERN_ERR, bfad, bfa_log_level,
  264. "Target (WWN = %s) connectivity lost for "
  265. "initiator (WWN = %s)\n", rpwwn_buf, lpwwn_buf);
  266. else
  267. BFA_LOG(KERN_INFO, bfad, bfa_log_level,
  268. "Target (WWN = %s) offlined by initiator (WWN = %s)\n",
  269. rpwwn_buf, lpwwn_buf);
  270. break;
  271. case BFA_FCS_ITNIM_SM_DELETE:
  272. bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
  273. bfa_fcs_itnim_free(itnim);
  274. break;
  275. default:
  276. bfa_sm_fault(itnim->fcs, event);
  277. }
  278. }
  279. static void
  280. bfa_fcs_itnim_sm_hcb_offline(struct bfa_fcs_itnim_s *itnim,
  281. enum bfa_fcs_itnim_event event)
  282. {
  283. bfa_trc(itnim->fcs, itnim->rport->pwwn);
  284. bfa_trc(itnim->fcs, event);
  285. switch (event) {
  286. case BFA_FCS_ITNIM_SM_HCB_OFFLINE:
  287. bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
  288. bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_OFFLINE);
  289. break;
  290. case BFA_FCS_ITNIM_SM_DELETE:
  291. bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
  292. bfa_fcs_itnim_free(itnim);
  293. break;
  294. default:
  295. bfa_sm_fault(itnim->fcs, event);
  296. }
  297. }
  298. /*
  299. * This state is set when a discovered rport is also in intiator mode.
  300. * This ITN is marked as no_op and is not active and will not be truned into
  301. * online state.
  302. */
  303. static void
  304. bfa_fcs_itnim_sm_initiator(struct bfa_fcs_itnim_s *itnim,
  305. enum bfa_fcs_itnim_event event)
  306. {
  307. bfa_trc(itnim->fcs, itnim->rport->pwwn);
  308. bfa_trc(itnim->fcs, event);
  309. switch (event) {
  310. case BFA_FCS_ITNIM_SM_OFFLINE:
  311. bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
  312. bfa_sm_send_event(itnim->rport, RPSM_EVENT_FC4_OFFLINE);
  313. break;
  314. case BFA_FCS_ITNIM_SM_RSP_ERROR:
  315. case BFA_FCS_ITNIM_SM_ONLINE:
  316. case BFA_FCS_ITNIM_SM_INITIATOR:
  317. break;
  318. case BFA_FCS_ITNIM_SM_DELETE:
  319. bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
  320. bfa_fcs_itnim_free(itnim);
  321. break;
  322. default:
  323. bfa_sm_fault(itnim->fcs, event);
  324. }
  325. }
  326. static void
  327. bfa_fcs_itnim_send_prli(void *itnim_cbarg, struct bfa_fcxp_s *fcxp_alloced)
  328. {
  329. struct bfa_fcs_itnim_s *itnim = itnim_cbarg;
  330. struct bfa_fcs_rport_s *rport = itnim->rport;
  331. struct bfa_fcs_lport_s *port = rport->port;
  332. struct fchs_s fchs;
  333. struct bfa_fcxp_s *fcxp;
  334. int len;
  335. bfa_trc(itnim->fcs, itnim->rport->pwwn);
  336. fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
  337. if (!fcxp) {
  338. itnim->stats.fcxp_alloc_wait++;
  339. bfa_fcs_fcxp_alloc_wait(port->fcs->bfa, &itnim->fcxp_wqe,
  340. bfa_fcs_itnim_send_prli, itnim);
  341. return;
  342. }
  343. itnim->fcxp = fcxp;
  344. len = fc_prli_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
  345. itnim->rport->pid, bfa_fcs_lport_get_fcid(port), 0);
  346. bfa_fcxp_send(fcxp, rport->bfa_rport, port->fabric->vf_id, port->lp_tag,
  347. BFA_FALSE, FC_CLASS_3, len, &fchs,
  348. bfa_fcs_itnim_prli_response, (void *)itnim,
  349. FC_MAX_PDUSZ, FC_ELS_TOV);
  350. itnim->stats.prli_sent++;
  351. bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_FRMSENT);
  352. }
  353. static void
  354. bfa_fcs_itnim_prli_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
  355. bfa_status_t req_status, u32 rsp_len,
  356. u32 resid_len, struct fchs_s *rsp_fchs)
  357. {
  358. struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *) cbarg;
  359. struct fc_els_cmd_s *els_cmd;
  360. struct fc_prli_s *prli_resp;
  361. struct fc_ls_rjt_s *ls_rjt;
  362. struct fc_prli_params_s *sparams;
  363. bfa_trc(itnim->fcs, req_status);
  364. /*
  365. * Sanity Checks
  366. */
  367. if (req_status != BFA_STATUS_OK) {
  368. itnim->stats.prli_rsp_err++;
  369. bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_RSP_ERROR);
  370. return;
  371. }
  372. els_cmd = (struct fc_els_cmd_s *) BFA_FCXP_RSP_PLD(fcxp);
  373. if (els_cmd->els_code == FC_ELS_ACC) {
  374. prli_resp = (struct fc_prli_s *) els_cmd;
  375. if (fc_prli_rsp_parse(prli_resp, rsp_len) != FC_PARSE_OK) {
  376. bfa_trc(itnim->fcs, rsp_len);
  377. /*
  378. * Check if this r-port is also in Initiator mode.
  379. * If so, we need to set this ITN as a no-op.
  380. */
  381. if (prli_resp->parampage.servparams.initiator) {
  382. bfa_trc(itnim->fcs, prli_resp->parampage.type);
  383. itnim->rport->scsi_function =
  384. BFA_RPORT_INITIATOR;
  385. itnim->stats.prli_rsp_acc++;
  386. itnim->stats.initiator++;
  387. bfa_sm_send_event(itnim,
  388. BFA_FCS_ITNIM_SM_RSP_OK);
  389. return;
  390. }
  391. itnim->stats.prli_rsp_parse_err++;
  392. return;
  393. }
  394. itnim->rport->scsi_function = BFA_RPORT_TARGET;
  395. sparams = &prli_resp->parampage.servparams;
  396. itnim->seq_rec = sparams->retry;
  397. itnim->rec_support = sparams->rec_support;
  398. itnim->task_retry_id = sparams->task_retry_id;
  399. itnim->conf_comp = sparams->confirm;
  400. itnim->stats.prli_rsp_acc++;
  401. bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_RSP_OK);
  402. } else {
  403. ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);
  404. bfa_trc(itnim->fcs, ls_rjt->reason_code);
  405. bfa_trc(itnim->fcs, ls_rjt->reason_code_expl);
  406. itnim->stats.prli_rsp_rjt++;
  407. if (ls_rjt->reason_code == FC_LS_RJT_RSN_CMD_NOT_SUPP) {
  408. bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_RSP_NOT_SUPP);
  409. return;
  410. }
  411. bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_RSP_ERROR);
  412. }
  413. }
  414. static void
  415. bfa_fcs_itnim_timeout(void *arg)
  416. {
  417. struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *) arg;
  418. itnim->stats.timeout++;
  419. bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_TIMEOUT);
  420. }
  421. static void
  422. bfa_fcs_itnim_free(struct bfa_fcs_itnim_s *itnim)
  423. {
  424. bfa_itnim_delete(itnim->bfa_itnim);
  425. bfa_fcb_itnim_free(itnim->fcs->bfad, itnim->itnim_drv);
  426. }
  427. /*
  428. * itnim_public FCS ITNIM public interfaces
  429. */
  430. /*
  431. * Called by rport when a new rport is created.
  432. *
  433. * @param[in] rport - remote port.
  434. */
  435. struct bfa_fcs_itnim_s *
  436. bfa_fcs_itnim_create(struct bfa_fcs_rport_s *rport)
  437. {
  438. struct bfa_fcs_lport_s *port = rport->port;
  439. struct bfa_fcs_itnim_s *itnim;
  440. struct bfad_itnim_s *itnim_drv;
  441. struct bfa_itnim_s *bfa_itnim;
  442. /*
  443. * call bfad to allocate the itnim
  444. */
  445. bfa_fcb_itnim_alloc(port->fcs->bfad, &itnim, &itnim_drv);
  446. if (itnim == NULL) {
  447. bfa_trc(port->fcs, rport->pwwn);
  448. return NULL;
  449. }
  450. /*
  451. * Initialize itnim
  452. */
  453. itnim->rport = rport;
  454. itnim->fcs = rport->fcs;
  455. itnim->itnim_drv = itnim_drv;
  456. /*
  457. * call BFA to create the itnim
  458. */
  459. bfa_itnim =
  460. bfa_itnim_create(port->fcs->bfa, rport->bfa_rport, itnim);
  461. if (bfa_itnim == NULL) {
  462. bfa_trc(port->fcs, rport->pwwn);
  463. bfa_fcb_itnim_free(port->fcs->bfad, itnim_drv);
  464. WARN_ON(1);
  465. return NULL;
  466. }
  467. itnim->bfa_itnim = bfa_itnim;
  468. itnim->seq_rec = BFA_FALSE;
  469. itnim->rec_support = BFA_FALSE;
  470. itnim->conf_comp = BFA_FALSE;
  471. itnim->task_retry_id = BFA_FALSE;
  472. /*
  473. * Set State machine
  474. */
  475. bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline);
  476. return itnim;
  477. }
  478. /*
  479. * Called by rport to delete the instance of FCPIM.
  480. *
  481. * @param[in] rport - remote port.
  482. */
  483. void
  484. bfa_fcs_itnim_delete(struct bfa_fcs_itnim_s *itnim)
  485. {
  486. bfa_trc(itnim->fcs, itnim->rport->pid);
  487. bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_DELETE);
  488. }
  489. /*
  490. * Notification from rport that PLOGI is complete to initiate FC-4 session.
  491. */
  492. void
  493. bfa_fcs_itnim_rport_online(struct bfa_fcs_itnim_s *itnim)
  494. {
  495. itnim->stats.onlines++;
  496. if (!BFA_FCS_PID_IS_WKA(itnim->rport->pid)) {
  497. bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_ONLINE);
  498. } else {
  499. /*
  500. * For well known addresses, we set the itnim to initiator
  501. * state
  502. */
  503. itnim->stats.initiator++;
  504. bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_INITIATOR);
  505. }
  506. }
  507. /*
  508. * Called by rport to handle a remote device offline.
  509. */
  510. void
  511. bfa_fcs_itnim_rport_offline(struct bfa_fcs_itnim_s *itnim)
  512. {
  513. itnim->stats.offlines++;
  514. bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_OFFLINE);
  515. }
  516. /*
  517. * Called by rport when remote port is known to be an initiator from
  518. * PRLI received.
  519. */
  520. void
  521. bfa_fcs_itnim_is_initiator(struct bfa_fcs_itnim_s *itnim)
  522. {
  523. bfa_trc(itnim->fcs, itnim->rport->pid);
  524. itnim->stats.initiator++;
  525. bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_INITIATOR);
  526. }
  527. /*
  528. * Called by rport to check if the itnim is online.
  529. */
  530. bfa_status_t
  531. bfa_fcs_itnim_get_online_state(struct bfa_fcs_itnim_s *itnim)
  532. {
  533. bfa_trc(itnim->fcs, itnim->rport->pid);
  534. switch (bfa_sm_to_state(itnim_sm_table, itnim->sm)) {
  535. case BFA_ITNIM_ONLINE:
  536. case BFA_ITNIM_INITIATIOR:
  537. return BFA_STATUS_OK;
  538. default:
  539. return BFA_STATUS_NO_FCPIM_NEXUS;
  540. }
  541. }
  542. /*
  543. * BFA completion callback for bfa_itnim_online().
  544. */
  545. void
  546. bfa_cb_itnim_online(void *cbarg)
  547. {
  548. struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *) cbarg;
  549. bfa_trc(itnim->fcs, itnim->rport->pwwn);
  550. bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_HCB_ONLINE);
  551. }
  552. /*
  553. * BFA completion callback for bfa_itnim_offline().
  554. */
  555. void
  556. bfa_cb_itnim_offline(void *cb_arg)
  557. {
  558. struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *) cb_arg;
  559. bfa_trc(itnim->fcs, itnim->rport->pwwn);
  560. bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_HCB_OFFLINE);
  561. }
  562. /*
  563. * Mark the beginning of PATH TOV handling. IO completion callbacks
  564. * are still pending.
  565. */
  566. void
  567. bfa_cb_itnim_tov_begin(void *cb_arg)
  568. {
  569. struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *) cb_arg;
  570. bfa_trc(itnim->fcs, itnim->rport->pwwn);
  571. }
  572. /*
  573. * Mark the end of PATH TOV handling. All pending IOs are already cleaned up.
  574. */
  575. void
  576. bfa_cb_itnim_tov(void *cb_arg)
  577. {
  578. struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *) cb_arg;
  579. struct bfad_itnim_s *itnim_drv = itnim->itnim_drv;
  580. bfa_trc(itnim->fcs, itnim->rport->pwwn);
  581. itnim_drv->state = ITNIM_STATE_TIMEOUT;
  582. }
  583. /*
  584. * BFA notification to FCS/driver for second level error recovery.
  585. *
  586. * Atleast one I/O request has timedout and target is unresponsive to
  587. * repeated abort requests. Second level error recovery should be initiated
  588. * by starting implicit logout and recovery procedures.
  589. */
  590. void
  591. bfa_cb_itnim_sler(void *cb_arg)
  592. {
  593. struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *) cb_arg;
  594. itnim->stats.sler++;
  595. bfa_trc(itnim->fcs, itnim->rport->pwwn);
  596. bfa_sm_send_event(itnim->rport, RPSM_EVENT_LOGO_IMP);
  597. }
  598. struct bfa_fcs_itnim_s *
  599. bfa_fcs_itnim_lookup(struct bfa_fcs_lport_s *port, wwn_t rpwwn)
  600. {
  601. struct bfa_fcs_rport_s *rport;
  602. rport = bfa_fcs_rport_lookup(port, rpwwn);
  603. if (!rport)
  604. return NULL;
  605. WARN_ON(rport->itnim == NULL);
  606. return rport->itnim;
  607. }
  608. bfa_status_t
  609. bfa_fcs_itnim_attr_get(struct bfa_fcs_lport_s *port, wwn_t rpwwn,
  610. struct bfa_itnim_attr_s *attr)
  611. {
  612. struct bfa_fcs_itnim_s *itnim = NULL;
  613. itnim = bfa_fcs_itnim_lookup(port, rpwwn);
  614. if (itnim == NULL)
  615. return BFA_STATUS_NO_FCPIM_NEXUS;
  616. attr->state = bfa_sm_to_state(itnim_sm_table, itnim->sm);
  617. attr->retry = itnim->seq_rec;
  618. attr->rec_support = itnim->rec_support;
  619. attr->conf_comp = itnim->conf_comp;
  620. attr->task_retry_id = itnim->task_retry_id;
  621. return BFA_STATUS_OK;
  622. }
  623. bfa_status_t
  624. bfa_fcs_itnim_stats_get(struct bfa_fcs_lport_s *port, wwn_t rpwwn,
  625. struct bfa_itnim_stats_s *stats)
  626. {
  627. struct bfa_fcs_itnim_s *itnim = NULL;
  628. WARN_ON(port == NULL);
  629. itnim = bfa_fcs_itnim_lookup(port, rpwwn);
  630. if (itnim == NULL)
  631. return BFA_STATUS_NO_FCPIM_NEXUS;
  632. memcpy(stats, &itnim->stats, sizeof(struct bfa_itnim_stats_s));
  633. return BFA_STATUS_OK;
  634. }
  635. bfa_status_t
  636. bfa_fcs_itnim_stats_clear(struct bfa_fcs_lport_s *port, wwn_t rpwwn)
  637. {
  638. struct bfa_fcs_itnim_s *itnim = NULL;
  639. WARN_ON(port == NULL);
  640. itnim = bfa_fcs_itnim_lookup(port, rpwwn);
  641. if (itnim == NULL)
  642. return BFA_STATUS_NO_FCPIM_NEXUS;
  643. memset(&itnim->stats, 0, sizeof(struct bfa_itnim_stats_s));
  644. return BFA_STATUS_OK;
  645. }
  646. void
  647. bfa_fcs_fcpim_uf_recv(struct bfa_fcs_itnim_s *itnim,
  648. struct fchs_s *fchs, u16 len)
  649. {
  650. struct fc_els_cmd_s *els_cmd;
  651. bfa_trc(itnim->fcs, fchs->type);
  652. if (fchs->type != FC_TYPE_ELS)
  653. return;
  654. els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
  655. bfa_trc(itnim->fcs, els_cmd->els_code);
  656. switch (els_cmd->els_code) {
  657. case FC_ELS_PRLO:
  658. bfa_fcs_rport_prlo(itnim->rport, fchs->ox_id);
  659. break;
  660. default:
  661. WARN_ON(1);
  662. }
  663. }