rport.c 65 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618
  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. * Module initialization
  2208. */
  2209. void
  2210. bfa_fcs_rport_modinit(struct bfa_fcs_s *fcs)
  2211. {
  2212. }
  2213. /**
  2214. * Module cleanup
  2215. */
  2216. void
  2217. bfa_fcs_rport_modexit(struct bfa_fcs_s *fcs)
  2218. {
  2219. bfa_fcs_modexit_comp(fcs);
  2220. }
  2221. /**
  2222. * Return state of rport.
  2223. */
  2224. int
  2225. bfa_fcs_rport_get_state(struct bfa_fcs_rport_s *rport)
  2226. {
  2227. return bfa_sm_to_state(rport_sm_table, rport->sm);
  2228. }
  2229. /**
  2230. * Called by the Driver to set rport delete/ageout timeout
  2231. *
  2232. * param[in] rport timeout value in seconds.
  2233. *
  2234. * return None
  2235. */
  2236. void
  2237. bfa_fcs_rport_set_del_timeout(u8 rport_tmo)
  2238. {
  2239. /*
  2240. * convert to Millisecs
  2241. */
  2242. if (rport_tmo > 0)
  2243. bfa_fcs_rport_del_timeout = rport_tmo * 1000;
  2244. }