rport.c 65 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601
  1. /*
  2. * Copyright (c) 2005-2009 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. * rport.c Remote port implementation.
  19. */
  20. #include <bfa.h>
  21. #include <bfa_svc.h>
  22. #include "fcbuild.h"
  23. #include "fcs_vport.h"
  24. #include "fcs_lport.h"
  25. #include "fcs_rport.h"
  26. #include "fcs_fcpim.h"
  27. #include "fcs_fcptm.h"
  28. #include "fcs_trcmod.h"
  29. #include "fcs_fcxp.h"
  30. #include "fcs.h"
  31. #include <fcb/bfa_fcb_rport.h>
  32. #include <aen/bfa_aen_rport.h>
  33. BFA_TRC_FILE(FCS, RPORT);
  34. #define BFA_FCS_RPORT_MAX_RETRIES (5)
  35. /* In millisecs */
  36. static u32 bfa_fcs_rport_del_timeout =
  37. BFA_FCS_RPORT_DEF_DEL_TIMEOUT * 1000;
  38. /*
  39. * forward declarations
  40. */
  41. static struct bfa_fcs_rport_s *bfa_fcs_rport_alloc(struct bfa_fcs_port_s *port,
  42. wwn_t pwwn, u32 rpid);
  43. static void bfa_fcs_rport_free(struct bfa_fcs_rport_s *rport);
  44. static void bfa_fcs_rport_hal_online(struct bfa_fcs_rport_s *rport);
  45. static void bfa_fcs_rport_online_action(struct bfa_fcs_rport_s *rport);
  46. static void bfa_fcs_rport_offline_action(struct bfa_fcs_rport_s *rport);
  47. static void bfa_fcs_rport_update(struct bfa_fcs_rport_s *rport,
  48. struct fc_logi_s *plogi);
  49. static void bfa_fcs_rport_fc4_pause(struct bfa_fcs_rport_s *rport);
  50. static void bfa_fcs_rport_fc4_resume(struct bfa_fcs_rport_s *rport);
  51. static void bfa_fcs_rport_timeout(void *arg);
  52. static void bfa_fcs_rport_send_plogi(void *rport_cbarg,
  53. struct bfa_fcxp_s *fcxp_alloced);
  54. static void bfa_fcs_rport_send_plogiacc(void *rport_cbarg,
  55. struct bfa_fcxp_s *fcxp_alloced);
  56. static void bfa_fcs_rport_plogi_response(void *fcsarg,
  57. struct bfa_fcxp_s *fcxp,
  58. void *cbarg,
  59. bfa_status_t req_status,
  60. u32 rsp_len,
  61. u32 resid_len,
  62. struct fchs_s *rsp_fchs);
  63. static void bfa_fcs_rport_send_adisc(void *rport_cbarg,
  64. struct bfa_fcxp_s *fcxp_alloced);
  65. static void bfa_fcs_rport_adisc_response(void *fcsarg,
  66. struct bfa_fcxp_s *fcxp,
  67. void *cbarg,
  68. bfa_status_t req_status,
  69. u32 rsp_len,
  70. u32 resid_len,
  71. struct fchs_s *rsp_fchs);
  72. static void bfa_fcs_rport_send_gidpn(void *rport_cbarg,
  73. struct bfa_fcxp_s *fcxp_alloced);
  74. static void bfa_fcs_rport_gidpn_response(void *fcsarg,
  75. struct bfa_fcxp_s *fcxp,
  76. void *cbarg,
  77. bfa_status_t req_status,
  78. u32 rsp_len,
  79. u32 resid_len,
  80. struct fchs_s *rsp_fchs);
  81. static void bfa_fcs_rport_send_logo(void *rport_cbarg,
  82. struct bfa_fcxp_s *fcxp_alloced);
  83. static void bfa_fcs_rport_send_logo_acc(void *rport_cbarg);
  84. static void bfa_fcs_rport_process_prli(struct bfa_fcs_rport_s *rport,
  85. struct fchs_s *rx_fchs, u16 len);
  86. static void bfa_fcs_rport_send_ls_rjt(struct bfa_fcs_rport_s *rport,
  87. struct fchs_s *rx_fchs, u8 reason_code,
  88. u8 reason_code_expl);
  89. static void bfa_fcs_rport_process_adisc(struct bfa_fcs_rport_s *rport,
  90. struct fchs_s *rx_fchs, u16 len);
  91. /**
  92. * fcs_rport_sm FCS rport state machine events
  93. */
  94. enum rport_event {
  95. RPSM_EVENT_PLOGI_SEND = 1, /* new rport; start with PLOGI */
  96. RPSM_EVENT_PLOGI_RCVD = 2, /* Inbound PLOGI from remote port */
  97. RPSM_EVENT_PLOGI_COMP = 3, /* PLOGI completed to rport */
  98. RPSM_EVENT_LOGO_RCVD = 4, /* LOGO from remote device */
  99. RPSM_EVENT_LOGO_IMP = 5, /* implicit logo for SLER */
  100. RPSM_EVENT_FCXP_SENT = 6, /* Frame from has been sent */
  101. RPSM_EVENT_DELETE = 7, /* RPORT delete request */
  102. RPSM_EVENT_SCN = 8, /* state change notification */
  103. RPSM_EVENT_ACCEPTED = 9,/* Good response from remote device */
  104. RPSM_EVENT_FAILED = 10, /* Request to rport failed. */
  105. RPSM_EVENT_TIMEOUT = 11, /* Rport SM timeout event */
  106. RPSM_EVENT_HCB_ONLINE = 12, /* BFA rport online callback */
  107. RPSM_EVENT_HCB_OFFLINE = 13, /* BFA rport offline callback */
  108. RPSM_EVENT_FC4_OFFLINE = 14, /* FC-4 offline complete */
  109. RPSM_EVENT_ADDRESS_CHANGE = 15, /* Rport's PID has changed */
  110. RPSM_EVENT_ADDRESS_DISC = 16 /* Need to Discover rport's PID */
  111. };
  112. static void bfa_fcs_rport_sm_uninit(struct bfa_fcs_rport_s *rport,
  113. enum rport_event event);
  114. static void bfa_fcs_rport_sm_plogi_sending(struct bfa_fcs_rport_s *rport,
  115. enum rport_event event);
  116. static void bfa_fcs_rport_sm_plogiacc_sending(struct bfa_fcs_rport_s *rport,
  117. enum rport_event event);
  118. static void bfa_fcs_rport_sm_plogi_retry(struct bfa_fcs_rport_s *rport,
  119. enum rport_event event);
  120. static void bfa_fcs_rport_sm_plogi(struct bfa_fcs_rport_s *rport,
  121. enum rport_event event);
  122. static void bfa_fcs_rport_sm_hal_online(struct bfa_fcs_rport_s *rport,
  123. enum rport_event event);
  124. static void bfa_fcs_rport_sm_online(struct bfa_fcs_rport_s *rport,
  125. enum rport_event event);
  126. static void bfa_fcs_rport_sm_nsquery_sending(struct bfa_fcs_rport_s *rport,
  127. enum rport_event event);
  128. static void bfa_fcs_rport_sm_nsquery(struct bfa_fcs_rport_s *rport,
  129. enum rport_event event);
  130. static void bfa_fcs_rport_sm_adisc_sending(struct bfa_fcs_rport_s *rport,
  131. enum rport_event event);
  132. static void bfa_fcs_rport_sm_adisc(struct bfa_fcs_rport_s *rport,
  133. enum rport_event event);
  134. static void bfa_fcs_rport_sm_fc4_logorcv(struct bfa_fcs_rport_s *rport,
  135. enum rport_event event);
  136. static void bfa_fcs_rport_sm_fc4_logosend(struct bfa_fcs_rport_s *rport,
  137. enum rport_event event);
  138. static void bfa_fcs_rport_sm_fc4_offline(struct bfa_fcs_rport_s *rport,
  139. enum rport_event event);
  140. static void bfa_fcs_rport_sm_hcb_offline(struct bfa_fcs_rport_s *rport,
  141. enum rport_event event);
  142. static void bfa_fcs_rport_sm_hcb_logorcv(struct bfa_fcs_rport_s *rport,
  143. enum rport_event event);
  144. static void bfa_fcs_rport_sm_hcb_logosend(struct bfa_fcs_rport_s *rport,
  145. enum rport_event event);
  146. static void bfa_fcs_rport_sm_logo_sending(struct bfa_fcs_rport_s *rport,
  147. enum rport_event event);
  148. static void bfa_fcs_rport_sm_offline(struct bfa_fcs_rport_s *rport,
  149. enum rport_event event);
  150. static void bfa_fcs_rport_sm_nsdisc_sending(struct bfa_fcs_rport_s *rport,
  151. enum rport_event event);
  152. static void bfa_fcs_rport_sm_nsdisc_retry(struct bfa_fcs_rport_s *rport,
  153. enum rport_event event);
  154. static void bfa_fcs_rport_sm_nsdisc_sent(struct bfa_fcs_rport_s *rport,
  155. enum rport_event event);
  156. static void bfa_fcs_rport_sm_nsdisc_sent(struct bfa_fcs_rport_s *rport,
  157. enum rport_event event);
  158. static struct bfa_sm_table_s rport_sm_table[] = {
  159. {BFA_SM(bfa_fcs_rport_sm_uninit), BFA_RPORT_UNINIT},
  160. {BFA_SM(bfa_fcs_rport_sm_plogi_sending), BFA_RPORT_PLOGI},
  161. {BFA_SM(bfa_fcs_rport_sm_plogiacc_sending), BFA_RPORT_ONLINE},
  162. {BFA_SM(bfa_fcs_rport_sm_plogi_retry), BFA_RPORT_PLOGI_RETRY},
  163. {BFA_SM(bfa_fcs_rport_sm_plogi), BFA_RPORT_PLOGI},
  164. {BFA_SM(bfa_fcs_rport_sm_hal_online), BFA_RPORT_ONLINE},
  165. {BFA_SM(bfa_fcs_rport_sm_online), BFA_RPORT_ONLINE},
  166. {BFA_SM(bfa_fcs_rport_sm_nsquery_sending), BFA_RPORT_NSQUERY},
  167. {BFA_SM(bfa_fcs_rport_sm_nsquery), BFA_RPORT_NSQUERY},
  168. {BFA_SM(bfa_fcs_rport_sm_adisc_sending), BFA_RPORT_ADISC},
  169. {BFA_SM(bfa_fcs_rport_sm_adisc), BFA_RPORT_ADISC},
  170. {BFA_SM(bfa_fcs_rport_sm_fc4_logorcv), BFA_RPORT_LOGORCV},
  171. {BFA_SM(bfa_fcs_rport_sm_fc4_logosend), BFA_RPORT_LOGO},
  172. {BFA_SM(bfa_fcs_rport_sm_fc4_offline), BFA_RPORT_OFFLINE},
  173. {BFA_SM(bfa_fcs_rport_sm_hcb_offline), BFA_RPORT_OFFLINE},
  174. {BFA_SM(bfa_fcs_rport_sm_hcb_logorcv), BFA_RPORT_LOGORCV},
  175. {BFA_SM(bfa_fcs_rport_sm_hcb_logosend), BFA_RPORT_LOGO},
  176. {BFA_SM(bfa_fcs_rport_sm_logo_sending), BFA_RPORT_LOGO},
  177. {BFA_SM(bfa_fcs_rport_sm_offline), BFA_RPORT_OFFLINE},
  178. {BFA_SM(bfa_fcs_rport_sm_nsdisc_sending), BFA_RPORT_NSDISC},
  179. {BFA_SM(bfa_fcs_rport_sm_nsdisc_retry), BFA_RPORT_NSDISC},
  180. {BFA_SM(bfa_fcs_rport_sm_nsdisc_sent), BFA_RPORT_NSDISC},
  181. };
  182. /**
  183. * Beginning state.
  184. */
  185. static void
  186. bfa_fcs_rport_sm_uninit(struct bfa_fcs_rport_s *rport, enum rport_event event)
  187. {
  188. bfa_trc(rport->fcs, rport->pwwn);
  189. bfa_trc(rport->fcs, rport->pid);
  190. bfa_trc(rport->fcs, event);
  191. switch (event) {
  192. case RPSM_EVENT_PLOGI_SEND:
  193. bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_sending);
  194. rport->plogi_retries = 0;
  195. bfa_fcs_rport_send_plogi(rport, NULL);
  196. break;
  197. case RPSM_EVENT_PLOGI_RCVD:
  198. bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
  199. bfa_fcs_rport_send_plogiacc(rport, NULL);
  200. break;
  201. case RPSM_EVENT_PLOGI_COMP:
  202. bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
  203. bfa_fcs_rport_hal_online(rport);
  204. break;
  205. case RPSM_EVENT_ADDRESS_CHANGE:
  206. case RPSM_EVENT_ADDRESS_DISC:
  207. bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
  208. rport->ns_retries = 0;
  209. bfa_fcs_rport_send_gidpn(rport, NULL);
  210. break;
  211. default:
  212. bfa_assert(0);
  213. }
  214. }
  215. /**
  216. * PLOGI is being sent.
  217. */
  218. static void
  219. bfa_fcs_rport_sm_plogi_sending(struct bfa_fcs_rport_s *rport,
  220. enum rport_event event)
  221. {
  222. bfa_trc(rport->fcs, rport->pwwn);
  223. bfa_trc(rport->fcs, rport->pid);
  224. bfa_trc(rport->fcs, event);
  225. switch (event) {
  226. case RPSM_EVENT_FCXP_SENT:
  227. bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi);
  228. break;
  229. case RPSM_EVENT_DELETE:
  230. bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
  231. bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
  232. bfa_fcs_rport_free(rport);
  233. break;
  234. case RPSM_EVENT_PLOGI_RCVD:
  235. bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
  236. bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
  237. bfa_fcs_rport_send_plogiacc(rport, NULL);
  238. break;
  239. case RPSM_EVENT_ADDRESS_CHANGE:
  240. bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
  241. bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
  242. rport->ns_retries = 0;
  243. bfa_fcs_rport_send_gidpn(rport, NULL);
  244. break;
  245. case RPSM_EVENT_LOGO_IMP:
  246. rport->pid = 0;
  247. bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
  248. bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
  249. bfa_timer_start(rport->fcs->bfa, &rport->timer,
  250. bfa_fcs_rport_timeout, rport,
  251. bfa_fcs_rport_del_timeout);
  252. break;
  253. case RPSM_EVENT_SCN:
  254. break;
  255. default:
  256. bfa_assert(0);
  257. }
  258. }
  259. /**
  260. * PLOGI is being sent.
  261. */
  262. static void
  263. bfa_fcs_rport_sm_plogiacc_sending(struct bfa_fcs_rport_s *rport,
  264. enum rport_event event)
  265. {
  266. bfa_trc(rport->fcs, rport->pwwn);
  267. bfa_trc(rport->fcs, rport->pid);
  268. bfa_trc(rport->fcs, event);
  269. switch (event) {
  270. case RPSM_EVENT_FCXP_SENT:
  271. bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
  272. bfa_fcs_rport_hal_online(rport);
  273. break;
  274. case RPSM_EVENT_DELETE:
  275. bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
  276. bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
  277. bfa_fcs_rport_free(rport);
  278. break;
  279. case RPSM_EVENT_SCN:
  280. /**
  281. * Ignore, SCN is possibly online notification.
  282. */
  283. break;
  284. case RPSM_EVENT_ADDRESS_CHANGE:
  285. bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
  286. bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
  287. rport->ns_retries = 0;
  288. bfa_fcs_rport_send_gidpn(rport, NULL);
  289. break;
  290. case RPSM_EVENT_LOGO_IMP:
  291. rport->pid = 0;
  292. bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
  293. bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
  294. bfa_timer_start(rport->fcs->bfa, &rport->timer,
  295. bfa_fcs_rport_timeout, rport,
  296. bfa_fcs_rport_del_timeout);
  297. break;
  298. case RPSM_EVENT_HCB_OFFLINE:
  299. /**
  300. * Ignore BFA callback, on a PLOGI receive we call bfa offline.
  301. */
  302. break;
  303. default:
  304. bfa_assert(0);
  305. }
  306. }
  307. /**
  308. * PLOGI is sent.
  309. */
  310. static void
  311. bfa_fcs_rport_sm_plogi_retry(struct bfa_fcs_rport_s *rport,
  312. enum rport_event event)
  313. {
  314. bfa_trc(rport->fcs, rport->pwwn);
  315. bfa_trc(rport->fcs, rport->pid);
  316. bfa_trc(rport->fcs, event);
  317. switch (event) {
  318. case RPSM_EVENT_SCN:
  319. bfa_timer_stop(&rport->timer);
  320. /*
  321. * !! fall through !!
  322. */
  323. case RPSM_EVENT_TIMEOUT:
  324. rport->plogi_retries++;
  325. if (rport->plogi_retries < BFA_FCS_RPORT_MAX_RETRIES) {
  326. bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_sending);
  327. bfa_fcs_rport_send_plogi(rport, NULL);
  328. } else {
  329. rport->pid = 0;
  330. bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
  331. bfa_timer_start(rport->fcs->bfa, &rport->timer,
  332. bfa_fcs_rport_timeout, rport,
  333. bfa_fcs_rport_del_timeout);
  334. }
  335. break;
  336. case RPSM_EVENT_DELETE:
  337. bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
  338. bfa_timer_stop(&rport->timer);
  339. bfa_fcs_rport_free(rport);
  340. break;
  341. case RPSM_EVENT_LOGO_RCVD:
  342. break;
  343. case RPSM_EVENT_PLOGI_RCVD:
  344. bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
  345. bfa_timer_stop(&rport->timer);
  346. bfa_fcs_rport_send_plogiacc(rport, NULL);
  347. break;
  348. case RPSM_EVENT_ADDRESS_CHANGE:
  349. bfa_timer_stop(&rport->timer);
  350. bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
  351. rport->ns_retries = 0;
  352. bfa_fcs_rport_send_gidpn(rport, NULL);
  353. break;
  354. case RPSM_EVENT_LOGO_IMP:
  355. rport->pid = 0;
  356. bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
  357. bfa_timer_stop(&rport->timer);
  358. bfa_timer_start(rport->fcs->bfa, &rport->timer,
  359. bfa_fcs_rport_timeout, rport,
  360. bfa_fcs_rport_del_timeout);
  361. break;
  362. case RPSM_EVENT_PLOGI_COMP:
  363. bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
  364. bfa_timer_stop(&rport->timer);
  365. bfa_fcs_rport_hal_online(rport);
  366. break;
  367. default:
  368. bfa_assert(0);
  369. }
  370. }
  371. /**
  372. * PLOGI is sent.
  373. */
  374. static void
  375. bfa_fcs_rport_sm_plogi(struct bfa_fcs_rport_s *rport, enum rport_event event)
  376. {
  377. bfa_trc(rport->fcs, rport->pwwn);
  378. bfa_trc(rport->fcs, rport->pid);
  379. bfa_trc(rport->fcs, event);
  380. switch (event) {
  381. case RPSM_EVENT_ACCEPTED:
  382. bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
  383. rport->plogi_retries = 0;
  384. bfa_fcs_rport_hal_online(rport);
  385. break;
  386. case RPSM_EVENT_LOGO_RCVD:
  387. bfa_fcs_rport_send_logo_acc(rport);
  388. bfa_fcxp_discard(rport->fcxp);
  389. /*
  390. * !! fall through !!
  391. */
  392. case RPSM_EVENT_FAILED:
  393. bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_retry);
  394. bfa_timer_start(rport->fcs->bfa, &rport->timer,
  395. bfa_fcs_rport_timeout, rport,
  396. BFA_FCS_RETRY_TIMEOUT);
  397. break;
  398. case RPSM_EVENT_LOGO_IMP:
  399. rport->pid = 0;
  400. bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
  401. bfa_fcxp_discard(rport->fcxp);
  402. bfa_timer_start(rport->fcs->bfa, &rport->timer,
  403. bfa_fcs_rport_timeout, rport,
  404. bfa_fcs_rport_del_timeout);
  405. break;
  406. case RPSM_EVENT_ADDRESS_CHANGE:
  407. bfa_fcxp_discard(rport->fcxp);
  408. bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
  409. rport->ns_retries = 0;
  410. bfa_fcs_rport_send_gidpn(rport, NULL);
  411. break;
  412. case RPSM_EVENT_PLOGI_RCVD:
  413. bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
  414. bfa_fcxp_discard(rport->fcxp);
  415. bfa_fcs_rport_send_plogiacc(rport, NULL);
  416. break;
  417. case RPSM_EVENT_SCN:
  418. /**
  419. * Ignore SCN - wait for PLOGI response.
  420. */
  421. break;
  422. case RPSM_EVENT_DELETE:
  423. bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
  424. bfa_fcxp_discard(rport->fcxp);
  425. bfa_fcs_rport_free(rport);
  426. break;
  427. case RPSM_EVENT_PLOGI_COMP:
  428. bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
  429. bfa_fcxp_discard(rport->fcxp);
  430. bfa_fcs_rport_hal_online(rport);
  431. break;
  432. default:
  433. bfa_assert(0);
  434. }
  435. }
  436. /**
  437. * PLOGI is complete. Awaiting BFA rport online callback. FC-4s
  438. * are offline.
  439. */
  440. static void
  441. bfa_fcs_rport_sm_hal_online(struct bfa_fcs_rport_s *rport,
  442. enum rport_event event)
  443. {
  444. bfa_trc(rport->fcs, rport->pwwn);
  445. bfa_trc(rport->fcs, rport->pid);
  446. bfa_trc(rport->fcs, event);
  447. switch (event) {
  448. case RPSM_EVENT_HCB_ONLINE:
  449. bfa_sm_set_state(rport, bfa_fcs_rport_sm_online);
  450. bfa_fcs_rport_online_action(rport);
  451. break;
  452. case RPSM_EVENT_LOGO_RCVD:
  453. bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logorcv);
  454. bfa_rport_offline(rport->bfa_rport);
  455. break;
  456. case RPSM_EVENT_LOGO_IMP:
  457. case RPSM_EVENT_ADDRESS_CHANGE:
  458. bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_offline);
  459. bfa_rport_offline(rport->bfa_rport);
  460. break;
  461. case RPSM_EVENT_PLOGI_RCVD:
  462. bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
  463. bfa_rport_offline(rport->bfa_rport);
  464. bfa_fcs_rport_send_plogiacc(rport, NULL);
  465. break;
  466. case RPSM_EVENT_DELETE:
  467. bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logosend);
  468. bfa_rport_offline(rport->bfa_rport);
  469. break;
  470. case RPSM_EVENT_SCN:
  471. /**
  472. * @todo
  473. * Ignore SCN - PLOGI just completed, FC-4 login should detect
  474. * device failures.
  475. */
  476. break;
  477. default:
  478. bfa_assert(0);
  479. }
  480. }
  481. /**
  482. * Rport is ONLINE. FC-4s active.
  483. */
  484. static void
  485. bfa_fcs_rport_sm_online(struct bfa_fcs_rport_s *rport, enum rport_event event)
  486. {
  487. bfa_trc(rport->fcs, rport->pwwn);
  488. bfa_trc(rport->fcs, rport->pid);
  489. bfa_trc(rport->fcs, event);
  490. switch (event) {
  491. case RPSM_EVENT_SCN:
  492. /**
  493. * Pause FC-4 activity till rport is authenticated.
  494. * In switched fabrics, check presence of device in nameserver
  495. * first.
  496. */
  497. bfa_fcs_rport_fc4_pause(rport);
  498. if (bfa_fcs_fabric_is_switched(rport->port->fabric)) {
  499. bfa_sm_set_state(rport,
  500. bfa_fcs_rport_sm_nsquery_sending);
  501. rport->ns_retries = 0;
  502. bfa_fcs_rport_send_gidpn(rport, NULL);
  503. } else {
  504. bfa_sm_set_state(rport, bfa_fcs_rport_sm_adisc_sending);
  505. bfa_fcs_rport_send_adisc(rport, NULL);
  506. }
  507. break;
  508. case RPSM_EVENT_PLOGI_RCVD:
  509. case RPSM_EVENT_LOGO_IMP:
  510. case RPSM_EVENT_ADDRESS_CHANGE:
  511. bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
  512. bfa_fcs_rport_offline_action(rport);
  513. break;
  514. case RPSM_EVENT_DELETE:
  515. bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
  516. bfa_fcs_rport_offline_action(rport);
  517. break;
  518. case RPSM_EVENT_LOGO_RCVD:
  519. bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);
  520. bfa_fcs_rport_offline_action(rport);
  521. break;
  522. case RPSM_EVENT_PLOGI_COMP:
  523. break;
  524. default:
  525. bfa_assert(0);
  526. }
  527. }
  528. /**
  529. * An SCN event is received in ONLINE state. NS query is being sent
  530. * prior to ADISC authentication with rport. FC-4s are paused.
  531. */
  532. static void
  533. bfa_fcs_rport_sm_nsquery_sending(struct bfa_fcs_rport_s *rport,
  534. enum rport_event event)
  535. {
  536. bfa_trc(rport->fcs, rport->pwwn);
  537. bfa_trc(rport->fcs, rport->pid);
  538. bfa_trc(rport->fcs, event);
  539. switch (event) {
  540. case RPSM_EVENT_FCXP_SENT:
  541. bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsquery);
  542. break;
  543. case RPSM_EVENT_DELETE:
  544. bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
  545. bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
  546. bfa_fcs_rport_offline_action(rport);
  547. break;
  548. case RPSM_EVENT_SCN:
  549. /**
  550. * ignore SCN, wait for response to query itself
  551. */
  552. break;
  553. case RPSM_EVENT_LOGO_RCVD:
  554. bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);
  555. bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
  556. bfa_fcs_rport_offline_action(rport);
  557. break;
  558. case RPSM_EVENT_LOGO_IMP:
  559. rport->pid = 0;
  560. bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
  561. bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
  562. bfa_timer_start(rport->fcs->bfa, &rport->timer,
  563. bfa_fcs_rport_timeout, rport,
  564. bfa_fcs_rport_del_timeout);
  565. break;
  566. case RPSM_EVENT_PLOGI_RCVD:
  567. case RPSM_EVENT_ADDRESS_CHANGE:
  568. case RPSM_EVENT_PLOGI_COMP:
  569. bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
  570. bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
  571. bfa_fcs_rport_offline_action(rport);
  572. break;
  573. default:
  574. bfa_assert(0);
  575. }
  576. }
  577. /**
  578. * An SCN event is received in ONLINE state. NS query is sent to rport.
  579. * FC-4s are paused.
  580. */
  581. static void
  582. bfa_fcs_rport_sm_nsquery(struct bfa_fcs_rport_s *rport, enum rport_event event)
  583. {
  584. bfa_trc(rport->fcs, rport->pwwn);
  585. bfa_trc(rport->fcs, rport->pid);
  586. bfa_trc(rport->fcs, event);
  587. switch (event) {
  588. case RPSM_EVENT_ACCEPTED:
  589. bfa_sm_set_state(rport, bfa_fcs_rport_sm_adisc_sending);
  590. bfa_fcs_rport_send_adisc(rport, NULL);
  591. break;
  592. case RPSM_EVENT_FAILED:
  593. rport->ns_retries++;
  594. if (rport->ns_retries < BFA_FCS_RPORT_MAX_RETRIES) {
  595. bfa_sm_set_state(rport,
  596. bfa_fcs_rport_sm_nsquery_sending);
  597. bfa_fcs_rport_send_gidpn(rport, NULL);
  598. } else {
  599. bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
  600. bfa_fcs_rport_offline_action(rport);
  601. }
  602. break;
  603. case RPSM_EVENT_DELETE:
  604. bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
  605. bfa_fcxp_discard(rport->fcxp);
  606. bfa_fcs_rport_offline_action(rport);
  607. break;
  608. case RPSM_EVENT_SCN:
  609. break;
  610. case RPSM_EVENT_LOGO_RCVD:
  611. bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);
  612. bfa_fcxp_discard(rport->fcxp);
  613. bfa_fcs_rport_offline_action(rport);
  614. break;
  615. case RPSM_EVENT_PLOGI_COMP:
  616. case RPSM_EVENT_ADDRESS_CHANGE:
  617. case RPSM_EVENT_PLOGI_RCVD:
  618. case RPSM_EVENT_LOGO_IMP:
  619. bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
  620. bfa_fcxp_discard(rport->fcxp);
  621. bfa_fcs_rport_offline_action(rport);
  622. break;
  623. default:
  624. bfa_assert(0);
  625. }
  626. }
  627. /**
  628. * An SCN event is received in ONLINE state. ADISC is being sent for
  629. * authenticating with rport. FC-4s are paused.
  630. */
  631. static void
  632. bfa_fcs_rport_sm_adisc_sending(struct bfa_fcs_rport_s *rport,
  633. enum rport_event event)
  634. {
  635. bfa_trc(rport->fcs, rport->pwwn);
  636. bfa_trc(rport->fcs, rport->pid);
  637. bfa_trc(rport->fcs, event);
  638. switch (event) {
  639. case RPSM_EVENT_FCXP_SENT:
  640. bfa_sm_set_state(rport, bfa_fcs_rport_sm_adisc);
  641. break;
  642. case RPSM_EVENT_DELETE:
  643. bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
  644. bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
  645. bfa_fcs_rport_offline_action(rport);
  646. break;
  647. case RPSM_EVENT_LOGO_IMP:
  648. case RPSM_EVENT_ADDRESS_CHANGE:
  649. bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
  650. bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
  651. bfa_fcs_rport_offline_action(rport);
  652. break;
  653. case RPSM_EVENT_LOGO_RCVD:
  654. bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);
  655. bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
  656. bfa_fcs_rport_offline_action(rport);
  657. break;
  658. case RPSM_EVENT_SCN:
  659. break;
  660. case RPSM_EVENT_PLOGI_RCVD:
  661. bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
  662. bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
  663. bfa_fcs_rport_offline_action(rport);
  664. break;
  665. default:
  666. bfa_assert(0);
  667. }
  668. }
  669. /**
  670. * An SCN event is received in ONLINE state. ADISC is to rport.
  671. * FC-4s are paused.
  672. */
  673. static void
  674. bfa_fcs_rport_sm_adisc(struct bfa_fcs_rport_s *rport, enum rport_event event)
  675. {
  676. bfa_trc(rport->fcs, rport->pwwn);
  677. bfa_trc(rport->fcs, rport->pid);
  678. bfa_trc(rport->fcs, event);
  679. switch (event) {
  680. case RPSM_EVENT_ACCEPTED:
  681. bfa_sm_set_state(rport, bfa_fcs_rport_sm_online);
  682. bfa_fcs_rport_fc4_resume(rport);
  683. break;
  684. case RPSM_EVENT_PLOGI_RCVD:
  685. /**
  686. * Too complex to cleanup FC-4 & rport and then acc to PLOGI.
  687. * At least go offline when a PLOGI is received.
  688. */
  689. bfa_fcxp_discard(rport->fcxp);
  690. /*
  691. * !!! fall through !!!
  692. */
  693. case RPSM_EVENT_FAILED:
  694. case RPSM_EVENT_ADDRESS_CHANGE:
  695. bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
  696. bfa_fcs_rport_offline_action(rport);
  697. break;
  698. case RPSM_EVENT_DELETE:
  699. bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
  700. bfa_fcxp_discard(rport->fcxp);
  701. bfa_fcs_rport_offline_action(rport);
  702. break;
  703. case RPSM_EVENT_SCN:
  704. /**
  705. * already processing RSCN
  706. */
  707. break;
  708. case RPSM_EVENT_LOGO_IMP:
  709. bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline);
  710. bfa_fcxp_discard(rport->fcxp);
  711. bfa_fcs_rport_offline_action(rport);
  712. break;
  713. case RPSM_EVENT_LOGO_RCVD:
  714. bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv);
  715. bfa_fcxp_discard(rport->fcxp);
  716. bfa_fcs_rport_offline_action(rport);
  717. break;
  718. default:
  719. bfa_assert(0);
  720. }
  721. }
  722. /**
  723. * Rport has sent LOGO. Awaiting FC-4 offline completion callback.
  724. */
  725. static void
  726. bfa_fcs_rport_sm_fc4_logorcv(struct bfa_fcs_rport_s *rport,
  727. enum rport_event event)
  728. {
  729. bfa_trc(rport->fcs, rport->pwwn);
  730. bfa_trc(rport->fcs, rport->pid);
  731. bfa_trc(rport->fcs, event);
  732. switch (event) {
  733. case RPSM_EVENT_FC4_OFFLINE:
  734. bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logorcv);
  735. bfa_rport_offline(rport->bfa_rport);
  736. break;
  737. case RPSM_EVENT_DELETE:
  738. bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
  739. break;
  740. case RPSM_EVENT_LOGO_RCVD:
  741. case RPSM_EVENT_ADDRESS_CHANGE:
  742. break;
  743. default:
  744. bfa_assert(0);
  745. }
  746. }
  747. /**
  748. * LOGO needs to be sent to rport. Awaiting FC-4 offline completion
  749. * callback.
  750. */
  751. static void
  752. bfa_fcs_rport_sm_fc4_logosend(struct bfa_fcs_rport_s *rport,
  753. enum rport_event event)
  754. {
  755. bfa_trc(rport->fcs, rport->pwwn);
  756. bfa_trc(rport->fcs, rport->pid);
  757. bfa_trc(rport->fcs, event);
  758. switch (event) {
  759. case RPSM_EVENT_FC4_OFFLINE:
  760. bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logosend);
  761. bfa_rport_offline(rport->bfa_rport);
  762. break;
  763. default:
  764. bfa_assert(0);
  765. }
  766. }
  767. /**
  768. * Rport is going offline. Awaiting FC-4 offline completion callback.
  769. */
  770. static void
  771. bfa_fcs_rport_sm_fc4_offline(struct bfa_fcs_rport_s *rport,
  772. enum rport_event event)
  773. {
  774. bfa_trc(rport->fcs, rport->pwwn);
  775. bfa_trc(rport->fcs, rport->pid);
  776. bfa_trc(rport->fcs, event);
  777. switch (event) {
  778. case RPSM_EVENT_FC4_OFFLINE:
  779. bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_offline);
  780. bfa_rport_offline(rport->bfa_rport);
  781. break;
  782. case RPSM_EVENT_SCN:
  783. case RPSM_EVENT_LOGO_IMP:
  784. case RPSM_EVENT_LOGO_RCVD:
  785. case RPSM_EVENT_ADDRESS_CHANGE:
  786. /**
  787. * rport is already going offline.
  788. * SCN - ignore and wait till transitioning to offline state
  789. */
  790. break;
  791. case RPSM_EVENT_DELETE:
  792. bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend);
  793. break;
  794. default:
  795. bfa_assert(0);
  796. }
  797. }
  798. /**
  799. * Rport is offline. FC-4s are offline. Awaiting BFA rport offline
  800. * callback.
  801. */
  802. static void
  803. bfa_fcs_rport_sm_hcb_offline(struct bfa_fcs_rport_s *rport,
  804. enum rport_event event)
  805. {
  806. bfa_trc(rport->fcs, rport->pwwn);
  807. bfa_trc(rport->fcs, rport->pid);
  808. bfa_trc(rport->fcs, event);
  809. switch (event) {
  810. case RPSM_EVENT_HCB_OFFLINE:
  811. case RPSM_EVENT_ADDRESS_CHANGE:
  812. if (bfa_fcs_port_is_online(rport->port)) {
  813. bfa_sm_set_state(rport,
  814. bfa_fcs_rport_sm_nsdisc_sending);
  815. rport->ns_retries = 0;
  816. bfa_fcs_rport_send_gidpn(rport, NULL);
  817. } else {
  818. rport->pid = 0;
  819. bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
  820. bfa_timer_start(rport->fcs->bfa, &rport->timer,
  821. bfa_fcs_rport_timeout, rport,
  822. bfa_fcs_rport_del_timeout);
  823. }
  824. break;
  825. case RPSM_EVENT_DELETE:
  826. bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
  827. bfa_fcs_rport_free(rport);
  828. break;
  829. case RPSM_EVENT_SCN:
  830. case RPSM_EVENT_LOGO_RCVD:
  831. /**
  832. * Ignore, already offline.
  833. */
  834. break;
  835. default:
  836. bfa_assert(0);
  837. }
  838. }
  839. /**
  840. * Rport is offline. FC-4s are offline. Awaiting BFA rport offline
  841. * callback to send LOGO accept.
  842. */
  843. static void
  844. bfa_fcs_rport_sm_hcb_logorcv(struct bfa_fcs_rport_s *rport,
  845. enum rport_event event)
  846. {
  847. bfa_trc(rport->fcs, rport->pwwn);
  848. bfa_trc(rport->fcs, rport->pid);
  849. bfa_trc(rport->fcs, event);
  850. switch (event) {
  851. case RPSM_EVENT_HCB_OFFLINE:
  852. case RPSM_EVENT_ADDRESS_CHANGE:
  853. if (rport->pid)
  854. bfa_fcs_rport_send_logo_acc(rport);
  855. /*
  856. * If the lport is online and if the rport is not a well known
  857. * address port, we try to re-discover the r-port.
  858. */
  859. if (bfa_fcs_port_is_online(rport->port)
  860. && (!BFA_FCS_PID_IS_WKA(rport->pid))) {
  861. bfa_sm_set_state(rport,
  862. bfa_fcs_rport_sm_nsdisc_sending);
  863. rport->ns_retries = 0;
  864. bfa_fcs_rport_send_gidpn(rport, NULL);
  865. } else {
  866. /*
  867. * if it is not a well known address, reset the pid to
  868. *
  869. */
  870. if (!BFA_FCS_PID_IS_WKA(rport->pid))
  871. rport->pid = 0;
  872. bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
  873. bfa_timer_start(rport->fcs->bfa, &rport->timer,
  874. bfa_fcs_rport_timeout, rport,
  875. bfa_fcs_rport_del_timeout);
  876. }
  877. break;
  878. case RPSM_EVENT_DELETE:
  879. bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logosend);
  880. break;
  881. case RPSM_EVENT_LOGO_IMP:
  882. bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_offline);
  883. break;
  884. case RPSM_EVENT_LOGO_RCVD:
  885. /**
  886. * Ignore - already processing a LOGO.
  887. */
  888. break;
  889. default:
  890. bfa_assert(0);
  891. }
  892. }
  893. /**
  894. * Rport is being deleted. FC-4s are offline. Awaiting BFA rport offline
  895. * callback to send LOGO.
  896. */
  897. static void
  898. bfa_fcs_rport_sm_hcb_logosend(struct bfa_fcs_rport_s *rport,
  899. enum rport_event event)
  900. {
  901. bfa_trc(rport->fcs, rport->pwwn);
  902. bfa_trc(rport->fcs, rport->pid);
  903. bfa_trc(rport->fcs, event);
  904. switch (event) {
  905. case RPSM_EVENT_HCB_OFFLINE:
  906. bfa_sm_set_state(rport, bfa_fcs_rport_sm_logo_sending);
  907. bfa_fcs_rport_send_logo(rport, NULL);
  908. break;
  909. case RPSM_EVENT_LOGO_RCVD:
  910. case RPSM_EVENT_ADDRESS_CHANGE:
  911. break;
  912. default:
  913. bfa_assert(0);
  914. }
  915. }
  916. /**
  917. * Rport is being deleted. FC-4s are offline. LOGO is being sent.
  918. */
  919. static void
  920. bfa_fcs_rport_sm_logo_sending(struct bfa_fcs_rport_s *rport,
  921. enum rport_event event)
  922. {
  923. bfa_trc(rport->fcs, rport->pwwn);
  924. bfa_trc(rport->fcs, rport->pid);
  925. bfa_trc(rport->fcs, event);
  926. switch (event) {
  927. case RPSM_EVENT_FCXP_SENT:
  928. /*
  929. * Once LOGO is sent, we donot wait for the response
  930. */
  931. bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
  932. bfa_fcs_rport_free(rport);
  933. break;
  934. case RPSM_EVENT_SCN:
  935. case RPSM_EVENT_ADDRESS_CHANGE:
  936. break;
  937. case RPSM_EVENT_LOGO_RCVD:
  938. bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
  939. bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
  940. bfa_fcs_rport_free(rport);
  941. break;
  942. default:
  943. bfa_assert(0);
  944. }
  945. }
  946. /**
  947. * Rport is offline. FC-4s are offline. BFA rport is offline.
  948. * Timer active to delete stale rport.
  949. */
  950. static void
  951. bfa_fcs_rport_sm_offline(struct bfa_fcs_rport_s *rport, enum rport_event event)
  952. {
  953. bfa_trc(rport->fcs, rport->pwwn);
  954. bfa_trc(rport->fcs, rport->pid);
  955. bfa_trc(rport->fcs, event);
  956. switch (event) {
  957. case RPSM_EVENT_TIMEOUT:
  958. bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
  959. bfa_fcs_rport_free(rport);
  960. break;
  961. case RPSM_EVENT_SCN:
  962. case RPSM_EVENT_ADDRESS_CHANGE:
  963. bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
  964. bfa_timer_stop(&rport->timer);
  965. rport->ns_retries = 0;
  966. bfa_fcs_rport_send_gidpn(rport, NULL);
  967. break;
  968. case RPSM_EVENT_DELETE:
  969. bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
  970. bfa_timer_stop(&rport->timer);
  971. bfa_fcs_rport_free(rport);
  972. break;
  973. case RPSM_EVENT_PLOGI_RCVD:
  974. bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
  975. bfa_timer_stop(&rport->timer);
  976. bfa_fcs_rport_send_plogiacc(rport, NULL);
  977. break;
  978. case RPSM_EVENT_LOGO_RCVD:
  979. case RPSM_EVENT_LOGO_IMP:
  980. break;
  981. case RPSM_EVENT_PLOGI_COMP:
  982. bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
  983. bfa_timer_stop(&rport->timer);
  984. bfa_fcs_rport_hal_online(rport);
  985. break;
  986. case RPSM_EVENT_PLOGI_SEND:
  987. bfa_timer_stop(&rport->timer);
  988. bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_sending);
  989. rport->plogi_retries = 0;
  990. bfa_fcs_rport_send_plogi(rport, NULL);
  991. break;
  992. default:
  993. bfa_assert(0);
  994. }
  995. }
  996. /**
  997. * Rport address has changed. Nameserver discovery request is being sent.
  998. */
  999. static void
  1000. bfa_fcs_rport_sm_nsdisc_sending(struct bfa_fcs_rport_s *rport,
  1001. enum rport_event event)
  1002. {
  1003. bfa_trc(rport->fcs, rport->pwwn);
  1004. bfa_trc(rport->fcs, rport->pid);
  1005. bfa_trc(rport->fcs, event);
  1006. switch (event) {
  1007. case RPSM_EVENT_FCXP_SENT:
  1008. bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sent);
  1009. break;
  1010. case RPSM_EVENT_DELETE:
  1011. bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
  1012. bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
  1013. bfa_fcs_rport_free(rport);
  1014. break;
  1015. case RPSM_EVENT_PLOGI_RCVD:
  1016. bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
  1017. bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
  1018. bfa_fcs_rport_send_plogiacc(rport, NULL);
  1019. break;
  1020. case RPSM_EVENT_SCN:
  1021. case RPSM_EVENT_LOGO_RCVD:
  1022. case RPSM_EVENT_PLOGI_SEND:
  1023. break;
  1024. case RPSM_EVENT_ADDRESS_CHANGE:
  1025. rport->ns_retries = 0; /* reset the retry count */
  1026. break;
  1027. case RPSM_EVENT_LOGO_IMP:
  1028. bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
  1029. bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
  1030. bfa_timer_start(rport->fcs->bfa, &rport->timer,
  1031. bfa_fcs_rport_timeout, rport,
  1032. bfa_fcs_rport_del_timeout);
  1033. break;
  1034. case RPSM_EVENT_PLOGI_COMP:
  1035. bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
  1036. bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe);
  1037. bfa_fcs_rport_hal_online(rport);
  1038. break;
  1039. default:
  1040. bfa_assert(0);
  1041. }
  1042. }
  1043. /**
  1044. * Nameserver discovery failed. Waiting for timeout to retry.
  1045. */
  1046. static void
  1047. bfa_fcs_rport_sm_nsdisc_retry(struct bfa_fcs_rport_s *rport,
  1048. enum rport_event event)
  1049. {
  1050. bfa_trc(rport->fcs, rport->pwwn);
  1051. bfa_trc(rport->fcs, rport->pid);
  1052. bfa_trc(rport->fcs, event);
  1053. switch (event) {
  1054. case RPSM_EVENT_TIMEOUT:
  1055. bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
  1056. bfa_fcs_rport_send_gidpn(rport, NULL);
  1057. break;
  1058. case RPSM_EVENT_SCN:
  1059. case RPSM_EVENT_ADDRESS_CHANGE:
  1060. bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending);
  1061. bfa_timer_stop(&rport->timer);
  1062. rport->ns_retries = 0;
  1063. bfa_fcs_rport_send_gidpn(rport, NULL);
  1064. break;
  1065. case RPSM_EVENT_DELETE:
  1066. bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
  1067. bfa_timer_stop(&rport->timer);
  1068. bfa_fcs_rport_free(rport);
  1069. break;
  1070. case RPSM_EVENT_PLOGI_RCVD:
  1071. bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
  1072. bfa_timer_stop(&rport->timer);
  1073. bfa_fcs_rport_send_plogiacc(rport, NULL);
  1074. break;
  1075. case RPSM_EVENT_LOGO_IMP:
  1076. rport->pid = 0;
  1077. bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
  1078. bfa_timer_stop(&rport->timer);
  1079. bfa_timer_start(rport->fcs->bfa, &rport->timer,
  1080. bfa_fcs_rport_timeout, rport,
  1081. bfa_fcs_rport_del_timeout);
  1082. break;
  1083. case RPSM_EVENT_LOGO_RCVD:
  1084. bfa_fcs_rport_send_logo_acc(rport);
  1085. break;
  1086. case RPSM_EVENT_PLOGI_COMP:
  1087. bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
  1088. bfa_timer_stop(&rport->timer);
  1089. bfa_fcs_rport_hal_online(rport);
  1090. break;
  1091. default:
  1092. bfa_assert(0);
  1093. }
  1094. }
  1095. /**
  1096. * Rport address has changed. Nameserver discovery request is sent.
  1097. */
  1098. static void
  1099. bfa_fcs_rport_sm_nsdisc_sent(struct bfa_fcs_rport_s *rport,
  1100. enum rport_event event)
  1101. {
  1102. bfa_trc(rport->fcs, rport->pwwn);
  1103. bfa_trc(rport->fcs, rport->pid);
  1104. bfa_trc(rport->fcs, event);
  1105. switch (event) {
  1106. case RPSM_EVENT_ACCEPTED:
  1107. case RPSM_EVENT_ADDRESS_CHANGE:
  1108. if (rport->pid) {
  1109. bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_sending);
  1110. bfa_fcs_rport_send_plogi(rport, NULL);
  1111. } else {
  1112. bfa_sm_set_state(rport,
  1113. bfa_fcs_rport_sm_nsdisc_sending);
  1114. rport->ns_retries = 0;
  1115. bfa_fcs_rport_send_gidpn(rport, NULL);
  1116. }
  1117. break;
  1118. case RPSM_EVENT_FAILED:
  1119. rport->ns_retries++;
  1120. if (rport->ns_retries < BFA_FCS_RPORT_MAX_RETRIES) {
  1121. bfa_sm_set_state(rport,
  1122. bfa_fcs_rport_sm_nsdisc_sending);
  1123. bfa_fcs_rport_send_gidpn(rport, NULL);
  1124. } else {
  1125. rport->pid = 0;
  1126. bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
  1127. bfa_timer_start(rport->fcs->bfa, &rport->timer,
  1128. bfa_fcs_rport_timeout, rport,
  1129. bfa_fcs_rport_del_timeout);
  1130. };
  1131. break;
  1132. case RPSM_EVENT_DELETE:
  1133. bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
  1134. bfa_fcxp_discard(rport->fcxp);
  1135. bfa_fcs_rport_free(rport);
  1136. break;
  1137. case RPSM_EVENT_PLOGI_RCVD:
  1138. bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending);
  1139. bfa_fcxp_discard(rport->fcxp);
  1140. bfa_fcs_rport_send_plogiacc(rport, NULL);
  1141. break;
  1142. case RPSM_EVENT_LOGO_IMP:
  1143. rport->pid = 0;
  1144. bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline);
  1145. bfa_fcxp_discard(rport->fcxp);
  1146. bfa_timer_start(rport->fcs->bfa, &rport->timer,
  1147. bfa_fcs_rport_timeout, rport,
  1148. bfa_fcs_rport_del_timeout);
  1149. break;
  1150. case RPSM_EVENT_SCN:
  1151. /**
  1152. * ignore, wait for NS query response
  1153. */
  1154. break;
  1155. case RPSM_EVENT_LOGO_RCVD:
  1156. /**
  1157. * Not logged-in yet. Accept LOGO.
  1158. */
  1159. bfa_fcs_rport_send_logo_acc(rport);
  1160. break;
  1161. case RPSM_EVENT_PLOGI_COMP:
  1162. bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online);
  1163. bfa_fcxp_discard(rport->fcxp);
  1164. bfa_fcs_rport_hal_online(rport);
  1165. break;
  1166. default:
  1167. bfa_assert(0);
  1168. }
  1169. }
  1170. /**
  1171. * fcs_rport_private FCS RPORT provate functions
  1172. */
  1173. static void
  1174. bfa_fcs_rport_send_plogi(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)
  1175. {
  1176. struct bfa_fcs_rport_s *rport = rport_cbarg;
  1177. struct bfa_fcs_port_s *port = rport->port;
  1178. struct fchs_s fchs;
  1179. int len;
  1180. struct bfa_fcxp_s *fcxp;
  1181. bfa_trc(rport->fcs, rport->pwwn);
  1182. fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
  1183. if (!fcxp) {
  1184. bfa_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe,
  1185. bfa_fcs_rport_send_plogi, rport);
  1186. return;
  1187. }
  1188. rport->fcxp = fcxp;
  1189. len = fc_plogi_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rport->pid,
  1190. bfa_fcs_port_get_fcid(port), 0,
  1191. port->port_cfg.pwwn, port->port_cfg.nwwn,
  1192. bfa_pport_get_maxfrsize(port->fcs->bfa));
  1193. bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
  1194. FC_CLASS_3, len, &fchs, bfa_fcs_rport_plogi_response,
  1195. (void *)rport, FC_MAX_PDUSZ, FC_RA_TOV);
  1196. rport->stats.plogis++;
  1197. bfa_sm_send_event(rport, RPSM_EVENT_FCXP_SENT);
  1198. }
  1199. static void
  1200. bfa_fcs_rport_plogi_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
  1201. bfa_status_t req_status, u32 rsp_len,
  1202. u32 resid_len, struct fchs_s *rsp_fchs)
  1203. {
  1204. struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *)cbarg;
  1205. struct fc_logi_s *plogi_rsp;
  1206. struct fc_ls_rjt_s *ls_rjt;
  1207. struct bfa_fcs_rport_s *twin;
  1208. struct list_head *qe;
  1209. bfa_trc(rport->fcs, rport->pwwn);
  1210. /*
  1211. * Sanity Checks
  1212. */
  1213. if (req_status != BFA_STATUS_OK) {
  1214. bfa_trc(rport->fcs, req_status);
  1215. rport->stats.plogi_failed++;
  1216. bfa_sm_send_event(rport, RPSM_EVENT_FAILED);
  1217. return;
  1218. }
  1219. plogi_rsp = (struct fc_logi_s *) BFA_FCXP_RSP_PLD(fcxp);
  1220. /**
  1221. * Check for failure first.
  1222. */
  1223. if (plogi_rsp->els_cmd.els_code != FC_ELS_ACC) {
  1224. ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp);
  1225. bfa_trc(rport->fcs, ls_rjt->reason_code);
  1226. bfa_trc(rport->fcs, ls_rjt->reason_code_expl);
  1227. rport->stats.plogi_rejects++;
  1228. bfa_sm_send_event(rport, RPSM_EVENT_FAILED);
  1229. return;
  1230. }
  1231. /**
  1232. * PLOGI is complete. Make sure this device is not one of the known
  1233. * device with a new FC port address.
  1234. */
  1235. list_for_each(qe, &rport->port->rport_q) {
  1236. twin = (struct bfa_fcs_rport_s *)qe;
  1237. if (twin == rport)
  1238. continue;
  1239. if (!rport->pwwn && (plogi_rsp->port_name == twin->pwwn)) {
  1240. bfa_trc(rport->fcs, twin->pid);
  1241. bfa_trc(rport->fcs, rport->pid);
  1242. /*
  1243. * Update plogi stats in twin
  1244. */
  1245. twin->stats.plogis += rport->stats.plogis;
  1246. twin->stats.plogi_rejects += rport->stats.plogi_rejects;
  1247. twin->stats.plogi_timeouts +=
  1248. rport->stats.plogi_timeouts;
  1249. twin->stats.plogi_failed += rport->stats.plogi_failed;
  1250. twin->stats.plogi_rcvd += rport->stats.plogi_rcvd;
  1251. twin->stats.plogi_accs++;
  1252. bfa_fcs_rport_delete(rport);
  1253. bfa_fcs_rport_update(twin, plogi_rsp);
  1254. twin->pid = rsp_fchs->s_id;
  1255. bfa_sm_send_event(twin, RPSM_EVENT_PLOGI_COMP);
  1256. return;
  1257. }
  1258. }
  1259. /**
  1260. * Normal login path -- no evil twins.
  1261. */
  1262. rport->stats.plogi_accs++;
  1263. bfa_fcs_rport_update(rport, plogi_rsp);
  1264. bfa_sm_send_event(rport, RPSM_EVENT_ACCEPTED);
  1265. }
  1266. static void
  1267. bfa_fcs_rport_send_plogiacc(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)
  1268. {
  1269. struct bfa_fcs_rport_s *rport = rport_cbarg;
  1270. struct bfa_fcs_port_s *port = rport->port;
  1271. struct fchs_s fchs;
  1272. int len;
  1273. struct bfa_fcxp_s *fcxp;
  1274. bfa_trc(rport->fcs, rport->pwwn);
  1275. bfa_trc(rport->fcs, rport->reply_oxid);
  1276. fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
  1277. if (!fcxp) {
  1278. bfa_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe,
  1279. bfa_fcs_rport_send_plogiacc, rport);
  1280. return;
  1281. }
  1282. rport->fcxp = fcxp;
  1283. len = fc_plogi_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rport->pid,
  1284. bfa_fcs_port_get_fcid(port), rport->reply_oxid,
  1285. port->port_cfg.pwwn, port->port_cfg.nwwn,
  1286. bfa_pport_get_maxfrsize(port->fcs->bfa));
  1287. bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
  1288. FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0);
  1289. bfa_sm_send_event(rport, RPSM_EVENT_FCXP_SENT);
  1290. }
  1291. static void
  1292. bfa_fcs_rport_send_adisc(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)
  1293. {
  1294. struct bfa_fcs_rport_s *rport = rport_cbarg;
  1295. struct bfa_fcs_port_s *port = rport->port;
  1296. struct fchs_s fchs;
  1297. int len;
  1298. struct bfa_fcxp_s *fcxp;
  1299. bfa_trc(rport->fcs, rport->pwwn);
  1300. fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
  1301. if (!fcxp) {
  1302. bfa_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe,
  1303. bfa_fcs_rport_send_adisc, rport);
  1304. return;
  1305. }
  1306. rport->fcxp = fcxp;
  1307. len = fc_adisc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rport->pid,
  1308. bfa_fcs_port_get_fcid(port), 0,
  1309. port->port_cfg.pwwn, port->port_cfg.nwwn);
  1310. bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
  1311. FC_CLASS_3, len, &fchs, bfa_fcs_rport_adisc_response,
  1312. rport, FC_MAX_PDUSZ, FC_RA_TOV);
  1313. rport->stats.adisc_sent++;
  1314. bfa_sm_send_event(rport, RPSM_EVENT_FCXP_SENT);
  1315. }
  1316. static void
  1317. bfa_fcs_rport_adisc_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
  1318. bfa_status_t req_status, u32 rsp_len,
  1319. u32 resid_len, struct fchs_s *rsp_fchs)
  1320. {
  1321. struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *)cbarg;
  1322. void *pld = bfa_fcxp_get_rspbuf(fcxp);
  1323. struct fc_ls_rjt_s *ls_rjt;
  1324. if (req_status != BFA_STATUS_OK) {
  1325. bfa_trc(rport->fcs, req_status);
  1326. rport->stats.adisc_failed++;
  1327. bfa_sm_send_event(rport, RPSM_EVENT_FAILED);
  1328. return;
  1329. }
  1330. if (fc_adisc_rsp_parse((struct fc_adisc_s *)pld, rsp_len, rport->pwwn,
  1331. rport->nwwn) == FC_PARSE_OK) {
  1332. rport->stats.adisc_accs++;
  1333. bfa_sm_send_event(rport, RPSM_EVENT_ACCEPTED);
  1334. return;
  1335. }
  1336. rport->stats.adisc_rejects++;
  1337. ls_rjt = pld;
  1338. bfa_trc(rport->fcs, ls_rjt->els_cmd.els_code);
  1339. bfa_trc(rport->fcs, ls_rjt->reason_code);
  1340. bfa_trc(rport->fcs, ls_rjt->reason_code_expl);
  1341. bfa_sm_send_event(rport, RPSM_EVENT_FAILED);
  1342. }
  1343. static void
  1344. bfa_fcs_rport_send_gidpn(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)
  1345. {
  1346. struct bfa_fcs_rport_s *rport = rport_cbarg;
  1347. struct bfa_fcs_port_s *port = rport->port;
  1348. struct fchs_s fchs;
  1349. struct bfa_fcxp_s *fcxp;
  1350. int len;
  1351. bfa_trc(rport->fcs, rport->pid);
  1352. fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
  1353. if (!fcxp) {
  1354. bfa_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe,
  1355. bfa_fcs_rport_send_gidpn, rport);
  1356. return;
  1357. }
  1358. rport->fcxp = fcxp;
  1359. len = fc_gidpn_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
  1360. bfa_fcs_port_get_fcid(port), 0, rport->pwwn);
  1361. bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
  1362. FC_CLASS_3, len, &fchs, bfa_fcs_rport_gidpn_response,
  1363. (void *)rport, FC_MAX_PDUSZ, FC_RA_TOV);
  1364. bfa_sm_send_event(rport, RPSM_EVENT_FCXP_SENT);
  1365. }
  1366. static void
  1367. bfa_fcs_rport_gidpn_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg,
  1368. bfa_status_t req_status, u32 rsp_len,
  1369. u32 resid_len, struct fchs_s *rsp_fchs)
  1370. {
  1371. struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *)cbarg;
  1372. struct bfa_fcs_rport_s *twin;
  1373. struct list_head *qe;
  1374. struct ct_hdr_s *cthdr;
  1375. struct fcgs_gidpn_resp_s *gidpn_rsp;
  1376. bfa_trc(rport->fcs, rport->pwwn);
  1377. cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp);
  1378. cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code);
  1379. if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) {
  1380. /*
  1381. * Check if the pid is the same as before.
  1382. */
  1383. gidpn_rsp = (struct fcgs_gidpn_resp_s *) (cthdr + 1);
  1384. if (gidpn_rsp->dap == rport->pid) {
  1385. /*
  1386. * Device is online
  1387. */
  1388. bfa_sm_send_event(rport, RPSM_EVENT_ACCEPTED);
  1389. } else {
  1390. /*
  1391. * Device's PID has changed. We need to cleanup and
  1392. * re-login. If there is another device with the the
  1393. * newly discovered pid, send an scn notice so that its
  1394. * new pid can be discovered.
  1395. */
  1396. list_for_each(qe, &rport->port->rport_q) {
  1397. twin = (struct bfa_fcs_rport_s *)qe;
  1398. if (twin == rport)
  1399. continue;
  1400. if (gidpn_rsp->dap == twin->pid) {
  1401. bfa_trc(rport->fcs, twin->pid);
  1402. bfa_trc(rport->fcs, rport->pid);
  1403. twin->pid = 0;
  1404. bfa_sm_send_event(twin,
  1405. RPSM_EVENT_ADDRESS_CHANGE);
  1406. }
  1407. }
  1408. rport->pid = gidpn_rsp->dap;
  1409. bfa_sm_send_event(rport, RPSM_EVENT_ADDRESS_CHANGE);
  1410. }
  1411. return;
  1412. }
  1413. /*
  1414. * Reject Response
  1415. */
  1416. switch (cthdr->reason_code) {
  1417. case CT_RSN_LOGICAL_BUSY:
  1418. /*
  1419. * Need to retry
  1420. */
  1421. bfa_sm_send_event(rport, RPSM_EVENT_TIMEOUT);
  1422. break;
  1423. case CT_RSN_UNABLE_TO_PERF:
  1424. /*
  1425. * device doesn't exist : Start timer to cleanup this later.
  1426. */
  1427. bfa_sm_send_event(rport, RPSM_EVENT_FAILED);
  1428. break;
  1429. default:
  1430. bfa_sm_send_event(rport, RPSM_EVENT_FAILED);
  1431. break;
  1432. }
  1433. }
  1434. /**
  1435. * Called to send a logout to the rport.
  1436. */
  1437. static void
  1438. bfa_fcs_rport_send_logo(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced)
  1439. {
  1440. struct bfa_fcs_rport_s *rport = rport_cbarg;
  1441. struct bfa_fcs_port_s *port;
  1442. struct fchs_s fchs;
  1443. struct bfa_fcxp_s *fcxp;
  1444. u16 len;
  1445. bfa_trc(rport->fcs, rport->pid);
  1446. port = rport->port;
  1447. fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs);
  1448. if (!fcxp) {
  1449. bfa_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe,
  1450. bfa_fcs_rport_send_logo, rport);
  1451. return;
  1452. }
  1453. rport->fcxp = fcxp;
  1454. len = fc_logo_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rport->pid,
  1455. bfa_fcs_port_get_fcid(port), 0,
  1456. bfa_fcs_port_get_pwwn(port));
  1457. bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
  1458. FC_CLASS_3, len, &fchs, NULL, rport, FC_MAX_PDUSZ,
  1459. FC_ED_TOV);
  1460. rport->stats.logos++;
  1461. bfa_fcxp_discard(rport->fcxp);
  1462. bfa_sm_send_event(rport, RPSM_EVENT_FCXP_SENT);
  1463. }
  1464. /**
  1465. * Send ACC for a LOGO received.
  1466. */
  1467. static void
  1468. bfa_fcs_rport_send_logo_acc(void *rport_cbarg)
  1469. {
  1470. struct bfa_fcs_rport_s *rport = rport_cbarg;
  1471. struct bfa_fcs_port_s *port;
  1472. struct fchs_s fchs;
  1473. struct bfa_fcxp_s *fcxp;
  1474. u16 len;
  1475. bfa_trc(rport->fcs, rport->pid);
  1476. port = rport->port;
  1477. fcxp = bfa_fcs_fcxp_alloc(port->fcs);
  1478. if (!fcxp)
  1479. return;
  1480. rport->stats.logo_rcvd++;
  1481. len = fc_logo_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rport->pid,
  1482. bfa_fcs_port_get_fcid(port), rport->reply_oxid);
  1483. bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
  1484. FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0);
  1485. }
  1486. /**
  1487. * This routine will be called by bfa_timer on timer timeouts.
  1488. *
  1489. * param[in] rport - pointer to bfa_fcs_port_ns_t.
  1490. * param[out] rport_status - pointer to return vport status in
  1491. *
  1492. * return
  1493. * void
  1494. *
  1495. * Special Considerations:
  1496. *
  1497. * note
  1498. */
  1499. static void
  1500. bfa_fcs_rport_timeout(void *arg)
  1501. {
  1502. struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *)arg;
  1503. rport->stats.plogi_timeouts++;
  1504. bfa_sm_send_event(rport, RPSM_EVENT_TIMEOUT);
  1505. }
  1506. static void
  1507. bfa_fcs_rport_process_prli(struct bfa_fcs_rport_s *rport,
  1508. struct fchs_s *rx_fchs, u16 len)
  1509. {
  1510. struct bfa_fcxp_s *fcxp;
  1511. struct fchs_s fchs;
  1512. struct bfa_fcs_port_s *port = rport->port;
  1513. struct fc_prli_s *prli;
  1514. bfa_trc(port->fcs, rx_fchs->s_id);
  1515. bfa_trc(port->fcs, rx_fchs->d_id);
  1516. rport->stats.prli_rcvd++;
  1517. if (BFA_FCS_VPORT_IS_TARGET_MODE(port)) {
  1518. /*
  1519. * Target Mode : Let the fcptm handle it
  1520. */
  1521. bfa_fcs_tin_rx_prli(rport->tin, rx_fchs, len);
  1522. return;
  1523. }
  1524. /*
  1525. * We are either in Initiator or ipfc Mode
  1526. */
  1527. prli = (struct fc_prli_s *) (rx_fchs + 1);
  1528. if (prli->parampage.servparams.initiator) {
  1529. bfa_trc(rport->fcs, prli->parampage.type);
  1530. rport->scsi_function = BFA_RPORT_INITIATOR;
  1531. bfa_fcs_itnim_is_initiator(rport->itnim);
  1532. } else {
  1533. /*
  1534. * @todo: PRLI from a target ?
  1535. */
  1536. bfa_trc(port->fcs, rx_fchs->s_id);
  1537. rport->scsi_function = BFA_RPORT_TARGET;
  1538. }
  1539. fcxp = bfa_fcs_fcxp_alloc(port->fcs);
  1540. if (!fcxp)
  1541. return;
  1542. len = fc_prli_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rx_fchs->s_id,
  1543. bfa_fcs_port_get_fcid(port), rx_fchs->ox_id,
  1544. port->port_cfg.roles);
  1545. bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
  1546. FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0);
  1547. }
  1548. static void
  1549. bfa_fcs_rport_process_rpsc(struct bfa_fcs_rport_s *rport,
  1550. struct fchs_s *rx_fchs, u16 len)
  1551. {
  1552. struct bfa_fcxp_s *fcxp;
  1553. struct fchs_s fchs;
  1554. struct bfa_fcs_port_s *port = rport->port;
  1555. struct fc_rpsc_speed_info_s speeds;
  1556. struct bfa_pport_attr_s pport_attr;
  1557. bfa_trc(port->fcs, rx_fchs->s_id);
  1558. bfa_trc(port->fcs, rx_fchs->d_id);
  1559. rport->stats.rpsc_rcvd++;
  1560. speeds.port_speed_cap =
  1561. RPSC_SPEED_CAP_1G | RPSC_SPEED_CAP_2G | RPSC_SPEED_CAP_4G |
  1562. RPSC_SPEED_CAP_8G;
  1563. /*
  1564. * get curent speed from pport attributes from BFA
  1565. */
  1566. bfa_pport_get_attr(port->fcs->bfa, &pport_attr);
  1567. speeds.port_op_speed = fc_bfa_speed_to_rpsc_operspeed(pport_attr.speed);
  1568. fcxp = bfa_fcs_fcxp_alloc(port->fcs);
  1569. if (!fcxp)
  1570. return;
  1571. len = fc_rpsc_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rx_fchs->s_id,
  1572. bfa_fcs_port_get_fcid(port), rx_fchs->ox_id,
  1573. &speeds);
  1574. bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
  1575. FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0);
  1576. }
  1577. static void
  1578. bfa_fcs_rport_process_adisc(struct bfa_fcs_rport_s *rport,
  1579. struct fchs_s *rx_fchs, u16 len)
  1580. {
  1581. struct bfa_fcxp_s *fcxp;
  1582. struct fchs_s fchs;
  1583. struct bfa_fcs_port_s *port = rport->port;
  1584. struct fc_adisc_s *adisc;
  1585. bfa_trc(port->fcs, rx_fchs->s_id);
  1586. bfa_trc(port->fcs, rx_fchs->d_id);
  1587. rport->stats.adisc_rcvd++;
  1588. if (BFA_FCS_VPORT_IS_TARGET_MODE(port)) {
  1589. /*
  1590. * @todo : Target Mode handling
  1591. */
  1592. bfa_trc(port->fcs, rx_fchs->d_id);
  1593. bfa_assert(0);
  1594. return;
  1595. }
  1596. adisc = (struct fc_adisc_s *) (rx_fchs + 1);
  1597. /*
  1598. * Accept if the itnim for this rport is online. Else reject the ADISC
  1599. */
  1600. if (bfa_fcs_itnim_get_online_state(rport->itnim) == BFA_STATUS_OK) {
  1601. fcxp = bfa_fcs_fcxp_alloc(port->fcs);
  1602. if (!fcxp)
  1603. return;
  1604. len = fc_adisc_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
  1605. rx_fchs->s_id,
  1606. bfa_fcs_port_get_fcid(port),
  1607. rx_fchs->ox_id, port->port_cfg.pwwn,
  1608. port->port_cfg.nwwn);
  1609. bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag,
  1610. BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL,
  1611. FC_MAX_PDUSZ, 0);
  1612. } else {
  1613. rport->stats.adisc_rejected++;
  1614. bfa_fcs_rport_send_ls_rjt(rport, rx_fchs,
  1615. FC_LS_RJT_RSN_UNABLE_TO_PERF_CMD,
  1616. FC_LS_RJT_EXP_LOGIN_REQUIRED);
  1617. }
  1618. }
  1619. static void
  1620. bfa_fcs_rport_hal_online(struct bfa_fcs_rport_s *rport)
  1621. {
  1622. struct bfa_fcs_port_s *port = rport->port;
  1623. struct bfa_rport_info_s rport_info;
  1624. rport_info.pid = rport->pid;
  1625. rport_info.local_pid = port->pid;
  1626. rport_info.lp_tag = port->lp_tag;
  1627. rport_info.vf_id = port->fabric->vf_id;
  1628. rport_info.vf_en = port->fabric->is_vf;
  1629. rport_info.fc_class = rport->fc_cos;
  1630. rport_info.cisc = rport->cisc;
  1631. rport_info.max_frmsz = rport->maxfrsize;
  1632. bfa_rport_online(rport->bfa_rport, &rport_info);
  1633. }
  1634. static void
  1635. bfa_fcs_rport_fc4_pause(struct bfa_fcs_rport_s *rport)
  1636. {
  1637. if (bfa_fcs_port_is_initiator(rport->port))
  1638. bfa_fcs_itnim_pause(rport->itnim);
  1639. if (bfa_fcs_port_is_target(rport->port))
  1640. bfa_fcs_tin_pause(rport->tin);
  1641. }
  1642. static void
  1643. bfa_fcs_rport_fc4_resume(struct bfa_fcs_rport_s *rport)
  1644. {
  1645. if (bfa_fcs_port_is_initiator(rport->port))
  1646. bfa_fcs_itnim_resume(rport->itnim);
  1647. if (bfa_fcs_port_is_target(rport->port))
  1648. bfa_fcs_tin_resume(rport->tin);
  1649. }
  1650. static struct bfa_fcs_rport_s *
  1651. bfa_fcs_rport_alloc(struct bfa_fcs_port_s *port, wwn_t pwwn, u32 rpid)
  1652. {
  1653. struct bfa_fcs_s *fcs = port->fcs;
  1654. struct bfa_fcs_rport_s *rport;
  1655. struct bfad_rport_s *rport_drv;
  1656. /**
  1657. * allocate rport
  1658. */
  1659. if (bfa_fcb_rport_alloc(fcs->bfad, &rport, &rport_drv)
  1660. != BFA_STATUS_OK) {
  1661. bfa_trc(fcs, rpid);
  1662. return NULL;
  1663. }
  1664. /*
  1665. * Initialize r-port
  1666. */
  1667. rport->port = port;
  1668. rport->fcs = fcs;
  1669. rport->rp_drv = rport_drv;
  1670. rport->pid = rpid;
  1671. rport->pwwn = pwwn;
  1672. /**
  1673. * allocate BFA rport
  1674. */
  1675. rport->bfa_rport = bfa_rport_create(port->fcs->bfa, rport);
  1676. if (!rport->bfa_rport) {
  1677. bfa_trc(fcs, rpid);
  1678. kfree(rport_drv);
  1679. return NULL;
  1680. }
  1681. /**
  1682. * allocate FC-4s
  1683. */
  1684. bfa_assert(bfa_fcs_port_is_initiator(port) ^
  1685. bfa_fcs_port_is_target(port));
  1686. if (bfa_fcs_port_is_initiator(port)) {
  1687. rport->itnim = bfa_fcs_itnim_create(rport);
  1688. if (!rport->itnim) {
  1689. bfa_trc(fcs, rpid);
  1690. bfa_rport_delete(rport->bfa_rport);
  1691. kfree(rport_drv);
  1692. return NULL;
  1693. }
  1694. }
  1695. if (bfa_fcs_port_is_target(port)) {
  1696. rport->tin = bfa_fcs_tin_create(rport);
  1697. if (!rport->tin) {
  1698. bfa_trc(fcs, rpid);
  1699. bfa_rport_delete(rport->bfa_rport);
  1700. kfree(rport_drv);
  1701. return NULL;
  1702. }
  1703. }
  1704. bfa_fcs_port_add_rport(port, rport);
  1705. bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit);
  1706. /*
  1707. * Initialize the Rport Features(RPF) Sub Module
  1708. */
  1709. if (!BFA_FCS_PID_IS_WKA(rport->pid))
  1710. bfa_fcs_rpf_init(rport);
  1711. return rport;
  1712. }
  1713. static void
  1714. bfa_fcs_rport_free(struct bfa_fcs_rport_s *rport)
  1715. {
  1716. struct bfa_fcs_port_s *port = rport->port;
  1717. /**
  1718. * - delete FC-4s
  1719. * - delete BFA rport
  1720. * - remove from queue of rports
  1721. */
  1722. if (bfa_fcs_port_is_initiator(port))
  1723. bfa_fcs_itnim_delete(rport->itnim);
  1724. if (bfa_fcs_port_is_target(port))
  1725. bfa_fcs_tin_delete(rport->tin);
  1726. bfa_rport_delete(rport->bfa_rport);
  1727. bfa_fcs_port_del_rport(port, rport);
  1728. kfree(rport->rp_drv);
  1729. }
  1730. static void
  1731. bfa_fcs_rport_aen_post(struct bfa_fcs_rport_s *rport,
  1732. enum bfa_rport_aen_event event,
  1733. struct bfa_rport_aen_data_s *data)
  1734. {
  1735. union bfa_aen_data_u aen_data;
  1736. struct bfa_log_mod_s *logmod = rport->fcs->logm;
  1737. wwn_t lpwwn = bfa_fcs_port_get_pwwn(rport->port);
  1738. wwn_t rpwwn = rport->pwwn;
  1739. char lpwwn_ptr[BFA_STRING_32];
  1740. char rpwwn_ptr[BFA_STRING_32];
  1741. char *prio_str[] = { "unknown", "high", "medium", "low" };
  1742. wwn2str(lpwwn_ptr, lpwwn);
  1743. wwn2str(rpwwn_ptr, rpwwn);
  1744. switch (event) {
  1745. case BFA_RPORT_AEN_ONLINE:
  1746. bfa_log(logmod, BFA_AEN_RPORT_ONLINE, rpwwn_ptr, lpwwn_ptr);
  1747. break;
  1748. case BFA_RPORT_AEN_OFFLINE:
  1749. bfa_log(logmod, BFA_AEN_RPORT_OFFLINE, rpwwn_ptr, lpwwn_ptr);
  1750. break;
  1751. case BFA_RPORT_AEN_DISCONNECT:
  1752. bfa_log(logmod, BFA_AEN_RPORT_DISCONNECT, rpwwn_ptr, lpwwn_ptr);
  1753. break;
  1754. case BFA_RPORT_AEN_QOS_PRIO:
  1755. aen_data.rport.priv.qos = data->priv.qos;
  1756. bfa_log(logmod, BFA_AEN_RPORT_QOS_PRIO,
  1757. prio_str[aen_data.rport.priv.qos.qos_priority],
  1758. rpwwn_ptr, lpwwn_ptr);
  1759. break;
  1760. case BFA_RPORT_AEN_QOS_FLOWID:
  1761. aen_data.rport.priv.qos = data->priv.qos;
  1762. bfa_log(logmod, BFA_AEN_RPORT_QOS_FLOWID,
  1763. aen_data.rport.priv.qos.qos_flow_id, rpwwn_ptr,
  1764. lpwwn_ptr);
  1765. break;
  1766. default:
  1767. break;
  1768. }
  1769. aen_data.rport.vf_id = rport->port->fabric->vf_id;
  1770. aen_data.rport.ppwwn =
  1771. bfa_fcs_port_get_pwwn(bfa_fcs_get_base_port(rport->fcs));
  1772. aen_data.rport.lpwwn = lpwwn;
  1773. aen_data.rport.rpwwn = rpwwn;
  1774. }
  1775. static void
  1776. bfa_fcs_rport_online_action(struct bfa_fcs_rport_s *rport)
  1777. {
  1778. struct bfa_fcs_port_s *port = rport->port;
  1779. rport->stats.onlines++;
  1780. if (bfa_fcs_port_is_initiator(port)) {
  1781. bfa_fcs_itnim_rport_online(rport->itnim);
  1782. if (!BFA_FCS_PID_IS_WKA(rport->pid))
  1783. bfa_fcs_rpf_rport_online(rport);
  1784. };
  1785. if (bfa_fcs_port_is_target(port))
  1786. bfa_fcs_tin_rport_online(rport->tin);
  1787. /*
  1788. * Don't post events for well known addresses
  1789. */
  1790. if (!BFA_FCS_PID_IS_WKA(rport->pid))
  1791. bfa_fcs_rport_aen_post(rport, BFA_RPORT_AEN_ONLINE, NULL);
  1792. }
  1793. static void
  1794. bfa_fcs_rport_offline_action(struct bfa_fcs_rport_s *rport)
  1795. {
  1796. struct bfa_fcs_port_s *port = rport->port;
  1797. rport->stats.offlines++;
  1798. /*
  1799. * Don't post events for well known addresses
  1800. */
  1801. if (!BFA_FCS_PID_IS_WKA(rport->pid)) {
  1802. if (bfa_fcs_port_is_online(rport->port) == BFA_TRUE) {
  1803. bfa_fcs_rport_aen_post(rport, BFA_RPORT_AEN_DISCONNECT,
  1804. NULL);
  1805. } else {
  1806. bfa_fcs_rport_aen_post(rport, BFA_RPORT_AEN_OFFLINE,
  1807. NULL);
  1808. }
  1809. }
  1810. if (bfa_fcs_port_is_initiator(port)) {
  1811. bfa_fcs_itnim_rport_offline(rport->itnim);
  1812. if (!BFA_FCS_PID_IS_WKA(rport->pid))
  1813. bfa_fcs_rpf_rport_offline(rport);
  1814. }
  1815. if (bfa_fcs_port_is_target(port))
  1816. bfa_fcs_tin_rport_offline(rport->tin);
  1817. }
  1818. /**
  1819. * Update rport parameters from PLOGI or PLOGI accept.
  1820. */
  1821. static void
  1822. bfa_fcs_rport_update(struct bfa_fcs_rport_s *rport, struct fc_logi_s *plogi)
  1823. {
  1824. struct bfa_fcs_port_s *port = rport->port;
  1825. /**
  1826. * - port name
  1827. * - node name
  1828. */
  1829. rport->pwwn = plogi->port_name;
  1830. rport->nwwn = plogi->node_name;
  1831. /**
  1832. * - class of service
  1833. */
  1834. rport->fc_cos = 0;
  1835. if (plogi->class3.class_valid)
  1836. rport->fc_cos = FC_CLASS_3;
  1837. if (plogi->class2.class_valid)
  1838. rport->fc_cos |= FC_CLASS_2;
  1839. /**
  1840. * - CISC
  1841. * - MAX receive frame size
  1842. */
  1843. rport->cisc = plogi->csp.cisc;
  1844. rport->maxfrsize = bfa_os_ntohs(plogi->class3.rxsz);
  1845. bfa_trc(port->fcs, bfa_os_ntohs(plogi->csp.bbcred));
  1846. bfa_trc(port->fcs, port->fabric->bb_credit);
  1847. /**
  1848. * Direct Attach P2P mode :
  1849. * This is to handle a bug (233476) in IBM targets in Direct Attach
  1850. * Mode. Basically, in FLOGI Accept the target would have erroneously
  1851. * set the BB Credit to the value used in the FLOGI sent by the HBA.
  1852. * It uses the correct value (its own BB credit) in PLOGI.
  1853. */
  1854. if ((!bfa_fcs_fabric_is_switched(port->fabric))
  1855. && (bfa_os_ntohs(plogi->csp.bbcred) < port->fabric->bb_credit)) {
  1856. bfa_trc(port->fcs, bfa_os_ntohs(plogi->csp.bbcred));
  1857. bfa_trc(port->fcs, port->fabric->bb_credit);
  1858. port->fabric->bb_credit = bfa_os_ntohs(plogi->csp.bbcred);
  1859. bfa_pport_set_tx_bbcredit(port->fcs->bfa,
  1860. port->fabric->bb_credit);
  1861. }
  1862. }
  1863. /**
  1864. * Called to handle LOGO received from an existing remote port.
  1865. */
  1866. static void
  1867. bfa_fcs_rport_process_logo(struct bfa_fcs_rport_s *rport, struct fchs_s *fchs)
  1868. {
  1869. rport->reply_oxid = fchs->ox_id;
  1870. bfa_trc(rport->fcs, rport->reply_oxid);
  1871. rport->stats.logo_rcvd++;
  1872. bfa_sm_send_event(rport, RPSM_EVENT_LOGO_RCVD);
  1873. }
  1874. /**
  1875. * fcs_rport_public FCS rport public interfaces
  1876. */
  1877. /**
  1878. * Called by bport/vport to create a remote port instance for a discovered
  1879. * remote device.
  1880. *
  1881. * @param[in] port - base port or vport
  1882. * @param[in] rpid - remote port ID
  1883. *
  1884. * @return None
  1885. */
  1886. struct bfa_fcs_rport_s *
  1887. bfa_fcs_rport_create(struct bfa_fcs_port_s *port, u32 rpid)
  1888. {
  1889. struct bfa_fcs_rport_s *rport;
  1890. bfa_trc(port->fcs, rpid);
  1891. rport = bfa_fcs_rport_alloc(port, WWN_NULL, rpid);
  1892. if (!rport)
  1893. return NULL;
  1894. bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_SEND);
  1895. return rport;
  1896. }
  1897. /**
  1898. * Called to create a rport for which only the wwn is known.
  1899. *
  1900. * @param[in] port - base port
  1901. * @param[in] rpwwn - remote port wwn
  1902. *
  1903. * @return None
  1904. */
  1905. struct bfa_fcs_rport_s *
  1906. bfa_fcs_rport_create_by_wwn(struct bfa_fcs_port_s *port, wwn_t rpwwn)
  1907. {
  1908. struct bfa_fcs_rport_s *rport;
  1909. bfa_trc(port->fcs, rpwwn);
  1910. rport = bfa_fcs_rport_alloc(port, rpwwn, 0);
  1911. if (!rport)
  1912. return NULL;
  1913. bfa_sm_send_event(rport, RPSM_EVENT_ADDRESS_DISC);
  1914. return rport;
  1915. }
  1916. /**
  1917. * Called by bport in private loop topology to indicate that a
  1918. * rport has been discovered and plogi has been completed.
  1919. *
  1920. * @param[in] port - base port or vport
  1921. * @param[in] rpid - remote port ID
  1922. */
  1923. void
  1924. bfa_fcs_rport_start(struct bfa_fcs_port_s *port, struct fchs_s *fchs,
  1925. struct fc_logi_s *plogi)
  1926. {
  1927. struct bfa_fcs_rport_s *rport;
  1928. rport = bfa_fcs_rport_alloc(port, WWN_NULL, fchs->s_id);
  1929. if (!rport)
  1930. return;
  1931. bfa_fcs_rport_update(rport, plogi);
  1932. bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_COMP);
  1933. }
  1934. /**
  1935. * Called by bport/vport to handle PLOGI received from a new remote port.
  1936. * If an existing rport does a plogi, it will be handled separately.
  1937. */
  1938. void
  1939. bfa_fcs_rport_plogi_create(struct bfa_fcs_port_s *port, struct fchs_s *fchs,
  1940. struct fc_logi_s *plogi)
  1941. {
  1942. struct bfa_fcs_rport_s *rport;
  1943. rport = bfa_fcs_rport_alloc(port, plogi->port_name, fchs->s_id);
  1944. if (!rport)
  1945. return;
  1946. bfa_fcs_rport_update(rport, plogi);
  1947. rport->reply_oxid = fchs->ox_id;
  1948. bfa_trc(rport->fcs, rport->reply_oxid);
  1949. rport->stats.plogi_rcvd++;
  1950. bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_RCVD);
  1951. }
  1952. static int
  1953. wwn_compare(wwn_t wwn1, wwn_t wwn2)
  1954. {
  1955. u8 *b1 = (u8 *) &wwn1;
  1956. u8 *b2 = (u8 *) &wwn2;
  1957. int i;
  1958. for (i = 0; i < sizeof(wwn_t); i++) {
  1959. if (b1[i] < b2[i])
  1960. return -1;
  1961. if (b1[i] > b2[i])
  1962. return 1;
  1963. }
  1964. return 0;
  1965. }
  1966. /**
  1967. * Called by bport/vport to handle PLOGI received from an existing
  1968. * remote port.
  1969. */
  1970. void
  1971. bfa_fcs_rport_plogi(struct bfa_fcs_rport_s *rport, struct fchs_s *rx_fchs,
  1972. struct fc_logi_s *plogi)
  1973. {
  1974. /**
  1975. * @todo Handle P2P and initiator-initiator.
  1976. */
  1977. bfa_fcs_rport_update(rport, plogi);
  1978. rport->reply_oxid = rx_fchs->ox_id;
  1979. bfa_trc(rport->fcs, rport->reply_oxid);
  1980. /**
  1981. * In Switched fabric topology,
  1982. * PLOGI to each other. If our pwwn is smaller, ignore it,
  1983. * if it is not a well known address.
  1984. * If the link topology is N2N,
  1985. * this Plogi should be accepted.
  1986. */
  1987. if ((wwn_compare(rport->port->port_cfg.pwwn, rport->pwwn) == -1)
  1988. && (bfa_fcs_fabric_is_switched(rport->port->fabric))
  1989. && (!BFA_FCS_PID_IS_WKA(rport->pid))) {
  1990. bfa_trc(rport->fcs, rport->pid);
  1991. return;
  1992. }
  1993. rport->stats.plogi_rcvd++;
  1994. bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_RCVD);
  1995. }
  1996. /**
  1997. * Called by bport/vport to delete a remote port instance.
  1998. *
  1999. * Rport delete is called under the following conditions:
  2000. * - vport is deleted
  2001. * - vf is deleted
  2002. * - explicit request from OS to delete rport (vmware)
  2003. */
  2004. void
  2005. bfa_fcs_rport_delete(struct bfa_fcs_rport_s *rport)
  2006. {
  2007. bfa_sm_send_event(rport, RPSM_EVENT_DELETE);
  2008. }
  2009. /**
  2010. * Called by bport/vport to when a target goes offline.
  2011. *
  2012. */
  2013. void
  2014. bfa_fcs_rport_offline(struct bfa_fcs_rport_s *rport)
  2015. {
  2016. bfa_sm_send_event(rport, RPSM_EVENT_LOGO_IMP);
  2017. }
  2018. /**
  2019. * Called by bport in n2n when a target (attached port) becomes online.
  2020. *
  2021. */
  2022. void
  2023. bfa_fcs_rport_online(struct bfa_fcs_rport_s *rport)
  2024. {
  2025. bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_SEND);
  2026. }
  2027. /**
  2028. * Called by bport/vport to notify SCN for the remote port
  2029. */
  2030. void
  2031. bfa_fcs_rport_scn(struct bfa_fcs_rport_s *rport)
  2032. {
  2033. rport->stats.rscns++;
  2034. bfa_sm_send_event(rport, RPSM_EVENT_SCN);
  2035. }
  2036. /**
  2037. * Called by fcpim to notify that the ITN cleanup is done.
  2038. */
  2039. void
  2040. bfa_fcs_rport_itnim_ack(struct bfa_fcs_rport_s *rport)
  2041. {
  2042. bfa_sm_send_event(rport, RPSM_EVENT_FC4_OFFLINE);
  2043. }
  2044. /**
  2045. * Called by fcptm to notify that the ITN cleanup is done.
  2046. */
  2047. void
  2048. bfa_fcs_rport_tin_ack(struct bfa_fcs_rport_s *rport)
  2049. {
  2050. bfa_sm_send_event(rport, RPSM_EVENT_FC4_OFFLINE);
  2051. }
  2052. /**
  2053. * This routine BFA callback for bfa_rport_online() call.
  2054. *
  2055. * param[in] cb_arg - rport struct.
  2056. *
  2057. * return
  2058. * void
  2059. *
  2060. * Special Considerations:
  2061. *
  2062. * note
  2063. */
  2064. void
  2065. bfa_cb_rport_online(void *cbarg)
  2066. {
  2067. struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *)cbarg;
  2068. bfa_trc(rport->fcs, rport->pwwn);
  2069. bfa_sm_send_event(rport, RPSM_EVENT_HCB_ONLINE);
  2070. }
  2071. /**
  2072. * This routine BFA callback for bfa_rport_offline() call.
  2073. *
  2074. * param[in] rport -
  2075. *
  2076. * return
  2077. * void
  2078. *
  2079. * Special Considerations:
  2080. *
  2081. * note
  2082. */
  2083. void
  2084. bfa_cb_rport_offline(void *cbarg)
  2085. {
  2086. struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *)cbarg;
  2087. bfa_trc(rport->fcs, rport->pwwn);
  2088. bfa_sm_send_event(rport, RPSM_EVENT_HCB_OFFLINE);
  2089. }
  2090. /**
  2091. * This routine is a static BFA callback when there is a QoS flow_id
  2092. * change notification
  2093. *
  2094. * @param[in] rport -
  2095. *
  2096. * @return void
  2097. *
  2098. * Special Considerations:
  2099. *
  2100. * @note
  2101. */
  2102. void
  2103. bfa_cb_rport_qos_scn_flowid(void *cbarg,
  2104. struct bfa_rport_qos_attr_s old_qos_attr,
  2105. struct bfa_rport_qos_attr_s new_qos_attr)
  2106. {
  2107. struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *)cbarg;
  2108. struct bfa_rport_aen_data_s aen_data;
  2109. bfa_trc(rport->fcs, rport->pwwn);
  2110. aen_data.priv.qos = new_qos_attr;
  2111. bfa_fcs_rport_aen_post(rport, BFA_RPORT_AEN_QOS_FLOWID, &aen_data);
  2112. }
  2113. /**
  2114. * This routine is a static BFA callback when there is a QoS priority
  2115. * change notification
  2116. *
  2117. * @param[in] rport -
  2118. *
  2119. * @return void
  2120. *
  2121. * Special Considerations:
  2122. *
  2123. * @note
  2124. */
  2125. void
  2126. bfa_cb_rport_qos_scn_prio(void *cbarg, struct bfa_rport_qos_attr_s old_qos_attr,
  2127. struct bfa_rport_qos_attr_s new_qos_attr)
  2128. {
  2129. struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *)cbarg;
  2130. struct bfa_rport_aen_data_s aen_data;
  2131. bfa_trc(rport->fcs, rport->pwwn);
  2132. aen_data.priv.qos = new_qos_attr;
  2133. bfa_fcs_rport_aen_post(rport, BFA_RPORT_AEN_QOS_PRIO, &aen_data);
  2134. }
  2135. /**
  2136. * Called to process any unsolicted frames from this remote port
  2137. */
  2138. void
  2139. bfa_fcs_rport_logo_imp(struct bfa_fcs_rport_s *rport)
  2140. {
  2141. bfa_sm_send_event(rport, RPSM_EVENT_LOGO_IMP);
  2142. }
  2143. /**
  2144. * Called to process any unsolicted frames from this remote port
  2145. */
  2146. void
  2147. bfa_fcs_rport_uf_recv(struct bfa_fcs_rport_s *rport, struct fchs_s *fchs,
  2148. u16 len)
  2149. {
  2150. struct bfa_fcs_port_s *port = rport->port;
  2151. struct fc_els_cmd_s *els_cmd;
  2152. bfa_trc(rport->fcs, fchs->s_id);
  2153. bfa_trc(rport->fcs, fchs->d_id);
  2154. bfa_trc(rport->fcs, fchs->type);
  2155. if (fchs->type != FC_TYPE_ELS)
  2156. return;
  2157. els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
  2158. bfa_trc(rport->fcs, els_cmd->els_code);
  2159. switch (els_cmd->els_code) {
  2160. case FC_ELS_LOGO:
  2161. bfa_fcs_rport_process_logo(rport, fchs);
  2162. break;
  2163. case FC_ELS_ADISC:
  2164. bfa_fcs_rport_process_adisc(rport, fchs, len);
  2165. break;
  2166. case FC_ELS_PRLO:
  2167. if (bfa_fcs_port_is_initiator(port))
  2168. bfa_fcs_fcpim_uf_recv(rport->itnim, fchs, len);
  2169. if (bfa_fcs_port_is_target(port))
  2170. bfa_fcs_fcptm_uf_recv(rport->tin, fchs, len);
  2171. break;
  2172. case FC_ELS_PRLI:
  2173. bfa_fcs_rport_process_prli(rport, fchs, len);
  2174. break;
  2175. case FC_ELS_RPSC:
  2176. bfa_fcs_rport_process_rpsc(rport, fchs, len);
  2177. break;
  2178. default:
  2179. bfa_fcs_rport_send_ls_rjt(rport, fchs,
  2180. FC_LS_RJT_RSN_CMD_NOT_SUPP,
  2181. FC_LS_RJT_EXP_NO_ADDL_INFO);
  2182. break;
  2183. }
  2184. }
  2185. /*
  2186. * Send a LS reject
  2187. */
  2188. static void
  2189. bfa_fcs_rport_send_ls_rjt(struct bfa_fcs_rport_s *rport, struct fchs_s *rx_fchs,
  2190. u8 reason_code, u8 reason_code_expl)
  2191. {
  2192. struct bfa_fcs_port_s *port = rport->port;
  2193. struct fchs_s fchs;
  2194. struct bfa_fcxp_s *fcxp;
  2195. int len;
  2196. bfa_trc(rport->fcs, rx_fchs->s_id);
  2197. fcxp = bfa_fcs_fcxp_alloc(rport->fcs);
  2198. if (!fcxp)
  2199. return;
  2200. len = fc_ls_rjt_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rx_fchs->s_id,
  2201. bfa_fcs_port_get_fcid(port), rx_fchs->ox_id,
  2202. reason_code, reason_code_expl);
  2203. bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE,
  2204. FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0);
  2205. }
  2206. /**
  2207. * Return state of rport.
  2208. */
  2209. int
  2210. bfa_fcs_rport_get_state(struct bfa_fcs_rport_s *rport)
  2211. {
  2212. return bfa_sm_to_state(rport_sm_table, rport->sm);
  2213. }
  2214. /**
  2215. * Called by the Driver to set rport delete/ageout timeout
  2216. *
  2217. * param[in] rport timeout value in seconds.
  2218. *
  2219. * return None
  2220. */
  2221. void
  2222. bfa_fcs_rport_set_del_timeout(u8 rport_tmo)
  2223. {
  2224. /*
  2225. * convert to Millisecs
  2226. */
  2227. if (rport_tmo > 0)
  2228. bfa_fcs_rport_del_timeout = rport_tmo * 1000;
  2229. }