bfa_fcs_fcpim.c 20 KB

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