rport.c 67 KB

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