bfa_fcs_fcpim.c 22 KB

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