| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093 |
- // SPDX-License-Identifier: GPL-2.0-only
- /*
- * Copyright 2008 Cisco Systems, Inc. All rights reserved.
- * Copyright 2007 Nuova Systems, Inc. All rights reserved.
- */
- #include <linux/workqueue.h>
- #include "fnic.h"
- #include "fdls_fc.h"
- #include "fnic_fdls.h"
- #include <scsi/fc/fc_fcp.h>
- #include <scsi/scsi_transport_fc.h>
- #include <linux/utsname.h>
- #define FC_FC4_TYPE_SCSI 0x08
- #define PORT_SPEED_BIT_8 8
- #define PORT_SPEED_BIT_9 9
- #define PORT_SPEED_BIT_14 14
- #define PORT_SPEED_BIT_15 15
- /* FNIC FDMI Register HBA Macros */
- #define FNIC_FDMI_NUM_PORTS 1
- #define FNIC_FDMI_NUM_HBA_ATTRS 9
- #define FNIC_FDMI_TYPE_NODE_NAME 0X1
- #define FNIC_FDMI_TYPE_MANUFACTURER 0X2
- #define FNIC_FDMI_MANUFACTURER "Cisco Systems"
- #define FNIC_FDMI_TYPE_SERIAL_NUMBER 0X3
- #define FNIC_FDMI_TYPE_MODEL 0X4
- #define FNIC_FDMI_TYPE_MODEL_DES 0X5
- #define FNIC_FDMI_MODEL_DESCRIPTION "Cisco Virtual Interface Card"
- #define FNIC_FDMI_TYPE_HARDWARE_VERSION 0X6
- #define FNIC_FDMI_TYPE_DRIVER_VERSION 0X7
- #define FNIC_FDMI_TYPE_ROM_VERSION 0X8
- #define FNIC_FDMI_TYPE_FIRMWARE_VERSION 0X9
- #define FNIC_FDMI_NN_LEN 8
- #define FNIC_FDMI_MANU_LEN 20
- #define FNIC_FDMI_SERIAL_LEN 16
- #define FNIC_FDMI_MODEL_LEN 12
- #define FNIC_FDMI_MODEL_DES_LEN 56
- #define FNIC_FDMI_HW_VER_LEN 16
- #define FNIC_FDMI_DR_VER_LEN 28
- #define FNIC_FDMI_ROM_VER_LEN 8
- #define FNIC_FDMI_FW_VER_LEN 16
- /* FNIC FDMI Register PA Macros */
- #define FNIC_FDMI_TYPE_FC4_TYPES 0X1
- #define FNIC_FDMI_TYPE_SUPPORTED_SPEEDS 0X2
- #define FNIC_FDMI_TYPE_CURRENT_SPEED 0X3
- #define FNIC_FDMI_TYPE_MAX_FRAME_SIZE 0X4
- #define FNIC_FDMI_TYPE_OS_NAME 0X5
- #define FNIC_FDMI_TYPE_HOST_NAME 0X6
- #define FNIC_FDMI_NUM_PORT_ATTRS 6
- #define FNIC_FDMI_FC4_LEN 32
- #define FNIC_FDMI_SUPP_SPEED_LEN 4
- #define FNIC_FDMI_CUR_SPEED_LEN 4
- #define FNIC_FDMI_MFS_LEN 4
- #define FNIC_FDMI_MFS 0x800
- #define FNIC_FDMI_OS_NAME_LEN 16
- #define FNIC_FDMI_HN_LEN 24
- #define FDLS_FDMI_PLOGI_PENDING 0x1
- #define FDLS_FDMI_REG_HBA_PENDING 0x2
- #define FDLS_FDMI_RPA_PENDING 0x4
- #define FDLS_FDMI_ABORT_PENDING 0x8
- #define FDLS_FDMI_MAX_RETRY 3
- #define RETRIES_EXHAUSTED(iport) \
- (iport->fabric.retry_counter == FABRIC_LOGO_MAX_RETRY)
- #define FNIC_TPORT_MAX_NEXUS_RESTART (8)
- #define SCHEDULE_OXID_FREE_RETRY_TIME (300)
- /* Private Functions */
- static void fdls_fdmi_register_hba(struct fnic_iport_s *iport);
- static void fdls_fdmi_register_pa(struct fnic_iport_s *iport);
- static void fdls_send_rpn_id(struct fnic_iport_s *iport);
- static void fdls_process_flogi_rsp(struct fnic_iport_s *iport,
- struct fc_frame_header *fchdr,
- void *rx_frame);
- static void fnic_fdls_start_plogi(struct fnic_iport_s *iport);
- static void fnic_fdls_start_flogi(struct fnic_iport_s *iport);
- static struct fnic_tport_s *fdls_create_tport(struct fnic_iport_s *iport,
- uint32_t fcid,
- uint64_t wwpn);
- static void fdls_target_restart_nexus(struct fnic_tport_s *tport);
- static void fdls_start_tport_timer(struct fnic_iport_s *iport,
- struct fnic_tport_s *tport, int timeout);
- static void fdls_tport_timer_callback(struct timer_list *t);
- static void fdls_send_fdmi_plogi(struct fnic_iport_s *iport);
- static void fdls_start_fabric_timer(struct fnic_iport_s *iport,
- int timeout);
- static void fdls_init_plogi_frame(uint8_t *frame, struct fnic_iport_s *iport);
- static void fdls_init_els_acc_frame(uint8_t *frame, struct fnic_iport_s *iport);
- static void fdls_init_els_rjt_frame(uint8_t *frame, struct fnic_iport_s *iport);
- static void fdls_init_logo_frame(uint8_t *frame, struct fnic_iport_s *iport);
- static void fdls_init_fabric_abts_frame(uint8_t *frame,
- struct fnic_iport_s *iport);
- uint8_t *fdls_alloc_frame(struct fnic_iport_s *iport)
- {
- struct fnic *fnic = iport->fnic;
- uint8_t *frame = NULL;
- frame = mempool_alloc(fnic->frame_pool, GFP_ATOMIC);
- if (frame == NULL) {
- FNIC_FCS_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
- "Failed to allocate frame");
- return NULL;
- }
- memset(frame, 0, FNIC_FCOE_FRAME_MAXSZ);
- return frame;
- }
- /**
- * fdls_alloc_oxid - Allocate an oxid from the bitmap based oxid pool
- * @iport: Handle to iport instance
- * @oxid_frame_type: Type of frame to allocate
- * @active_oxid: the oxid which is in use
- *
- * Called with fnic lock held
- */
- uint16_t fdls_alloc_oxid(struct fnic_iport_s *iport, int oxid_frame_type,
- uint16_t *active_oxid)
- {
- struct fnic *fnic = iport->fnic;
- struct fnic_oxid_pool_s *oxid_pool = &iport->oxid_pool;
- int idx;
- uint16_t oxid;
- lockdep_assert_held(&fnic->fnic_lock);
- /*
- * Allocate next available oxid from bitmap
- */
- idx = find_next_zero_bit(oxid_pool->bitmap, FNIC_OXID_POOL_SZ, oxid_pool->next_idx);
- if (idx == FNIC_OXID_POOL_SZ) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "Alloc oxid: all oxid slots are busy iport state:%d\n",
- iport->state);
- return FNIC_UNASSIGNED_OXID;
- }
- WARN_ON(test_and_set_bit(idx, oxid_pool->bitmap));
- oxid_pool->next_idx = (idx + 1) % FNIC_OXID_POOL_SZ; /* cycle through the bitmap */
- oxid = FNIC_OXID_ENCODE(idx, oxid_frame_type);
- *active_oxid = oxid;
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "alloc oxid: 0x%x, iport state: %d\n",
- oxid, iport->state);
- return oxid;
- }
- /**
- * fdls_free_oxid_idx - Free the oxid using the idx
- * @iport: Handle to iport instance
- * @oxid_idx: The index to free
- *
- * Free the oxid immediately and make it available for new requests
- * Called with fnic lock held
- */
- static void fdls_free_oxid_idx(struct fnic_iport_s *iport, uint16_t oxid_idx)
- {
- struct fnic *fnic = iport->fnic;
- struct fnic_oxid_pool_s *oxid_pool = &iport->oxid_pool;
- lockdep_assert_held(&fnic->fnic_lock);
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "free oxid idx: 0x%x\n", oxid_idx);
- WARN_ON(!test_and_clear_bit(oxid_idx, oxid_pool->bitmap));
- }
- /**
- * fdls_reclaim_oxid_handler - Callback handler for delayed_oxid_work
- * @work: Handle to work_struct
- *
- * Scheduled when an oxid is to be freed later
- * After freeing expired oxid(s), the handler schedules
- * another callback with the remaining time
- * of next unexpired entry in the reclaim list.
- */
- void fdls_reclaim_oxid_handler(struct work_struct *work)
- {
- struct fnic_oxid_pool_s *oxid_pool = container_of(work,
- struct fnic_oxid_pool_s, oxid_reclaim_work.work);
- struct fnic_iport_s *iport = container_of(oxid_pool,
- struct fnic_iport_s, oxid_pool);
- struct fnic *fnic = iport->fnic;
- struct reclaim_entry_s *reclaim_entry, *next;
- unsigned long delay_j, cur_jiffies;
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "Reclaim oxid callback\n");
- spin_lock_irqsave(&fnic->fnic_lock, fnic->lock_flags);
- /* Though the work was scheduled for one entry,
- * walk through and free the expired entries which might have been scheduled
- * at around the same time as the first entry
- */
- list_for_each_entry_safe(reclaim_entry, next,
- &(oxid_pool->oxid_reclaim_list), links) {
- /* The list is always maintained in the order of expiry time */
- cur_jiffies = jiffies;
- if (time_before(cur_jiffies, reclaim_entry->expires))
- break;
- list_del(&reclaim_entry->links);
- fdls_free_oxid_idx(iport, reclaim_entry->oxid_idx);
- kfree(reclaim_entry);
- }
- /* schedule to free up the next entry */
- if (!list_empty(&oxid_pool->oxid_reclaim_list)) {
- reclaim_entry = list_first_entry(&oxid_pool->oxid_reclaim_list,
- struct reclaim_entry_s, links);
- delay_j = reclaim_entry->expires - cur_jiffies;
- schedule_delayed_work(&oxid_pool->oxid_reclaim_work, delay_j);
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "Scheduling next callback at:%ld jiffies\n", delay_j);
- }
- spin_unlock_irqrestore(&fnic->fnic_lock, fnic->lock_flags);
- }
- /**
- * fdls_free_oxid - Helper function to free the oxid
- * @iport: Handle to iport instance
- * @oxid: oxid to free
- * @active_oxid: the oxid which is in use
- *
- * Called with fnic lock held
- */
- void fdls_free_oxid(struct fnic_iport_s *iport,
- uint16_t oxid, uint16_t *active_oxid)
- {
- fdls_free_oxid_idx(iport, FNIC_OXID_IDX(oxid));
- *active_oxid = FNIC_UNASSIGNED_OXID;
- }
- /**
- * fdls_schedule_oxid_free - Schedule oxid to be freed later
- * @iport: Handle to iport instance
- * @active_oxid: the oxid which is in use
- *
- * Gets called in a rare case scenario when both a command
- * (fdls or target discovery) timed out and the following ABTS
- * timed out as well, without a link change.
- *
- * Called with fnic lock held
- */
- void fdls_schedule_oxid_free(struct fnic_iport_s *iport, uint16_t *active_oxid)
- {
- struct fnic *fnic = iport->fnic;
- struct fnic_oxid_pool_s *oxid_pool = &iport->oxid_pool;
- struct reclaim_entry_s *reclaim_entry;
- unsigned long delay_j = msecs_to_jiffies(OXID_RECLAIM_TOV(iport));
- int oxid_idx = FNIC_OXID_IDX(*active_oxid);
- lockdep_assert_held(&fnic->fnic_lock);
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "Schedule oxid free. oxid: 0x%x\n", *active_oxid);
- *active_oxid = FNIC_UNASSIGNED_OXID;
- reclaim_entry = (struct reclaim_entry_s *)
- kzalloc_obj(struct reclaim_entry_s, GFP_ATOMIC);
- if (!reclaim_entry) {
- FNIC_FCS_DBG(KERN_WARNING, fnic->host, fnic->fnic_num,
- "Failed to allocate memory for reclaim struct for oxid idx: %d\n",
- oxid_idx);
- /* Retry the scheduling */
- WARN_ON(test_and_set_bit(oxid_idx, oxid_pool->pending_schedule_free));
- schedule_delayed_work(&oxid_pool->schedule_oxid_free_retry, 0);
- return;
- }
- reclaim_entry->oxid_idx = oxid_idx;
- reclaim_entry->expires = round_jiffies(jiffies + delay_j);
- list_add_tail(&reclaim_entry->links, &oxid_pool->oxid_reclaim_list);
- schedule_delayed_work(&oxid_pool->oxid_reclaim_work, delay_j);
- }
- /**
- * fdls_schedule_oxid_free_retry_work - Thread to schedule the
- * oxid to be freed later
- *
- * @work: Handle to the work struct
- */
- void fdls_schedule_oxid_free_retry_work(struct work_struct *work)
- {
- struct fnic_oxid_pool_s *oxid_pool = container_of(work,
- struct fnic_oxid_pool_s, schedule_oxid_free_retry.work);
- struct fnic_iport_s *iport = container_of(oxid_pool,
- struct fnic_iport_s, oxid_pool);
- struct fnic *fnic = iport->fnic;
- struct reclaim_entry_s *reclaim_entry;
- unsigned long delay_j = msecs_to_jiffies(OXID_RECLAIM_TOV(iport));
- unsigned long flags;
- int idx;
- for_each_set_bit(idx, oxid_pool->pending_schedule_free, FNIC_OXID_POOL_SZ) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "Schedule oxid free. oxid idx: %d\n", idx);
- reclaim_entry = kzalloc_obj(*reclaim_entry);
- if (!reclaim_entry) {
- schedule_delayed_work(&oxid_pool->schedule_oxid_free_retry,
- msecs_to_jiffies(SCHEDULE_OXID_FREE_RETRY_TIME));
- return;
- }
- clear_bit(idx, oxid_pool->pending_schedule_free);
- reclaim_entry->oxid_idx = idx;
- reclaim_entry->expires = round_jiffies(jiffies + delay_j);
- spin_lock_irqsave(&fnic->fnic_lock, flags);
- list_add_tail(&reclaim_entry->links, &oxid_pool->oxid_reclaim_list);
- spin_unlock_irqrestore(&fnic->fnic_lock, flags);
- schedule_delayed_work(&oxid_pool->oxid_reclaim_work, delay_j);
- }
- }
- static bool fdls_is_oxid_fabric_req(uint16_t oxid)
- {
- int oxid_frame_type = FNIC_FRAME_TYPE(oxid);
- switch (oxid_frame_type) {
- case FNIC_FRAME_TYPE_FABRIC_FLOGI:
- case FNIC_FRAME_TYPE_FABRIC_PLOGI:
- case FNIC_FRAME_TYPE_FABRIC_RPN:
- case FNIC_FRAME_TYPE_FABRIC_RFT:
- case FNIC_FRAME_TYPE_FABRIC_RFF:
- case FNIC_FRAME_TYPE_FABRIC_GPN_FT:
- case FNIC_FRAME_TYPE_FABRIC_LOGO:
- break;
- default:
- return false;
- }
- return true;
- }
- static bool fdls_is_oxid_fdmi_req(uint16_t oxid)
- {
- int oxid_frame_type = FNIC_FRAME_TYPE(oxid);
- switch (oxid_frame_type) {
- case FNIC_FRAME_TYPE_FDMI_PLOGI:
- case FNIC_FRAME_TYPE_FDMI_RHBA:
- case FNIC_FRAME_TYPE_FDMI_RPA:
- break;
- default:
- return false;
- }
- return true;
- }
- static bool fdls_is_oxid_tgt_req(uint16_t oxid)
- {
- int oxid_frame_type = FNIC_FRAME_TYPE(oxid);
- switch (oxid_frame_type) {
- case FNIC_FRAME_TYPE_TGT_PLOGI:
- case FNIC_FRAME_TYPE_TGT_PRLI:
- case FNIC_FRAME_TYPE_TGT_ADISC:
- case FNIC_FRAME_TYPE_TGT_LOGO:
- break;
- default:
- return false;
- }
- return true;
- }
- static void fdls_reset_oxid_pool(struct fnic_iport_s *iport)
- {
- struct fnic_oxid_pool_s *oxid_pool = &iport->oxid_pool;
- oxid_pool->next_idx = 0;
- }
- void fnic_del_fabric_timer_sync(struct fnic *fnic)
- {
- fnic->iport.fabric.del_timer_inprogress = 1;
- spin_unlock_irqrestore(&fnic->fnic_lock, fnic->lock_flags);
- timer_delete_sync(&fnic->iport.fabric.retry_timer);
- spin_lock_irqsave(&fnic->fnic_lock, fnic->lock_flags);
- fnic->iport.fabric.del_timer_inprogress = 0;
- }
- void fnic_del_tport_timer_sync(struct fnic *fnic,
- struct fnic_tport_s *tport)
- {
- tport->del_timer_inprogress = 1;
- spin_unlock_irqrestore(&fnic->fnic_lock, fnic->lock_flags);
- timer_delete_sync(&tport->retry_timer);
- spin_lock_irqsave(&fnic->fnic_lock, fnic->lock_flags);
- tport->del_timer_inprogress = 0;
- }
- static void
- fdls_start_fabric_timer(struct fnic_iport_s *iport, int timeout)
- {
- u64 fabric_tov;
- struct fnic *fnic = iport->fnic;
- if (iport->fabric.timer_pending) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "iport fcid: 0x%x: Canceling fabric disc timer\n",
- iport->fcid);
- fnic_del_fabric_timer_sync(fnic);
- iport->fabric.timer_pending = 0;
- }
- if (!(iport->fabric.flags & FNIC_FDLS_FABRIC_ABORT_ISSUED))
- iport->fabric.retry_counter++;
- fabric_tov = jiffies + msecs_to_jiffies(timeout);
- mod_timer(&iport->fabric.retry_timer, round_jiffies(fabric_tov));
- iport->fabric.timer_pending = 1;
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "fabric timer is %d ", timeout);
- }
- static void
- fdls_start_tport_timer(struct fnic_iport_s *iport,
- struct fnic_tport_s *tport, int timeout)
- {
- u64 fabric_tov;
- struct fnic *fnic = iport->fnic;
- if (tport->timer_pending) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "tport fcid 0x%x: Canceling disc timer\n",
- tport->fcid);
- fnic_del_tport_timer_sync(fnic, tport);
- tport->timer_pending = 0;
- }
- if (!(tport->flags & FNIC_FDLS_TGT_ABORT_ISSUED))
- tport->retry_counter++;
- fabric_tov = jiffies + msecs_to_jiffies(timeout);
- mod_timer(&tport->retry_timer, round_jiffies(fabric_tov));
- tport->timer_pending = 1;
- }
- void fdls_init_plogi_frame(uint8_t *frame,
- struct fnic_iport_s *iport)
- {
- struct fc_std_flogi *pplogi;
- uint8_t s_id[3];
- pplogi = (struct fc_std_flogi *) (frame + FNIC_ETH_FCOE_HDRS_OFFSET);
- *pplogi = (struct fc_std_flogi) {
- .fchdr = {.fh_r_ctl = FC_RCTL_ELS_REQ, .fh_d_id = {0xFF, 0xFF, 0xFC},
- .fh_type = FC_TYPE_ELS, .fh_f_ctl = {FNIC_ELS_REQ_FCTL, 0, 0},
- .fh_rx_id = cpu_to_be16(FNIC_UNASSIGNED_RXID)},
- .els = {
- .fl_cmd = ELS_PLOGI,
- .fl_csp = {.sp_hi_ver = FNIC_FC_PH_VER_HI,
- .sp_lo_ver = FNIC_FC_PH_VER_LO,
- .sp_bb_cred = cpu_to_be16(FNIC_FC_B2B_CREDIT),
- .sp_features = cpu_to_be16(FC_SP_FT_CIRO),
- .sp_bb_data = cpu_to_be16(FNIC_FC_B2B_RDF_SZ),
- .sp_tot_seq = cpu_to_be16(FNIC_FC_CONCUR_SEQS),
- .sp_rel_off = cpu_to_be16(FNIC_FC_RO_INFO),
- .sp_e_d_tov = cpu_to_be32(FC_DEF_E_D_TOV)},
- .fl_cssp[2].cp_class = cpu_to_be16(FC_CPC_VALID | FC_CPC_SEQ),
- .fl_cssp[2].cp_rdfs = cpu_to_be16(0x800),
- .fl_cssp[2].cp_con_seq = cpu_to_be16(0xFF),
- .fl_cssp[2].cp_open_seq = 1}
- };
- FNIC_STD_SET_NPORT_NAME(&pplogi->els.fl_wwpn, iport->wwpn);
- FNIC_STD_SET_NODE_NAME(&pplogi->els.fl_wwnn, iport->wwnn);
- FNIC_LOGI_SET_RDF_SIZE(pplogi->els, iport->max_payload_size);
- hton24(s_id, iport->fcid);
- FNIC_STD_SET_S_ID(pplogi->fchdr, s_id);
- }
- static void fdls_init_els_acc_frame(uint8_t *frame,
- struct fnic_iport_s *iport)
- {
- struct fc_std_els_acc_rsp *pels_acc;
- uint8_t s_id[3];
- pels_acc = (struct fc_std_els_acc_rsp *) (frame + FNIC_ETH_FCOE_HDRS_OFFSET);
- *pels_acc = (struct fc_std_els_acc_rsp) {
- .fchdr = {.fh_r_ctl = FC_RCTL_ELS_REP,
- .fh_type = FC_TYPE_ELS, .fh_f_ctl = {FNIC_ELS_REP_FCTL, 0, 0}},
- .acc.la_cmd = ELS_LS_ACC,
- };
- hton24(s_id, iport->fcid);
- FNIC_STD_SET_S_ID(pels_acc->fchdr, s_id);
- FNIC_STD_SET_RX_ID(pels_acc->fchdr, FNIC_UNASSIGNED_RXID);
- }
- static void fdls_init_els_rjt_frame(uint8_t *frame,
- struct fnic_iport_s *iport)
- {
- struct fc_std_els_rjt_rsp *pels_rjt;
- pels_rjt = (struct fc_std_els_rjt_rsp *) (frame + FNIC_ETH_FCOE_HDRS_OFFSET);
- *pels_rjt = (struct fc_std_els_rjt_rsp) {
- .fchdr = {.fh_r_ctl = FC_RCTL_ELS_REP, .fh_type = FC_TYPE_ELS,
- .fh_f_ctl = {FNIC_ELS_REP_FCTL, 0, 0}},
- .rej.er_cmd = ELS_LS_RJT,
- };
- FNIC_STD_SET_RX_ID(pels_rjt->fchdr, FNIC_UNASSIGNED_RXID);
- }
- static void fdls_init_logo_frame(uint8_t *frame,
- struct fnic_iport_s *iport)
- {
- struct fc_std_logo *plogo;
- uint8_t s_id[3];
- plogo = (struct fc_std_logo *) (frame + FNIC_ETH_FCOE_HDRS_OFFSET);
- *plogo = (struct fc_std_logo) {
- .fchdr = {.fh_r_ctl = FC_RCTL_ELS_REQ, .fh_type = FC_TYPE_ELS,
- .fh_f_ctl = {FNIC_ELS_REQ_FCTL, 0, 0}},
- .els.fl_cmd = ELS_LOGO,
- };
- hton24(s_id, iport->fcid);
- FNIC_STD_SET_S_ID(plogo->fchdr, s_id);
- memcpy(plogo->els.fl_n_port_id, s_id, 3);
- FNIC_STD_SET_NPORT_NAME(&plogo->els.fl_n_port_wwn,
- iport->wwpn);
- }
- static void fdls_init_fabric_abts_frame(uint8_t *frame,
- struct fnic_iport_s *iport)
- {
- struct fc_frame_header *pfabric_abts;
- pfabric_abts = (struct fc_frame_header *) (frame + FNIC_ETH_FCOE_HDRS_OFFSET);
- *pfabric_abts = (struct fc_frame_header) {
- .fh_r_ctl = FC_RCTL_BA_ABTS, /* ABTS */
- .fh_s_id = {0x00, 0x00, 0x00},
- .fh_cs_ctl = 0x00, .fh_type = FC_TYPE_BLS,
- .fh_f_ctl = {FNIC_REQ_ABTS_FCTL, 0, 0}, .fh_seq_id = 0x00,
- .fh_df_ctl = 0x00, .fh_seq_cnt = 0x0000,
- .fh_rx_id = cpu_to_be16(FNIC_UNASSIGNED_RXID),
- .fh_parm_offset = 0x00000000, /* bit:0 = 0 Abort a exchange */
- };
- }
- static void
- fdls_send_rscn_resp(struct fnic_iport_s *iport,
- struct fc_frame_header *rscn_fchdr)
- {
- uint8_t *frame;
- struct fc_std_els_acc_rsp *pels_acc;
- struct fnic *fnic = iport->fnic;
- uint16_t oxid;
- uint16_t frame_size = FNIC_ETH_FCOE_HDRS_OFFSET +
- sizeof(struct fc_std_els_acc_rsp);
- frame = fdls_alloc_frame(iport);
- if (frame == NULL) {
- FNIC_FCS_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
- "Failed to allocate frame to send RSCN response");
- return;
- }
- pels_acc = (struct fc_std_els_acc_rsp *) (frame + FNIC_ETH_FCOE_HDRS_OFFSET);
- fdls_init_els_acc_frame(frame, iport);
- FNIC_STD_SET_D_ID(pels_acc->fchdr, rscn_fchdr->fh_s_id);
- oxid = FNIC_STD_GET_OX_ID(rscn_fchdr);
- FNIC_STD_SET_OX_ID(pels_acc->fchdr, oxid);
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "0x%x: FDLS send RSCN response with oxid: 0x%x",
- iport->fcid, oxid);
- fnic_send_fcoe_frame(iport, frame, frame_size);
- }
- static void
- fdls_send_logo_resp(struct fnic_iport_s *iport,
- struct fc_frame_header *req_fchdr)
- {
- uint8_t *frame;
- struct fc_std_els_acc_rsp *plogo_resp;
- struct fnic *fnic = iport->fnic;
- uint16_t oxid;
- uint16_t frame_size = FNIC_ETH_FCOE_HDRS_OFFSET +
- sizeof(struct fc_std_els_acc_rsp);
- frame = fdls_alloc_frame(iport);
- if (frame == NULL) {
- FNIC_FCS_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
- "Failed to allocate frame to send LOGO response");
- return;
- }
- plogo_resp = (struct fc_std_els_acc_rsp *) (frame + FNIC_ETH_FCOE_HDRS_OFFSET);
- fdls_init_els_acc_frame(frame, iport);
- FNIC_STD_SET_D_ID(plogo_resp->fchdr, req_fchdr->fh_s_id);
- oxid = FNIC_STD_GET_OX_ID(req_fchdr);
- FNIC_STD_SET_OX_ID(plogo_resp->fchdr, oxid);
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "0x%x: FDLS send LOGO response with oxid: 0x%x",
- iport->fcid, oxid);
- fnic_send_fcoe_frame(iport, frame, frame_size);
- }
- void
- fdls_send_tport_abts(struct fnic_iport_s *iport,
- struct fnic_tport_s *tport)
- {
- uint8_t *frame;
- uint8_t s_id[3];
- uint8_t d_id[3];
- struct fnic *fnic = iport->fnic;
- struct fc_frame_header *ptport_abts;
- uint16_t frame_size = FNIC_ETH_FCOE_HDRS_OFFSET +
- sizeof(struct fc_frame_header);
- frame = fdls_alloc_frame(iport);
- if (frame == NULL) {
- FNIC_FCS_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
- "Failed to allocate frame to send tport ABTS");
- return;
- }
- ptport_abts = (struct fc_frame_header *) (frame + FNIC_ETH_FCOE_HDRS_OFFSET);
- *ptport_abts = (struct fc_frame_header) {
- .fh_r_ctl = FC_RCTL_BA_ABTS, /* ABTS */
- .fh_cs_ctl = 0x00, .fh_type = FC_TYPE_BLS,
- .fh_f_ctl = {FNIC_REQ_ABTS_FCTL, 0, 0}, .fh_seq_id = 0x00,
- .fh_df_ctl = 0x00, .fh_seq_cnt = 0x0000,
- .fh_rx_id = cpu_to_be16(FNIC_UNASSIGNED_RXID),
- .fh_parm_offset = 0x00000000, /* bit:0 = 0 Abort a exchange */
- };
- hton24(s_id, iport->fcid);
- hton24(d_id, tport->fcid);
- FNIC_STD_SET_S_ID(*ptport_abts, s_id);
- FNIC_STD_SET_D_ID(*ptport_abts, d_id);
- tport->flags |= FNIC_FDLS_TGT_ABORT_ISSUED;
- FNIC_STD_SET_OX_ID(*ptport_abts, tport->active_oxid);
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "0x%x: FDLS send tport abts: tport->state: %d ",
- iport->fcid, tport->state);
- fnic_send_fcoe_frame(iport, frame, frame_size);
- /* Even if fnic_send_fcoe_frame() fails we want to retry after timeout */
- fdls_start_tport_timer(iport, tport, 2 * iport->e_d_tov);
- }
- static void fdls_send_fabric_abts(struct fnic_iport_s *iport)
- {
- uint8_t *frame;
- uint8_t s_id[3];
- uint8_t d_id[3];
- struct fnic *fnic = iport->fnic;
- struct fc_frame_header *pfabric_abts;
- uint16_t oxid;
- uint16_t frame_size = FNIC_ETH_FCOE_HDRS_OFFSET +
- sizeof(struct fc_frame_header);
- frame = fdls_alloc_frame(iport);
- if (frame == NULL) {
- FNIC_FCS_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
- "Failed to allocate frame to send fabric ABTS");
- return;
- }
- pfabric_abts = (struct fc_frame_header *) (frame + FNIC_ETH_FCOE_HDRS_OFFSET);
- fdls_init_fabric_abts_frame(frame, iport);
- hton24(s_id, iport->fcid);
- switch (iport->fabric.state) {
- case FDLS_STATE_FABRIC_LOGO:
- hton24(d_id, FC_FID_FLOGI);
- FNIC_STD_SET_D_ID(*pfabric_abts, d_id);
- break;
- case FDLS_STATE_FABRIC_FLOGI:
- hton24(d_id, FC_FID_FLOGI);
- FNIC_STD_SET_D_ID(*pfabric_abts, d_id);
- break;
- case FDLS_STATE_FABRIC_PLOGI:
- FNIC_STD_SET_S_ID(*pfabric_abts, s_id);
- hton24(d_id, FC_FID_DIR_SERV);
- FNIC_STD_SET_D_ID(*pfabric_abts, d_id);
- break;
- case FDLS_STATE_RPN_ID:
- FNIC_STD_SET_S_ID(*pfabric_abts, s_id);
- hton24(d_id, FC_FID_DIR_SERV);
- FNIC_STD_SET_D_ID(*pfabric_abts, d_id);
- break;
- case FDLS_STATE_SCR:
- FNIC_STD_SET_S_ID(*pfabric_abts, s_id);
- hton24(d_id, FC_FID_FCTRL);
- FNIC_STD_SET_D_ID(*pfabric_abts, d_id);
- break;
- case FDLS_STATE_REGISTER_FC4_TYPES:
- FNIC_STD_SET_S_ID(*pfabric_abts, s_id);
- hton24(d_id, FC_FID_DIR_SERV);
- FNIC_STD_SET_D_ID(*pfabric_abts, d_id);
- break;
- case FDLS_STATE_REGISTER_FC4_FEATURES:
- FNIC_STD_SET_S_ID(*pfabric_abts, s_id);
- hton24(d_id, FC_FID_DIR_SERV);
- FNIC_STD_SET_D_ID(*pfabric_abts, d_id);
- break;
- case FDLS_STATE_GPN_FT:
- FNIC_STD_SET_S_ID(*pfabric_abts, s_id);
- hton24(d_id, FC_FID_DIR_SERV);
- FNIC_STD_SET_D_ID(*pfabric_abts, d_id);
- break;
- default:
- return;
- }
- oxid = iport->active_oxid_fabric_req;
- FNIC_STD_SET_OX_ID(*pfabric_abts, oxid);
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "0x%x: FDLS send fabric abts. iport->fabric.state: %d oxid: 0x%x",
- iport->fcid, iport->fabric.state, oxid);
- iport->fabric.flags |= FNIC_FDLS_FABRIC_ABORT_ISSUED;
- fnic_send_fcoe_frame(iport, frame, frame_size);
- /* Even if fnic_send_fcoe_frame() fails we want to retry after timeout */
- fdls_start_fabric_timer(iport, 2 * iport->e_d_tov);
- iport->fabric.timer_pending = 1;
- }
- static uint8_t *fdls_alloc_init_fdmi_abts_frame(struct fnic_iport_s *iport,
- uint16_t oxid)
- {
- struct fc_frame_header *pfdmi_abts;
- uint8_t d_id[3];
- uint8_t *frame;
- struct fnic *fnic = iport->fnic;
- frame = fdls_alloc_frame(iport);
- if (frame == NULL) {
- FNIC_FCS_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
- "Failed to allocate frame to send FDMI ABTS");
- return NULL;
- }
- pfdmi_abts = (struct fc_frame_header *) (frame + FNIC_ETH_FCOE_HDRS_OFFSET);
- fdls_init_fabric_abts_frame(frame, iport);
- hton24(d_id, FC_FID_MGMT_SERV);
- FNIC_STD_SET_D_ID(*pfdmi_abts, d_id);
- FNIC_STD_SET_OX_ID(*pfdmi_abts, oxid);
- return frame;
- }
- static void fdls_send_fdmi_abts(struct fnic_iport_s *iport)
- {
- uint8_t *frame;
- struct fnic *fnic = iport->fnic;
- unsigned long fdmi_tov;
- uint16_t frame_size = FNIC_ETH_FCOE_HDRS_OFFSET +
- sizeof(struct fc_frame_header);
- if (iport->fabric.fdmi_pending & FDLS_FDMI_PLOGI_PENDING) {
- frame = fdls_alloc_init_fdmi_abts_frame(iport,
- iport->active_oxid_fdmi_plogi);
- if (frame == NULL)
- return;
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "0x%x: FDLS send FDMI PLOGI abts. iport->fabric.state: %d oxid: 0x%x",
- iport->fcid, iport->fabric.state, iport->active_oxid_fdmi_plogi);
- fnic_send_fcoe_frame(iport, frame, frame_size);
- } else {
- if (iport->fabric.fdmi_pending & FDLS_FDMI_REG_HBA_PENDING) {
- frame = fdls_alloc_init_fdmi_abts_frame(iport,
- iport->active_oxid_fdmi_rhba);
- if (frame == NULL)
- return;
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "0x%x: FDLS send FDMI RHBA abts. iport->fabric.state: %d oxid: 0x%x",
- iport->fcid, iport->fabric.state, iport->active_oxid_fdmi_rhba);
- fnic_send_fcoe_frame(iport, frame, frame_size);
- }
- if (iport->fabric.fdmi_pending & FDLS_FDMI_RPA_PENDING) {
- frame = fdls_alloc_init_fdmi_abts_frame(iport,
- iport->active_oxid_fdmi_rpa);
- if (frame == NULL) {
- if (iport->fabric.fdmi_pending & FDLS_FDMI_REG_HBA_PENDING)
- goto arm_timer;
- else
- return;
- }
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "0x%x: FDLS send FDMI RPA abts. iport->fabric.state: %d oxid: 0x%x",
- iport->fcid, iport->fabric.state, iport->active_oxid_fdmi_rpa);
- fnic_send_fcoe_frame(iport, frame, frame_size);
- }
- }
- arm_timer:
- fdmi_tov = jiffies + msecs_to_jiffies(2 * iport->e_d_tov);
- mod_timer(&iport->fabric.fdmi_timer, round_jiffies(fdmi_tov));
- iport->fabric.fdmi_pending |= FDLS_FDMI_ABORT_PENDING;
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "0x%x: iport->fabric.fdmi_pending: 0x%x",
- iport->fcid, iport->fabric.fdmi_pending);
- }
- static void fdls_send_fabric_flogi(struct fnic_iport_s *iport)
- {
- uint8_t *frame;
- struct fc_std_flogi *pflogi;
- struct fnic *fnic = iport->fnic;
- uint16_t oxid;
- uint16_t frame_size = FNIC_ETH_FCOE_HDRS_OFFSET +
- sizeof(struct fc_std_flogi);
- frame = fdls_alloc_frame(iport);
- if (frame == NULL) {
- FNIC_FCS_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
- "Failed to allocate frame to send FLOGI");
- iport->fabric.flags |= FNIC_FDLS_RETRY_FRAME;
- goto err_out;
- }
- pflogi = (struct fc_std_flogi *) (frame + FNIC_ETH_FCOE_HDRS_OFFSET);
- *pflogi = (struct fc_std_flogi) {
- .fchdr = {.fh_r_ctl = FC_RCTL_ELS_REQ, .fh_d_id = {0xFF, 0xFF, 0xFE},
- .fh_type = FC_TYPE_ELS, .fh_f_ctl = {FNIC_ELS_REQ_FCTL, 0, 0},
- .fh_rx_id = cpu_to_be16(FNIC_UNASSIGNED_RXID)},
- .els.fl_cmd = ELS_FLOGI,
- .els.fl_csp = {.sp_hi_ver = FNIC_FC_PH_VER_HI,
- .sp_lo_ver = FNIC_FC_PH_VER_LO,
- .sp_bb_cred = cpu_to_be16(FNIC_FC_B2B_CREDIT),
- .sp_bb_data = cpu_to_be16(FNIC_FC_B2B_RDF_SZ)},
- .els.fl_cssp[2].cp_class = cpu_to_be16(FC_CPC_VALID | FC_CPC_SEQ)
- };
- FNIC_STD_SET_NPORT_NAME(&pflogi->els.fl_wwpn, iport->wwpn);
- FNIC_STD_SET_NODE_NAME(&pflogi->els.fl_wwnn, iport->wwnn);
- FNIC_LOGI_SET_RDF_SIZE(pflogi->els, iport->max_payload_size);
- FNIC_LOGI_SET_R_A_TOV(pflogi->els, iport->r_a_tov);
- FNIC_LOGI_SET_E_D_TOV(pflogi->els, iport->e_d_tov);
- oxid = fdls_alloc_oxid(iport, FNIC_FRAME_TYPE_FABRIC_FLOGI,
- &iport->active_oxid_fabric_req);
- if (oxid == FNIC_UNASSIGNED_OXID) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "0x%x: Failed to allocate OXID to send FLOGI",
- iport->fcid);
- mempool_free(frame, fnic->frame_pool);
- iport->fabric.flags |= FNIC_FDLS_RETRY_FRAME;
- goto err_out;
- }
- FNIC_STD_SET_OX_ID(pflogi->fchdr, oxid);
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "0x%x: FDLS send fabric FLOGI with oxid: 0x%x", iport->fcid,
- oxid);
- fnic_send_fcoe_frame(iport, frame, frame_size);
- atomic64_inc(&iport->iport_stats.fabric_flogi_sent);
- err_out:
- /* Even if fnic_send_fcoe_frame() fails we want to retry after timeout */
- fdls_start_fabric_timer(iport, 2 * iport->e_d_tov);
- }
- static void fdls_send_fabric_plogi(struct fnic_iport_s *iport)
- {
- uint8_t *frame;
- struct fc_std_flogi *pplogi;
- struct fnic *fnic = iport->fnic;
- uint16_t oxid;
- uint16_t frame_size = FNIC_ETH_FCOE_HDRS_OFFSET +
- sizeof(struct fc_std_flogi);
- frame = fdls_alloc_frame(iport);
- if (frame == NULL) {
- FNIC_FCS_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
- "Failed to allocate frame to send PLOGI");
- iport->fabric.flags |= FNIC_FDLS_RETRY_FRAME;
- goto err_out;
- }
- pplogi = (struct fc_std_flogi *) (frame + FNIC_ETH_FCOE_HDRS_OFFSET);
- fdls_init_plogi_frame(frame, iport);
- oxid = fdls_alloc_oxid(iport, FNIC_FRAME_TYPE_FABRIC_PLOGI,
- &iport->active_oxid_fabric_req);
- if (oxid == FNIC_UNASSIGNED_OXID) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "0x%x: Failed to allocate OXID to send fabric PLOGI",
- iport->fcid);
- mempool_free(frame, fnic->frame_pool);
- iport->fabric.flags |= FNIC_FDLS_RETRY_FRAME;
- goto err_out;
- }
- FNIC_STD_SET_OX_ID(pplogi->fchdr, oxid);
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "0x%x: FDLS send fabric PLOGI with oxid: 0x%x", iport->fcid,
- oxid);
- fnic_send_fcoe_frame(iport, frame, frame_size);
- atomic64_inc(&iport->iport_stats.fabric_plogi_sent);
- err_out:
- /* Even if fnic_send_fcoe_frame() fails we want to retry after timeout */
- fdls_start_fabric_timer(iport, 2 * iport->e_d_tov);
- }
- static void fdls_send_fdmi_plogi(struct fnic_iport_s *iport)
- {
- uint8_t *frame;
- struct fc_std_flogi *pplogi;
- struct fnic *fnic = iport->fnic;
- uint16_t oxid;
- uint16_t frame_size = FNIC_ETH_FCOE_HDRS_OFFSET +
- sizeof(struct fc_std_flogi);
- uint8_t d_id[3];
- u64 fdmi_tov;
- frame = fdls_alloc_frame(iport);
- if (frame == NULL) {
- FNIC_FCS_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
- "Failed to allocate frame to send FDMI PLOGI");
- goto err_out;
- }
- pplogi = (struct fc_std_flogi *) (frame + FNIC_ETH_FCOE_HDRS_OFFSET);
- fdls_init_plogi_frame(frame, iport);
- oxid = fdls_alloc_oxid(iport, FNIC_FRAME_TYPE_FDMI_PLOGI,
- &iport->active_oxid_fdmi_plogi);
- if (oxid == FNIC_UNASSIGNED_OXID) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "0x%x: Failed to allocate OXID to send FDMI PLOGI",
- iport->fcid);
- mempool_free(frame, fnic->frame_pool);
- goto err_out;
- }
- FNIC_STD_SET_OX_ID(pplogi->fchdr, oxid);
- hton24(d_id, FC_FID_MGMT_SERV);
- FNIC_STD_SET_D_ID(pplogi->fchdr, d_id);
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "0x%x: FDLS send FDMI PLOGI with oxid: 0x%x",
- iport->fcid, oxid);
- fnic_send_fcoe_frame(iport, frame, frame_size);
- err_out:
- fdmi_tov = jiffies + msecs_to_jiffies(2 * iport->e_d_tov);
- mod_timer(&iport->fabric.fdmi_timer, round_jiffies(fdmi_tov));
- iport->fabric.fdmi_pending = FDLS_FDMI_PLOGI_PENDING;
- }
- static void fdls_send_rpn_id(struct fnic_iport_s *iport)
- {
- uint8_t *frame;
- struct fc_std_rpn_id *prpn_id;
- struct fnic *fnic = iport->fnic;
- uint16_t oxid;
- uint16_t frame_size = FNIC_ETH_FCOE_HDRS_OFFSET +
- sizeof(struct fc_std_rpn_id);
- uint8_t fcid[3];
- frame = fdls_alloc_frame(iport);
- if (frame == NULL) {
- FNIC_FCS_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
- "Failed to allocate frame to send RPN_ID");
- iport->fabric.flags |= FNIC_FDLS_RETRY_FRAME;
- goto err_out;
- }
- prpn_id = (struct fc_std_rpn_id *) (frame + FNIC_ETH_FCOE_HDRS_OFFSET);
- *prpn_id = (struct fc_std_rpn_id) {
- .fchdr = {.fh_r_ctl = FC_RCTL_DD_UNSOL_CTL,
- .fh_d_id = {0xFF, 0xFF, 0xFC}, .fh_type = FC_TYPE_CT,
- .fh_f_ctl = {FNIC_ELS_REQ_FCTL, 0, 0},
- .fh_rx_id = cpu_to_be16(FNIC_UNASSIGNED_RXID)},
- .fc_std_ct_hdr = {.ct_rev = FC_CT_REV, .ct_fs_type = FC_FST_DIR,
- .ct_fs_subtype = FC_NS_SUBTYPE,
- .ct_cmd = cpu_to_be16(FC_NS_RPN_ID)}
- };
- hton24(fcid, iport->fcid);
- FNIC_STD_SET_S_ID(prpn_id->fchdr, fcid);
- FNIC_STD_SET_PORT_ID(prpn_id->rpn_id, fcid);
- FNIC_STD_SET_PORT_NAME(prpn_id->rpn_id, iport->wwpn);
- oxid = fdls_alloc_oxid(iport, FNIC_FRAME_TYPE_FABRIC_RPN,
- &iport->active_oxid_fabric_req);
- if (oxid == FNIC_UNASSIGNED_OXID) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "0x%x: Failed to allocate OXID to send RPN_ID",
- iport->fcid);
- mempool_free(frame, fnic->frame_pool);
- iport->fabric.flags |= FNIC_FDLS_RETRY_FRAME;
- goto err_out;
- }
- FNIC_STD_SET_OX_ID(prpn_id->fchdr, oxid);
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "0x%x: FDLS send RPN ID with oxid: 0x%x", iport->fcid,
- oxid);
- fnic_send_fcoe_frame(iport, frame, frame_size);
- err_out:
- /* Even if fnic_send_fcoe_frame() fails we want to retry after timeout */
- fdls_start_fabric_timer(iport, 2 * iport->e_d_tov);
- }
- static void fdls_send_scr(struct fnic_iport_s *iport)
- {
- uint8_t *frame;
- struct fc_std_scr *pscr;
- struct fnic *fnic = iport->fnic;
- uint16_t oxid;
- uint16_t frame_size = FNIC_ETH_FCOE_HDRS_OFFSET +
- sizeof(struct fc_std_scr);
- uint8_t fcid[3];
- frame = fdls_alloc_frame(iport);
- if (frame == NULL) {
- FNIC_FCS_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
- "Failed to allocate frame to send SCR");
- iport->fabric.flags |= FNIC_FDLS_RETRY_FRAME;
- goto err_out;
- }
- pscr = (struct fc_std_scr *) (frame + FNIC_ETH_FCOE_HDRS_OFFSET);
- *pscr = (struct fc_std_scr) {
- .fchdr = {.fh_r_ctl = FC_RCTL_ELS_REQ,
- .fh_d_id = {0xFF, 0xFF, 0xFD}, .fh_type = FC_TYPE_ELS,
- .fh_f_ctl = {FNIC_ELS_REQ_FCTL, 0, 0},
- .fh_rx_id = cpu_to_be16(FNIC_UNASSIGNED_RXID)},
- .scr = {.scr_cmd = ELS_SCR,
- .scr_reg_func = ELS_SCRF_FULL}
- };
- hton24(fcid, iport->fcid);
- FNIC_STD_SET_S_ID(pscr->fchdr, fcid);
- oxid = fdls_alloc_oxid(iport, FNIC_FRAME_TYPE_FABRIC_SCR,
- &iport->active_oxid_fabric_req);
- if (oxid == FNIC_UNASSIGNED_OXID) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "0x%x: Failed to allocate OXID to send SCR",
- iport->fcid);
- mempool_free(frame, fnic->frame_pool);
- iport->fabric.flags |= FNIC_FDLS_RETRY_FRAME;
- goto err_out;
- }
- FNIC_STD_SET_OX_ID(pscr->fchdr, oxid);
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "0x%x: FDLS send SCR with oxid: 0x%x", iport->fcid,
- oxid);
- fnic_send_fcoe_frame(iport, frame, frame_size);
- atomic64_inc(&iport->iport_stats.fabric_scr_sent);
- err_out:
- /* Even if fnic_send_fcoe_frame() fails we want to retry after timeout */
- fdls_start_fabric_timer(iport, 2 * iport->e_d_tov);
- }
- static void fdls_send_gpn_ft(struct fnic_iport_s *iport, int fdls_state)
- {
- uint8_t *frame;
- struct fc_std_gpn_ft *pgpn_ft;
- struct fnic *fnic = iport->fnic;
- uint16_t oxid;
- uint16_t frame_size = FNIC_ETH_FCOE_HDRS_OFFSET +
- sizeof(struct fc_std_gpn_ft);
- uint8_t fcid[3];
- frame = fdls_alloc_frame(iport);
- if (frame == NULL) {
- FNIC_FCS_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
- "Failed to allocate frame to send GPN FT");
- iport->fabric.flags |= FNIC_FDLS_RETRY_FRAME;
- goto err_out;
- }
- pgpn_ft = (struct fc_std_gpn_ft *) (frame + FNIC_ETH_FCOE_HDRS_OFFSET);
- *pgpn_ft = (struct fc_std_gpn_ft) {
- .fchdr = {.fh_r_ctl = FC_RCTL_DD_UNSOL_CTL,
- .fh_d_id = {0xFF, 0xFF, 0xFC}, .fh_type = FC_TYPE_CT,
- .fh_f_ctl = {FNIC_ELS_REQ_FCTL, 0, 0},
- .fh_rx_id = cpu_to_be16(FNIC_UNASSIGNED_RXID)},
- .fc_std_ct_hdr = {.ct_rev = FC_CT_REV, .ct_fs_type = FC_FST_DIR,
- .ct_fs_subtype = FC_NS_SUBTYPE,
- .ct_cmd = cpu_to_be16(FC_NS_GPN_FT)},
- .gpn_ft.fn_fc4_type = 0x08
- };
- hton24(fcid, iport->fcid);
- FNIC_STD_SET_S_ID(pgpn_ft->fchdr, fcid);
- oxid = fdls_alloc_oxid(iport, FNIC_FRAME_TYPE_FABRIC_GPN_FT,
- &iport->active_oxid_fabric_req);
- if (oxid == FNIC_UNASSIGNED_OXID) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "0x%x: Failed to allocate OXID to send GPN FT",
- iport->fcid);
- mempool_free(frame, fnic->frame_pool);
- iport->fabric.flags |= FNIC_FDLS_RETRY_FRAME;
- goto err_out;
- }
- FNIC_STD_SET_OX_ID(pgpn_ft->fchdr, oxid);
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "0x%x: FDLS send GPN FT with oxid: 0x%x", iport->fcid,
- oxid);
- fnic_send_fcoe_frame(iport, frame, frame_size);
- err_out:
- /* Even if fnic_send_fcoe_frame() fails we want to retry after timeout */
- fdls_start_fabric_timer(iport, 2 * iport->e_d_tov);
- fdls_set_state((&iport->fabric), fdls_state);
- }
- static void
- fdls_send_tgt_adisc(struct fnic_iport_s *iport, struct fnic_tport_s *tport)
- {
- uint8_t *frame;
- struct fc_std_els_adisc *padisc;
- uint8_t s_id[3];
- uint8_t d_id[3];
- uint16_t oxid;
- struct fnic *fnic = iport->fnic;
- uint16_t frame_size = FNIC_ETH_FCOE_HDRS_OFFSET +
- sizeof(struct fc_std_els_adisc);
- frame = fdls_alloc_frame(iport);
- if (frame == NULL) {
- FNIC_FCS_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
- "Failed to allocate frame to send TGT ADISC");
- tport->flags |= FNIC_FDLS_RETRY_FRAME;
- goto err_out;
- }
- padisc = (struct fc_std_els_adisc *) (frame + FNIC_ETH_FCOE_HDRS_OFFSET);
- hton24(s_id, iport->fcid);
- hton24(d_id, tport->fcid);
- memcpy(padisc->els.adisc_port_id, s_id, 3);
- FNIC_STD_SET_S_ID(padisc->fchdr, s_id);
- FNIC_STD_SET_D_ID(padisc->fchdr, d_id);
- FNIC_STD_SET_F_CTL(padisc->fchdr, FNIC_ELS_REQ_FCTL << 16);
- FNIC_STD_SET_R_CTL(padisc->fchdr, FC_RCTL_ELS_REQ);
- FNIC_STD_SET_TYPE(padisc->fchdr, FC_TYPE_ELS);
- oxid = fdls_alloc_oxid(iport, FNIC_FRAME_TYPE_TGT_ADISC, &tport->active_oxid);
- if (oxid == FNIC_UNASSIGNED_OXID) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "0x%x: Failed to allocate OXID to send TGT ADISC",
- iport->fcid);
- mempool_free(frame, fnic->frame_pool);
- tport->flags |= FNIC_FDLS_RETRY_FRAME;
- goto err_out;
- }
- FNIC_STD_SET_OX_ID(padisc->fchdr, oxid);
- FNIC_STD_SET_RX_ID(padisc->fchdr, FNIC_UNASSIGNED_RXID);
- tport->flags &= ~FNIC_FDLS_TGT_ABORT_ISSUED;
- FNIC_STD_SET_NPORT_NAME(&padisc->els.adisc_wwpn,
- iport->wwpn);
- FNIC_STD_SET_NODE_NAME(&padisc->els.adisc_wwnn,
- iport->wwnn);
- padisc->els.adisc_cmd = ELS_ADISC;
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "0x%x: FDLS send ADISC to tgt fcid: 0x%x",
- iport->fcid, tport->fcid);
- atomic64_inc(&iport->iport_stats.tport_adisc_sent);
- fnic_send_fcoe_frame(iport, frame, frame_size);
- err_out:
- /* Even if fnic_send_fcoe_frame() fails we want to retry after timeout */
- fdls_start_tport_timer(iport, tport, 2 * iport->e_d_tov);
- }
- bool fdls_delete_tport(struct fnic_iport_s *iport, struct fnic_tport_s *tport)
- {
- struct fnic_tport_event_s *tport_del_evt;
- struct fnic *fnic = iport->fnic;
- if ((tport->state == FDLS_TGT_STATE_OFFLINING)
- || (tport->state == FDLS_TGT_STATE_OFFLINE)) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "tport fcid 0x%x: tport state is offlining/offline\n",
- tport->fcid);
- return false;
- }
- fdls_set_tport_state(tport, FDLS_TGT_STATE_OFFLINING);
- /*
- * By setting this flag, the tport will not be seen in a look-up
- * in an RSCN. Even if we move to multithreaded model, this tport
- * will be destroyed and a new RSCN will have to create a new one
- */
- tport->flags |= FNIC_FDLS_TPORT_TERMINATING;
- if (tport->timer_pending) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "tport fcid 0x%x: Canceling disc timer\n",
- tport->fcid);
- fnic_del_tport_timer_sync(fnic, tport);
- tport->timer_pending = 0;
- }
- spin_unlock_irqrestore(&fnic->fnic_lock, fnic->lock_flags);
- fnic_rport_exch_reset(iport->fnic, tport->fcid);
- spin_lock_irqsave(&fnic->fnic_lock, fnic->lock_flags);
- if (tport->flags & FNIC_FDLS_SCSI_REGISTERED) {
- tport_del_evt =
- kzalloc_obj(struct fnic_tport_event_s, GFP_ATOMIC);
- if (!tport_del_evt) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "Failed to allocate memory for tport fcid: 0x%0x\n",
- tport->fcid);
- return false;
- }
- tport_del_evt->event = TGT_EV_RPORT_DEL;
- tport_del_evt->arg1 = (void *) tport;
- list_add_tail(&tport_del_evt->links, &fnic->tport_event_list);
- queue_work(fnic_event_queue, &fnic->tport_work);
- } else {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "tport 0x%x not reg with scsi_transport. Freeing locally",
- tport->fcid);
- list_del(&tport->links);
- kfree(tport);
- }
- return true;
- }
- static void
- fdls_send_tgt_plogi(struct fnic_iport_s *iport, struct fnic_tport_s *tport)
- {
- uint8_t *frame;
- struct fc_std_flogi *pplogi;
- struct fnic *fnic = iport->fnic;
- uint16_t oxid;
- uint16_t frame_size = FNIC_ETH_FCOE_HDRS_OFFSET +
- sizeof(struct fc_std_flogi);
- uint8_t d_id[3];
- uint32_t timeout;
- frame = fdls_alloc_frame(iport);
- if (frame == NULL) {
- FNIC_FCS_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
- "Failed to allocate frame to send TGT PLOGI");
- tport->flags |= FNIC_FDLS_RETRY_FRAME;
- goto err_out;
- }
- pplogi = (struct fc_std_flogi *) (frame + FNIC_ETH_FCOE_HDRS_OFFSET);
- fdls_init_plogi_frame(frame, iport);
- oxid = fdls_alloc_oxid(iport, FNIC_FRAME_TYPE_TGT_PLOGI, &tport->active_oxid);
- if (oxid == FNIC_UNASSIGNED_OXID) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "0x%x: Failed to allocate oxid to send PLOGI to fcid: 0x%x",
- iport->fcid, tport->fcid);
- mempool_free(frame, fnic->frame_pool);
- tport->flags |= FNIC_FDLS_RETRY_FRAME;
- goto err_out;
- }
- FNIC_STD_SET_OX_ID(pplogi->fchdr, oxid);
- tport->flags &= ~FNIC_FDLS_TGT_ABORT_ISSUED;
- hton24(d_id, tport->fcid);
- FNIC_STD_SET_D_ID(pplogi->fchdr, d_id);
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "0x%x: FDLS send tgt PLOGI to tgt: 0x%x with oxid: 0x%x",
- iport->fcid, tport->fcid, oxid);
- fnic_send_fcoe_frame(iport, frame, frame_size);
- atomic64_inc(&iport->iport_stats.tport_plogi_sent);
- err_out:
- timeout = max(2 * iport->e_d_tov, iport->plogi_timeout);
- /* Even if fnic_send_fcoe_frame() fails we want to retry after timeout */
- fdls_start_tport_timer(iport, tport, timeout);
- }
- static uint16_t
- fnic_fc_plogi_rsp_rdf(struct fnic_iport_s *iport,
- struct fc_std_flogi *plogi_rsp)
- {
- uint16_t b2b_rdf_size =
- be16_to_cpu(FNIC_LOGI_RDF_SIZE(plogi_rsp->els));
- uint16_t spc3_rdf_size =
- be16_to_cpu(plogi_rsp->els.fl_cssp[2].cp_rdfs) & FNIC_FC_C3_RDF;
- struct fnic *fnic = iport->fnic;
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "MFS: b2b_rdf_size: 0x%x spc3_rdf_size: 0x%x",
- b2b_rdf_size, spc3_rdf_size);
- return min(b2b_rdf_size, spc3_rdf_size);
- }
- static void fdls_send_register_fc4_types(struct fnic_iport_s *iport)
- {
- uint8_t *frame;
- struct fc_std_rft_id *prft_id;
- struct fnic *fnic = iport->fnic;
- uint16_t oxid;
- uint16_t frame_size = FNIC_ETH_FCOE_HDRS_OFFSET +
- sizeof(struct fc_std_rft_id);
- uint8_t fcid[3];
- frame = fdls_alloc_frame(iport);
- if (frame == NULL) {
- FNIC_FCS_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
- "Failed to allocate frame to send RFT");
- return;
- }
- prft_id = (struct fc_std_rft_id *) (frame + FNIC_ETH_FCOE_HDRS_OFFSET);
- *prft_id = (struct fc_std_rft_id) {
- .fchdr = {.fh_r_ctl = FC_RCTL_DD_UNSOL_CTL,
- .fh_d_id = {0xFF, 0xFF, 0xFC}, .fh_type = FC_TYPE_CT,
- .fh_f_ctl = {FNIC_ELS_REQ_FCTL, 0, 0},
- .fh_rx_id = cpu_to_be16(FNIC_UNASSIGNED_RXID)},
- .fc_std_ct_hdr = {.ct_rev = FC_CT_REV, .ct_fs_type = FC_FST_DIR,
- .ct_fs_subtype = FC_NS_SUBTYPE,
- .ct_cmd = cpu_to_be16(FC_NS_RFT_ID)}
- };
- hton24(fcid, iport->fcid);
- FNIC_STD_SET_S_ID(prft_id->fchdr, fcid);
- FNIC_STD_SET_PORT_ID(prft_id->rft_id, fcid);
- oxid = fdls_alloc_oxid(iport, FNIC_FRAME_TYPE_FABRIC_RFT,
- &iport->active_oxid_fabric_req);
- if (oxid == FNIC_UNASSIGNED_OXID) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "0x%x: Failed to allocate OXID to send RFT",
- iport->fcid);
- mempool_free(frame, fnic->frame_pool);
- return;
- }
- FNIC_STD_SET_OX_ID(prft_id->fchdr, oxid);
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "0x%x: FDLS send RFT with oxid: 0x%x", iport->fcid,
- oxid);
- prft_id->rft_id.fr_fts.ff_type_map[0] =
- cpu_to_be32(1 << FC_TYPE_FCP);
- prft_id->rft_id.fr_fts.ff_type_map[1] =
- cpu_to_be32(1 << (FC_TYPE_CT % FC_NS_BPW));
- fnic_send_fcoe_frame(iport, frame, frame_size);
- /* Even if fnic_send_fcoe_frame() fails we want to retry after timeout */
- fdls_start_fabric_timer(iport, 2 * iport->e_d_tov);
- }
- static void fdls_send_register_fc4_features(struct fnic_iport_s *iport)
- {
- uint8_t *frame;
- struct fc_std_rff_id *prff_id;
- struct fnic *fnic = iport->fnic;
- uint16_t oxid;
- uint16_t frame_size = FNIC_ETH_FCOE_HDRS_OFFSET +
- sizeof(struct fc_std_rff_id);
- uint8_t fcid[3];
- frame = fdls_alloc_frame(iport);
- if (frame == NULL) {
- FNIC_FCS_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
- "Failed to allocate frame to send RFF");
- return;
- }
- prff_id = (struct fc_std_rff_id *) (frame + FNIC_ETH_FCOE_HDRS_OFFSET);
- *prff_id = (struct fc_std_rff_id) {
- .fchdr = {.fh_r_ctl = FC_RCTL_DD_UNSOL_CTL,
- .fh_d_id = {0xFF, 0xFF, 0xFC}, .fh_type = FC_TYPE_CT,
- .fh_f_ctl = {FNIC_ELS_REQ_FCTL, 0, 0},
- .fh_rx_id = cpu_to_be16(FNIC_UNASSIGNED_RXID)},
- .fc_std_ct_hdr = {.ct_rev = FC_CT_REV, .ct_fs_type = FC_FST_DIR,
- .ct_fs_subtype = FC_NS_SUBTYPE,
- .ct_cmd = cpu_to_be16(FC_NS_RFF_ID)},
- .rff_id.fr_feat = 0x2,
- .rff_id.fr_type = FC_TYPE_FCP
- };
- hton24(fcid, iport->fcid);
- FNIC_STD_SET_S_ID(prff_id->fchdr, fcid);
- FNIC_STD_SET_PORT_ID(prff_id->rff_id, fcid);
- oxid = fdls_alloc_oxid(iport, FNIC_FRAME_TYPE_FABRIC_RFF,
- &iport->active_oxid_fabric_req);
- if (oxid == FNIC_UNASSIGNED_OXID) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "0x%x: Failed to allocate OXID to send RFF",
- iport->fcid);
- mempool_free(frame, fnic->frame_pool);
- return;
- }
- FNIC_STD_SET_OX_ID(prff_id->fchdr, oxid);
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "0x%x: FDLS send RFF with oxid: 0x%x", iport->fcid,
- oxid);
- prff_id->rff_id.fr_type = FC_TYPE_FCP;
- fnic_send_fcoe_frame(iport, frame, frame_size);
- /* Even if fnic_send_fcoe_frame() fails we want to retry after timeout */
- fdls_start_fabric_timer(iport, 2 * iport->e_d_tov);
- }
- static void
- fdls_send_tgt_prli(struct fnic_iport_s *iport, struct fnic_tport_s *tport)
- {
- uint8_t *frame;
- struct fc_std_els_prli *pprli;
- struct fnic *fnic = iport->fnic;
- uint16_t oxid;
- uint16_t frame_size = FNIC_ETH_FCOE_HDRS_OFFSET +
- sizeof(struct fc_std_els_prli);
- uint8_t s_id[3];
- uint8_t d_id[3];
- uint32_t timeout;
- frame = fdls_alloc_frame(iport);
- if (frame == NULL) {
- FNIC_FCS_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
- "Failed to allocate frame to send TGT PRLI");
- tport->flags |= FNIC_FDLS_RETRY_FRAME;
- goto err_out;
- }
- pprli = (struct fc_std_els_prli *) (frame + FNIC_ETH_FCOE_HDRS_OFFSET);
- *pprli = (struct fc_std_els_prli) {
- .fchdr = {.fh_r_ctl = FC_RCTL_ELS_REQ, .fh_type = FC_TYPE_ELS,
- .fh_f_ctl = {FNIC_ELS_REQ_FCTL, 0, 0},
- .fh_rx_id = cpu_to_be16(FNIC_UNASSIGNED_RXID)},
- .els_prli = {.prli_cmd = ELS_PRLI,
- .prli_spp_len = 16,
- .prli_len = cpu_to_be16(0x14)},
- .sp = {.spp_type = 0x08, .spp_flags = 0x0020,
- .spp_params = cpu_to_be32(0xA2)}
- };
- oxid = fdls_alloc_oxid(iport, FNIC_FRAME_TYPE_TGT_PRLI, &tport->active_oxid);
- if (oxid == FNIC_UNASSIGNED_OXID) {
- FNIC_FCS_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
- "0x%x: Failed to allocate OXID to send TGT PRLI to 0x%x",
- iport->fcid, tport->fcid);
- mempool_free(frame, fnic->frame_pool);
- tport->flags |= FNIC_FDLS_RETRY_FRAME;
- goto err_out;
- }
- tport->flags &= ~FNIC_FDLS_TGT_ABORT_ISSUED;
- hton24(s_id, iport->fcid);
- hton24(d_id, tport->fcid);
- FNIC_STD_SET_OX_ID(pprli->fchdr, oxid);
- FNIC_STD_SET_S_ID(pprli->fchdr, s_id);
- FNIC_STD_SET_D_ID(pprli->fchdr, d_id);
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "0x%x: FDLS send PRLI to tgt: 0x%x with oxid: 0x%x",
- iport->fcid, tport->fcid, oxid);
- fnic_send_fcoe_frame(iport, frame, frame_size);
- atomic64_inc(&iport->iport_stats.tport_prli_sent);
- err_out:
- timeout = max(2 * iport->e_d_tov, iport->plogi_timeout);
- /* Even if fnic_send_fcoe_frame() fails we want to retry after timeout */
- fdls_start_tport_timer(iport, tport, timeout);
- }
- /**
- * fdls_send_fabric_logo - Send flogo to the fcf
- * @iport: Handle to fnic iport
- *
- * This function does not change or check the fabric state.
- * It the caller's responsibility to set the appropriate iport fabric
- * state when this is called. Normally it is FDLS_STATE_FABRIC_LOGO.
- * Currently this assumes to be called with fnic lock held.
- */
- void fdls_send_fabric_logo(struct fnic_iport_s *iport)
- {
- uint8_t *frame;
- struct fc_std_logo *plogo;
- struct fnic *fnic = iport->fnic;
- uint8_t d_id[3];
- uint16_t oxid;
- uint16_t frame_size = FNIC_ETH_FCOE_HDRS_OFFSET +
- sizeof(struct fc_std_logo);
- frame = fdls_alloc_frame(iport);
- if (frame == NULL) {
- FNIC_FCS_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
- "Failed to allocate frame to send fabric LOGO");
- return;
- }
- plogo = (struct fc_std_logo *) (frame + FNIC_ETH_FCOE_HDRS_OFFSET);
- fdls_init_logo_frame(frame, iport);
- oxid = fdls_alloc_oxid(iport, FNIC_FRAME_TYPE_FABRIC_LOGO,
- &iport->active_oxid_fabric_req);
- if (oxid == FNIC_UNASSIGNED_OXID) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "0x%x: Failed to allocate OXID to send fabric LOGO",
- iport->fcid);
- mempool_free(frame, fnic->frame_pool);
- return;
- }
- FNIC_STD_SET_OX_ID(plogo->fchdr, oxid);
- hton24(d_id, FC_FID_FLOGI);
- FNIC_STD_SET_D_ID(plogo->fchdr, d_id);
- iport->fabric.flags &= ~FNIC_FDLS_FABRIC_ABORT_ISSUED;
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "0x%x: FDLS send fabric LOGO with oxid: 0x%x",
- iport->fcid, oxid);
- fnic_send_fcoe_frame(iport, frame, frame_size);
- fdls_start_fabric_timer(iport, 2 * iport->e_d_tov);
- }
- /**
- * fdls_tgt_logout - Send plogo to the remote port
- * @iport: Handle to fnic iport
- * @tport: Handle to remote port
- *
- * This function does not change or check the fabric/tport state.
- * It the caller's responsibility to set the appropriate tport/fabric
- * state when this is called. Normally that is fdls_tgt_state_plogo.
- * This could be used to send plogo to nameserver process
- * also not just target processes
- */
- void fdls_tgt_logout(struct fnic_iport_s *iport, struct fnic_tport_s *tport)
- {
- uint8_t *frame;
- struct fc_std_logo *plogo;
- struct fnic *fnic = iport->fnic;
- uint8_t d_id[3];
- uint16_t oxid;
- uint16_t frame_size = FNIC_ETH_FCOE_HDRS_OFFSET +
- sizeof(struct fc_std_logo);
- frame = fdls_alloc_frame(iport);
- if (frame == NULL) {
- FNIC_FCS_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
- "Failed to allocate frame to send fabric LOGO");
- return;
- }
- plogo = (struct fc_std_logo *) (frame + FNIC_ETH_FCOE_HDRS_OFFSET);
- fdls_init_logo_frame(frame, iport);
- oxid = fdls_alloc_oxid(iport, FNIC_FRAME_TYPE_TGT_LOGO, &tport->active_oxid);
- if (oxid == FNIC_UNASSIGNED_OXID) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "0x%x: Failed to allocate OXID to send tgt LOGO",
- iport->fcid);
- mempool_free(frame, fnic->frame_pool);
- return;
- }
- FNIC_STD_SET_OX_ID(plogo->fchdr, oxid);
- hton24(d_id, tport->fcid);
- FNIC_STD_SET_D_ID(plogo->fchdr, d_id);
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "0x%x: FDLS send tgt LOGO with oxid: 0x%x",
- iport->fcid, oxid);
- fnic_send_fcoe_frame(iport, frame, frame_size);
- atomic64_inc(&iport->iport_stats.tport_logo_sent);
- }
- static void fdls_tgt_discovery_start(struct fnic_iport_s *iport)
- {
- struct fnic_tport_s *tport, *next;
- u32 old_link_down_cnt = iport->fnic->link_down_cnt;
- struct fnic *fnic = iport->fnic;
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "0x%x: Starting FDLS target discovery", iport->fcid);
- list_for_each_entry_safe(tport, next, &iport->tport_list, links) {
- if ((old_link_down_cnt != iport->fnic->link_down_cnt)
- || (iport->state != FNIC_IPORT_STATE_READY)) {
- break;
- }
- /* if we marked the tport as deleted due to GPN_FT
- * We should not send ADISC anymore
- */
- if ((tport->state == FDLS_TGT_STATE_OFFLINING) ||
- (tport->state == FDLS_TGT_STATE_OFFLINE))
- continue;
- /* For tports which have received RSCN */
- if (tport->flags & FNIC_FDLS_TPORT_SEND_ADISC) {
- tport->retry_counter = 0;
- fdls_set_tport_state(tport, FDLS_TGT_STATE_ADISC);
- tport->flags &= ~FNIC_FDLS_TPORT_SEND_ADISC;
- fdls_send_tgt_adisc(iport, tport);
- continue;
- }
- if (fdls_get_tport_state(tport) != FDLS_TGT_STATE_INIT) {
- /* Not a new port, skip */
- continue;
- }
- tport->retry_counter = 0;
- fdls_set_tport_state(tport, FDLS_TGT_STATE_PLOGI);
- fdls_send_tgt_plogi(iport, tport);
- }
- fdls_set_state((&iport->fabric), FDLS_STATE_TGT_DISCOVERY);
- }
- /*
- * Function to restart the IT nexus if we received any out of
- * sequence PLOGI/PRLI response from the target.
- * The memory for the new tport structure is allocated
- * inside fdls_create_tport and added to the iport's tport list.
- * This will get freed later during tport_offline/linkdown
- * or module unload. The new_tport pointer will go out of scope
- * safely since the memory it is
- * pointing to it will be freed later
- */
- static void fdls_target_restart_nexus(struct fnic_tport_s *tport)
- {
- struct fnic_iport_s *iport = tport->iport;
- struct fnic_tport_s *new_tport = NULL;
- uint32_t fcid;
- uint64_t wwpn;
- int nexus_restart_count;
- struct fnic *fnic = iport->fnic;
- bool retval = true;
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "tport fcid: 0x%x state: %d restart_count: %d",
- tport->fcid, tport->state, tport->nexus_restart_count);
- fcid = tport->fcid;
- wwpn = tport->wwpn;
- nexus_restart_count = tport->nexus_restart_count;
- retval = fdls_delete_tport(iport, tport);
- if (retval != true) {
- FNIC_FCS_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
- "Error deleting tport: 0x%x", fcid);
- return;
- }
- if (nexus_restart_count >= FNIC_TPORT_MAX_NEXUS_RESTART) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "Exceeded nexus restart retries tport: 0x%x",
- fcid);
- return;
- }
- /*
- * Allocate memory for the new tport and add it to
- * iport's tport list.
- * This memory will be freed during tport_offline/linkdown
- * or module unload. The pointer new_tport is safe to go
- * out of scope when this function returns, since the memory
- * it is pointing to is guaranteed to be freed later
- * as mentioned above.
- */
- new_tport = fdls_create_tport(iport, fcid, wwpn);
- if (!new_tport) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "Error creating new tport: 0x%x", fcid);
- return;
- }
- new_tport->nexus_restart_count = nexus_restart_count + 1;
- fdls_send_tgt_plogi(iport, new_tport);
- fdls_set_tport_state(new_tport, FDLS_TGT_STATE_PLOGI);
- }
- struct fnic_tport_s *fnic_find_tport_by_fcid(struct fnic_iport_s *iport,
- uint32_t fcid)
- {
- struct fnic_tport_s *tport, *next;
- list_for_each_entry_safe(tport, next, &(iport->tport_list), links) {
- if ((tport->fcid == fcid)
- && !(tport->flags & FNIC_FDLS_TPORT_TERMINATING))
- return tport;
- }
- return NULL;
- }
- static struct fnic_tport_s *fdls_create_tport(struct fnic_iport_s *iport,
- uint32_t fcid, uint64_t wwpn)
- {
- struct fnic_tport_s *tport;
- struct fnic *fnic = iport->fnic;
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "FDLS create tport: fcid: 0x%x wwpn: 0x%llx", fcid, wwpn);
- tport = kzalloc_obj(struct fnic_tport_s, GFP_ATOMIC);
- if (!tport) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "Memory allocation failure while creating tport: 0x%x\n",
- fcid);
- return NULL;
- }
- tport->max_payload_size = FNIC_FCOE_MAX_FRAME_SZ;
- tport->r_a_tov = FC_DEF_R_A_TOV;
- tport->e_d_tov = FC_DEF_E_D_TOV;
- tport->fcid = fcid;
- tport->wwpn = wwpn;
- tport->iport = iport;
- FNIC_FCS_DBG(KERN_DEBUG, fnic->host, fnic->fnic_num,
- "Need to setup tport timer callback");
- timer_setup(&tport->retry_timer, fdls_tport_timer_callback, 0);
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "Added tport 0x%x", tport->fcid);
- fdls_set_tport_state(tport, FDLS_TGT_STATE_INIT);
- list_add_tail(&tport->links, &iport->tport_list);
- atomic_set(&tport->in_flight, 0);
- return tport;
- }
- struct fnic_tport_s *fnic_find_tport_by_wwpn(struct fnic_iport_s *iport,
- uint64_t wwpn)
- {
- struct fnic_tport_s *tport, *next;
- list_for_each_entry_safe(tport, next, &(iport->tport_list), links) {
- if ((tport->wwpn == wwpn)
- && !(tport->flags & FNIC_FDLS_TPORT_TERMINATING))
- return tport;
- }
- return NULL;
- }
- static void
- fnic_fdmi_attr_set(void *attr_start, u16 type, u16 len,
- void *data, u32 *off)
- {
- u16 size = len + FC_FDMI_ATTR_ENTRY_HEADER_LEN;
- struct fc_fdmi_attr_entry *fdmi_attr = (struct fc_fdmi_attr_entry *)
- ((u8 *)attr_start + *off);
- put_unaligned_be16(type, &fdmi_attr->type);
- put_unaligned_be16(size, &fdmi_attr->len);
- memcpy(fdmi_attr->value, data, len);
- *off += size;
- }
- static void fdls_fdmi_register_hba(struct fnic_iport_s *iport)
- {
- uint8_t *frame;
- struct fc_std_fdmi_rhba *prhba;
- struct fc_fdmi_attr_entry *fdmi_attr;
- uint8_t fcid[3];
- int err;
- struct fnic *fnic = iport->fnic;
- struct vnic_devcmd_fw_info *fw_info = NULL;
- uint16_t oxid;
- u32 attr_off_bytes, len;
- u8 data[64];
- uint16_t frame_size = FNIC_ETH_FCOE_HDRS_OFFSET;
- frame = fdls_alloc_frame(iport);
- if (frame == NULL) {
- FNIC_FCS_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
- "Failed to allocate frame to send FDMI RHBA");
- return;
- }
- prhba = (struct fc_std_fdmi_rhba *) (frame + FNIC_ETH_FCOE_HDRS_OFFSET);
- *prhba = (struct fc_std_fdmi_rhba) {
- .fchdr = {
- .fh_r_ctl = FC_RCTL_DD_UNSOL_CTL,
- .fh_d_id = {0xFF, 0XFF, 0XFA},
- .fh_type = FC_TYPE_CT,
- .fh_f_ctl = {FNIC_ELS_REQ_FCTL, 0, 0},
- .fh_rx_id = cpu_to_be16(FNIC_UNASSIGNED_RXID)
- },
- .fc_std_ct_hdr = {
- .ct_rev = FC_CT_REV, .ct_fs_type = FC_FST_MGMT,
- .ct_fs_subtype = FC_FDMI_SUBTYPE,
- .ct_cmd = cpu_to_be16(FC_FDMI_RHBA)
- },
- };
- hton24(fcid, iport->fcid);
- FNIC_STD_SET_S_ID(prhba->fchdr, fcid);
- oxid = fdls_alloc_oxid(iport, FNIC_FRAME_TYPE_FDMI_RHBA,
- &iport->active_oxid_fdmi_rhba);
- if (oxid == FNIC_UNASSIGNED_OXID) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "0x%x: Failed to allocate OXID to send FDMI RHBA",
- iport->fcid);
- mempool_free(frame, fnic->frame_pool);
- return;
- }
- FNIC_STD_SET_OX_ID(prhba->fchdr, oxid);
- put_unaligned_be64(iport->wwpn, &prhba->rhba.hbaid.id);
- put_unaligned_be32(FNIC_FDMI_NUM_PORTS, &prhba->rhba.port.numport);
- put_unaligned_be64(iport->wwpn, &prhba->rhba.port.port[0].portname);
- put_unaligned_be32(FNIC_FDMI_NUM_HBA_ATTRS,
- &prhba->rhba.hba_attrs.numattrs);
- fdmi_attr = prhba->rhba.hba_attrs.attr;
- attr_off_bytes = 0;
- put_unaligned_be64(iport->wwnn, data);
- fnic_fdmi_attr_set(fdmi_attr, FNIC_FDMI_TYPE_NODE_NAME,
- FNIC_FDMI_NN_LEN, data, &attr_off_bytes);
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "NN set, off=%d", attr_off_bytes);
- strscpy_pad(data, FNIC_FDMI_MANUFACTURER, FNIC_FDMI_MANU_LEN);
- fnic_fdmi_attr_set(fdmi_attr, FNIC_FDMI_TYPE_MANUFACTURER,
- FNIC_FDMI_MANU_LEN, data, &attr_off_bytes);
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "MFG set <%s>, off=%d", data, attr_off_bytes);
- err = vnic_dev_fw_info(fnic->vdev, &fw_info);
- if (!err) {
- strscpy_pad(data, fw_info->hw_serial_number,
- FNIC_FDMI_SERIAL_LEN);
- fnic_fdmi_attr_set(fdmi_attr, FNIC_FDMI_TYPE_SERIAL_NUMBER,
- FNIC_FDMI_SERIAL_LEN, data, &attr_off_bytes);
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "SERIAL set <%s>, off=%d", data, attr_off_bytes);
- }
- if (fnic->subsys_desc_len >= FNIC_FDMI_MODEL_LEN)
- fnic->subsys_desc_len = FNIC_FDMI_MODEL_LEN - 1;
- strscpy_pad(data, fnic->subsys_desc, FNIC_FDMI_MODEL_LEN);
- fnic_fdmi_attr_set(fdmi_attr, FNIC_FDMI_TYPE_MODEL, FNIC_FDMI_MODEL_LEN,
- data, &attr_off_bytes);
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "MODEL set <%s>, off=%d", data, attr_off_bytes);
- strscpy_pad(data, FNIC_FDMI_MODEL_DESCRIPTION, FNIC_FDMI_MODEL_DES_LEN);
- fnic_fdmi_attr_set(fdmi_attr, FNIC_FDMI_TYPE_MODEL_DES,
- FNIC_FDMI_MODEL_DES_LEN, data, &attr_off_bytes);
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "MODEL_DESC set <%s>, off=%d", data, attr_off_bytes);
- if (!err) {
- strscpy_pad(data, fw_info->hw_version, FNIC_FDMI_HW_VER_LEN);
- fnic_fdmi_attr_set(fdmi_attr, FNIC_FDMI_TYPE_HARDWARE_VERSION,
- FNIC_FDMI_HW_VER_LEN, data, &attr_off_bytes);
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "HW_VER set <%s>, off=%d", data, attr_off_bytes);
- }
- strscpy_pad(data, DRV_VERSION, FNIC_FDMI_DR_VER_LEN);
- fnic_fdmi_attr_set(fdmi_attr, FNIC_FDMI_TYPE_DRIVER_VERSION,
- FNIC_FDMI_DR_VER_LEN, data, &attr_off_bytes);
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "DRV_VER set <%s>, off=%d", data, attr_off_bytes);
- strscpy_pad(data, "N/A", FNIC_FDMI_ROM_VER_LEN);
- fnic_fdmi_attr_set(fdmi_attr, FNIC_FDMI_TYPE_ROM_VERSION,
- FNIC_FDMI_ROM_VER_LEN, data, &attr_off_bytes);
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "ROM_VER set <%s>, off=%d", data, attr_off_bytes);
- if (!err) {
- strscpy_pad(data, fw_info->fw_version, FNIC_FDMI_FW_VER_LEN);
- fnic_fdmi_attr_set(fdmi_attr, FNIC_FDMI_TYPE_FIRMWARE_VERSION,
- FNIC_FDMI_FW_VER_LEN, data, &attr_off_bytes);
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "FW_VER set <%s>, off=%d", data, attr_off_bytes);
- }
- len = sizeof(struct fc_std_fdmi_rhba) + attr_off_bytes;
- frame_size += len;
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "0x%x: FDLS send FDMI RHBA with oxid: 0x%x fs: %d", iport->fcid,
- oxid, frame_size);
- fnic_send_fcoe_frame(iport, frame, frame_size);
- iport->fabric.fdmi_pending |= FDLS_FDMI_REG_HBA_PENDING;
- }
- static void fdls_fdmi_register_pa(struct fnic_iport_s *iport)
- {
- uint8_t *frame;
- struct fc_std_fdmi_rpa *prpa;
- struct fc_fdmi_attr_entry *fdmi_attr;
- uint8_t fcid[3];
- struct fnic *fnic = iport->fnic;
- u32 port_speed_bm;
- u32 port_speed = vnic_dev_port_speed(fnic->vdev);
- uint16_t oxid;
- u32 attr_off_bytes, len;
- u8 tmp_data[16], data[64];
- uint16_t frame_size = FNIC_ETH_FCOE_HDRS_OFFSET;
- frame = fdls_alloc_frame(iport);
- if (frame == NULL) {
- FNIC_FCS_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
- "Failed to allocate frame to send FDMI RPA");
- return;
- }
- prpa = (struct fc_std_fdmi_rpa *) (frame + FNIC_ETH_FCOE_HDRS_OFFSET);
- *prpa = (struct fc_std_fdmi_rpa) {
- .fchdr = {
- .fh_r_ctl = FC_RCTL_DD_UNSOL_CTL,
- .fh_d_id = {0xFF, 0xFF, 0xFA},
- .fh_type = FC_TYPE_CT,
- .fh_f_ctl = {FNIC_ELS_REQ_FCTL, 0, 0},
- .fh_rx_id = cpu_to_be16(FNIC_UNASSIGNED_RXID)
- },
- .fc_std_ct_hdr = {
- .ct_rev = FC_CT_REV, .ct_fs_type = FC_FST_MGMT,
- .ct_fs_subtype = FC_FDMI_SUBTYPE,
- .ct_cmd = cpu_to_be16(FC_FDMI_RPA)
- },
- };
- hton24(fcid, iport->fcid);
- FNIC_STD_SET_S_ID(prpa->fchdr, fcid);
- oxid = fdls_alloc_oxid(iport, FNIC_FRAME_TYPE_FDMI_RPA,
- &iport->active_oxid_fdmi_rpa);
- if (oxid == FNIC_UNASSIGNED_OXID) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "0x%x: Failed to allocate OXID to send FDMI RPA",
- iport->fcid);
- mempool_free(frame, fnic->frame_pool);
- return;
- }
- FNIC_STD_SET_OX_ID(prpa->fchdr, oxid);
- put_unaligned_be64(iport->wwpn, &prpa->rpa.port.portname);
- put_unaligned_be32(FNIC_FDMI_NUM_PORT_ATTRS,
- &prpa->rpa.hba_attrs.numattrs);
- /* MDS does not support GIGE speed.
- * Bit shift standard definitions from scsi_transport_fc.h to
- * match FC spec.
- */
- switch (port_speed) {
- case DCEM_PORTSPEED_10G:
- case DCEM_PORTSPEED_20G:
- /* There is no bit for 20G */
- port_speed_bm = FC_PORTSPEED_10GBIT << PORT_SPEED_BIT_14;
- break;
- case DCEM_PORTSPEED_25G:
- port_speed_bm = FC_PORTSPEED_25GBIT << PORT_SPEED_BIT_8;
- break;
- case DCEM_PORTSPEED_40G:
- case DCEM_PORTSPEED_4x10G:
- port_speed_bm = FC_PORTSPEED_40GBIT << PORT_SPEED_BIT_9;
- break;
- case DCEM_PORTSPEED_100G:
- port_speed_bm = FC_PORTSPEED_100GBIT << PORT_SPEED_BIT_8;
- break;
- default:
- port_speed_bm = FC_PORTSPEED_1GBIT << PORT_SPEED_BIT_15;
- break;
- }
- attr_off_bytes = 0;
- fdmi_attr = prpa->rpa.hba_attrs.attr;
- put_unaligned_be64(iport->wwnn, data);
- memset(data, 0, FNIC_FDMI_FC4_LEN);
- data[2] = 1;
- fnic_fdmi_attr_set(fdmi_attr, FNIC_FDMI_TYPE_FC4_TYPES,
- FNIC_FDMI_FC4_LEN, data, &attr_off_bytes);
- put_unaligned_be32(port_speed_bm, data);
- fnic_fdmi_attr_set(fdmi_attr, FNIC_FDMI_TYPE_SUPPORTED_SPEEDS,
- FNIC_FDMI_SUPP_SPEED_LEN, data, &attr_off_bytes);
- put_unaligned_be32(port_speed_bm, data);
- fnic_fdmi_attr_set(fdmi_attr, FNIC_FDMI_TYPE_CURRENT_SPEED,
- FNIC_FDMI_CUR_SPEED_LEN, data, &attr_off_bytes);
- put_unaligned_be32(FNIC_FDMI_MFS, data);
- fnic_fdmi_attr_set(fdmi_attr, FNIC_FDMI_TYPE_MAX_FRAME_SIZE,
- FNIC_FDMI_MFS_LEN, data, &attr_off_bytes);
- snprintf(tmp_data, FNIC_FDMI_OS_NAME_LEN - 1, "host%d",
- fnic->host->host_no);
- strscpy_pad(data, tmp_data, FNIC_FDMI_OS_NAME_LEN);
- fnic_fdmi_attr_set(fdmi_attr, FNIC_FDMI_TYPE_OS_NAME,
- FNIC_FDMI_OS_NAME_LEN, data, &attr_off_bytes);
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "OS name set <%s>, off=%d", data, attr_off_bytes);
- sprintf(fc_host_system_hostname(fnic->host), "%s", utsname()->nodename);
- strscpy_pad(data, fc_host_system_hostname(fnic->host),
- FNIC_FDMI_HN_LEN);
- fnic_fdmi_attr_set(fdmi_attr, FNIC_FDMI_TYPE_HOST_NAME,
- FNIC_FDMI_HN_LEN, data, &attr_off_bytes);
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "Host name set <%s>, off=%d", data, attr_off_bytes);
- len = sizeof(struct fc_std_fdmi_rpa) + attr_off_bytes;
- frame_size += len;
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "0x%x: FDLS send FDMI RPA with oxid: 0x%x fs: %d", iport->fcid,
- oxid, frame_size);
- fnic_send_fcoe_frame(iport, frame, frame_size);
- iport->fabric.fdmi_pending |= FDLS_FDMI_RPA_PENDING;
- }
- void fdls_fabric_timer_callback(struct timer_list *t)
- {
- struct fnic_fdls_fabric_s *fabric = timer_container_of(fabric, t,
- retry_timer);
- struct fnic_iport_s *iport =
- container_of(fabric, struct fnic_iport_s, fabric);
- struct fnic *fnic = iport->fnic;
- unsigned long flags;
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "tp: %d fab state: %d fab retry counter: %d max_flogi_retries: %d",
- iport->fabric.timer_pending, iport->fabric.state,
- iport->fabric.retry_counter, iport->max_flogi_retries);
- spin_lock_irqsave(&fnic->fnic_lock, flags);
- if (!iport->fabric.timer_pending) {
- spin_unlock_irqrestore(&fnic->fnic_lock, flags);
- return;
- }
- if (iport->fabric.del_timer_inprogress) {
- iport->fabric.del_timer_inprogress = 0;
- spin_unlock_irqrestore(&fnic->fnic_lock, flags);
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "fabric_del_timer inprogress(%d). Skip timer cb",
- iport->fabric.del_timer_inprogress);
- return;
- }
- iport->fabric.timer_pending = 0;
- /* The fabric state indicates which frames have time out, and we retry */
- switch (iport->fabric.state) {
- case FDLS_STATE_FABRIC_FLOGI:
- /* Flogi received a LS_RJT with busy we retry from here */
- if ((iport->fabric.flags & FNIC_FDLS_RETRY_FRAME)
- && (iport->fabric.retry_counter < iport->max_flogi_retries)) {
- iport->fabric.flags &= ~FNIC_FDLS_RETRY_FRAME;
- fdls_send_fabric_flogi(iport);
- } else if (!(iport->fabric.flags & FNIC_FDLS_FABRIC_ABORT_ISSUED)) {
- /* Flogi has time out 2*ed_tov send abts */
- fdls_send_fabric_abts(iport);
- } else {
- /* ABTS has timed out
- * Mark the OXID to be freed after 2 * r_a_tov and retry the req
- */
- fdls_schedule_oxid_free(iport, &iport->active_oxid_fabric_req);
- if (iport->fabric.retry_counter < iport->max_flogi_retries) {
- iport->fabric.flags &= ~FNIC_FDLS_FABRIC_ABORT_ISSUED;
- fdls_send_fabric_flogi(iport);
- } else
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "Exceeded max FLOGI retries");
- }
- break;
- case FDLS_STATE_FABRIC_PLOGI:
- /* Plogi received a LS_RJT with busy we retry from here */
- if ((iport->fabric.flags & FNIC_FDLS_RETRY_FRAME)
- && (iport->fabric.retry_counter < iport->max_plogi_retries)) {
- iport->fabric.flags &= ~FNIC_FDLS_RETRY_FRAME;
- fdls_send_fabric_plogi(iport);
- } else if (!(iport->fabric.flags & FNIC_FDLS_FABRIC_ABORT_ISSUED)) {
- /* Plogi has timed out 2*ed_tov send abts */
- fdls_send_fabric_abts(iport);
- } else {
- /* ABTS has timed out
- * Mark the OXID to be freed after 2 * r_a_tov and retry the req
- */
- fdls_schedule_oxid_free(iport, &iport->active_oxid_fabric_req);
- if (iport->fabric.retry_counter < iport->max_plogi_retries) {
- iport->fabric.flags &= ~FNIC_FDLS_FABRIC_ABORT_ISSUED;
- fdls_send_fabric_plogi(iport);
- } else
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "Exceeded max PLOGI retries");
- }
- break;
- case FDLS_STATE_RPN_ID:
- /* Rpn_id received a LS_RJT with busy we retry from here */
- if ((iport->fabric.flags & FNIC_FDLS_RETRY_FRAME)
- && (iport->fabric.retry_counter < FDLS_RETRY_COUNT)) {
- iport->fabric.flags &= ~FNIC_FDLS_RETRY_FRAME;
- fdls_send_rpn_id(iport);
- } else if (!(iport->fabric.flags & FNIC_FDLS_FABRIC_ABORT_ISSUED))
- /* RPN has timed out. Send abts */
- fdls_send_fabric_abts(iport);
- else {
- /* ABTS has timed out */
- fdls_schedule_oxid_free(iport, &iport->active_oxid_fabric_req);
- fnic_fdls_start_plogi(iport); /* go back to fabric Plogi */
- }
- break;
- case FDLS_STATE_SCR:
- /* scr received a LS_RJT with busy we retry from here */
- if ((iport->fabric.flags & FNIC_FDLS_RETRY_FRAME)
- && (iport->fabric.retry_counter < FDLS_RETRY_COUNT)) {
- iport->fabric.flags &= ~FNIC_FDLS_RETRY_FRAME;
- fdls_send_scr(iport);
- } else if (!(iport->fabric.flags & FNIC_FDLS_FABRIC_ABORT_ISSUED))
- /* scr has timed out. Send abts */
- fdls_send_fabric_abts(iport);
- else {
- /* ABTS has timed out */
- fdls_schedule_oxid_free(iport, &iport->active_oxid_fabric_req);
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "ABTS timed out. Starting PLOGI: %p", iport);
- fnic_fdls_start_plogi(iport);
- }
- break;
- case FDLS_STATE_REGISTER_FC4_TYPES:
- /* scr received a LS_RJT with busy we retry from here */
- if ((iport->fabric.flags & FNIC_FDLS_RETRY_FRAME)
- && (iport->fabric.retry_counter < FDLS_RETRY_COUNT)) {
- iport->fabric.flags &= ~FNIC_FDLS_RETRY_FRAME;
- fdls_send_register_fc4_types(iport);
- } else if (!(iport->fabric.flags & FNIC_FDLS_FABRIC_ABORT_ISSUED)) {
- /* RFT_ID timed out send abts */
- fdls_send_fabric_abts(iport);
- } else {
- /* ABTS has timed out */
- fdls_schedule_oxid_free(iport, &iport->active_oxid_fabric_req);
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "ABTS timed out. Starting PLOGI: %p", iport);
- fnic_fdls_start_plogi(iport); /* go back to fabric Plogi */
- }
- break;
- case FDLS_STATE_REGISTER_FC4_FEATURES:
- /* scr received a LS_RJT with busy we retry from here */
- if ((iport->fabric.flags & FNIC_FDLS_RETRY_FRAME)
- && (iport->fabric.retry_counter < FDLS_RETRY_COUNT)) {
- iport->fabric.flags &= ~FNIC_FDLS_RETRY_FRAME;
- fdls_send_register_fc4_features(iport);
- } else if (!(iport->fabric.flags & FNIC_FDLS_FABRIC_ABORT_ISSUED))
- /* SCR has timed out. Send abts */
- fdls_send_fabric_abts(iport);
- else {
- /* ABTS has timed out */
- fdls_schedule_oxid_free(iport, &iport->active_oxid_fabric_req);
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "ABTS timed out. Starting PLOGI %p", iport);
- fnic_fdls_start_plogi(iport); /* go back to fabric Plogi */
- }
- break;
- case FDLS_STATE_RSCN_GPN_FT:
- case FDLS_STATE_SEND_GPNFT:
- case FDLS_STATE_GPN_FT:
- /* GPN_FT received a LS_RJT with busy we retry from here */
- if ((iport->fabric.flags & FNIC_FDLS_RETRY_FRAME)
- && (iport->fabric.retry_counter < FDLS_RETRY_COUNT)) {
- iport->fabric.flags &= ~FNIC_FDLS_RETRY_FRAME;
- fdls_send_gpn_ft(iport, iport->fabric.state);
- } else if (!(iport->fabric.flags & FNIC_FDLS_FABRIC_ABORT_ISSUED)) {
- /* gpn_ft has timed out. Send abts */
- fdls_send_fabric_abts(iport);
- } else {
- /* ABTS has timed out */
- fdls_schedule_oxid_free(iport, &iport->active_oxid_fabric_req);
- if (iport->fabric.retry_counter < FDLS_RETRY_COUNT) {
- fdls_send_gpn_ft(iport, iport->fabric.state);
- } else {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "ABTS timeout for fabric GPN_FT. Check name server: %p",
- iport);
- }
- }
- break;
- default:
- break;
- }
- spin_unlock_irqrestore(&fnic->fnic_lock, flags);
- }
- void fdls_fdmi_retry_plogi(struct fnic_iport_s *iport)
- {
- struct fnic *fnic = iport->fnic;
- iport->fabric.fdmi_pending = 0;
- /* If max retries not exhausted, start over from fdmi plogi */
- if (iport->fabric.fdmi_retry < FDLS_FDMI_MAX_RETRY) {
- iport->fabric.fdmi_retry++;
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "Retry FDMI PLOGI. FDMI retry: %d",
- iport->fabric.fdmi_retry);
- fdls_send_fdmi_plogi(iport);
- }
- }
- void fdls_fdmi_timer_callback(struct timer_list *t)
- {
- struct fnic_fdls_fabric_s *fabric = timer_container_of(fabric, t,
- fdmi_timer);
- struct fnic_iport_s *iport =
- container_of(fabric, struct fnic_iport_s, fabric);
- struct fnic *fnic = iport->fnic;
- unsigned long flags;
- spin_lock_irqsave(&fnic->fnic_lock, flags);
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "iport->fabric.fdmi_pending: 0x%x\n", iport->fabric.fdmi_pending);
- if (!iport->fabric.fdmi_pending) {
- /* timer expired after fdmi responses received. */
- spin_unlock_irqrestore(&fnic->fnic_lock, flags);
- return;
- }
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "iport->fabric.fdmi_pending: 0x%x\n", iport->fabric.fdmi_pending);
- /* if not abort pending, send an abort */
- if (!(iport->fabric.fdmi_pending & FDLS_FDMI_ABORT_PENDING)) {
- fdls_send_fdmi_abts(iport);
- spin_unlock_irqrestore(&fnic->fnic_lock, flags);
- return;
- }
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "iport->fabric.fdmi_pending: 0x%x\n", iport->fabric.fdmi_pending);
- /* ABTS pending for an active fdmi request that is pending.
- * That means FDMI ABTS timed out
- * Schedule to free the OXID after 2*r_a_tov and proceed
- */
- if (iport->fabric.fdmi_pending & FDLS_FDMI_PLOGI_PENDING) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "FDMI PLOGI ABTS timed out. Schedule oxid free: 0x%x\n",
- iport->active_oxid_fdmi_plogi);
- fdls_schedule_oxid_free(iport, &iport->active_oxid_fdmi_plogi);
- } else {
- if (iport->fabric.fdmi_pending & FDLS_FDMI_REG_HBA_PENDING) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "FDMI RHBA ABTS timed out. Schedule oxid free: 0x%x\n",
- iport->active_oxid_fdmi_rhba);
- fdls_schedule_oxid_free(iport, &iport->active_oxid_fdmi_rhba);
- }
- if (iport->fabric.fdmi_pending & FDLS_FDMI_RPA_PENDING) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "FDMI RPA ABTS timed out. Schedule oxid free: 0x%x\n",
- iport->active_oxid_fdmi_rpa);
- fdls_schedule_oxid_free(iport, &iport->active_oxid_fdmi_rpa);
- }
- }
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "iport->fabric.fdmi_pending: 0x%x\n", iport->fabric.fdmi_pending);
- fdls_fdmi_retry_plogi(iport);
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "iport->fabric.fdmi_pending: 0x%x\n", iport->fabric.fdmi_pending);
- spin_unlock_irqrestore(&fnic->fnic_lock, flags);
- }
- static void fdls_send_delete_tport_msg(struct fnic_tport_s *tport)
- {
- struct fnic_iport_s *iport = (struct fnic_iport_s *) tport->iport;
- struct fnic *fnic = iport->fnic;
- struct fnic_tport_event_s *tport_del_evt;
- tport_del_evt = kzalloc_obj(struct fnic_tport_event_s, GFP_ATOMIC);
- if (!tport_del_evt) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "Failed to allocate memory for tport event fcid: 0x%x",
- tport->fcid);
- return;
- }
- tport_del_evt->event = TGT_EV_TPORT_DELETE;
- tport_del_evt->arg1 = (void *) tport;
- list_add_tail(&tport_del_evt->links, &fnic->tport_event_list);
- queue_work(fnic_event_queue, &fnic->tport_work);
- }
- static void fdls_tport_timer_callback(struct timer_list *t)
- {
- struct fnic_tport_s *tport = timer_container_of(tport, t, retry_timer);
- struct fnic_iport_s *iport = (struct fnic_iport_s *) tport->iport;
- struct fnic *fnic = iport->fnic;
- uint16_t oxid;
- unsigned long flags;
- spin_lock_irqsave(&fnic->fnic_lock, flags);
- if (!tport->timer_pending) {
- spin_unlock_irqrestore(&fnic->fnic_lock, flags);
- return;
- }
- if (iport->state != FNIC_IPORT_STATE_READY) {
- spin_unlock_irqrestore(&fnic->fnic_lock, flags);
- return;
- }
- if (tport->del_timer_inprogress) {
- tport->del_timer_inprogress = 0;
- spin_unlock_irqrestore(&fnic->fnic_lock, flags);
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "tport_del_timer inprogress. Skip timer cb tport fcid: 0x%x\n",
- tport->fcid);
- return;
- }
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "tport fcid: 0x%x timer pending: %d state: %d retry counter: %d",
- tport->fcid, tport->timer_pending, tport->state,
- tport->retry_counter);
- tport->timer_pending = 0;
- oxid = tport->active_oxid;
- /* We retry plogi/prli/adisc frames depending on the tport state */
- switch (tport->state) {
- case FDLS_TGT_STATE_PLOGI:
- /* PLOGI frame received a LS_RJT with busy, we retry from here */
- if ((tport->flags & FNIC_FDLS_RETRY_FRAME)
- && (tport->retry_counter < iport->max_plogi_retries)) {
- tport->flags &= ~FNIC_FDLS_RETRY_FRAME;
- fdls_send_tgt_plogi(iport, tport);
- } else if (!(tport->flags & FNIC_FDLS_TGT_ABORT_ISSUED)) {
- /* Plogi frame has timed out, send abts */
- fdls_send_tport_abts(iport, tport);
- } else if (tport->retry_counter < iport->max_plogi_retries) {
- /*
- * ABTS has timed out
- */
- fdls_schedule_oxid_free(iport, &tport->active_oxid);
- fdls_send_tgt_plogi(iport, tport);
- } else {
- /* exceeded plogi retry count */
- fdls_schedule_oxid_free(iport, &tport->active_oxid);
- fdls_send_delete_tport_msg(tport);
- }
- break;
- case FDLS_TGT_STATE_PRLI:
- /* PRLI received a LS_RJT with busy , hence we retry from here */
- if ((tport->flags & FNIC_FDLS_RETRY_FRAME)
- && (tport->retry_counter < FDLS_RETRY_COUNT)) {
- tport->flags &= ~FNIC_FDLS_RETRY_FRAME;
- fdls_send_tgt_prli(iport, tport);
- } else if (!(tport->flags & FNIC_FDLS_TGT_ABORT_ISSUED)) {
- /* PRLI has time out, send abts */
- fdls_send_tport_abts(iport, tport);
- } else {
- /* ABTS has timed out for prli, we go back to PLOGI */
- fdls_schedule_oxid_free(iport, &tport->active_oxid);
- fdls_send_tgt_plogi(iport, tport);
- fdls_set_tport_state(tport, FDLS_TGT_STATE_PLOGI);
- }
- break;
- case FDLS_TGT_STATE_ADISC:
- /* ADISC timed out send an ABTS */
- if (!(tport->flags & FNIC_FDLS_TGT_ABORT_ISSUED)) {
- fdls_send_tport_abts(iport, tport);
- } else if ((tport->flags & FNIC_FDLS_TGT_ABORT_ISSUED)
- && (tport->retry_counter < FDLS_RETRY_COUNT)) {
- /*
- * ABTS has timed out
- */
- fdls_schedule_oxid_free(iport, &tport->active_oxid);
- fdls_send_tgt_adisc(iport, tport);
- } else {
- /* exceeded retry count */
- fdls_schedule_oxid_free(iport, &tport->active_oxid);
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "ADISC not responding. Deleting target port: 0x%x",
- tport->fcid);
- fdls_send_delete_tport_msg(tport);
- }
- break;
- default:
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "oxid: 0x%x Unknown tport state: 0x%x", oxid, tport->state);
- break;
- }
- spin_unlock_irqrestore(&fnic->fnic_lock, flags);
- }
- static void fnic_fdls_start_flogi(struct fnic_iport_s *iport)
- {
- iport->fabric.retry_counter = 0;
- fdls_send_fabric_flogi(iport);
- fdls_set_state((&iport->fabric), FDLS_STATE_FABRIC_FLOGI);
- iport->fabric.flags = 0;
- }
- static void fnic_fdls_start_plogi(struct fnic_iport_s *iport)
- {
- iport->fabric.retry_counter = 0;
- fdls_send_fabric_plogi(iport);
- fdls_set_state((&iport->fabric), FDLS_STATE_FABRIC_PLOGI);
- iport->fabric.flags &= ~FNIC_FDLS_FABRIC_ABORT_ISSUED;
- if ((fnic_fdmi_support == 1) && (!(iport->flags & FNIC_FDMI_ACTIVE))) {
- /* we can do FDMI at the same time */
- iport->fabric.fdmi_retry = 0;
- timer_setup(&iport->fabric.fdmi_timer, fdls_fdmi_timer_callback,
- 0);
- fdls_send_fdmi_plogi(iport);
- iport->flags |= FNIC_FDMI_ACTIVE;
- }
- }
- static void
- fdls_process_tgt_adisc_rsp(struct fnic_iport_s *iport,
- struct fc_frame_header *fchdr)
- {
- uint32_t tgt_fcid;
- struct fnic_tport_s *tport;
- uint8_t *fcid;
- uint64_t frame_wwnn;
- uint64_t frame_wwpn;
- uint16_t oxid;
- struct fc_std_els_adisc *adisc_rsp = (struct fc_std_els_adisc *)fchdr;
- struct fc_std_els_rjt_rsp *els_rjt = (struct fc_std_els_rjt_rsp *)fchdr;
- struct fnic *fnic = iport->fnic;
- fcid = FNIC_STD_GET_S_ID(fchdr);
- tgt_fcid = ntoh24(fcid);
- tport = fnic_find_tport_by_fcid(iport, tgt_fcid);
- if (!tport) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "Tgt ADISC response tport not found: 0x%x", tgt_fcid);
- return;
- }
- if ((iport->state != FNIC_IPORT_STATE_READY)
- || (tport->state != FDLS_TGT_STATE_ADISC)
- || (tport->flags & FNIC_FDLS_TGT_ABORT_ISSUED)) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "Dropping this ADISC response");
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "iport state: %d tport state: %d Is abort issued on PRLI? %d",
- iport->state, tport->state,
- (tport->flags & FNIC_FDLS_TGT_ABORT_ISSUED));
- return;
- }
- if (FNIC_STD_GET_OX_ID(fchdr) != tport->active_oxid) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "Dropping frame from target: 0x%x",
- tgt_fcid);
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "Reason: Stale ADISC/Aborted ADISC/OOO frame delivery");
- return;
- }
- oxid = FNIC_STD_GET_OX_ID(fchdr);
- fdls_free_oxid(iport, oxid, &tport->active_oxid);
- switch (adisc_rsp->els.adisc_cmd) {
- case ELS_LS_ACC:
- atomic64_inc(&iport->iport_stats.tport_adisc_ls_accepts);
- if (tport->timer_pending) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "tport 0x%p Canceling fabric disc timer\n",
- tport);
- fnic_del_tport_timer_sync(fnic, tport);
- }
- tport->timer_pending = 0;
- tport->retry_counter = 0;
- frame_wwnn = get_unaligned_be64(&adisc_rsp->els.adisc_wwnn);
- frame_wwpn = get_unaligned_be64(&adisc_rsp->els.adisc_wwpn);
- if ((frame_wwnn == tport->wwnn) && (frame_wwpn == tport->wwpn)) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "ADISC accepted from target: 0x%x. Target logged in",
- tgt_fcid);
- fdls_set_tport_state(tport, FDLS_TGT_STATE_READY);
- } else {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "Error mismatch frame: ADISC");
- }
- break;
- case ELS_LS_RJT:
- atomic64_inc(&iport->iport_stats.tport_adisc_ls_rejects);
- if (((els_rjt->rej.er_reason == ELS_RJT_BUSY)
- || (els_rjt->rej.er_reason == ELS_RJT_UNAB))
- && (tport->retry_counter < FDLS_RETRY_COUNT)) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "ADISC ret ELS_LS_RJT BUSY. Retry from timer routine: 0x%x",
- tgt_fcid);
- /* Retry ADISC again from the timer routine. */
- tport->flags |= FNIC_FDLS_RETRY_FRAME;
- } else {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "ADISC returned ELS_LS_RJT from target: 0x%x",
- tgt_fcid);
- fdls_delete_tport(iport, tport);
- }
- break;
- }
- }
- static void
- fdls_process_tgt_plogi_rsp(struct fnic_iport_s *iport,
- struct fc_frame_header *fchdr)
- {
- uint32_t tgt_fcid;
- struct fnic_tport_s *tport;
- uint8_t *fcid;
- uint16_t oxid;
- struct fc_std_flogi *plogi_rsp = (struct fc_std_flogi *)fchdr;
- struct fc_std_els_rjt_rsp *els_rjt = (struct fc_std_els_rjt_rsp *)fchdr;
- uint16_t max_payload_size;
- struct fnic *fnic = iport->fnic;
- fcid = FNIC_STD_GET_S_ID(fchdr);
- tgt_fcid = ntoh24(fcid);
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "FDLS processing target PLOGI response: tgt_fcid: 0x%x",
- tgt_fcid);
- tport = fnic_find_tport_by_fcid(iport, tgt_fcid);
- if (!tport) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "tport not found: 0x%x", tgt_fcid);
- return;
- }
- if ((iport->state != FNIC_IPORT_STATE_READY)
- || (tport->flags & FNIC_FDLS_TGT_ABORT_ISSUED)) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "Dropping frame! iport state: %d tport state: %d",
- iport->state, tport->state);
- return;
- }
- if (tport->state != FDLS_TGT_STATE_PLOGI) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "PLOGI rsp recvd in wrong state. Drop the frame and restart nexus");
- fdls_target_restart_nexus(tport);
- return;
- }
- if (FNIC_STD_GET_OX_ID(fchdr) != tport->active_oxid) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "PLOGI response from target: 0x%x. Dropping frame",
- tgt_fcid);
- return;
- }
- oxid = FNIC_STD_GET_OX_ID(fchdr);
- fdls_free_oxid(iport, oxid, &tport->active_oxid);
- switch (plogi_rsp->els.fl_cmd) {
- case ELS_LS_ACC:
- atomic64_inc(&iport->iport_stats.tport_plogi_ls_accepts);
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "PLOGI accepted by target: 0x%x", tgt_fcid);
- break;
- case ELS_LS_RJT:
- atomic64_inc(&iport->iport_stats.tport_plogi_ls_rejects);
- if (((els_rjt->rej.er_reason == ELS_RJT_BUSY)
- || (els_rjt->rej.er_reason == ELS_RJT_UNAB))
- && (tport->retry_counter < iport->max_plogi_retries)) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "PLOGI ret ELS_LS_RJT BUSY. Retry from timer routine: 0x%x",
- tgt_fcid);
- /* Retry plogi again from the timer routine. */
- tport->flags |= FNIC_FDLS_RETRY_FRAME;
- return;
- }
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "PLOGI returned ELS_LS_RJT from target: 0x%x",
- tgt_fcid);
- fdls_delete_tport(iport, tport);
- return;
- default:
- atomic64_inc(&iport->iport_stats.tport_plogi_misc_rejects);
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "PLOGI not accepted from target fcid: 0x%x",
- tgt_fcid);
- return;
- }
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "Found the PLOGI target: 0x%x and state: %d",
- (unsigned int) tgt_fcid, tport->state);
- if (tport->timer_pending) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "tport fcid 0x%x: Canceling disc timer\n",
- tport->fcid);
- fnic_del_tport_timer_sync(fnic, tport);
- }
- tport->timer_pending = 0;
- tport->wwpn = get_unaligned_be64(&FNIC_LOGI_PORT_NAME(plogi_rsp->els));
- tport->wwnn = get_unaligned_be64(&FNIC_LOGI_NODE_NAME(plogi_rsp->els));
- /* Learn the Service Params */
- /* Max frame size - choose the lowest */
- max_payload_size = fnic_fc_plogi_rsp_rdf(iport, plogi_rsp);
- tport->max_payload_size =
- min(max_payload_size, iport->max_payload_size);
- if (tport->max_payload_size < FNIC_MIN_DATA_FIELD_SIZE) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "MFS: tport max frame size below spec bounds: %d",
- tport->max_payload_size);
- tport->max_payload_size = FNIC_MIN_DATA_FIELD_SIZE;
- }
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "MAX frame size: %u iport max_payload_size: %d tport mfs: %d",
- max_payload_size, iport->max_payload_size,
- tport->max_payload_size);
- tport->max_concur_seqs = FNIC_FC_PLOGI_RSP_CONCUR_SEQ(plogi_rsp);
- tport->retry_counter = 0;
- fdls_set_tport_state(tport, FDLS_TGT_STATE_PRLI);
- fdls_send_tgt_prli(iport, tport);
- }
- static void
- fdls_process_tgt_prli_rsp(struct fnic_iport_s *iport,
- struct fc_frame_header *fchdr)
- {
- uint32_t tgt_fcid;
- struct fnic_tport_s *tport;
- uint8_t *fcid;
- uint16_t oxid;
- struct fc_std_els_prli *prli_rsp = (struct fc_std_els_prli *)fchdr;
- struct fc_std_els_rjt_rsp *els_rjt = (struct fc_std_els_rjt_rsp *)fchdr;
- struct fnic_tport_event_s *tport_add_evt;
- struct fnic *fnic = iport->fnic;
- bool mismatched_tgt = false;
- fcid = FNIC_STD_GET_S_ID(fchdr);
- tgt_fcid = ntoh24(fcid);
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "FDLS process tgt PRLI response: 0x%x", tgt_fcid);
- tport = fnic_find_tport_by_fcid(iport, tgt_fcid);
- if (!tport) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "tport not found: 0x%x", tgt_fcid);
- /* Handle or just drop? */
- return;
- }
- if ((iport->state != FNIC_IPORT_STATE_READY)
- || (tport->flags & FNIC_FDLS_TGT_ABORT_ISSUED)) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "Dropping frame! iport st: %d tport st: %d tport fcid: 0x%x",
- iport->state, tport->state, tport->fcid);
- return;
- }
- if (tport->state != FDLS_TGT_STATE_PRLI) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "PRLI rsp recvd in wrong state. Drop frame. Restarting nexus");
- fdls_target_restart_nexus(tport);
- return;
- }
- if (FNIC_STD_GET_OX_ID(fchdr) != tport->active_oxid) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "Dropping PRLI response from target: 0x%x ",
- tgt_fcid);
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "Reason: Stale PRLI response/Aborted PDISC/OOO frame delivery");
- return;
- }
- oxid = FNIC_STD_GET_OX_ID(fchdr);
- fdls_free_oxid(iport, oxid, &tport->active_oxid);
- switch (prli_rsp->els_prli.prli_cmd) {
- case ELS_LS_ACC:
- atomic64_inc(&iport->iport_stats.tport_prli_ls_accepts);
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "PRLI accepted from target: 0x%x", tgt_fcid);
- if (prli_rsp->sp.spp_type != FC_FC4_TYPE_SCSI) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "mismatched target zoned with FC SCSI initiator: 0x%x",
- tgt_fcid);
- mismatched_tgt = true;
- }
- if (mismatched_tgt) {
- fdls_tgt_logout(iport, tport);
- fdls_delete_tport(iport, tport);
- return;
- }
- break;
- case ELS_LS_RJT:
- atomic64_inc(&iport->iport_stats.tport_prli_ls_rejects);
- if (((els_rjt->rej.er_reason == ELS_RJT_BUSY)
- || (els_rjt->rej.er_reason == ELS_RJT_UNAB))
- && (tport->retry_counter < FDLS_RETRY_COUNT)) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "PRLI ret ELS_LS_RJT BUSY. Retry from timer routine: 0x%x",
- tgt_fcid);
- /*Retry Plogi again from the timer routine. */
- tport->flags |= FNIC_FDLS_RETRY_FRAME;
- return;
- }
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "PRLI returned ELS_LS_RJT from target: 0x%x",
- tgt_fcid);
- fdls_tgt_logout(iport, tport);
- fdls_delete_tport(iport, tport);
- return;
- default:
- atomic64_inc(&iport->iport_stats.tport_prli_misc_rejects);
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "PRLI not accepted from target: 0x%x", tgt_fcid);
- return;
- }
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "Found the PRLI target: 0x%x and state: %d",
- (unsigned int) tgt_fcid, tport->state);
- if (tport->timer_pending) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "tport fcid 0x%x: Canceling disc timer\n",
- tport->fcid);
- fnic_del_tport_timer_sync(fnic, tport);
- }
- tport->timer_pending = 0;
- /* Learn Service Params */
- tport->fcp_csp = be32_to_cpu(prli_rsp->sp.spp_params);
- tport->retry_counter = 0;
- if (tport->fcp_csp & FCP_SPPF_RETRY)
- tport->tgt_flags |= FNIC_FC_RP_FLAGS_RETRY;
- /* Check if the device plays Target Mode Function */
- if (!(tport->fcp_csp & FCP_PRLI_FUNC_TARGET)) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "Remote port(0x%x): no target support. Deleting it\n",
- tgt_fcid);
- fdls_tgt_logout(iport, tport);
- fdls_delete_tport(iport, tport);
- return;
- }
- fdls_set_tport_state(tport, FDLS_TGT_STATE_READY);
- /* Inform the driver about new target added */
- tport_add_evt = kzalloc_obj(struct fnic_tport_event_s, GFP_ATOMIC);
- if (!tport_add_evt) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "tport event memory allocation failure: 0x%0x\n",
- tport->fcid);
- return;
- }
- tport_add_evt->event = TGT_EV_RPORT_ADD;
- tport_add_evt->arg1 = (void *) tport;
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "iport fcid: 0x%x add tport event fcid: 0x%x\n",
- tport->fcid, iport->fcid);
- list_add_tail(&tport_add_evt->links, &fnic->tport_event_list);
- queue_work(fnic_event_queue, &fnic->tport_work);
- }
- static void
- fdls_process_rff_id_rsp(struct fnic_iport_s *iport,
- struct fc_frame_header *fchdr)
- {
- struct fnic *fnic = iport->fnic;
- struct fnic_fdls_fabric_s *fdls = &iport->fabric;
- struct fc_std_rff_id *rff_rsp = (struct fc_std_rff_id *) fchdr;
- uint16_t rsp;
- uint8_t reason_code;
- uint16_t oxid = FNIC_STD_GET_OX_ID(fchdr);
- if (fdls_get_state(fdls) != FDLS_STATE_REGISTER_FC4_FEATURES) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "RFF_ID resp recvd in state(%d). Dropping.",
- fdls_get_state(fdls));
- return;
- }
- if (iport->active_oxid_fabric_req != oxid) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "Incorrect OXID in response. state: %d, oxid recvd: 0x%x, active oxid: 0x%x\n",
- fdls_get_state(fdls), oxid, iport->active_oxid_fabric_req);
- return;
- }
- rsp = FNIC_STD_GET_FC_CT_CMD((&rff_rsp->fc_std_ct_hdr));
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "0x%x: FDLS process RFF ID response: 0x%04x", iport->fcid,
- (uint32_t) rsp);
- fdls_free_oxid(iport, oxid, &iport->active_oxid_fabric_req);
- switch (rsp) {
- case FC_FS_ACC:
- if (iport->fabric.timer_pending) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "Canceling fabric disc timer %p\n", iport);
- fnic_del_fabric_timer_sync(fnic);
- }
- iport->fabric.timer_pending = 0;
- fdls->retry_counter = 0;
- fdls_set_state((&iport->fabric), FDLS_STATE_SCR);
- fdls_send_scr(iport);
- break;
- case FC_FS_RJT:
- reason_code = rff_rsp->fc_std_ct_hdr.ct_reason;
- if (((reason_code == FC_FS_RJT_BSY)
- || (reason_code == FC_FS_RJT_UNABL))
- && (fdls->retry_counter < FDLS_RETRY_COUNT)) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "RFF_ID ret ELS_LS_RJT BUSY. Retry from timer routine %p",
- iport);
- /* Retry again from the timer routine */
- fdls->flags |= FNIC_FDLS_RETRY_FRAME;
- } else {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "RFF_ID returned ELS_LS_RJT. Halting discovery %p",
- iport);
- if (iport->fabric.timer_pending) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "Canceling fabric disc timer %p\n", iport);
- fnic_del_fabric_timer_sync(fnic);
- }
- fdls->timer_pending = 0;
- fdls->retry_counter = 0;
- }
- break;
- default:
- break;
- }
- }
- static void
- fdls_process_rft_id_rsp(struct fnic_iport_s *iport,
- struct fc_frame_header *fchdr)
- {
- struct fnic_fdls_fabric_s *fdls = &iport->fabric;
- struct fc_std_rft_id *rft_rsp = (struct fc_std_rft_id *) fchdr;
- uint16_t rsp;
- uint8_t reason_code;
- struct fnic *fnic = iport->fnic;
- uint16_t oxid = FNIC_STD_GET_OX_ID(fchdr);
- if (fdls_get_state(fdls) != FDLS_STATE_REGISTER_FC4_TYPES) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "RFT_ID resp recvd in state(%d). Dropping.",
- fdls_get_state(fdls));
- return;
- }
- if (iport->active_oxid_fabric_req != oxid) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "Incorrect OXID in response. state: %d, oxid recvd: 0x%x, active oxid: 0x%x\n",
- fdls_get_state(fdls), oxid, iport->active_oxid_fabric_req);
- return;
- }
- rsp = FNIC_STD_GET_FC_CT_CMD((&rft_rsp->fc_std_ct_hdr));
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "0x%x: FDLS process RFT ID response: 0x%04x", iport->fcid,
- (uint32_t) rsp);
- fdls_free_oxid(iport, oxid, &iport->active_oxid_fabric_req);
- switch (rsp) {
- case FC_FS_ACC:
- if (iport->fabric.timer_pending) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "Canceling fabric disc timer %p\n", iport);
- fnic_del_fabric_timer_sync(fnic);
- }
- iport->fabric.timer_pending = 0;
- fdls->retry_counter = 0;
- fdls_send_register_fc4_features(iport);
- fdls_set_state((&iport->fabric), FDLS_STATE_REGISTER_FC4_FEATURES);
- break;
- case FC_FS_RJT:
- reason_code = rft_rsp->fc_std_ct_hdr.ct_reason;
- if (((reason_code == FC_FS_RJT_BSY)
- || (reason_code == FC_FS_RJT_UNABL))
- && (fdls->retry_counter < FDLS_RETRY_COUNT)) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "0x%x: RFT_ID ret ELS_LS_RJT BUSY. Retry from timer routine",
- iport->fcid);
- /* Retry again from the timer routine */
- fdls->flags |= FNIC_FDLS_RETRY_FRAME;
- } else {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "0x%x: RFT_ID REJ. Halting discovery reason %d expl %d",
- iport->fcid, reason_code,
- rft_rsp->fc_std_ct_hdr.ct_explan);
- if (iport->fabric.timer_pending) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "Canceling fabric disc timer %p\n", iport);
- fnic_del_fabric_timer_sync(fnic);
- }
- fdls->timer_pending = 0;
- fdls->retry_counter = 0;
- }
- break;
- default:
- break;
- }
- }
- static void
- fdls_process_rpn_id_rsp(struct fnic_iport_s *iport,
- struct fc_frame_header *fchdr)
- {
- struct fnic_fdls_fabric_s *fdls = &iport->fabric;
- struct fc_std_rpn_id *rpn_rsp = (struct fc_std_rpn_id *) fchdr;
- uint16_t rsp;
- uint8_t reason_code;
- struct fnic *fnic = iport->fnic;
- uint16_t oxid = FNIC_STD_GET_OX_ID(fchdr);
- if (fdls_get_state(fdls) != FDLS_STATE_RPN_ID) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "RPN_ID resp recvd in state(%d). Dropping.",
- fdls_get_state(fdls));
- return;
- }
- if (iport->active_oxid_fabric_req != oxid) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "Incorrect OXID in response. state: %d, oxid recvd: 0x%x, active oxid: 0x%x\n",
- fdls_get_state(fdls), oxid, iport->active_oxid_fabric_req);
- return;
- }
- rsp = FNIC_STD_GET_FC_CT_CMD((&rpn_rsp->fc_std_ct_hdr));
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "0x%x: FDLS process RPN ID response: 0x%04x", iport->fcid,
- (uint32_t) rsp);
- fdls_free_oxid(iport, oxid, &iport->active_oxid_fabric_req);
- switch (rsp) {
- case FC_FS_ACC:
- if (iport->fabric.timer_pending) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "Canceling fabric disc timer %p\n", iport);
- fnic_del_fabric_timer_sync(fnic);
- }
- iport->fabric.timer_pending = 0;
- fdls->retry_counter = 0;
- fdls_send_register_fc4_types(iport);
- fdls_set_state((&iport->fabric), FDLS_STATE_REGISTER_FC4_TYPES);
- break;
- case FC_FS_RJT:
- reason_code = rpn_rsp->fc_std_ct_hdr.ct_reason;
- if (((reason_code == FC_FS_RJT_BSY)
- || (reason_code == FC_FS_RJT_UNABL))
- && (fdls->retry_counter < FDLS_RETRY_COUNT)) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "RPN_ID returned REJ BUSY. Retry from timer routine %p",
- iport);
- /* Retry again from the timer routine */
- fdls->flags |= FNIC_FDLS_RETRY_FRAME;
- } else {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "RPN_ID ELS_LS_RJT. Halting discovery %p", iport);
- if (iport->fabric.timer_pending) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "Canceling fabric disc timer %p\n", iport);
- fnic_del_fabric_timer_sync(fnic);
- }
- fdls->timer_pending = 0;
- fdls->retry_counter = 0;
- }
- break;
- default:
- break;
- }
- }
- static void
- fdls_process_scr_rsp(struct fnic_iport_s *iport,
- struct fc_frame_header *fchdr)
- {
- struct fnic_fdls_fabric_s *fdls = &iport->fabric;
- struct fc_std_scr *scr_rsp = (struct fc_std_scr *) fchdr;
- struct fc_std_els_rjt_rsp *els_rjt = (struct fc_std_els_rjt_rsp *) fchdr;
- struct fnic *fnic = iport->fnic;
- uint16_t oxid = FNIC_STD_GET_OX_ID(fchdr);
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "FDLS process SCR response: 0x%04x",
- (uint32_t) scr_rsp->scr.scr_cmd);
- if (fdls_get_state(fdls) != FDLS_STATE_SCR) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "SCR resp recvd in state(%d). Dropping.",
- fdls_get_state(fdls));
- return;
- }
- if (iport->active_oxid_fabric_req != oxid) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "Incorrect OXID in response. state: %d, oxid recvd: 0x%x, active oxid: 0x%x\n",
- fdls_get_state(fdls), oxid, iport->active_oxid_fabric_req);
- }
- fdls_free_oxid(iport, oxid, &iport->active_oxid_fabric_req);
- switch (scr_rsp->scr.scr_cmd) {
- case ELS_LS_ACC:
- atomic64_inc(&iport->iport_stats.fabric_scr_ls_accepts);
- if (iport->fabric.timer_pending) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "Canceling fabric disc timer %p\n", iport);
- fnic_del_fabric_timer_sync(fnic);
- }
- iport->fabric.timer_pending = 0;
- iport->fabric.retry_counter = 0;
- fdls_send_gpn_ft(iport, FDLS_STATE_GPN_FT);
- break;
- case ELS_LS_RJT:
- atomic64_inc(&iport->iport_stats.fabric_scr_ls_rejects);
- if (((els_rjt->rej.er_reason == ELS_RJT_BUSY)
- || (els_rjt->rej.er_reason == ELS_RJT_UNAB))
- && (fdls->retry_counter < FDLS_RETRY_COUNT)) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "SCR ELS_LS_RJT BUSY. Retry from timer routine %p",
- iport);
- /* Retry again from the timer routine */
- fdls->flags |= FNIC_FDLS_RETRY_FRAME;
- } else {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "SCR returned ELS_LS_RJT. Halting discovery %p",
- iport);
- if (iport->fabric.timer_pending) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "Canceling fabric disc timer %p\n",
- iport);
- fnic_del_fabric_timer_sync(fnic);
- }
- fdls->timer_pending = 0;
- fdls->retry_counter = 0;
- }
- break;
- default:
- atomic64_inc(&iport->iport_stats.fabric_scr_misc_rejects);
- break;
- }
- }
- static void
- fdls_process_gpn_ft_tgt_list(struct fnic_iport_s *iport,
- struct fc_frame_header *fchdr, int len)
- {
- struct fc_gpn_ft_rsp_iu *gpn_ft_tgt;
- struct fnic_tport_s *tport, *next;
- uint32_t fcid;
- uint64_t wwpn;
- int rem_len = len;
- u32 old_link_down_cnt = iport->fnic->link_down_cnt;
- struct fnic *fnic = iport->fnic;
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "0x%x: FDLS process GPN_FT tgt list", iport->fcid);
- gpn_ft_tgt =
- (struct fc_gpn_ft_rsp_iu *)((uint8_t *) fchdr +
- sizeof(struct fc_frame_header)
- + sizeof(struct fc_ct_hdr));
- len -= sizeof(struct fc_frame_header) + sizeof(struct fc_ct_hdr);
- while (rem_len > 0) {
- fcid = ntoh24(gpn_ft_tgt->fcid);
- wwpn = be64_to_cpu(gpn_ft_tgt->wwpn);
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "tport: 0x%x: ctrl:0x%x", fcid, gpn_ft_tgt->ctrl);
- if (fcid == iport->fcid) {
- if (gpn_ft_tgt->ctrl & FC_NS_FID_LAST)
- break;
- gpn_ft_tgt++;
- rem_len -= sizeof(struct fc_gpn_ft_rsp_iu);
- continue;
- }
- tport = fnic_find_tport_by_wwpn(iport, wwpn);
- if (!tport) {
- /*
- * New port registered with the switch or first time query
- */
- tport = fdls_create_tport(iport, fcid, wwpn);
- if (!tport)
- return;
- }
- /*
- * check if this was an existing tport with same fcid
- * but whose wwpn has changed now ,then remove it and
- * create a new one
- */
- if (tport->fcid != fcid) {
- fdls_delete_tport(iport, tport);
- tport = fdls_create_tport(iport, fcid, wwpn);
- if (!tport)
- return;
- }
- /*
- * If this GPN_FT rsp is after RSCN then mark the tports which
- * matches with the new GPN_FT list, if some tport is not
- * found in GPN_FT we went to delete that tport later.
- */
- if (fdls_get_state((&iport->fabric)) == FDLS_STATE_RSCN_GPN_FT)
- tport->flags |= FNIC_FDLS_TPORT_IN_GPN_FT_LIST;
- if (gpn_ft_tgt->ctrl & FC_NS_FID_LAST)
- break;
- gpn_ft_tgt++;
- rem_len -= sizeof(struct fc_gpn_ft_rsp_iu);
- }
- if (rem_len <= 0) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "GPN_FT response: malformed/corrupt frame rxlen: %d remlen: %d",
- len, rem_len);
- }
- /*remove those ports which was not listed in GPN_FT */
- if (fdls_get_state((&iport->fabric)) == FDLS_STATE_RSCN_GPN_FT) {
- list_for_each_entry_safe(tport, next, &iport->tport_list, links) {
- if (!(tport->flags & FNIC_FDLS_TPORT_IN_GPN_FT_LIST)) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "Remove port: 0x%x not found in GPN_FT list",
- tport->fcid);
- fdls_delete_tport(iport, tport);
- } else {
- tport->flags &= ~FNIC_FDLS_TPORT_IN_GPN_FT_LIST;
- }
- if ((old_link_down_cnt != iport->fnic->link_down_cnt)
- || (iport->state != FNIC_IPORT_STATE_READY)) {
- return;
- }
- }
- }
- }
- static void
- fdls_process_gpn_ft_rsp(struct fnic_iport_s *iport,
- struct fc_frame_header *fchdr, int len)
- {
- struct fnic_fdls_fabric_s *fdls = &iport->fabric;
- struct fc_std_gpn_ft *gpn_ft_rsp = (struct fc_std_gpn_ft *) fchdr;
- uint16_t rsp;
- uint8_t reason_code;
- int count = 0;
- struct fnic_tport_s *tport, *next;
- u32 old_link_down_cnt = iport->fnic->link_down_cnt;
- struct fnic *fnic = iport->fnic;
- uint16_t oxid = FNIC_STD_GET_OX_ID(fchdr);
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "FDLS process GPN_FT response: iport state: %d len: %d",
- iport->state, len);
- /*
- * GPNFT response :-
- * FDLS_STATE_GPN_FT : GPNFT send after SCR state
- * during fabric discovery(FNIC_IPORT_STATE_FABRIC_DISC)
- * FDLS_STATE_RSCN_GPN_FT : GPNFT send in response to RSCN
- * FDLS_STATE_SEND_GPNFT : GPNFT send after deleting a Target,
- * e.g. after receiving Target LOGO
- * FDLS_STATE_TGT_DISCOVERY :Target discovery is currently in progress
- * from previous GPNFT response,a new GPNFT response has come.
- */
- if (!(((iport->state == FNIC_IPORT_STATE_FABRIC_DISC)
- && (fdls_get_state(fdls) == FDLS_STATE_GPN_FT))
- || ((iport->state == FNIC_IPORT_STATE_READY)
- && ((fdls_get_state(fdls) == FDLS_STATE_RSCN_GPN_FT)
- || (fdls_get_state(fdls) == FDLS_STATE_SEND_GPNFT)
- || (fdls_get_state(fdls) == FDLS_STATE_TGT_DISCOVERY))))) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "GPNFT resp recvd in fab state(%d) iport_state(%d). Dropping.",
- fdls_get_state(fdls), iport->state);
- return;
- }
- if (iport->active_oxid_fabric_req != oxid) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "Incorrect OXID in response. state: %d, oxid recvd: 0x%x, active oxid: 0x%x\n",
- fdls_get_state(fdls), oxid, iport->active_oxid_fabric_req);
- }
- fdls_free_oxid(iport, oxid, &iport->active_oxid_fabric_req);
- iport->state = FNIC_IPORT_STATE_READY;
- rsp = FNIC_STD_GET_FC_CT_CMD((&gpn_ft_rsp->fc_std_ct_hdr));
- switch (rsp) {
- case FC_FS_ACC:
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "0x%x: GPNFT_RSP accept", iport->fcid);
- if (iport->fabric.timer_pending) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "0x%x: Canceling fabric disc timer\n",
- iport->fcid);
- fnic_del_fabric_timer_sync(fnic);
- }
- iport->fabric.timer_pending = 0;
- iport->fabric.retry_counter = 0;
- fdls_process_gpn_ft_tgt_list(iport, fchdr, len);
- /*
- * iport state can change only if link down event happened
- * We don't need to undo fdls_process_gpn_ft_tgt_list,
- * that will be taken care in next link up event
- */
- if (iport->state != FNIC_IPORT_STATE_READY) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "Halting target discovery: fab st: %d iport st: %d ",
- fdls_get_state(fdls), iport->state);
- break;
- }
- fdls_tgt_discovery_start(iport);
- break;
- case FC_FS_RJT:
- reason_code = gpn_ft_rsp->fc_std_ct_hdr.ct_reason;
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "0x%x: GPNFT_RSP Reject reason: %d", iport->fcid, reason_code);
- if (((reason_code == FC_FS_RJT_BSY)
- || (reason_code == FC_FS_RJT_UNABL))
- && (fdls->retry_counter < FDLS_RETRY_COUNT)) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "0x%x: GPNFT_RSP ret REJ/BSY. Retry from timer routine",
- iport->fcid);
- /* Retry again from the timer routine */
- fdls->flags |= FNIC_FDLS_RETRY_FRAME;
- } else {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "0x%x: GPNFT_RSP reject", iport->fcid);
- if (iport->fabric.timer_pending) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "0x%x: Canceling fabric disc timer\n",
- iport->fcid);
- fnic_del_fabric_timer_sync(fnic);
- }
- iport->fabric.timer_pending = 0;
- iport->fabric.retry_counter = 0;
- /*
- * If GPN_FT ls_rjt then we should delete
- * all existing tports
- */
- count = 0;
- list_for_each_entry_safe(tport, next, &iport->tport_list,
- links) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "GPN_FT_REJECT: Remove port: 0x%x",
- tport->fcid);
- fdls_delete_tport(iport, tport);
- if ((old_link_down_cnt != iport->fnic->link_down_cnt)
- || (iport->state != FNIC_IPORT_STATE_READY)) {
- return;
- }
- count++;
- }
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "GPN_FT_REJECT: Removed (0x%x) ports", count);
- }
- break;
- default:
- break;
- }
- }
- /**
- * fdls_process_fabric_logo_rsp - Handle an flogo response from the fcf
- * @iport: Handle to fnic iport
- * @fchdr: Incoming frame
- */
- static void
- fdls_process_fabric_logo_rsp(struct fnic_iport_s *iport,
- struct fc_frame_header *fchdr)
- {
- struct fc_std_flogi *flogo_rsp = (struct fc_std_flogi *) fchdr;
- struct fnic_fdls_fabric_s *fdls = &iport->fabric;
- struct fnic *fnic = iport->fnic;
- uint16_t oxid = FNIC_STD_GET_OX_ID(fchdr);
- if (iport->active_oxid_fabric_req != oxid) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "Incorrect OXID in response. state: %d, oxid recvd: 0x%x, active oxid: 0x%x\n",
- fdls_get_state(fdls), oxid, iport->active_oxid_fabric_req);
- }
- fdls_free_oxid(iport, oxid, &iport->active_oxid_fabric_req);
- switch (flogo_rsp->els.fl_cmd) {
- case ELS_LS_ACC:
- if (iport->fabric.state != FDLS_STATE_FABRIC_LOGO) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "Flogo response. Fabric not in LOGO state. Dropping! %p",
- iport);
- return;
- }
- iport->fabric.state = FDLS_STATE_FLOGO_DONE;
- iport->state = FNIC_IPORT_STATE_LINK_WAIT;
- if (iport->fabric.timer_pending) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "iport 0x%p Canceling fabric disc timer\n",
- iport);
- fnic_del_fabric_timer_sync(fnic);
- }
- iport->fabric.timer_pending = 0;
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "Flogo response from Fabric for did: 0x%x",
- ntoh24(fchdr->fh_d_id));
- return;
- case ELS_LS_RJT:
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "Flogo response from Fabric for did: 0x%x returned ELS_LS_RJT",
- ntoh24(fchdr->fh_d_id));
- return;
- default:
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "FLOGO response not accepted or rejected: 0x%x",
- flogo_rsp->els.fl_cmd);
- }
- }
- static void
- fdls_process_flogi_rsp(struct fnic_iport_s *iport,
- struct fc_frame_header *fchdr, void *rx_frame)
- {
- struct fnic_fdls_fabric_s *fabric = &iport->fabric;
- struct fc_std_flogi *flogi_rsp = (struct fc_std_flogi *) fchdr;
- uint8_t *fcid;
- uint16_t rdf_size;
- uint8_t fcmac[6] = { 0x0E, 0XFC, 0x00, 0x00, 0x00, 0x00 };
- struct fnic *fnic = iport->fnic;
- uint16_t oxid = FNIC_STD_GET_OX_ID(fchdr);
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "0x%x: FDLS processing FLOGI response", iport->fcid);
- if (fdls_get_state(fabric) != FDLS_STATE_FABRIC_FLOGI) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "FLOGI response received in state (%d). Dropping frame",
- fdls_get_state(fabric));
- return;
- }
- if (iport->active_oxid_fabric_req != oxid) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "Incorrect OXID in response. state: %d, oxid recvd: 0x%x, active oxid: 0x%x\n",
- fdls_get_state(fabric), oxid, iport->active_oxid_fabric_req);
- return;
- }
- fdls_free_oxid(iport, oxid, &iport->active_oxid_fabric_req);
- switch (flogi_rsp->els.fl_cmd) {
- case ELS_LS_ACC:
- atomic64_inc(&iport->iport_stats.fabric_flogi_ls_accepts);
- if (iport->fabric.timer_pending) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "iport fcid: 0x%x Canceling fabric disc timer\n",
- iport->fcid);
- fnic_del_fabric_timer_sync(fnic);
- }
- iport->fabric.timer_pending = 0;
- iport->fabric.retry_counter = 0;
- fcid = FNIC_STD_GET_D_ID(fchdr);
- iport->fcid = ntoh24(fcid);
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "0x%x: FLOGI response accepted", iport->fcid);
- /* Learn the Service Params */
- rdf_size = be16_to_cpu(FNIC_LOGI_RDF_SIZE(flogi_rsp->els));
- if ((rdf_size >= FNIC_MIN_DATA_FIELD_SIZE)
- && (rdf_size < FNIC_FC_MAX_PAYLOAD_LEN))
- iport->max_payload_size = min(rdf_size,
- iport->max_payload_size);
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "max_payload_size from fabric: %u set: %d", rdf_size,
- iport->max_payload_size);
- iport->r_a_tov = be32_to_cpu(FNIC_LOGI_R_A_TOV(flogi_rsp->els));
- iport->e_d_tov = be32_to_cpu(FNIC_LOGI_E_D_TOV(flogi_rsp->els));
- if (FNIC_LOGI_FEATURES(flogi_rsp->els) & FNIC_FC_EDTOV_NSEC)
- iport->e_d_tov = iport->e_d_tov / FNIC_NSEC_TO_MSEC;
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "From fabric: R_A_TOV: %d E_D_TOV: %d",
- iport->r_a_tov, iport->e_d_tov);
- fc_host_fabric_name(iport->fnic->host) =
- get_unaligned_be64(&FNIC_LOGI_NODE_NAME(flogi_rsp->els));
- fc_host_port_id(iport->fnic->host) = iport->fcid;
- fnic_fdls_learn_fcoe_macs(iport, rx_frame, fcid);
- if (fnic_fdls_register_portid(iport, iport->fcid, rx_frame) != 0) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "0x%x: FLOGI registration failed", iport->fcid);
- break;
- }
- memcpy(&fcmac[3], fcid, 3);
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "Adding vNIC device MAC addr: %02x:%02x:%02x:%02x:%02x:%02x",
- fcmac[0], fcmac[1], fcmac[2], fcmac[3], fcmac[4],
- fcmac[5]);
- vnic_dev_add_addr(iport->fnic->vdev, fcmac);
- if (fdls_get_state(fabric) == FDLS_STATE_FABRIC_FLOGI) {
- fnic_fdls_start_plogi(iport);
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "FLOGI response received. Starting PLOGI");
- } else {
- /* From FDLS_STATE_FABRIC_FLOGI state fabric can only go to
- * FDLS_STATE_LINKDOWN
- * state, hence we don't have to worry about undoing:
- * the fnic_fdls_register_portid and vnic_dev_add_addr
- */
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "FLOGI response received in state (%d). Dropping frame",
- fdls_get_state(fabric));
- }
- break;
- case ELS_LS_RJT:
- atomic64_inc(&iport->iport_stats.fabric_flogi_ls_rejects);
- if (fabric->retry_counter < iport->max_flogi_retries) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "FLOGI returned ELS_LS_RJT BUSY. Retry from timer routine %p",
- iport);
- /* Retry Flogi again from the timer routine. */
- fabric->flags |= FNIC_FDLS_RETRY_FRAME;
- } else {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "FLOGI returned ELS_LS_RJT. Halting discovery %p",
- iport);
- if (iport->fabric.timer_pending) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "iport 0x%p Canceling fabric disc timer\n",
- iport);
- fnic_del_fabric_timer_sync(fnic);
- }
- fabric->timer_pending = 0;
- fabric->retry_counter = 0;
- }
- break;
- default:
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "FLOGI response not accepted: 0x%x",
- flogi_rsp->els.fl_cmd);
- atomic64_inc(&iport->iport_stats.fabric_flogi_misc_rejects);
- break;
- }
- }
- static void
- fdls_process_fabric_plogi_rsp(struct fnic_iport_s *iport,
- struct fc_frame_header *fchdr)
- {
- struct fc_std_flogi *plogi_rsp = (struct fc_std_flogi *) fchdr;
- struct fc_std_els_rjt_rsp *els_rjt = (struct fc_std_els_rjt_rsp *) fchdr;
- struct fnic_fdls_fabric_s *fdls = &iport->fabric;
- struct fnic *fnic = iport->fnic;
- uint16_t oxid = FNIC_STD_GET_OX_ID(fchdr);
- if (fdls_get_state((&iport->fabric)) != FDLS_STATE_FABRIC_PLOGI) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "Fabric PLOGI response received in state (%d). Dropping frame",
- fdls_get_state(&iport->fabric));
- return;
- }
- if (iport->active_oxid_fabric_req != oxid) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "Incorrect OXID in response. state: %d, oxid recvd: 0x%x, active oxid: 0x%x\n",
- fdls_get_state(fdls), oxid, iport->active_oxid_fabric_req);
- return;
- }
- fdls_free_oxid(iport, oxid, &iport->active_oxid_fabric_req);
- switch (plogi_rsp->els.fl_cmd) {
- case ELS_LS_ACC:
- atomic64_inc(&iport->iport_stats.fabric_plogi_ls_accepts);
- if (iport->fabric.timer_pending) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "iport fcid: 0x%x fabric PLOGI response: Accepted\n",
- iport->fcid);
- fnic_del_fabric_timer_sync(fnic);
- }
- iport->fabric.timer_pending = 0;
- iport->fabric.retry_counter = 0;
- fdls_set_state(&iport->fabric, FDLS_STATE_RPN_ID);
- fdls_send_rpn_id(iport);
- break;
- case ELS_LS_RJT:
- atomic64_inc(&iport->iport_stats.fabric_plogi_ls_rejects);
- if (((els_rjt->rej.er_reason == ELS_RJT_BUSY)
- || (els_rjt->rej.er_reason == ELS_RJT_UNAB))
- && (iport->fabric.retry_counter < iport->max_plogi_retries)) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "0x%x: Fabric PLOGI ELS_LS_RJT BUSY. Retry from timer routine",
- iport->fcid);
- } else {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "0x%x: Fabric PLOGI ELS_LS_RJT. Halting discovery",
- iport->fcid);
- if (iport->fabric.timer_pending) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "iport fcid: 0x%x Canceling fabric disc timer\n",
- iport->fcid);
- fnic_del_fabric_timer_sync(fnic);
- }
- iport->fabric.timer_pending = 0;
- iport->fabric.retry_counter = 0;
- return;
- }
- break;
- default:
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "PLOGI response not accepted: 0x%x",
- plogi_rsp->els.fl_cmd);
- atomic64_inc(&iport->iport_stats.fabric_plogi_misc_rejects);
- break;
- }
- }
- static void fdls_process_fdmi_plogi_rsp(struct fnic_iport_s *iport,
- struct fc_frame_header *fchdr)
- {
- struct fc_std_flogi *plogi_rsp = (struct fc_std_flogi *)fchdr;
- struct fc_std_els_rjt_rsp *els_rjt = (struct fc_std_els_rjt_rsp *)fchdr;
- struct fnic_fdls_fabric_s *fdls = &iport->fabric;
- struct fnic *fnic = iport->fnic;
- u64 fdmi_tov;
- uint16_t oxid = FNIC_STD_GET_OX_ID(fchdr);
- if (iport->active_oxid_fdmi_plogi != oxid) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "Incorrect OXID in response. state: %d, oxid recvd: 0x%x, active oxid: 0x%x\n",
- fdls_get_state(fdls), oxid, iport->active_oxid_fdmi_plogi);
- return;
- }
- iport->fabric.fdmi_pending &= ~FDLS_FDMI_PLOGI_PENDING;
- fdls_free_oxid(iport, oxid, &iport->active_oxid_fdmi_plogi);
- if (ntoh24(fchdr->fh_s_id) == FC_FID_MGMT_SERV) {
- timer_delete_sync(&iport->fabric.fdmi_timer);
- iport->fabric.fdmi_pending = 0;
- switch (plogi_rsp->els.fl_cmd) {
- case ELS_LS_ACC:
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "FDLS process fdmi PLOGI response status: ELS_LS_ACC\n");
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "Sending fdmi registration for port 0x%x\n",
- iport->fcid);
- fdls_fdmi_register_hba(iport);
- fdls_fdmi_register_pa(iport);
- fdmi_tov = jiffies + msecs_to_jiffies(5000);
- mod_timer(&iport->fabric.fdmi_timer,
- round_jiffies(fdmi_tov));
- break;
- case ELS_LS_RJT:
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "Fabric FDMI PLOGI returned ELS_LS_RJT reason: 0x%x",
- els_rjt->rej.er_reason);
- if (((els_rjt->rej.er_reason == ELS_RJT_BUSY)
- || (els_rjt->rej.er_reason == ELS_RJT_UNAB))
- && (iport->fabric.fdmi_retry < 7)) {
- iport->fabric.fdmi_retry++;
- fdls_send_fdmi_plogi(iport);
- }
- break;
- default:
- break;
- }
- }
- }
- static void fdls_process_fdmi_reg_ack(struct fnic_iport_s *iport,
- struct fc_frame_header *fchdr,
- int rsp_type)
- {
- struct fnic *fnic = iport->fnic;
- uint16_t oxid;
- if (!iport->fabric.fdmi_pending) {
- FNIC_FCS_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
- "Received FDMI ack while not waiting: 0x%x\n",
- FNIC_STD_GET_OX_ID(fchdr));
- return;
- }
- oxid = FNIC_STD_GET_OX_ID(fchdr);
- if ((iport->active_oxid_fdmi_rhba != oxid) &&
- (iport->active_oxid_fdmi_rpa != oxid)) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "Incorrect OXID in response. oxid recvd: 0x%x, active oxids(rhba,rpa): 0x%x, 0x%x\n",
- oxid, iport->active_oxid_fdmi_rhba, iport->active_oxid_fdmi_rpa);
- return;
- }
- if (FNIC_FRAME_TYPE(oxid) == FNIC_FRAME_TYPE_FDMI_RHBA) {
- iport->fabric.fdmi_pending &= ~FDLS_FDMI_REG_HBA_PENDING;
- fdls_free_oxid(iport, oxid, &iport->active_oxid_fdmi_rhba);
- } else {
- iport->fabric.fdmi_pending &= ~FDLS_FDMI_RPA_PENDING;
- fdls_free_oxid(iport, oxid, &iport->active_oxid_fdmi_rpa);
- }
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "iport fcid: 0x%x: Received FDMI registration ack\n",
- iport->fcid);
- if (!iport->fabric.fdmi_pending) {
- timer_delete_sync(&iport->fabric.fdmi_timer);
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "iport fcid: 0x%x: Canceling FDMI timer\n",
- iport->fcid);
- }
- }
- static void fdls_process_fdmi_abts_rsp(struct fnic_iport_s *iport,
- struct fc_frame_header *fchdr)
- {
- uint32_t s_id;
- struct fnic *fnic = iport->fnic;
- uint16_t oxid;
- s_id = ntoh24(FNIC_STD_GET_S_ID(fchdr));
- if (!(s_id != FC_FID_MGMT_SERV)) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "Received abts rsp with invalid SID: 0x%x. Dropping frame",
- s_id);
- return;
- }
- oxid = FNIC_STD_GET_OX_ID(fchdr);
- switch (FNIC_FRAME_TYPE(oxid)) {
- case FNIC_FRAME_TYPE_FDMI_PLOGI:
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "Received FDMI PLOGI ABTS rsp with oxid: 0x%x", oxid);
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "0x%x: iport->fabric.fdmi_pending: 0x%x",
- iport->fcid, iport->fabric.fdmi_pending);
- fdls_free_oxid(iport, oxid, &iport->active_oxid_fdmi_plogi);
- iport->fabric.fdmi_pending &= ~FDLS_FDMI_PLOGI_PENDING;
- iport->fabric.fdmi_pending &= ~FDLS_FDMI_ABORT_PENDING;
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "0x%x: iport->fabric.fdmi_pending: 0x%x",
- iport->fcid, iport->fabric.fdmi_pending);
- break;
- case FNIC_FRAME_TYPE_FDMI_RHBA:
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "Received FDMI RHBA ABTS rsp with oxid: 0x%x", oxid);
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "0x%x: iport->fabric.fdmi_pending: 0x%x",
- iport->fcid, iport->fabric.fdmi_pending);
- iport->fabric.fdmi_pending &= ~FDLS_FDMI_REG_HBA_PENDING;
- /* If RPA is still pending, don't turn off ABORT PENDING.
- * We count on the timer to detect the ABTS timeout and take
- * corrective action.
- */
- if (!(iport->fabric.fdmi_pending & FDLS_FDMI_RPA_PENDING))
- iport->fabric.fdmi_pending &= ~FDLS_FDMI_ABORT_PENDING;
- fdls_free_oxid(iport, oxid, &iport->active_oxid_fdmi_rhba);
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "0x%x: iport->fabric.fdmi_pending: 0x%x",
- iport->fcid, iport->fabric.fdmi_pending);
- break;
- case FNIC_FRAME_TYPE_FDMI_RPA:
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "Received FDMI RPA ABTS rsp with oxid: 0x%x", oxid);
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "0x%x: iport->fabric.fdmi_pending: 0x%x",
- iport->fcid, iport->fabric.fdmi_pending);
- iport->fabric.fdmi_pending &= ~FDLS_FDMI_RPA_PENDING;
- /* If RHBA is still pending, don't turn off ABORT PENDING.
- * We count on the timer to detect the ABTS timeout and take
- * corrective action.
- */
- if (!(iport->fabric.fdmi_pending & FDLS_FDMI_REG_HBA_PENDING))
- iport->fabric.fdmi_pending &= ~FDLS_FDMI_ABORT_PENDING;
- fdls_free_oxid(iport, oxid, &iport->active_oxid_fdmi_rpa);
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "0x%x: iport->fabric.fdmi_pending: 0x%x",
- iport->fcid, iport->fabric.fdmi_pending);
- break;
- default:
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "Received abts rsp with invalid oxid: 0x%x. Dropping frame",
- oxid);
- break;
- }
- /*
- * Only if ABORT PENDING is off, delete the timer, and if no other
- * operations are pending, retry FDMI.
- * Otherwise, let the timer pop and take the appropriate action.
- */
- if (!(iport->fabric.fdmi_pending & FDLS_FDMI_ABORT_PENDING)) {
- timer_delete_sync(&iport->fabric.fdmi_timer);
- if (!iport->fabric.fdmi_pending)
- fdls_fdmi_retry_plogi(iport);
- }
- }
- static void
- fdls_process_fabric_abts_rsp(struct fnic_iport_s *iport,
- struct fc_frame_header *fchdr)
- {
- uint32_t s_id;
- struct fc_std_abts_ba_acc *ba_acc = (struct fc_std_abts_ba_acc *)fchdr;
- struct fc_std_abts_ba_rjt *ba_rjt;
- uint32_t fabric_state = iport->fabric.state;
- struct fnic *fnic = iport->fnic;
- int frame_type;
- uint16_t oxid;
- s_id = ntoh24(fchdr->fh_s_id);
- ba_rjt = (struct fc_std_abts_ba_rjt *) fchdr;
- if (!((s_id == FC_FID_DIR_SERV) || (s_id == FC_FID_FLOGI)
- || (s_id == FC_FID_FCTRL))) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "Received abts rsp with invalid SID: 0x%x. Dropping frame",
- s_id);
- return;
- }
- oxid = FNIC_STD_GET_OX_ID(fchdr);
- if (iport->active_oxid_fabric_req != oxid) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "Received abts rsp with invalid oxid: 0x%x. Dropping frame",
- oxid);
- return;
- }
- if (iport->fabric.timer_pending) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "Canceling fabric disc timer %p\n", iport);
- fnic_del_fabric_timer_sync(fnic);
- }
- iport->fabric.timer_pending = 0;
- iport->fabric.flags &= ~FNIC_FDLS_FABRIC_ABORT_ISSUED;
- if (fchdr->fh_r_ctl == FC_RCTL_BA_ACC) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "Received abts rsp BA_ACC for fabric_state: %d OX_ID: 0x%x",
- fabric_state, be16_to_cpu(ba_acc->acc.ba_ox_id));
- } else if (fchdr->fh_r_ctl == FC_RCTL_BA_RJT) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "BA_RJT fs: %d OX_ID: 0x%x rc: 0x%x rce: 0x%x",
- fabric_state, FNIC_STD_GET_OX_ID(&ba_rjt->fchdr),
- ba_rjt->rjt.br_reason, ba_rjt->rjt.br_explan);
- }
- frame_type = FNIC_FRAME_TYPE(oxid);
- fdls_free_oxid(iport, oxid, &iport->active_oxid_fabric_req);
- /* currently error handling/retry logic is same for ABTS BA_ACC & BA_RJT */
- switch (frame_type) {
- case FNIC_FRAME_TYPE_FABRIC_FLOGI:
- if (iport->fabric.retry_counter < iport->max_flogi_retries)
- fdls_send_fabric_flogi(iport);
- else
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "Exceeded max FLOGI retries");
- break;
- case FNIC_FRAME_TYPE_FABRIC_LOGO:
- if (iport->fabric.retry_counter < FABRIC_LOGO_MAX_RETRY)
- fdls_send_fabric_logo(iport);
- break;
- case FNIC_FRAME_TYPE_FABRIC_PLOGI:
- if (iport->fabric.retry_counter < iport->max_plogi_retries)
- fdls_send_fabric_plogi(iport);
- else
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "Exceeded max PLOGI retries");
- break;
- case FNIC_FRAME_TYPE_FABRIC_RPN:
- if (iport->fabric.retry_counter < FDLS_RETRY_COUNT)
- fdls_send_rpn_id(iport);
- else
- /* go back to fabric Plogi */
- fnic_fdls_start_plogi(iport);
- break;
- case FNIC_FRAME_TYPE_FABRIC_SCR:
- if (iport->fabric.retry_counter < FDLS_RETRY_COUNT)
- fdls_send_scr(iport);
- else {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "SCR exhausted retries. Start fabric PLOGI %p",
- iport);
- fnic_fdls_start_plogi(iport); /* go back to fabric Plogi */
- }
- break;
- case FNIC_FRAME_TYPE_FABRIC_RFT:
- if (iport->fabric.retry_counter < FDLS_RETRY_COUNT)
- fdls_send_register_fc4_types(iport);
- else {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "RFT exhausted retries. Start fabric PLOGI %p",
- iport);
- fnic_fdls_start_plogi(iport); /* go back to fabric Plogi */
- }
- break;
- case FNIC_FRAME_TYPE_FABRIC_RFF:
- if (iport->fabric.retry_counter < FDLS_RETRY_COUNT)
- fdls_send_register_fc4_features(iport);
- else {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "RFF exhausted retries. Start fabric PLOGI %p",
- iport);
- fnic_fdls_start_plogi(iport); /* go back to fabric Plogi */
- }
- break;
- case FNIC_FRAME_TYPE_FABRIC_GPN_FT:
- if (iport->fabric.retry_counter <= FDLS_RETRY_COUNT)
- fdls_send_gpn_ft(iport, fabric_state);
- else
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "GPN FT exhausted retries. Start fabric PLOGI %p",
- iport);
- break;
- default:
- /*
- * We should not be here since we already validated rx oxid with
- * our active_oxid_fabric_req
- */
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "Invalid OXID/active oxid 0x%x\n", oxid);
- WARN_ON(true);
- return;
- }
- }
- static void
- fdls_process_abts_req(struct fnic_iport_s *iport, struct fc_frame_header *fchdr)
- {
- uint8_t *frame;
- struct fc_std_abts_ba_acc *pba_acc;
- uint32_t nport_id;
- uint16_t oxid = FNIC_STD_GET_OX_ID(fchdr);
- struct fnic_tport_s *tport;
- struct fnic *fnic = iport->fnic;
- uint16_t frame_size = FNIC_ETH_FCOE_HDRS_OFFSET +
- sizeof(struct fc_std_abts_ba_acc);
- nport_id = ntoh24(fchdr->fh_s_id);
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "Received abort from SID 0x%8x", nport_id);
- tport = fnic_find_tport_by_fcid(iport, nport_id);
- if (tport) {
- if (tport->active_oxid == oxid) {
- tport->flags |= FNIC_FDLS_TGT_ABORT_ISSUED;
- fdls_free_oxid(iport, oxid, &tport->active_oxid);
- }
- }
- frame = fdls_alloc_frame(iport);
- if (frame == NULL) {
- FNIC_FCS_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
- "0x%x: Failed to allocate frame to send response for ABTS req",
- iport->fcid);
- return;
- }
- pba_acc = (struct fc_std_abts_ba_acc *) (frame + FNIC_ETH_FCOE_HDRS_OFFSET);
- *pba_acc = (struct fc_std_abts_ba_acc) {
- .fchdr = {.fh_r_ctl = FC_RCTL_BA_ACC,
- .fh_f_ctl = {FNIC_FCP_RSP_FCTL, 0, 0}},
- .acc = {.ba_low_seq_cnt = 0, .ba_high_seq_cnt = cpu_to_be16(0xFFFF)}
- };
- FNIC_STD_SET_S_ID(pba_acc->fchdr, fchdr->fh_d_id);
- FNIC_STD_SET_D_ID(pba_acc->fchdr, fchdr->fh_s_id);
- FNIC_STD_SET_OX_ID(pba_acc->fchdr, FNIC_STD_GET_OX_ID(fchdr));
- FNIC_STD_SET_RX_ID(pba_acc->fchdr, FNIC_STD_GET_RX_ID(fchdr));
- pba_acc->acc.ba_rx_id = cpu_to_be16(FNIC_STD_GET_RX_ID(fchdr));
- pba_acc->acc.ba_ox_id = cpu_to_be16(FNIC_STD_GET_OX_ID(fchdr));
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "0x%x: FDLS send BA ACC with oxid: 0x%x",
- iport->fcid, oxid);
- fnic_send_fcoe_frame(iport, frame, frame_size);
- }
- static void
- fdls_process_unsupported_els_req(struct fnic_iport_s *iport,
- struct fc_frame_header *fchdr)
- {
- uint8_t *frame;
- struct fc_std_els_rjt_rsp *pls_rsp;
- uint16_t oxid;
- uint32_t d_id = ntoh24(fchdr->fh_d_id);
- struct fnic *fnic = iport->fnic;
- uint16_t frame_size = FNIC_ETH_FCOE_HDRS_OFFSET +
- sizeof(struct fc_std_els_rjt_rsp);
- if (iport->fcid != d_id) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "Dropping unsupported ELS with illegal frame bits 0x%x\n",
- d_id);
- atomic64_inc(&iport->iport_stats.unsupported_frames_dropped);
- return;
- }
- if ((iport->state != FNIC_IPORT_STATE_READY)
- && (iport->state != FNIC_IPORT_STATE_FABRIC_DISC)) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "Dropping unsupported ELS request in iport state: %d",
- iport->state);
- atomic64_inc(&iport->iport_stats.unsupported_frames_dropped);
- return;
- }
- frame = fdls_alloc_frame(iport);
- if (frame == NULL) {
- FNIC_FCS_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
- "Failed to allocate frame to send response to unsupported ELS request");
- return;
- }
- pls_rsp = (struct fc_std_els_rjt_rsp *) (frame + FNIC_ETH_FCOE_HDRS_OFFSET);
- fdls_init_els_rjt_frame(frame, iport);
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "0x%x: Process unsupported ELS request from SID: 0x%x",
- iport->fcid, ntoh24(fchdr->fh_s_id));
- /* We don't support this ELS request, send a reject */
- pls_rsp->rej.er_reason = 0x0B;
- pls_rsp->rej.er_explan = 0x0;
- pls_rsp->rej.er_vendor = 0x0;
- FNIC_STD_SET_S_ID(pls_rsp->fchdr, fchdr->fh_d_id);
- FNIC_STD_SET_D_ID(pls_rsp->fchdr, fchdr->fh_s_id);
- oxid = FNIC_STD_GET_OX_ID(fchdr);
- FNIC_STD_SET_OX_ID(pls_rsp->fchdr, oxid);
- fnic_send_fcoe_frame(iport, frame, frame_size);
- }
- static void
- fdls_process_rls_req(struct fnic_iport_s *iport, struct fc_frame_header *fchdr)
- {
- uint8_t *frame;
- struct fc_std_rls_acc *prls_acc_rsp;
- uint16_t oxid;
- struct fnic *fnic = iport->fnic;
- uint16_t frame_size = FNIC_ETH_FCOE_HDRS_OFFSET +
- sizeof(struct fc_std_rls_acc);
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "Process RLS request %d", iport->fnic->fnic_num);
- if ((iport->state != FNIC_IPORT_STATE_READY)
- && (iport->state != FNIC_IPORT_STATE_FABRIC_DISC)) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "Received RLS req in iport state: %d. Dropping the frame.",
- iport->state);
- return;
- }
- frame = fdls_alloc_frame(iport);
- if (frame == NULL) {
- FNIC_FCS_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
- "Failed to allocate frame to send RLS accept");
- return;
- }
- prls_acc_rsp = (struct fc_std_rls_acc *) (frame + FNIC_ETH_FCOE_HDRS_OFFSET);
- FNIC_STD_SET_S_ID(prls_acc_rsp->fchdr, fchdr->fh_d_id);
- FNIC_STD_SET_D_ID(prls_acc_rsp->fchdr, fchdr->fh_s_id);
- oxid = FNIC_STD_GET_OX_ID(fchdr);
- FNIC_STD_SET_OX_ID(prls_acc_rsp->fchdr, oxid);
- FNIC_STD_SET_RX_ID(prls_acc_rsp->fchdr, FNIC_UNASSIGNED_RXID);
- FNIC_STD_SET_F_CTL(prls_acc_rsp->fchdr, FNIC_ELS_REP_FCTL << 16);
- FNIC_STD_SET_R_CTL(prls_acc_rsp->fchdr, FC_RCTL_ELS_REP);
- FNIC_STD_SET_TYPE(prls_acc_rsp->fchdr, FC_TYPE_ELS);
- prls_acc_rsp->els.rls_cmd = ELS_LS_ACC;
- prls_acc_rsp->els.rls_lesb.lesb_link_fail =
- cpu_to_be32(iport->fnic->link_down_cnt);
- fnic_send_fcoe_frame(iport, frame, frame_size);
- }
- static void
- fdls_process_els_req(struct fnic_iport_s *iport, struct fc_frame_header *fchdr,
- uint32_t len)
- {
- uint8_t *frame;
- struct fc_std_els_acc_rsp *pels_acc;
- uint16_t oxid;
- uint8_t *fc_payload;
- uint8_t type;
- struct fnic *fnic = iport->fnic;
- uint16_t frame_size = FNIC_ETH_FCOE_HDRS_OFFSET;
- fc_payload = (uint8_t *) fchdr + sizeof(struct fc_frame_header);
- type = *fc_payload;
- if ((iport->state != FNIC_IPORT_STATE_READY)
- && (iport->state != FNIC_IPORT_STATE_FABRIC_DISC)) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "Dropping ELS frame type: 0x%x in iport state: %d",
- type, iport->state);
- return;
- }
- switch (type) {
- case ELS_ECHO:
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "sending LS_ACC for ECHO request %d\n",
- iport->fnic->fnic_num);
- break;
- case ELS_RRQ:
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "sending LS_ACC for RRQ request %d\n",
- iport->fnic->fnic_num);
- break;
- default:
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "sending LS_ACC for 0x%x ELS frame\n", type);
- break;
- }
- frame = fdls_alloc_frame(iport);
- if (frame == NULL) {
- FNIC_FCS_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
- "Failed to allocate frame to send ELS response for 0x%x",
- type);
- return;
- }
- if (type == ELS_ECHO) {
- /* Brocade sends a longer payload, copy all frame back */
- memcpy(frame, fchdr, len);
- }
- pels_acc = (struct fc_std_els_acc_rsp *) (frame + FNIC_ETH_FCOE_HDRS_OFFSET);
- fdls_init_els_acc_frame(frame, iport);
- FNIC_STD_SET_D_ID(pels_acc->fchdr, fchdr->fh_s_id);
- oxid = FNIC_STD_GET_OX_ID(fchdr);
- FNIC_STD_SET_OX_ID(pels_acc->fchdr, oxid);
- if (type == ELS_ECHO)
- frame_size += len;
- else
- frame_size += sizeof(struct fc_std_els_acc_rsp);
- fnic_send_fcoe_frame(iport, frame, frame_size);
- }
- static void
- fdls_process_tgt_abts_rsp(struct fnic_iport_s *iport,
- struct fc_frame_header *fchdr)
- {
- uint32_t s_id;
- struct fnic_tport_s *tport;
- uint32_t tport_state;
- struct fc_std_abts_ba_acc *ba_acc;
- struct fc_std_abts_ba_rjt *ba_rjt;
- uint16_t oxid;
- struct fnic *fnic = iport->fnic;
- int frame_type;
- s_id = ntoh24(fchdr->fh_s_id);
- ba_acc = (struct fc_std_abts_ba_acc *)fchdr;
- ba_rjt = (struct fc_std_abts_ba_rjt *)fchdr;
- tport = fnic_find_tport_by_fcid(iport, s_id);
- if (!tport) {
- FNIC_FCS_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
- "Received tgt abts rsp with invalid SID: 0x%x", s_id);
- return;
- }
- if (tport->timer_pending) {
- FNIC_FCS_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
- "tport 0x%p Canceling fabric disc timer\n", tport);
- fnic_del_tport_timer_sync(fnic, tport);
- }
- if (iport->state != FNIC_IPORT_STATE_READY) {
- FNIC_FCS_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
- "Received tgt abts rsp in iport state(%d). Dropping.",
- iport->state);
- return;
- }
- tport->timer_pending = 0;
- tport->flags &= ~FNIC_FDLS_TGT_ABORT_ISSUED;
- tport_state = tport->state;
- oxid = FNIC_STD_GET_OX_ID(fchdr);
- /*This abort rsp is for ADISC */
- frame_type = FNIC_FRAME_TYPE(oxid);
- switch (frame_type) {
- case FNIC_FRAME_TYPE_TGT_ADISC:
- if (fchdr->fh_r_ctl == FC_RCTL_BA_ACC) {
- FNIC_FCS_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
- "OX_ID: 0x%x tgt_fcid: 0x%x rcvd tgt adisc abts resp BA_ACC",
- be16_to_cpu(ba_acc->acc.ba_ox_id),
- tport->fcid);
- } else if (fchdr->fh_r_ctl == FC_RCTL_BA_RJT) {
- FNIC_FCS_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
- "ADISC BA_RJT rcvd tport_fcid: 0x%x tport_state: %d ",
- tport->fcid, tport_state);
- FNIC_FCS_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
- "reason code: 0x%x reason code explanation:0x%x ",
- ba_rjt->rjt.br_reason,
- ba_rjt->rjt.br_explan);
- }
- if ((tport->retry_counter < FDLS_RETRY_COUNT)
- && (fchdr->fh_r_ctl == FC_RCTL_BA_ACC)) {
- fdls_free_oxid(iport, oxid, &tport->active_oxid);
- fdls_send_tgt_adisc(iport, tport);
- return;
- }
- fdls_free_oxid(iport, oxid, &tport->active_oxid);
- FNIC_FCS_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
- "ADISC not responding. Deleting target port: 0x%x",
- tport->fcid);
- fdls_delete_tport(iport, tport);
- /* Restart discovery of targets */
- if ((iport->state == FNIC_IPORT_STATE_READY)
- && (iport->fabric.state != FDLS_STATE_SEND_GPNFT)
- && (iport->fabric.state != FDLS_STATE_RSCN_GPN_FT)) {
- fdls_send_gpn_ft(iport, FDLS_STATE_SEND_GPNFT);
- }
- break;
- case FNIC_FRAME_TYPE_TGT_PLOGI:
- if (fchdr->fh_r_ctl == FC_RCTL_BA_ACC) {
- FNIC_FCS_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
- "Received tgt PLOGI abts response BA_ACC tgt_fcid: 0x%x",
- tport->fcid);
- } else if (fchdr->fh_r_ctl == FC_RCTL_BA_RJT) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "PLOGI BA_RJT received for tport_fcid: 0x%x OX_ID: 0x%x",
- tport->fcid, FNIC_STD_GET_OX_ID(fchdr));
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "reason code: 0x%x reason code explanation: 0x%x",
- ba_rjt->rjt.br_reason,
- ba_rjt->rjt.br_explan);
- }
- if ((tport->retry_counter < iport->max_plogi_retries)
- && (fchdr->fh_r_ctl == FC_RCTL_BA_ACC)) {
- fdls_free_oxid(iport, oxid, &tport->active_oxid);
- fdls_send_tgt_plogi(iport, tport);
- return;
- }
- fdls_free_oxid(iport, oxid, &tport->active_oxid);
- fdls_delete_tport(iport, tport);
- /* Restart discovery of targets */
- if ((iport->state == FNIC_IPORT_STATE_READY)
- && (iport->fabric.state != FDLS_STATE_SEND_GPNFT)
- && (iport->fabric.state != FDLS_STATE_RSCN_GPN_FT)) {
- fdls_send_gpn_ft(iport, FDLS_STATE_SEND_GPNFT);
- }
- break;
- case FNIC_FRAME_TYPE_TGT_PRLI:
- if (fchdr->fh_r_ctl == FC_RCTL_BA_ACC) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "0x%x: Received tgt PRLI abts response BA_ACC",
- tport->fcid);
- } else if (fchdr->fh_r_ctl == FC_RCTL_BA_RJT) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "PRLI BA_RJT received for tport_fcid: 0x%x OX_ID: 0x%x ",
- tport->fcid, FNIC_STD_GET_OX_ID(fchdr));
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "reason code: 0x%x reason code explanation: 0x%x",
- ba_rjt->rjt.br_reason,
- ba_rjt->rjt.br_explan);
- }
- if ((tport->retry_counter < FDLS_RETRY_COUNT)
- && (fchdr->fh_r_ctl == FC_RCTL_BA_ACC)) {
- fdls_free_oxid(iport, oxid, &tport->active_oxid);
- fdls_send_tgt_prli(iport, tport);
- return;
- }
- fdls_free_oxid(iport, oxid, &tport->active_oxid);
- fdls_send_tgt_plogi(iport, tport); /* go back to plogi */
- fdls_set_tport_state(tport, FDLS_TGT_STATE_PLOGI);
- break;
- default:
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "Received ABTS response for unknown frame %p", iport);
- break;
- }
- }
- static void
- fdls_process_plogi_req(struct fnic_iport_s *iport,
- struct fc_frame_header *fchdr)
- {
- uint8_t *frame;
- struct fc_std_els_rjt_rsp *pplogi_rsp;
- uint16_t oxid;
- uint32_t d_id = ntoh24(fchdr->fh_d_id);
- struct fnic *fnic = iport->fnic;
- uint16_t frame_size = FNIC_ETH_FCOE_HDRS_OFFSET +
- sizeof(struct fc_std_els_rjt_rsp);
- if (iport->fcid != d_id) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "Received PLOGI with illegal frame bits. Dropping frame from 0x%x",
- d_id);
- return;
- }
- if (iport->state != FNIC_IPORT_STATE_READY) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "Received PLOGI request in iport state: %d Dropping frame",
- iport->state);
- return;
- }
- frame = fdls_alloc_frame(iport);
- if (frame == NULL) {
- FNIC_FCS_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
- "Failed to allocate frame to send response to PLOGI request");
- return;
- }
- pplogi_rsp = (struct fc_std_els_rjt_rsp *) (frame + FNIC_ETH_FCOE_HDRS_OFFSET);
- fdls_init_els_rjt_frame(frame, iport);
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "0x%x: Process PLOGI request from SID: 0x%x",
- iport->fcid, ntoh24(fchdr->fh_s_id));
- /* We don't support PLOGI request, send a reject */
- pplogi_rsp->rej.er_reason = 0x0B;
- pplogi_rsp->rej.er_explan = 0x0;
- pplogi_rsp->rej.er_vendor = 0x0;
- FNIC_STD_SET_S_ID(pplogi_rsp->fchdr, fchdr->fh_d_id);
- FNIC_STD_SET_D_ID(pplogi_rsp->fchdr, fchdr->fh_s_id);
- oxid = FNIC_STD_GET_OX_ID(fchdr);
- FNIC_STD_SET_OX_ID(pplogi_rsp->fchdr, oxid);
- fnic_send_fcoe_frame(iport, frame, frame_size);
- }
- static void
- fdls_process_logo_req(struct fnic_iport_s *iport, struct fc_frame_header *fchdr)
- {
- struct fc_std_logo *logo = (struct fc_std_logo *)fchdr;
- uint32_t nport_id;
- uint64_t nport_name;
- struct fnic_tport_s *tport;
- struct fnic *fnic = iport->fnic;
- uint16_t oxid;
- nport_id = ntoh24(logo->els.fl_n_port_id);
- nport_name = be64_to_cpu(logo->els.fl_n_port_wwn);
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "Process LOGO request from fcid: 0x%x", nport_id);
- if (iport->state != FNIC_IPORT_STATE_READY) {
- FNIC_FCS_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
- "Dropping LOGO req from 0x%x in iport state: %d",
- nport_id, iport->state);
- return;
- }
- tport = fnic_find_tport_by_fcid(iport, nport_id);
- if (!tport) {
- /* We are not logged in with the nport, log and drop... */
- FNIC_FCS_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
- "Received LOGO from an nport not logged in: 0x%x(0x%llx)",
- nport_id, nport_name);
- return;
- }
- if (tport->fcid != nport_id) {
- FNIC_FCS_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
- "Received LOGO with invalid target port fcid: 0x%x(0x%llx)",
- nport_id, nport_name);
- return;
- }
- if (tport->timer_pending) {
- FNIC_FCS_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
- "tport fcid 0x%x: Canceling disc timer\n",
- tport->fcid);
- fnic_del_tport_timer_sync(fnic, tport);
- tport->timer_pending = 0;
- }
- /* got a logo in response to adisc to a target which has logged out */
- if (tport->state == FDLS_TGT_STATE_ADISC) {
- tport->retry_counter = 0;
- oxid = tport->active_oxid;
- fdls_free_oxid(iport, oxid, &tport->active_oxid);
- fdls_delete_tport(iport, tport);
- fdls_send_logo_resp(iport, &logo->fchdr);
- if ((iport->state == FNIC_IPORT_STATE_READY)
- && (fdls_get_state(&iport->fabric) != FDLS_STATE_SEND_GPNFT)
- && (fdls_get_state(&iport->fabric) != FDLS_STATE_RSCN_GPN_FT)) {
- FNIC_FCS_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
- "Sending GPNFT in response to LOGO from Target:0x%x",
- nport_id);
- fdls_send_gpn_ft(iport, FDLS_STATE_SEND_GPNFT);
- return;
- }
- } else {
- fdls_delete_tport(iport, tport);
- }
- if (iport->state == FNIC_IPORT_STATE_READY) {
- fdls_send_logo_resp(iport, &logo->fchdr);
- if ((fdls_get_state(&iport->fabric) != FDLS_STATE_SEND_GPNFT) &&
- (fdls_get_state(&iport->fabric) != FDLS_STATE_RSCN_GPN_FT)) {
- FNIC_FCS_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
- "Sending GPNFT in response to LOGO from Target:0x%x",
- nport_id);
- fdls_send_gpn_ft(iport, FDLS_STATE_SEND_GPNFT);
- }
- }
- }
- static void
- fdls_process_rscn(struct fnic_iport_s *iport, struct fc_frame_header *fchdr)
- {
- struct fc_std_rscn *rscn;
- struct fc_els_rscn_page *rscn_port = NULL;
- int num_ports;
- struct fnic_tport_s *tport, *next;
- uint32_t nport_id;
- uint8_t fcid[3];
- int newports = 0;
- struct fnic_fdls_fabric_s *fdls = &iport->fabric;
- struct fnic *fnic = iport->fnic;
- int rscn_type = NOT_PC_RSCN;
- uint32_t sid = ntoh24(fchdr->fh_s_id);
- unsigned long reset_fnic_list_lock_flags = 0;
- uint16_t rscn_payload_len;
- atomic64_inc(&iport->iport_stats.num_rscns);
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "FDLS process RSCN %p", iport);
- if (iport->state != FNIC_IPORT_STATE_READY) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "FDLS RSCN received in state(%d). Dropping",
- fdls_get_state(fdls));
- return;
- }
- rscn = (struct fc_std_rscn *)fchdr;
- rscn_payload_len = be16_to_cpu(rscn->els.rscn_plen);
- /* frame validation */
- if ((rscn_payload_len % 4 != 0) || (rscn_payload_len < 8)
- || (rscn_payload_len > 1024)
- || (rscn->els.rscn_page_len != 4)) {
- num_ports = 0;
- if ((rscn_payload_len == 0xFFFF)
- && (sid == FC_FID_FCTRL)) {
- rscn_type = PC_RSCN;
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "pcrscn: PCRSCN received. sid: 0x%x payload len: 0x%x",
- sid, rscn_payload_len);
- } else {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "RSCN payload_len: 0x%x page_len: 0x%x",
- rscn_payload_len, rscn->els.rscn_page_len);
- /* if this happens then we need to send ADISC to all the tports. */
- list_for_each_entry_safe(tport, next, &iport->tport_list, links) {
- if (tport->state == FDLS_TGT_STATE_READY)
- tport->flags |= FNIC_FDLS_TPORT_SEND_ADISC;
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "RSCN for port id: 0x%x", tport->fcid);
- }
- } /* end else */
- } else {
- num_ports = (rscn_payload_len - 4) / rscn->els.rscn_page_len;
- rscn_port = (struct fc_els_rscn_page *)(rscn + 1);
- }
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "RSCN received for num_ports: %d payload_len: %d page_len: %d ",
- num_ports, rscn_payload_len, rscn->els.rscn_page_len);
- /*
- * RSCN have at least one Port_ID page , but may not have any port_id
- * in it. If no port_id is specified in the Port_ID page , we send
- * ADISC to all the tports
- */
- while (num_ports) {
- memcpy(fcid, rscn_port->rscn_fid, 3);
- nport_id = ntoh24(fcid);
- rscn_port++;
- num_ports--;
- /* if this happens then we need to send ADISC to all the tports. */
- if (nport_id == 0) {
- list_for_each_entry_safe(tport, next, &iport->tport_list,
- links) {
- if (tport->state == FDLS_TGT_STATE_READY)
- tport->flags |= FNIC_FDLS_TPORT_SEND_ADISC;
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "RSCN for port id: 0x%x", tport->fcid);
- }
- break;
- }
- tport = fnic_find_tport_by_fcid(iport, nport_id);
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "RSCN port id list: 0x%x", nport_id);
- if (!tport) {
- newports++;
- continue;
- }
- if (tport->state == FDLS_TGT_STATE_READY)
- tport->flags |= FNIC_FDLS_TPORT_SEND_ADISC;
- }
- if (pc_rscn_handling_feature_flag == PC_RSCN_HANDLING_FEATURE_ON &&
- rscn_type == PC_RSCN && fnic->role == FNIC_ROLE_FCP_INITIATOR) {
- if (fnic->pc_rscn_handling_status == PC_RSCN_HANDLING_IN_PROGRESS) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "PCRSCN handling already in progress. Skip host reset: %d",
- iport->fnic->fnic_num);
- return;
- }
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "Processing PCRSCN. Queuing fnic for host reset: %d",
- iport->fnic->fnic_num);
- fnic->pc_rscn_handling_status = PC_RSCN_HANDLING_IN_PROGRESS;
- spin_unlock_irqrestore(&fnic->fnic_lock, fnic->lock_flags);
- spin_lock_irqsave(&reset_fnic_list_lock,
- reset_fnic_list_lock_flags);
- list_add_tail(&fnic->links, &reset_fnic_list);
- spin_unlock_irqrestore(&reset_fnic_list_lock,
- reset_fnic_list_lock_flags);
- queue_work(reset_fnic_work_queue, &reset_fnic_work);
- spin_lock_irqsave(&fnic->fnic_lock, fnic->lock_flags);
- } else {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "FDLS process RSCN sending GPN_FT: newports: %d", newports);
- fdls_send_gpn_ft(iport, FDLS_STATE_RSCN_GPN_FT);
- fdls_send_rscn_resp(iport, fchdr);
- }
- }
- void fnic_fdls_disc_start(struct fnic_iport_s *iport)
- {
- struct fnic *fnic = iport->fnic;
- fc_host_fabric_name(iport->fnic->host) = 0;
- fc_host_post_event(iport->fnic->host, fc_get_event_number(),
- FCH_EVT_LIPRESET, 0);
- if (!iport->usefip) {
- if (iport->flags & FNIC_FIRST_LINK_UP) {
- spin_unlock_irqrestore(&fnic->fnic_lock, fnic->lock_flags);
- fnic_scsi_fcpio_reset(iport->fnic);
- spin_lock_irqsave(&fnic->fnic_lock, fnic->lock_flags);
- iport->flags &= ~FNIC_FIRST_LINK_UP;
- }
- fnic_fdls_start_flogi(iport);
- } else
- fnic_fdls_start_plogi(iport);
- }
- static void
- fdls_process_adisc_req(struct fnic_iport_s *iport,
- struct fc_frame_header *fchdr)
- {
- struct fc_std_els_adisc *padisc_acc;
- struct fc_std_els_adisc *adisc_req = (struct fc_std_els_adisc *)fchdr;
- uint64_t frame_wwnn;
- uint64_t frame_wwpn;
- uint32_t tgt_fcid;
- struct fnic_tport_s *tport;
- uint8_t *fcid;
- uint8_t *rjt_frame;
- uint8_t *acc_frame;
- struct fc_std_els_rjt_rsp *prjts_rsp;
- uint16_t oxid;
- struct fnic *fnic = iport->fnic;
- uint16_t rjt_frame_size = FNIC_ETH_FCOE_HDRS_OFFSET +
- sizeof(struct fc_std_els_rjt_rsp);
- uint16_t acc_frame_size = FNIC_ETH_FCOE_HDRS_OFFSET +
- sizeof(struct fc_std_els_adisc);
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "Process ADISC request %d", iport->fnic->fnic_num);
- fcid = FNIC_STD_GET_S_ID(fchdr);
- tgt_fcid = ntoh24(fcid);
- tport = fnic_find_tport_by_fcid(iport, tgt_fcid);
- if (!tport) {
- FNIC_FCS_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
- "tport for fcid: 0x%x not found. Dropping ADISC req.",
- tgt_fcid);
- return;
- }
- if (iport->state != FNIC_IPORT_STATE_READY) {
- FNIC_FCS_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
- "Dropping ADISC req from fcid: 0x%x in iport state: %d",
- tgt_fcid, iport->state);
- return;
- }
- frame_wwnn = be64_to_cpu(adisc_req->els.adisc_wwnn);
- frame_wwpn = be64_to_cpu(adisc_req->els.adisc_wwpn);
- if ((frame_wwnn != tport->wwnn) || (frame_wwpn != tport->wwpn)) {
- /* send reject */
- FNIC_FCS_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
- "ADISC req from fcid: 0x%x mismatch wwpn: 0x%llx wwnn: 0x%llx",
- tgt_fcid, frame_wwpn, frame_wwnn);
- FNIC_FCS_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
- "local tport wwpn: 0x%llx wwnn: 0x%llx. Sending RJT",
- tport->wwpn, tport->wwnn);
- rjt_frame = fdls_alloc_frame(iport);
- if (rjt_frame == NULL) {
- FNIC_FCS_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
- "Failed to allocate rjt_frame to send response to ADISC request");
- return;
- }
- prjts_rsp = (struct fc_std_els_rjt_rsp *) (rjt_frame + FNIC_ETH_FCOE_HDRS_OFFSET);
- fdls_init_els_rjt_frame(rjt_frame, iport);
- prjts_rsp->rej.er_reason = 0x03; /* logical error */
- prjts_rsp->rej.er_explan = 0x1E; /* N_port login required */
- prjts_rsp->rej.er_vendor = 0x0;
- FNIC_STD_SET_S_ID(prjts_rsp->fchdr, fchdr->fh_d_id);
- FNIC_STD_SET_D_ID(prjts_rsp->fchdr, fchdr->fh_s_id);
- oxid = FNIC_STD_GET_OX_ID(fchdr);
- FNIC_STD_SET_OX_ID(prjts_rsp->fchdr, oxid);
- fnic_send_fcoe_frame(iport, rjt_frame, rjt_frame_size);
- return;
- }
- acc_frame = fdls_alloc_frame(iport);
- if (acc_frame == NULL) {
- FNIC_FCS_DBG(KERN_ERR, fnic->host, fnic->fnic_num,
- "Failed to allocate frame to send ADISC accept");
- return;
- }
- padisc_acc = (struct fc_std_els_adisc *) (acc_frame + FNIC_ETH_FCOE_HDRS_OFFSET);
- FNIC_STD_SET_S_ID(padisc_acc->fchdr, fchdr->fh_d_id);
- FNIC_STD_SET_D_ID(padisc_acc->fchdr, fchdr->fh_s_id);
- FNIC_STD_SET_F_CTL(padisc_acc->fchdr, FNIC_ELS_REP_FCTL << 16);
- FNIC_STD_SET_R_CTL(padisc_acc->fchdr, FC_RCTL_ELS_REP);
- FNIC_STD_SET_TYPE(padisc_acc->fchdr, FC_TYPE_ELS);
- oxid = FNIC_STD_GET_OX_ID(fchdr);
- FNIC_STD_SET_OX_ID(padisc_acc->fchdr, oxid);
- FNIC_STD_SET_RX_ID(padisc_acc->fchdr, FNIC_UNASSIGNED_RXID);
- padisc_acc->els.adisc_cmd = ELS_LS_ACC;
- FNIC_STD_SET_NPORT_NAME(&padisc_acc->els.adisc_wwpn,
- iport->wwpn);
- FNIC_STD_SET_NODE_NAME(&padisc_acc->els.adisc_wwnn,
- iport->wwnn);
- memcpy(padisc_acc->els.adisc_port_id, fchdr->fh_d_id, 3);
- fnic_send_fcoe_frame(iport, acc_frame, acc_frame_size);
- }
- /*
- * Performs a validation for all FCOE frames and return the frame type
- */
- int
- fnic_fdls_validate_and_get_frame_type(struct fnic_iport_s *iport,
- struct fc_frame_header *fchdr)
- {
- uint8_t type;
- uint8_t *fc_payload;
- uint16_t oxid;
- uint32_t s_id;
- uint32_t d_id;
- struct fnic *fnic = iport->fnic;
- struct fnic_fdls_fabric_s *fabric = &iport->fabric;
- int oxid_frame_type;
- oxid = FNIC_STD_GET_OX_ID(fchdr);
- fc_payload = (uint8_t *) fchdr + sizeof(struct fc_frame_header);
- type = *fc_payload;
- s_id = ntoh24(fchdr->fh_s_id);
- d_id = ntoh24(fchdr->fh_d_id);
- /* some common validation */
- if (fdls_get_state(fabric) > FDLS_STATE_FABRIC_FLOGI) {
- if (iport->fcid != d_id || (!FNIC_FC_FRAME_CS_CTL(fchdr))) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "invalid frame received. Dropping frame");
- return -1;
- }
- }
- /* BLS ABTS response */
- if ((fchdr->fh_r_ctl == FC_RCTL_BA_ACC)
- || (fchdr->fh_r_ctl == FC_RCTL_BA_RJT)) {
- if (!(FNIC_FC_FRAME_TYPE_BLS(fchdr))) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "Received ABTS invalid frame. Dropping frame");
- return -1;
- }
- if (fdls_is_oxid_fabric_req(oxid)) {
- if (!(iport->fabric.flags & FNIC_FDLS_FABRIC_ABORT_ISSUED)) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "Received unexpected ABTS RSP(oxid:0x%x) from 0x%x. Dropping frame",
- oxid, s_id);
- return -1;
- }
- return FNIC_FABRIC_BLS_ABTS_RSP;
- } else if (fdls_is_oxid_fdmi_req(oxid)) {
- return FNIC_FDMI_BLS_ABTS_RSP;
- } else if (fdls_is_oxid_tgt_req(oxid)) {
- return FNIC_TPORT_BLS_ABTS_RSP;
- }
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "Received ABTS rsp with unknown oxid(0x%x) from 0x%x. Dropping frame",
- oxid, s_id);
- return -1;
- }
- /* BLS ABTS Req */
- if ((fchdr->fh_r_ctl == FC_RCTL_BA_ABTS)
- && (FNIC_FC_FRAME_TYPE_BLS(fchdr))) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "Receiving Abort Request from s_id: 0x%x", s_id);
- return FNIC_BLS_ABTS_REQ;
- }
- /* unsolicited requests frames */
- if (FNIC_FC_FRAME_UNSOLICITED(fchdr)) {
- switch (type) {
- case ELS_LOGO:
- if ((!FNIC_FC_FRAME_FCTL_FIRST_LAST_SEQINIT(fchdr))
- || (!FNIC_FC_FRAME_UNSOLICITED(fchdr))
- || (!FNIC_FC_FRAME_TYPE_ELS(fchdr))) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "Received LOGO invalid frame. Dropping frame");
- return -1;
- }
- return FNIC_ELS_LOGO_REQ;
- case ELS_RSCN:
- if ((!FNIC_FC_FRAME_FCTL_FIRST_LAST_SEQINIT(fchdr))
- || (!FNIC_FC_FRAME_TYPE_ELS(fchdr))
- || (!FNIC_FC_FRAME_UNSOLICITED(fchdr))) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "Received RSCN invalid FCTL. Dropping frame");
- return -1;
- }
- if (s_id != FC_FID_FCTRL)
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "Received RSCN from target FCTL: 0x%x type: 0x%x s_id: 0x%x.",
- fchdr->fh_f_ctl[0], fchdr->fh_type, s_id);
- return FNIC_ELS_RSCN_REQ;
- case ELS_PLOGI:
- return FNIC_ELS_PLOGI_REQ;
- case ELS_ECHO:
- return FNIC_ELS_ECHO_REQ;
- case ELS_ADISC:
- return FNIC_ELS_ADISC;
- case ELS_RLS:
- return FNIC_ELS_RLS;
- case ELS_RRQ:
- return FNIC_ELS_RRQ;
- default:
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "Unsupported frame (type:0x%02x) from fcid: 0x%x",
- type, s_id);
- return FNIC_ELS_UNSUPPORTED_REQ;
- }
- }
- /* solicited response from fabric or target */
- oxid_frame_type = FNIC_FRAME_TYPE(oxid);
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "oxid frame code: 0x%x, oxid: 0x%x\n", oxid_frame_type, oxid);
- switch (oxid_frame_type) {
- case FNIC_FRAME_TYPE_FABRIC_FLOGI:
- if (type == ELS_LS_ACC) {
- if ((s_id != FC_FID_FLOGI)
- || (!FNIC_FC_FRAME_TYPE_ELS(fchdr))) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "Received unknown frame. Dropping frame");
- return -1;
- }
- }
- return FNIC_FABRIC_FLOGI_RSP;
- case FNIC_FRAME_TYPE_FABRIC_PLOGI:
- if (type == ELS_LS_ACC) {
- if ((s_id != FC_FID_DIR_SERV)
- || (!FNIC_FC_FRAME_TYPE_ELS(fchdr))) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "Received unknown frame. Dropping frame");
- return -1;
- }
- }
- return FNIC_FABRIC_PLOGI_RSP;
- case FNIC_FRAME_TYPE_FABRIC_SCR:
- if (type == ELS_LS_ACC) {
- if ((s_id != FC_FID_FCTRL)
- || (!FNIC_FC_FRAME_TYPE_ELS(fchdr))) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "Received unknown frame. Dropping frame");
- return -1;
- }
- }
- return FNIC_FABRIC_SCR_RSP;
- case FNIC_FRAME_TYPE_FABRIC_RPN:
- if ((s_id != FC_FID_DIR_SERV) || (!FNIC_FC_FRAME_TYPE_FC_GS(fchdr))) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "Received unknown frame. Dropping frame");
- return -1;
- }
- return FNIC_FABRIC_RPN_RSP;
- case FNIC_FRAME_TYPE_FABRIC_RFT:
- if ((s_id != FC_FID_DIR_SERV) || (!FNIC_FC_FRAME_TYPE_FC_GS(fchdr))) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "Received unknown frame. Dropping frame");
- return -1;
- }
- return FNIC_FABRIC_RFT_RSP;
- case FNIC_FRAME_TYPE_FABRIC_RFF:
- if ((s_id != FC_FID_DIR_SERV) || (!FNIC_FC_FRAME_TYPE_FC_GS(fchdr))) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "Received unknown frame. Dropping frame");
- return -1;
- }
- return FNIC_FABRIC_RFF_RSP;
- case FNIC_FRAME_TYPE_FABRIC_GPN_FT:
- if ((s_id != FC_FID_DIR_SERV) || (!FNIC_FC_FRAME_TYPE_FC_GS(fchdr))) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "Received unknown frame. Dropping frame");
- return -1;
- }
- return FNIC_FABRIC_GPN_FT_RSP;
- case FNIC_FRAME_TYPE_FABRIC_LOGO:
- return FNIC_FABRIC_LOGO_RSP;
- case FNIC_FRAME_TYPE_FDMI_PLOGI:
- return FNIC_FDMI_PLOGI_RSP;
- case FNIC_FRAME_TYPE_FDMI_RHBA:
- return FNIC_FDMI_REG_HBA_RSP;
- case FNIC_FRAME_TYPE_FDMI_RPA:
- return FNIC_FDMI_RPA_RSP;
- case FNIC_FRAME_TYPE_TGT_PLOGI:
- return FNIC_TPORT_PLOGI_RSP;
- case FNIC_FRAME_TYPE_TGT_PRLI:
- return FNIC_TPORT_PRLI_RSP;
- case FNIC_FRAME_TYPE_TGT_ADISC:
- return FNIC_TPORT_ADISC_RSP;
- case FNIC_FRAME_TYPE_TGT_LOGO:
- if (!FNIC_FC_FRAME_TYPE_ELS(fchdr)) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "Dropping Unknown frame in tport solicited exchange range type: 0x%x.",
- fchdr->fh_type);
- return -1;
- }
- return FNIC_TPORT_LOGO_RSP;
- default:
- /* Drop the Rx frame and log/stats it */
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "Solicited response: unknown OXID: 0x%x", oxid);
- return -1;
- }
- return -1;
- }
- void fnic_fdls_recv_frame(struct fnic_iport_s *iport, void *rx_frame,
- int len, int fchdr_offset)
- {
- struct fc_frame_header *fchdr;
- uint32_t s_id = 0;
- uint32_t d_id = 0;
- struct fnic *fnic = iport->fnic;
- int frame_type;
- fchdr = (struct fc_frame_header *) ((uint8_t *) rx_frame + fchdr_offset);
- s_id = ntoh24(fchdr->fh_s_id);
- d_id = ntoh24(fchdr->fh_d_id);
- fnic_debug_dump_fc_frame(fnic, fchdr, len, "Incoming");
- frame_type =
- fnic_fdls_validate_and_get_frame_type(iport, fchdr);
- /*if we are in flogo drop everything else */
- if (iport->fabric.state == FDLS_STATE_FABRIC_LOGO &&
- frame_type != FNIC_FABRIC_LOGO_RSP)
- return;
- switch (frame_type) {
- case FNIC_FABRIC_FLOGI_RSP:
- fdls_process_flogi_rsp(iport, fchdr, rx_frame);
- break;
- case FNIC_FABRIC_PLOGI_RSP:
- fdls_process_fabric_plogi_rsp(iport, fchdr);
- break;
- case FNIC_FDMI_PLOGI_RSP:
- fdls_process_fdmi_plogi_rsp(iport, fchdr);
- break;
- case FNIC_FABRIC_RPN_RSP:
- fdls_process_rpn_id_rsp(iport, fchdr);
- break;
- case FNIC_FABRIC_RFT_RSP:
- fdls_process_rft_id_rsp(iport, fchdr);
- break;
- case FNIC_FABRIC_RFF_RSP:
- fdls_process_rff_id_rsp(iport, fchdr);
- break;
- case FNIC_FABRIC_SCR_RSP:
- fdls_process_scr_rsp(iport, fchdr);
- break;
- case FNIC_FABRIC_GPN_FT_RSP:
- fdls_process_gpn_ft_rsp(iport, fchdr, len);
- break;
- case FNIC_TPORT_PLOGI_RSP:
- fdls_process_tgt_plogi_rsp(iport, fchdr);
- break;
- case FNIC_TPORT_PRLI_RSP:
- fdls_process_tgt_prli_rsp(iport, fchdr);
- break;
- case FNIC_TPORT_ADISC_RSP:
- fdls_process_tgt_adisc_rsp(iport, fchdr);
- break;
- case FNIC_TPORT_BLS_ABTS_RSP:
- fdls_process_tgt_abts_rsp(iport, fchdr);
- break;
- case FNIC_TPORT_LOGO_RSP:
- /* Logo response from tgt which we have deleted */
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "Logo response from tgt: 0x%x",
- ntoh24(fchdr->fh_s_id));
- break;
- case FNIC_FABRIC_LOGO_RSP:
- fdls_process_fabric_logo_rsp(iport, fchdr);
- break;
- case FNIC_FABRIC_BLS_ABTS_RSP:
- fdls_process_fabric_abts_rsp(iport, fchdr);
- break;
- case FNIC_FDMI_BLS_ABTS_RSP:
- fdls_process_fdmi_abts_rsp(iport, fchdr);
- break;
- case FNIC_BLS_ABTS_REQ:
- fdls_process_abts_req(iport, fchdr);
- break;
- case FNIC_ELS_UNSUPPORTED_REQ:
- fdls_process_unsupported_els_req(iport, fchdr);
- break;
- case FNIC_ELS_PLOGI_REQ:
- fdls_process_plogi_req(iport, fchdr);
- break;
- case FNIC_ELS_RSCN_REQ:
- fdls_process_rscn(iport, fchdr);
- break;
- case FNIC_ELS_LOGO_REQ:
- fdls_process_logo_req(iport, fchdr);
- break;
- case FNIC_ELS_RRQ:
- case FNIC_ELS_ECHO_REQ:
- fdls_process_els_req(iport, fchdr, len);
- break;
- case FNIC_ELS_ADISC:
- fdls_process_adisc_req(iport, fchdr);
- break;
- case FNIC_ELS_RLS:
- fdls_process_rls_req(iport, fchdr);
- break;
- case FNIC_FDMI_REG_HBA_RSP:
- case FNIC_FDMI_RPA_RSP:
- fdls_process_fdmi_reg_ack(iport, fchdr, frame_type);
- break;
- default:
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "s_id: 0x%x d_did: 0x%x", s_id, d_id);
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "Received unknown FCoE frame of len: %d. Dropping frame", len);
- break;
- }
- }
- void fnic_fdls_disc_init(struct fnic_iport_s *iport)
- {
- fdls_reset_oxid_pool(iport);
- fdls_set_state((&iport->fabric), FDLS_STATE_INIT);
- }
- void fnic_fdls_link_down(struct fnic_iport_s *iport)
- {
- struct fnic_tport_s *tport, *next;
- struct fnic *fnic = iport->fnic;
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "0x%x: FDLS processing link down", iport->fcid);
- fdls_set_state((&iport->fabric), FDLS_STATE_LINKDOWN);
- iport->fabric.flags = 0;
- spin_unlock_irqrestore(&fnic->fnic_lock, fnic->lock_flags);
- fnic_scsi_fcpio_reset(iport->fnic);
- spin_lock_irqsave(&fnic->fnic_lock, fnic->lock_flags);
- list_for_each_entry_safe(tport, next, &iport->tport_list, links) {
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "removing rport: 0x%x", tport->fcid);
- fdls_delete_tport(iport, tport);
- }
- if (fnic_fdmi_support == 1) {
- if (iport->fabric.fdmi_pending > 0) {
- timer_delete_sync(&iport->fabric.fdmi_timer);
- iport->fabric.fdmi_pending = 0;
- }
- iport->flags &= ~FNIC_FDMI_ACTIVE;
- }
- FNIC_FCS_DBG(KERN_INFO, fnic->host, fnic->fnic_num,
- "0x%x: FDLS finish processing link down", iport->fcid);
- }
|