bfa_fcs_fcpim.c 22 KB

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