rport.c 66 KB

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