IxEthAccDataPlane.c 68 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483
  1. /**
  2. * @file IxEthDataPlane.c
  3. *
  4. * @author Intel Corporation
  5. * @date 12-Feb-2002
  6. *
  7. * @brief This file contains the implementation of the IXPxxx
  8. * Ethernet Access Data plane component
  9. *
  10. * Design Notes:
  11. *
  12. * @par
  13. * IXP400 SW Release version 2.0
  14. *
  15. * -- Copyright Notice --
  16. *
  17. * @par
  18. * Copyright 2001-2005, Intel Corporation.
  19. * All rights reserved.
  20. *
  21. * @par
  22. * Redistribution and use in source and binary forms, with or without
  23. * modification, are permitted provided that the following conditions
  24. * are met:
  25. * 1. Redistributions of source code must retain the above copyright
  26. * notice, this list of conditions and the following disclaimer.
  27. * 2. Redistributions in binary form must reproduce the above copyright
  28. * notice, this list of conditions and the following disclaimer in the
  29. * documentation and/or other materials provided with the distribution.
  30. * 3. Neither the name of the Intel Corporation nor the names of its contributors
  31. * may be used to endorse or promote products derived from this software
  32. * without specific prior written permission.
  33. *
  34. * @par
  35. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
  36. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  37. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  38. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
  39. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  40. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  41. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  42. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  43. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  44. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  45. * SUCH DAMAGE.
  46. *
  47. * @par
  48. * -- End of Copyright Notice --
  49. */
  50. #include "IxNpeMh.h"
  51. #include "IxEthAcc.h"
  52. #include "IxEthDB.h"
  53. #include "IxOsal.h"
  54. #include "IxEthDBPortDefs.h"
  55. #include "IxFeatureCtrl.h"
  56. #include "IxEthAcc_p.h"
  57. #include "IxEthAccQueueAssign_p.h"
  58. extern PUBLIC IxEthAccMacState ixEthAccMacState[];
  59. extern PUBLIC UINT32 ixEthAccNewSrcMask;
  60. /**
  61. * private functions prototype
  62. */
  63. PRIVATE IX_OSAL_MBUF *
  64. ixEthAccEntryFromQConvert(UINT32 qEntry, UINT32 mask);
  65. PRIVATE UINT32
  66. ixEthAccMbufRxQPrepare(IX_OSAL_MBUF *mbuf);
  67. PRIVATE UINT32
  68. ixEthAccMbufTxQPrepare(IX_OSAL_MBUF *mbuf);
  69. PRIVATE IxEthAccStatus
  70. ixEthAccTxSwQHighestPriorityGet(IxEthAccPortId portId,
  71. IxEthAccTxPriority *priorityPtr);
  72. PRIVATE IxEthAccStatus
  73. ixEthAccTxFromSwQ(IxEthAccPortId portId,
  74. IxEthAccTxPriority priority);
  75. PRIVATE IxEthAccStatus
  76. ixEthAccRxFreeFromSwQ(IxEthAccPortId portId);
  77. PRIVATE void
  78. ixEthAccMbufFromTxQ(IX_OSAL_MBUF *mbuf);
  79. PRIVATE void
  80. ixEthAccMbufFromRxQ(IX_OSAL_MBUF *mbuf);
  81. PRIVATE IX_STATUS
  82. ixEthAccQmgrLockTxWrite(IxEthAccPortId portId,
  83. UINT32 qBuffer);
  84. PRIVATE IX_STATUS
  85. ixEthAccQmgrLockRxWrite(IxEthAccPortId portId,
  86. UINT32 qBuffer);
  87. PRIVATE IX_STATUS
  88. ixEthAccQmgrTxWrite(IxEthAccPortId portId,
  89. UINT32 qBuffer,
  90. UINT32 priority);
  91. /**
  92. * @addtogroup IxEthAccPri
  93. *@{
  94. */
  95. /* increment a counter only when stats are enabled */
  96. #define TX_STATS_INC(port,field) \
  97. IX_ETH_ACC_STATS_INC(ixEthAccPortData[port].ixEthAccTxData.stats.field)
  98. #define RX_STATS_INC(port,field) \
  99. IX_ETH_ACC_STATS_INC(ixEthAccPortData[port].ixEthAccRxData.stats.field)
  100. /* always increment the counter (mainly used for unexpected errors) */
  101. #define TX_INC(port,field) \
  102. ixEthAccPortData[port].ixEthAccTxData.stats.field++
  103. #define RX_INC(port,field) \
  104. ixEthAccPortData[port].ixEthAccRxData.stats.field++
  105. PRIVATE IxEthAccDataPlaneStats ixEthAccDataStats;
  106. extern IxEthAccPortDataInfo ixEthAccPortData[];
  107. extern IxEthAccInfo ixEthAccDataInfo;
  108. PRIVATE IxOsalFastMutex txWriteMutex[IX_ETH_ACC_NUMBER_OF_PORTS];
  109. PRIVATE IxOsalFastMutex rxWriteMutex[IX_ETH_ACC_NUMBER_OF_PORTS];
  110. /**
  111. *
  112. * @brief Mbuf header conversion macros : they implement the
  113. * different conversions using a temporary value. They also double-check
  114. * that the parameters can be converted to/from NPE format.
  115. *
  116. */
  117. #if defined(__wince) && !defined(IN_KERNEL)
  118. #define PTR_VIRT2NPE(ptrSrc,dst) \
  119. do { UINT32 temp; \
  120. IX_OSAL_ENSURE(sizeof(ptrSrc) == sizeof(UINT32), "Wrong parameter type"); \
  121. IX_OSAL_ENSURE(sizeof(dst) == sizeof(UINT32), "Wrong parameter type"); \
  122. temp = (UINT32)IX_OSAL_MBUF_MBUF_VIRTUAL_TO_PHYSICAL_TRANSLATION((IX_OSAL_MBUF*)ptrSrc); \
  123. (dst) = IX_OSAL_SWAP_BE_SHARED_LONG(temp); } \
  124. while(0)
  125. #define PTR_NPE2VIRT(type,src,ptrDst) \
  126. do { void *temp; \
  127. IX_OSAL_ENSURE(sizeof(type) == sizeof(UINT32), "Wrong parameter type"); \
  128. IX_OSAL_ENSURE(sizeof(src) == sizeof(UINT32), "Wrong parameter type"); \
  129. IX_OSAL_ENSURE(sizeof(ptrDst) == sizeof(UINT32), "Wrong parameter type"); \
  130. temp = (void *)IX_OSAL_SWAP_BE_SHARED_LONG(src); \
  131. (ptrDst) = (type)IX_OSAL_MBUF_MBUF_PHYSICAL_TO_VIRTUAL_TRANSLATION(temp); } \
  132. while(0)
  133. #else
  134. #define PTR_VIRT2NPE(ptrSrc,dst) \
  135. do { UINT32 temp; \
  136. IX_OSAL_ENSURE(sizeof(ptrSrc) == sizeof(UINT32), "Wrong parameter type"); \
  137. IX_OSAL_ENSURE(sizeof(dst) == sizeof(UINT32), "Wrong parameter type"); \
  138. temp = (UINT32)IX_OSAL_MMU_VIRT_TO_PHYS(ptrSrc); \
  139. (dst) = IX_OSAL_SWAP_BE_SHARED_LONG(temp); } \
  140. while(0)
  141. #define PTR_NPE2VIRT(type,src,ptrDst) \
  142. do { void *temp; \
  143. IX_OSAL_ENSURE(sizeof(type) == sizeof(UINT32), "Wrong parameter type"); \
  144. IX_OSAL_ENSURE(sizeof(src) == sizeof(UINT32), "Wrong parameter type"); \
  145. IX_OSAL_ENSURE(sizeof(ptrDst) == sizeof(UINT32), "Wrong parameter type"); \
  146. temp = (void *)IX_OSAL_SWAP_BE_SHARED_LONG(src); \
  147. (ptrDst) = (type)IX_OSAL_MMU_PHYS_TO_VIRT(temp); } \
  148. while(0)
  149. #endif
  150. /**
  151. *
  152. * @brief Mbuf payload pointer conversion macros : Wince has its own
  153. * method to convert the buffer pointers
  154. */
  155. #if defined(__wince) && !defined(IN_KERNEL)
  156. #define DATAPTR_VIRT2NPE(ptrSrc,dst) \
  157. do { UINT32 temp; \
  158. temp = (UINT32)IX_OSAL_MBUF_DATA_VIRTUAL_TO_PHYSICAL_TRANSLATION(ptrSrc); \
  159. (dst) = IX_OSAL_SWAP_BE_SHARED_LONG(temp); } \
  160. while(0)
  161. #else
  162. #define DATAPTR_VIRT2NPE(ptrSrc,dst) PTR_VIRT2NPE(IX_OSAL_MBUF_MDATA(ptrSrc),dst)
  163. #endif
  164. /* Flush the shared part of the mbuf header */
  165. #define IX_ETHACC_NE_CACHE_FLUSH(mbufPtr) \
  166. do { \
  167. IX_OSAL_CACHE_FLUSH(IX_ETHACC_NE_SHARED(mbufPtr), \
  168. sizeof(IxEthAccNe)); \
  169. } \
  170. while(0)
  171. /* Invalidate the shared part of the mbuf header */
  172. #define IX_ETHACC_NE_CACHE_INVALIDATE(mbufPtr) \
  173. do { \
  174. IX_OSAL_CACHE_INVALIDATE(IX_ETHACC_NE_SHARED(mbufPtr), \
  175. sizeof(IxEthAccNe)); \
  176. } \
  177. while(0)
  178. /* Preload one cache line (shared mbuf headers are aligned
  179. * and their size is 1 cache line)
  180. *
  181. * IX_OSAL_CACHED is defined when the mbuf headers are
  182. * allocated from cached memory.
  183. *
  184. * Other processor on emulation environment may not implement
  185. * preload function
  186. */
  187. #ifdef IX_OSAL_CACHED
  188. #if (CPU!=SIMSPARCSOLARIS) && !defined (__wince)
  189. #define IX_ACC_DATA_CACHE_PRELOAD(ptr) \
  190. do { /* preload a cache line (Xscale Processor) */ \
  191. __asm__ (" pld [%0]\n": : "r" (ptr)); \
  192. } \
  193. while(0)
  194. #else
  195. /* preload not implemented on different processor */
  196. #define IX_ACC_DATA_CACHE_PRELOAD(mbufPtr) \
  197. do { /* nothing */ } while (0)
  198. #endif
  199. #else
  200. /* preload not needed if cache is not enabled */
  201. #define IX_ACC_DATA_CACHE_PRELOAD(mbufPtr) \
  202. do { /* nothing */ } while (0)
  203. #endif
  204. /**
  205. *
  206. * @brief function to retrieve the correct pointer from
  207. * a queue entry posted by the NPE
  208. *
  209. * @param qEntry : entry from qmgr queue
  210. * mask : applicable mask for this queue
  211. * (4 most significant bits are used for additional informations)
  212. *
  213. * @return IX_OSAL_MBUF * pointer to mbuf header
  214. *
  215. * @internal
  216. */
  217. PRIVATE IX_OSAL_MBUF *
  218. ixEthAccEntryFromQConvert(UINT32 qEntry, UINT32 mask)
  219. {
  220. IX_OSAL_MBUF *mbufPtr;
  221. if (qEntry != 0)
  222. {
  223. /* mask NPE bits (e.g. priority, port ...) */
  224. qEntry &= mask;
  225. #if IX_ACC_DRAM_PHYS_OFFSET != 0
  226. /* restore the original address pointer (if PHYS_OFFSET is not 0) */
  227. qEntry |= (IX_ACC_DRAM_PHYS_OFFSET & ~IX_ETHNPE_QM_Q_RXENET_ADDR_MASK);
  228. #endif
  229. /* get the mbuf pointer address from the npe-shared address */
  230. qEntry -= offsetof(IX_OSAL_MBUF,ix_ne);
  231. /* phys2virt mbuf */
  232. mbufPtr = (IX_OSAL_MBUF *)IX_OSAL_MMU_PHYS_TO_VIRT(qEntry);
  233. /* preload the cacheline shared with NPE */
  234. IX_ACC_DATA_CACHE_PRELOAD(IX_ETHACC_NE_SHARED(mbufPtr));
  235. /* preload the cacheline used by xscale */
  236. IX_ACC_DATA_CACHE_PRELOAD(mbufPtr);
  237. }
  238. else
  239. {
  240. mbufPtr = NULL;
  241. }
  242. return mbufPtr;
  243. }
  244. /* Convert the mbuf header for NPE transmission */
  245. PRIVATE UINT32
  246. ixEthAccMbufTxQPrepare(IX_OSAL_MBUF *mbuf)
  247. {
  248. UINT32 qbuf;
  249. UINT32 len;
  250. /* endianess swap for tci and flags
  251. note: this is done only once, even for chained buffers */
  252. IX_ETHACC_NE_FLAGS(mbuf) = IX_OSAL_SWAP_BE_SHARED_SHORT(IX_ETHACC_NE_FLAGS(mbuf));
  253. IX_ETHACC_NE_VLANTCI(mbuf) = IX_OSAL_SWAP_BE_SHARED_SHORT(IX_ETHACC_NE_VLANTCI(mbuf));
  254. /* test for unchained mbufs */
  255. if (IX_OSAL_MBUF_NEXT_BUFFER_IN_PKT_PTR(mbuf) == NULL)
  256. {
  257. /* "best case" scenario : unchained mbufs */
  258. IX_ETH_ACC_STATS_INC(ixEthAccDataStats.unchainedTxMBufs);
  259. /* payload pointer conversion */
  260. DATAPTR_VIRT2NPE(mbuf, IX_ETHACC_NE_DATA(mbuf));
  261. /* unchained mbufs : the frame length is the mbuf length
  262. * and the 2 identical lengths are stored in the same
  263. * word.
  264. */
  265. len = IX_OSAL_MBUF_MLEN(mbuf);
  266. /* set the length in both length and pktLen 16-bits fields */
  267. len |= (len << IX_ETHNPE_ACC_LENGTH_OFFSET);
  268. IX_ETHACC_NE_LEN(mbuf) = IX_OSAL_SWAP_BE_SHARED_LONG(len);
  269. /* unchained mbufs : next contains 0 */
  270. IX_ETHACC_NE_NEXT(mbuf) = 0;
  271. /* flush shared header after all address conversions */
  272. IX_ETHACC_NE_CACHE_FLUSH(mbuf);
  273. }
  274. else
  275. {
  276. /* chained mbufs */
  277. IX_OSAL_MBUF *ptr = mbuf;
  278. IX_OSAL_MBUF *nextPtr;
  279. UINT32 frmLen;
  280. /* get the frame length from the header of the first buffer */
  281. frmLen = IX_OSAL_MBUF_PKT_LEN(mbuf);
  282. do
  283. {
  284. IX_ETH_ACC_STATS_INC(ixEthAccDataStats.chainedTxMBufs);
  285. /* payload pointer */
  286. DATAPTR_VIRT2NPE(ptr,IX_ETHACC_NE_DATA(ptr));
  287. /* Buffer length and frame length are stored in the same word */
  288. len = IX_OSAL_MBUF_MLEN(ptr);
  289. len = frmLen | (len << IX_ETHNPE_ACC_LENGTH_OFFSET);
  290. IX_ETHACC_NE_LEN(ptr) = IX_OSAL_SWAP_BE_SHARED_LONG(len);
  291. /* get the virtual next chain pointer */
  292. nextPtr = IX_OSAL_MBUF_NEXT_BUFFER_IN_PKT_PTR(ptr);
  293. if (nextPtr != NULL)
  294. {
  295. /* shared pointer of the next buffer is chained */
  296. PTR_VIRT2NPE(IX_ETHACC_NE_SHARED(nextPtr),
  297. IX_ETHACC_NE_NEXT(ptr));
  298. }
  299. else
  300. {
  301. IX_ETHACC_NE_NEXT(ptr) = 0;
  302. }
  303. /* flush shared header after all address conversions */
  304. IX_ETHACC_NE_CACHE_FLUSH(ptr);
  305. /* move to next buffer */
  306. ptr = nextPtr;
  307. /* the frame length field is set only in the first buffer
  308. * and is zeroed in the next buffers
  309. */
  310. frmLen = 0;
  311. }
  312. while(ptr != NULL);
  313. }
  314. /* virt2phys mbuf itself */
  315. qbuf = (UINT32)IX_OSAL_MMU_VIRT_TO_PHYS(
  316. IX_ETHACC_NE_SHARED(mbuf));
  317. /* Ensure the bits which are reserved to exchange information with
  318. * the NPE are cleared
  319. *
  320. * If the mbuf address is not correctly aligned, or from an
  321. * incompatible memory range, there is no point to continue
  322. */
  323. IX_OSAL_ENSURE(((qbuf & ~IX_ETHNPE_QM_Q_TXENET_ADDR_MASK) == 0),
  324. "Invalid address range");
  325. return qbuf;
  326. }
  327. /* Convert the mbuf header for NPE reception */
  328. PRIVATE UINT32
  329. ixEthAccMbufRxQPrepare(IX_OSAL_MBUF *mbuf)
  330. {
  331. UINT32 len;
  332. UINT32 qbuf;
  333. if (IX_OSAL_MBUF_NEXT_BUFFER_IN_PKT_PTR(mbuf) == NULL)
  334. {
  335. /* "best case" scenario : unchained mbufs */
  336. IX_ETH_ACC_STATS_INC(ixEthAccDataStats.unchainedRxFreeMBufs);
  337. /* unchained mbufs : payload pointer */
  338. DATAPTR_VIRT2NPE(mbuf, IX_ETHACC_NE_DATA(mbuf));
  339. /* unchained mbufs : set the buffer length
  340. * and the frame length field is zeroed
  341. */
  342. len = (IX_OSAL_MBUF_MLEN(mbuf) << IX_ETHNPE_ACC_LENGTH_OFFSET);
  343. IX_ETHACC_NE_LEN(mbuf) = IX_OSAL_SWAP_BE_SHARED_LONG(len);
  344. /* unchained mbufs : next pointer is null */
  345. IX_ETHACC_NE_NEXT(mbuf) = 0;
  346. /* flush shared header after all address conversions */
  347. IX_ETHACC_NE_CACHE_FLUSH(mbuf);
  348. /* remove shared header cache line */
  349. IX_ETHACC_NE_CACHE_INVALIDATE(mbuf);
  350. }
  351. else
  352. {
  353. /* chained mbufs */
  354. IX_OSAL_MBUF *ptr = mbuf;
  355. IX_OSAL_MBUF *nextPtr;
  356. do
  357. {
  358. /* chained mbufs */
  359. IX_ETH_ACC_STATS_INC(ixEthAccDataStats.chainedRxFreeMBufs);
  360. /* we must save virtual next chain pointer */
  361. nextPtr = IX_OSAL_MBUF_NEXT_BUFFER_IN_PKT_PTR(ptr);
  362. if (nextPtr != NULL)
  363. {
  364. /* chaining pointer for NPE */
  365. PTR_VIRT2NPE(IX_ETHACC_NE_SHARED(nextPtr),
  366. IX_ETHACC_NE_NEXT(ptr));
  367. }
  368. else
  369. {
  370. IX_ETHACC_NE_NEXT(ptr) = 0;
  371. }
  372. /* payload pointer */
  373. DATAPTR_VIRT2NPE(ptr,IX_ETHACC_NE_DATA(ptr));
  374. /* buffer length */
  375. len = (IX_OSAL_MBUF_MLEN(ptr) << IX_ETHNPE_ACC_LENGTH_OFFSET);
  376. IX_ETHACC_NE_LEN(ptr) = IX_OSAL_SWAP_BE_SHARED_LONG(len);
  377. /* flush shared header after all address conversions */
  378. IX_ETHACC_NE_CACHE_FLUSH(ptr);
  379. /* remove shared header cache line */
  380. IX_ETHACC_NE_CACHE_INVALIDATE(ptr);
  381. /* next mbuf in the chain */
  382. ptr = nextPtr;
  383. }
  384. while(ptr != NULL);
  385. }
  386. /* virt2phys mbuf itself */
  387. qbuf = (UINT32)IX_OSAL_MMU_VIRT_TO_PHYS(
  388. IX_ETHACC_NE_SHARED(mbuf));
  389. /* Ensure the bits which are reserved to exchange information with
  390. * the NPE are cleared
  391. *
  392. * If the mbuf address is not correctly aligned, or from an
  393. * incompatible memory range, there is no point to continue
  394. */
  395. IX_OSAL_ENSURE(((qbuf & ~IX_ETHNPE_QM_Q_RXENET_ADDR_MASK) == 0),
  396. "Invalid address range");
  397. return qbuf;
  398. }
  399. /* Convert the mbuf header after NPE transmission
  400. * Since there is nothing changed by the NPE, there is no need
  401. * to process anything but the update of internal stats
  402. * when they are enabled
  403. */
  404. PRIVATE void
  405. ixEthAccMbufFromTxQ(IX_OSAL_MBUF *mbuf)
  406. {
  407. #ifndef NDEBUG
  408. /* test for unchained mbufs */
  409. if (IX_ETHACC_NE_NEXT(mbuf) == 0)
  410. {
  411. /* unchained mbufs : update the stats */
  412. IX_ETH_ACC_STATS_INC(ixEthAccDataStats.unchainedTxDoneMBufs);
  413. }
  414. else
  415. {
  416. /* chained mbufs : walk the chain and update the stats */
  417. IX_OSAL_MBUF *ptr = mbuf;
  418. do
  419. {
  420. IX_ETH_ACC_STATS_INC(ixEthAccDataStats.chainedTxDoneMBufs);
  421. ptr = IX_OSAL_MBUF_NEXT_BUFFER_IN_PKT_PTR(ptr);
  422. }
  423. while (ptr != NULL);
  424. }
  425. #endif
  426. }
  427. /* Convert the mbuf header after NPE reception */
  428. PRIVATE void
  429. ixEthAccMbufFromRxQ(IX_OSAL_MBUF *mbuf)
  430. {
  431. UINT32 len;
  432. /* endianess swap for tci and flags
  433. note: this is done only once, even for chained buffers */
  434. IX_ETHACC_NE_FLAGS(mbuf) = IX_OSAL_SWAP_BE_SHARED_SHORT(IX_ETHACC_NE_FLAGS(mbuf));
  435. IX_ETHACC_NE_VLANTCI(mbuf) = IX_OSAL_SWAP_BE_SHARED_SHORT(IX_ETHACC_NE_VLANTCI(mbuf));
  436. /* test for unchained mbufs */
  437. if (IX_ETHACC_NE_NEXT(mbuf) == 0)
  438. {
  439. /* unchained mbufs */
  440. IX_ETH_ACC_STATS_INC(ixEthAccDataStats.unchainedRxMBufs);
  441. /* get the frame length. it is the same than the buffer length */
  442. len = IX_OSAL_SWAP_BE_SHARED_LONG(IX_ETHACC_NE_LEN(mbuf));
  443. len &= IX_ETHNPE_ACC_PKTLENGTH_MASK;
  444. IX_OSAL_MBUF_PKT_LEN(mbuf) = IX_OSAL_MBUF_MLEN(mbuf) = len;
  445. /* clears the next packet field */
  446. IX_OSAL_MBUF_NEXT_BUFFER_IN_PKT_PTR(mbuf) = NULL;
  447. }
  448. else
  449. {
  450. IX_OSAL_MBUF *ptr = mbuf;
  451. IX_OSAL_MBUF *nextPtr;
  452. UINT32 frmLen;
  453. /* convert the frame length */
  454. frmLen = IX_OSAL_SWAP_BE_SHARED_LONG(IX_ETHACC_NE_LEN(mbuf));
  455. IX_OSAL_MBUF_PKT_LEN(mbuf) = (frmLen & IX_ETHNPE_ACC_PKTLENGTH_MASK);
  456. /* chained mbufs */
  457. do
  458. {
  459. IX_ETH_ACC_STATS_INC(ixEthAccDataStats.chainedRxMBufs);
  460. /* convert the length */
  461. len = IX_OSAL_SWAP_BE_SHARED_LONG(IX_ETHACC_NE_LEN(ptr));
  462. IX_OSAL_MBUF_MLEN(ptr) = (len >> IX_ETHNPE_ACC_LENGTH_OFFSET);
  463. /* get the next pointer */
  464. PTR_NPE2VIRT(IX_OSAL_MBUF *,IX_ETHACC_NE_NEXT(ptr), nextPtr);
  465. if (nextPtr != NULL)
  466. {
  467. nextPtr = (IX_OSAL_MBUF *)((UINT8 *)nextPtr - offsetof(IX_OSAL_MBUF,ix_ne));
  468. }
  469. /* set the next pointer */
  470. IX_OSAL_MBUF_NEXT_BUFFER_IN_PKT_PTR(ptr) = nextPtr;
  471. /* move to the next buffer */
  472. ptr = nextPtr;
  473. }
  474. while (ptr != NULL);
  475. }
  476. }
  477. /* write to qmgr if possible and report an overflow if not possible
  478. * Use a fast lock to protect the queue write.
  479. * This way, the tx feature is reentrant.
  480. */
  481. PRIVATE IX_STATUS
  482. ixEthAccQmgrLockTxWrite(IxEthAccPortId portId, UINT32 qBuffer)
  483. {
  484. IX_STATUS qStatus;
  485. if (ixOsalFastMutexTryLock(&txWriteMutex[portId]) == IX_SUCCESS)
  486. {
  487. qStatus = ixQMgrQWrite(
  488. IX_ETH_ACC_PORT_TO_TX_Q_ID(portId),
  489. &qBuffer);
  490. #ifndef NDEBUG
  491. if (qStatus != IX_SUCCESS)
  492. {
  493. TX_STATS_INC(portId, txOverflow);
  494. }
  495. #endif
  496. ixOsalFastMutexUnlock(&txWriteMutex[portId]);
  497. }
  498. else
  499. {
  500. TX_STATS_INC(portId, txLock);
  501. qStatus = IX_QMGR_Q_OVERFLOW;
  502. }
  503. return qStatus;
  504. }
  505. /* write to qmgr if possible and report an overflow if not possible
  506. * Use a fast lock to protect the queue write.
  507. * This way, the Rx feature is reentrant.
  508. */
  509. PRIVATE IX_STATUS
  510. ixEthAccQmgrLockRxWrite(IxEthAccPortId portId, UINT32 qBuffer)
  511. {
  512. IX_STATUS qStatus;
  513. if (ixOsalFastMutexTryLock(&rxWriteMutex[portId]) == IX_SUCCESS)
  514. {
  515. qStatus = ixQMgrQWrite(
  516. IX_ETH_ACC_PORT_TO_RX_FREE_Q_ID(portId),
  517. &qBuffer);
  518. #ifndef NDEBUG
  519. if (qStatus != IX_SUCCESS)
  520. {
  521. RX_STATS_INC(portId, rxFreeOverflow);
  522. }
  523. #endif
  524. ixOsalFastMutexUnlock(&rxWriteMutex[portId]);
  525. }
  526. else
  527. {
  528. RX_STATS_INC(portId, rxFreeLock);
  529. qStatus = IX_QMGR_Q_OVERFLOW;
  530. }
  531. return qStatus;
  532. }
  533. /*
  534. * Set the priority and write to a qmgr queue.
  535. */
  536. PRIVATE IX_STATUS
  537. ixEthAccQmgrTxWrite(IxEthAccPortId portId, UINT32 qBuffer, UINT32 priority)
  538. {
  539. /* fill the priority field */
  540. qBuffer |= (priority << IX_ETHNPE_QM_Q_FIELD_PRIOR_R);
  541. return ixEthAccQmgrLockTxWrite(portId, qBuffer);
  542. }
  543. /**
  544. *
  545. * @brief This function will discover the highest priority S/W Tx Q that
  546. * has entries in it
  547. *
  548. * @param portId - (in) the id of the port whose S/W Tx queues are to be searched
  549. * priorityPtr - (out) the priority of the highest priority occupied q will be written
  550. * here
  551. *
  552. * @return IX_ETH_ACC_SUCCESS if an occupied Q is found
  553. * IX_ETH_ACC_FAIL if no Q has entries
  554. *
  555. * @internal
  556. */
  557. PRIVATE IxEthAccStatus
  558. ixEthAccTxSwQHighestPriorityGet(IxEthAccPortId portId,
  559. IxEthAccTxPriority *priorityPtr)
  560. {
  561. if (ixEthAccPortData[portId].ixEthAccTxData.schDiscipline
  562. == FIFO_NO_PRIORITY)
  563. {
  564. if(IX_ETH_ACC_DATAPLANE_IS_Q_EMPTY(ixEthAccPortData[portId].
  565. ixEthAccTxData.txQ[IX_ETH_ACC_TX_DEFAULT_PRIORITY]))
  566. {
  567. return IX_ETH_ACC_FAIL;
  568. }
  569. else
  570. {
  571. *priorityPtr = IX_ETH_ACC_TX_DEFAULT_PRIORITY;
  572. TX_STATS_INC(portId,txPriority[*priorityPtr]);
  573. return IX_ETH_ACC_SUCCESS;
  574. }
  575. }
  576. else
  577. {
  578. IxEthAccTxPriority highestPriority = IX_ETH_ACC_TX_PRIORITY_7;
  579. while(1)
  580. {
  581. if(!IX_ETH_ACC_DATAPLANE_IS_Q_EMPTY(ixEthAccPortData[portId].
  582. ixEthAccTxData.txQ[highestPriority]))
  583. {
  584. *priorityPtr = highestPriority;
  585. TX_STATS_INC(portId,txPriority[highestPriority]);
  586. return IX_ETH_ACC_SUCCESS;
  587. }
  588. if (highestPriority == IX_ETH_ACC_TX_PRIORITY_0)
  589. {
  590. return IX_ETH_ACC_FAIL;
  591. }
  592. highestPriority--;
  593. }
  594. }
  595. }
  596. /**
  597. *
  598. * @brief This function will take a buffer from a TX S/W Q and attempt
  599. * to add it to the relevant TX H/W Q
  600. *
  601. * @param portId - the port whose TX queue is to be written to
  602. * priority - identifies the queue from which the entry is to be read
  603. *
  604. * @internal
  605. */
  606. PRIVATE IxEthAccStatus
  607. ixEthAccTxFromSwQ(IxEthAccPortId portId,
  608. IxEthAccTxPriority priority)
  609. {
  610. IX_OSAL_MBUF *mbuf;
  611. IX_STATUS qStatus;
  612. IX_OSAL_ENSURE((UINT32)priority <= (UINT32)7, "Invalid priority");
  613. IX_ETH_ACC_DATAPLANE_REMOVE_MBUF_FROM_Q_HEAD(
  614. ixEthAccPortData[portId].ixEthAccTxData.txQ[priority],
  615. mbuf);
  616. if (mbuf != NULL)
  617. {
  618. /*
  619. * Add the Tx buffer to the H/W Tx Q
  620. * We do not need to flush here as it is already done
  621. * in TxFrameSubmit().
  622. */
  623. qStatus = ixEthAccQmgrTxWrite(
  624. portId,
  625. IX_OSAL_MMU_VIRT_TO_PHYS((UINT32)IX_ETHACC_NE_SHARED(mbuf)),
  626. priority);
  627. if (qStatus == IX_SUCCESS)
  628. {
  629. TX_STATS_INC(portId,txFromSwQOK);
  630. return IX_SUCCESS;
  631. }
  632. else if (qStatus == IX_QMGR_Q_OVERFLOW)
  633. {
  634. /*
  635. * H/W Q overflow, need to save the buffer
  636. * back on the s/w Q.
  637. * we must put it back on the head of the q to avoid
  638. * reordering packet tx
  639. */
  640. TX_STATS_INC(portId,txFromSwQDelayed);
  641. IX_ETH_ACC_DATAPLANE_ADD_MBUF_TO_Q_HEAD(
  642. ixEthAccPortData[portId].ixEthAccTxData.txQ[priority],
  643. mbuf);
  644. /*enable Q notification*/
  645. qStatus = ixQMgrNotificationEnable(
  646. IX_ETH_ACC_PORT_TO_TX_Q_ID(portId),
  647. IX_ETH_ACC_PORT_TO_TX_Q_SOURCE(portId));
  648. if (qStatus != IX_SUCCESS && qStatus != IX_QMGR_WARNING)
  649. {
  650. TX_INC(portId,txUnexpectedError);
  651. IX_ETH_ACC_FATAL_LOG(
  652. "ixEthAccTxFromSwQ:Unexpected Error: %u\n",
  653. qStatus, 0, 0, 0, 0, 0);
  654. }
  655. }
  656. else
  657. {
  658. TX_INC(portId,txUnexpectedError);
  659. /* recovery attempt */
  660. IX_ETH_ACC_DATAPLANE_ADD_MBUF_TO_Q_HEAD(
  661. ixEthAccPortData[portId].ixEthAccTxData.txQ[priority],
  662. mbuf);
  663. IX_ETH_ACC_FATAL_LOG(
  664. "ixEthAccTxFromSwQ:Error: unexpected QM status 0x%08X\n",
  665. qStatus, 0, 0, 0, 0, 0);
  666. }
  667. }
  668. else
  669. {
  670. /* sw queue is empty */
  671. }
  672. return IX_ETH_ACC_FAIL;
  673. }
  674. /**
  675. *
  676. * @brief This function will take a buffer from a RXfree S/W Q and attempt
  677. * to add it to the relevant RxFree H/W Q
  678. *
  679. * @param portId - the port whose RXFree queue is to be written to
  680. *
  681. * @internal
  682. */
  683. PRIVATE IxEthAccStatus
  684. ixEthAccRxFreeFromSwQ(IxEthAccPortId portId)
  685. {
  686. IX_OSAL_MBUF *mbuf;
  687. IX_STATUS qStatus = IX_SUCCESS;
  688. IX_ETH_ACC_DATAPLANE_REMOVE_MBUF_FROM_Q_HEAD(
  689. ixEthAccPortData[portId].ixEthAccRxData.freeBufferList,
  690. mbuf);
  691. if (mbuf != NULL)
  692. {
  693. /*
  694. * Add The Rx Buffer to the H/W Free buffer Q if possible
  695. */
  696. qStatus = ixEthAccQmgrLockRxWrite(portId,
  697. IX_OSAL_MMU_VIRT_TO_PHYS(
  698. (UINT32)IX_ETHACC_NE_SHARED(mbuf)));
  699. if (qStatus == IX_SUCCESS)
  700. {
  701. RX_STATS_INC(portId,rxFreeRepFromSwQOK);
  702. /*
  703. * Buffer added to h/w Q.
  704. */
  705. return IX_SUCCESS;
  706. }
  707. else if (qStatus == IX_QMGR_Q_OVERFLOW)
  708. {
  709. /*
  710. * H/W Q overflow, need to save the buffer back on the s/w Q.
  711. */
  712. RX_STATS_INC(portId,rxFreeRepFromSwQDelayed);
  713. IX_ETH_ACC_DATAPLANE_ADD_MBUF_TO_Q_HEAD(
  714. ixEthAccPortData[portId].ixEthAccRxData.freeBufferList,
  715. mbuf);
  716. }
  717. else
  718. {
  719. /* unexpected qmgr error */
  720. RX_INC(portId,rxUnexpectedError);
  721. IX_ETH_ACC_DATAPLANE_ADD_MBUF_TO_Q_HEAD(
  722. ixEthAccPortData[portId].ixEthAccRxData.freeBufferList,
  723. mbuf);
  724. IX_ETH_ACC_FATAL_LOG("IxEthAccRxFreeFromSwQ:Error: unexpected QM status 0x%08X\n",
  725. qStatus, 0, 0, 0, 0, 0);
  726. }
  727. }
  728. else
  729. {
  730. /* sw queue is empty */
  731. }
  732. return IX_ETH_ACC_FAIL;
  733. }
  734. IX_ETH_ACC_PUBLIC
  735. IxEthAccStatus ixEthAccInitDataPlane()
  736. {
  737. UINT32 portId;
  738. /*
  739. * Initialize the service and register callback to other services.
  740. */
  741. IX_ETH_ACC_MEMSET(&ixEthAccDataStats,
  742. 0,
  743. sizeof(ixEthAccDataStats));
  744. for(portId=0; portId < IX_ETH_ACC_NUMBER_OF_PORTS; portId++)
  745. {
  746. ixOsalFastMutexInit(&txWriteMutex[portId]);
  747. ixOsalFastMutexInit(&rxWriteMutex[portId]);
  748. IX_ETH_ACC_MEMSET(&ixEthAccPortData[portId],
  749. 0,
  750. sizeof(ixEthAccPortData[portId]));
  751. ixEthAccPortData[portId].ixEthAccTxData.schDiscipline = FIFO_NO_PRIORITY;
  752. }
  753. return (IX_ETH_ACC_SUCCESS);
  754. }
  755. IX_ETH_ACC_PUBLIC
  756. IxEthAccStatus ixEthAccPortTxDoneCallbackRegister(IxEthAccPortId portId,
  757. IxEthAccPortTxDoneCallback
  758. txCallbackFn,
  759. UINT32 callbackTag)
  760. {
  761. if (!IX_ETH_ACC_IS_SERVICE_INITIALIZED())
  762. {
  763. return (IX_ETH_ACC_FAIL);
  764. }
  765. if (!IX_ETH_ACC_IS_PORT_VALID(portId))
  766. {
  767. return (IX_ETH_ACC_INVALID_PORT);
  768. }
  769. /* HACK: removing this code to enable NPE-A preliminary testing
  770. * if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
  771. * {
  772. * IX_ETH_ACC_WARNING_LOG("ixEthAccPortTxDoneCallbackRegister: Unavailable Eth %d: Cannot register TxDone Callback.\n",(INT32)portId,0,0,0,0,0);
  773. * return IX_ETH_ACC_SUCCESS ;
  774. * }
  775. */
  776. if (!IX_ETH_IS_PORT_INITIALIZED(portId))
  777. {
  778. return (IX_ETH_ACC_PORT_UNINITIALIZED);
  779. }
  780. if (txCallbackFn == 0)
  781. /* Check for null function pointer here. */
  782. {
  783. return (IX_ETH_ACC_INVALID_ARG);
  784. }
  785. ixEthAccPortData[portId].ixEthAccTxData.txBufferDoneCallbackFn = txCallbackFn;
  786. ixEthAccPortData[portId].ixEthAccTxData.txCallbackTag = callbackTag;
  787. return (IX_ETH_ACC_SUCCESS);
  788. }
  789. IX_ETH_ACC_PUBLIC
  790. IxEthAccStatus ixEthAccPortRxCallbackRegister(IxEthAccPortId portId,
  791. IxEthAccPortRxCallback
  792. rxCallbackFn,
  793. UINT32 callbackTag)
  794. {
  795. IxEthAccPortId port;
  796. if (!IX_ETH_ACC_IS_SERVICE_INITIALIZED())
  797. {
  798. return (IX_ETH_ACC_FAIL);
  799. }
  800. if (!IX_ETH_ACC_IS_PORT_VALID(portId))
  801. {
  802. return (IX_ETH_ACC_INVALID_PORT);
  803. }
  804. if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
  805. {
  806. IX_ETH_ACC_WARNING_LOG("ixEthAccPortRxCallbackRegister: Unavailable Eth %d: Cannot register Rx Callback.\n",(INT32)portId,0,0,0,0,0);
  807. return IX_ETH_ACC_SUCCESS ;
  808. }
  809. if (!IX_ETH_IS_PORT_INITIALIZED(portId))
  810. {
  811. return (IX_ETH_ACC_PORT_UNINITIALIZED);
  812. }
  813. /* Check for null function pointer here. */
  814. if (rxCallbackFn == NULL)
  815. {
  816. return (IX_ETH_ACC_INVALID_ARG);
  817. }
  818. /* Check the user is not changing the callback type
  819. * when the port is enabled.
  820. */
  821. if (ixEthAccMacState[portId].portDisableState == ACTIVE)
  822. {
  823. for (port = 0; port < IX_ETH_ACC_NUMBER_OF_PORTS; port++)
  824. {
  825. if ((ixEthAccMacState[port].portDisableState == ACTIVE)
  826. && (ixEthAccPortData[port].ixEthAccRxData.rxMultiBufferCallbackInUse == true))
  827. {
  828. /* one of the active ports has a different rx callback type.
  829. * Changing the callback type when the port is enabled
  830. * is not safe
  831. */
  832. return (IX_ETH_ACC_INVALID_ARG);
  833. }
  834. }
  835. }
  836. /* update the callback pointer : this is done before
  837. * registering the new qmgr callback
  838. */
  839. ixEthAccPortData[portId].ixEthAccRxData.rxCallbackFn = rxCallbackFn;
  840. ixEthAccPortData[portId].ixEthAccRxData.rxCallbackTag = callbackTag;
  841. /* update the qmgr callback for rx queues */
  842. if (ixEthAccQMgrRxCallbacksRegister(ixEthRxFrameQMCallback)
  843. != IX_ETH_ACC_SUCCESS)
  844. {
  845. /* unexpected qmgr error */
  846. IX_ETH_ACC_FATAL_LOG("ixEthAccPortRxCallbackRegister: unexpected QMgr error, " \
  847. "could not register Rx single-buffer callback\n", 0, 0, 0, 0, 0, 0);
  848. RX_INC(portId,rxUnexpectedError);
  849. return (IX_ETH_ACC_INVALID_ARG);
  850. }
  851. ixEthAccPortData[portId].ixEthAccRxData.rxMultiBufferCallbackInUse = false;
  852. return (IX_ETH_ACC_SUCCESS);
  853. }
  854. IX_ETH_ACC_PUBLIC
  855. IxEthAccStatus ixEthAccPortMultiBufferRxCallbackRegister(
  856. IxEthAccPortId portId,
  857. IxEthAccPortMultiBufferRxCallback
  858. rxCallbackFn,
  859. UINT32 callbackTag)
  860. {
  861. IxEthAccPortId port;
  862. if (!IX_ETH_ACC_IS_SERVICE_INITIALIZED())
  863. {
  864. return (IX_ETH_ACC_FAIL);
  865. }
  866. if (!IX_ETH_ACC_IS_PORT_VALID(portId))
  867. {
  868. return (IX_ETH_ACC_INVALID_PORT);
  869. }
  870. if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
  871. {
  872. IX_ETH_ACC_WARNING_LOG("ixEthAccPortMultiBufferRxCallbackRegister: Unavailable Eth %d: Cannot register Rx Callback.\n",(INT32)portId,0,0,0,0,0);
  873. return IX_ETH_ACC_SUCCESS ;
  874. }
  875. if (!IX_ETH_IS_PORT_INITIALIZED(portId))
  876. {
  877. return (IX_ETH_ACC_PORT_UNINITIALIZED);
  878. }
  879. /* Check for null function pointer here. */
  880. if (rxCallbackFn == NULL)
  881. {
  882. return (IX_ETH_ACC_INVALID_ARG);
  883. }
  884. /* Check the user is not changing the callback type
  885. * when the port is enabled.
  886. */
  887. if (ixEthAccMacState[portId].portDisableState == ACTIVE)
  888. {
  889. for (port = 0; port < IX_ETH_ACC_NUMBER_OF_PORTS; port++)
  890. {
  891. if ((ixEthAccMacState[port].portDisableState == ACTIVE)
  892. && (ixEthAccPortData[port].ixEthAccRxData.rxMultiBufferCallbackInUse == false))
  893. {
  894. /* one of the active ports has a different rx callback type.
  895. * Changing the callback type when the port is enabled
  896. * is not safe
  897. */
  898. return (IX_ETH_ACC_INVALID_ARG);
  899. }
  900. }
  901. }
  902. /* update the callback pointer : this is done before
  903. * registering the new qmgr callback
  904. */
  905. ixEthAccPortData[portId].ixEthAccRxData.rxMultiBufferCallbackFn = rxCallbackFn;
  906. ixEthAccPortData[portId].ixEthAccRxData.rxMultiBufferCallbackTag = callbackTag;
  907. /* update the qmgr callback for rx queues */
  908. if (ixEthAccQMgrRxCallbacksRegister(ixEthRxMultiBufferQMCallback)
  909. != IX_ETH_ACC_SUCCESS)
  910. {
  911. /* unexpected qmgr error */
  912. RX_INC(portId,rxUnexpectedError);
  913. IX_ETH_ACC_FATAL_LOG("ixEthAccPortMultiBufferRxCallbackRegister: unexpected QMgr error, " \
  914. "could not register Rx multi-buffer callback\n", 0, 0, 0, 0, 0, 0);
  915. return (IX_ETH_ACC_INVALID_ARG);
  916. }
  917. ixEthAccPortData[portId].ixEthAccRxData.rxMultiBufferCallbackInUse = true;
  918. return (IX_ETH_ACC_SUCCESS);
  919. }
  920. IX_ETH_ACC_PUBLIC
  921. IxEthAccStatus ixEthAccPortTxFrameSubmit(IxEthAccPortId portId,
  922. IX_OSAL_MBUF *buffer,
  923. IxEthAccTxPriority priority)
  924. {
  925. IX_STATUS qStatus = IX_SUCCESS;
  926. UINT32 qBuffer;
  927. IxEthAccTxPriority highestPriority;
  928. IxQMgrQStatus txQStatus;
  929. #ifndef NDEBUG
  930. if (buffer == NULL)
  931. {
  932. return (IX_ETH_ACC_FAIL);
  933. }
  934. if (!IX_ETH_ACC_IS_SERVICE_INITIALIZED())
  935. {
  936. return (IX_ETH_ACC_FAIL);
  937. }
  938. if (!IX_ETH_ACC_IS_PORT_VALID(portId))
  939. {
  940. return (IX_ETH_ACC_INVALID_PORT);
  941. }
  942. if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
  943. {
  944. IX_ETH_ACC_FATAL_LOG("ixEthAccPortTxFrameSubmit: Unavailable Eth %d: Cannot submit Tx Frame.\n",
  945. (INT32)portId,0,0,0,0,0);
  946. return IX_ETH_ACC_PORT_UNINITIALIZED ;
  947. }
  948. if (!IX_ETH_IS_PORT_INITIALIZED(portId))
  949. {
  950. return (IX_ETH_ACC_PORT_UNINITIALIZED);
  951. }
  952. if ((UINT32)priority > (UINT32)IX_ETH_ACC_TX_PRIORITY_7)
  953. {
  954. return (IX_ETH_ACC_INVALID_ARG);
  955. }
  956. #endif
  957. /*
  958. * Need to Flush the MBUF and its contents (data) as it may be
  959. * read from the NPE. Convert virtual addresses to physical addresses also.
  960. */
  961. qBuffer = ixEthAccMbufTxQPrepare(buffer);
  962. /*
  963. * If no fifo priority set on Xscale ...
  964. */
  965. if (ixEthAccPortData[portId].ixEthAccTxData.schDiscipline ==
  966. FIFO_NO_PRIORITY)
  967. {
  968. /*
  969. * Add The Tx Buffer to the H/W Tx Q if possible
  970. * (the priority is passed to the NPE, because
  971. * the NPE is able to reorder the frames
  972. * before transmission to the underlying hardware)
  973. */
  974. qStatus = ixEthAccQmgrTxWrite(portId,
  975. qBuffer,
  976. IX_ETH_ACC_TX_DEFAULT_PRIORITY);
  977. if (qStatus == IX_SUCCESS)
  978. {
  979. TX_STATS_INC(portId,txQOK);
  980. /*
  981. * "best case" scenario : Buffer added to h/w Q.
  982. */
  983. return (IX_SUCCESS);
  984. }
  985. else if (qStatus == IX_QMGR_Q_OVERFLOW)
  986. {
  987. /*
  988. * We were unable to write the buffer to the
  989. * appropriate H/W Q, Save it in the sw Q.
  990. * (use the default priority queue regardless of
  991. * input parameter)
  992. */
  993. priority = IX_ETH_ACC_TX_DEFAULT_PRIORITY;
  994. }
  995. else
  996. {
  997. /* unexpected qmgr error */
  998. TX_INC(portId,txUnexpectedError);
  999. IX_ETH_ACC_FATAL_LOG(
  1000. "ixEthAccPortTxFrameSubmit:Error: qStatus = %u\n",
  1001. (UINT32)qStatus, 0, 0, 0, 0, 0);
  1002. return (IX_ETH_ACC_FAIL);
  1003. }
  1004. }
  1005. else if (ixEthAccPortData[portId].ixEthAccTxData.schDiscipline ==
  1006. FIFO_PRIORITY)
  1007. {
  1008. /*
  1009. * For priority transmission, put the frame directly on the H/W queue
  1010. * if the H/W queue is empty, otherwise, put it in a S/W Q
  1011. */
  1012. ixQMgrQStatusGet(IX_ETH_ACC_PORT_TO_TX_Q_ID(portId), &txQStatus);
  1013. if((txQStatus & IX_QMGR_Q_STATUS_E_BIT_MASK) != 0)
  1014. {
  1015. /*The tx queue is empty, check whether there are buffers on the s/w queues*/
  1016. if(ixEthAccTxSwQHighestPriorityGet(portId, &highestPriority)
  1017. !=IX_ETH_ACC_FAIL)
  1018. {
  1019. /*there are buffers on the s/w queues, submit them*/
  1020. ixEthAccTxFromSwQ(portId, highestPriority);
  1021. /* the queue was empty, 1 buffer is already supplied
  1022. * but is likely to be immediately transmitted and the
  1023. * hw queue is likely to be empty again, so submit
  1024. * more from the sw queues
  1025. */
  1026. if(ixEthAccTxSwQHighestPriorityGet(portId, &highestPriority)
  1027. !=IX_ETH_ACC_FAIL)
  1028. {
  1029. ixEthAccTxFromSwQ(portId, highestPriority);
  1030. /*
  1031. * and force the buffer supplied to be placed
  1032. * on a priority queue
  1033. */
  1034. qStatus = IX_QMGR_Q_OVERFLOW;
  1035. }
  1036. else
  1037. {
  1038. /*there are no buffers in the s/w queues, submit directly*/
  1039. qStatus = ixEthAccQmgrTxWrite(portId, qBuffer, priority);
  1040. }
  1041. }
  1042. else
  1043. {
  1044. /*there are no buffers in the s/w queues, submit directly*/
  1045. qStatus = ixEthAccQmgrTxWrite(portId, qBuffer, priority);
  1046. }
  1047. }
  1048. else
  1049. {
  1050. qStatus = IX_QMGR_Q_OVERFLOW;
  1051. }
  1052. }
  1053. else
  1054. {
  1055. TX_INC(portId,txUnexpectedError);
  1056. IX_ETH_ACC_FATAL_LOG(
  1057. "ixEthAccPortTxFrameSubmit:Error: wrong schedule discipline setup\n",
  1058. 0, 0, 0, 0, 0, 0);
  1059. return (IX_ETH_ACC_FAIL);
  1060. }
  1061. if(qStatus == IX_SUCCESS )
  1062. {
  1063. TX_STATS_INC(portId,txQOK);
  1064. return IX_ETH_ACC_SUCCESS;
  1065. }
  1066. else if(qStatus == IX_QMGR_Q_OVERFLOW)
  1067. {
  1068. TX_STATS_INC(portId,txQDelayed);
  1069. /*
  1070. * We were unable to write the buffer to the
  1071. * appropriate H/W Q, Save it in a s/w Q.
  1072. */
  1073. IX_ETH_ACC_DATAPLANE_ADD_MBUF_TO_Q_TAIL(
  1074. ixEthAccPortData[portId].
  1075. ixEthAccTxData.txQ[priority],
  1076. buffer);
  1077. qStatus = ixQMgrNotificationEnable(
  1078. IX_ETH_ACC_PORT_TO_TX_Q_ID(portId),
  1079. IX_ETH_ACC_PORT_TO_TX_Q_SOURCE(portId));
  1080. if (qStatus != IX_SUCCESS)
  1081. {
  1082. if (qStatus == IX_QMGR_WARNING)
  1083. {
  1084. /* notification is enabled for a queue
  1085. * which is already empty (the condition is already met)
  1086. * and there will be no more queue event to drain the sw queue
  1087. */
  1088. TX_STATS_INC(portId,txLateNotificationEnabled);
  1089. /* pull a buffer from the sw queue */
  1090. if(ixEthAccTxSwQHighestPriorityGet(portId, &highestPriority)
  1091. !=IX_ETH_ACC_FAIL)
  1092. {
  1093. /*there are buffers on the s/w queues, submit from them*/
  1094. ixEthAccTxFromSwQ(portId, highestPriority);
  1095. }
  1096. }
  1097. else
  1098. {
  1099. TX_INC(portId,txUnexpectedError);
  1100. IX_ETH_ACC_FATAL_LOG(
  1101. "ixEthAccPortTxFrameSubmit: unexpected Error: %u\n",
  1102. qStatus, 0, 0, 0, 0, 0);
  1103. }
  1104. }
  1105. }
  1106. else
  1107. {
  1108. TX_INC(portId,txUnexpectedError);
  1109. IX_ETH_ACC_FATAL_LOG(
  1110. "ixEthAccPortTxFrameSubmit: unexpected Error: %u\n",
  1111. qStatus, 0, 0, 0, 0, 0);
  1112. return (IX_ETH_ACC_FAIL);
  1113. }
  1114. return (IX_ETH_ACC_SUCCESS);
  1115. }
  1116. /**
  1117. *
  1118. * @brief replenish: convert a chain of mbufs to the format
  1119. * expected by the NPE
  1120. *
  1121. */
  1122. IX_ETH_ACC_PUBLIC
  1123. IxEthAccStatus ixEthAccPortRxFreeReplenish(IxEthAccPortId portId,
  1124. IX_OSAL_MBUF *buffer)
  1125. {
  1126. IX_STATUS qStatus = IX_SUCCESS;
  1127. UINT32 qBuffer;
  1128. /*
  1129. * Check buffer is valid.
  1130. */
  1131. #ifndef NDEBUG
  1132. /* check parameter value */
  1133. if (buffer == 0)
  1134. {
  1135. return (IX_ETH_ACC_FAIL);
  1136. }
  1137. if (!IX_ETH_ACC_IS_SERVICE_INITIALIZED())
  1138. {
  1139. return (IX_ETH_ACC_FAIL);
  1140. }
  1141. if (!IX_ETH_ACC_IS_PORT_VALID(portId))
  1142. {
  1143. return (IX_ETH_ACC_INVALID_PORT);
  1144. }
  1145. /* check initialisation is done */
  1146. if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
  1147. {
  1148. IX_ETH_ACC_FATAL_LOG(" ixEthAccPortRxFreeReplenish: Unavailable Eth %d: Cannot replenish Rx Free Q.\n",(INT32)portId,0,0,0,0,0);
  1149. return IX_ETH_ACC_PORT_UNINITIALIZED ;
  1150. }
  1151. if (!IX_ETH_IS_PORT_INITIALIZED(portId))
  1152. {
  1153. return (IX_ETH_ACC_PORT_UNINITIALIZED);
  1154. }
  1155. /* check boundaries and constraints */
  1156. if (IX_OSAL_MBUF_MLEN(buffer) < IX_ETHNPE_ACC_RXFREE_BUFFER_LENGTH_MIN)
  1157. {
  1158. return (IX_ETH_ACC_FAIL);
  1159. }
  1160. #endif
  1161. qBuffer = ixEthAccMbufRxQPrepare(buffer);
  1162. /*
  1163. * Add The Rx Buffer to the H/W Free buffer Q if possible
  1164. */
  1165. qStatus = ixEthAccQmgrLockRxWrite(portId, qBuffer);
  1166. if (qStatus == IX_SUCCESS)
  1167. {
  1168. RX_STATS_INC(portId,rxFreeRepOK);
  1169. /*
  1170. * Buffer added to h/w Q.
  1171. */
  1172. return (IX_SUCCESS);
  1173. }
  1174. else if (qStatus == IX_QMGR_Q_OVERFLOW)
  1175. {
  1176. RX_STATS_INC(portId,rxFreeRepDelayed);
  1177. /*
  1178. * We were unable to write the buffer to the approprate H/W Q,
  1179. * Save it in a s/w Q.
  1180. */
  1181. IX_ETH_ACC_DATAPLANE_ADD_MBUF_TO_Q_TAIL(
  1182. ixEthAccPortData[portId].ixEthAccRxData.freeBufferList,
  1183. buffer);
  1184. qStatus = ixQMgrNotificationEnable(
  1185. IX_ETH_ACC_PORT_TO_RX_FREE_Q_ID(portId),
  1186. IX_ETH_ACC_PORT_TO_RX_FREE_Q_SOURCE(portId));
  1187. if (qStatus != IX_SUCCESS)
  1188. {
  1189. if (qStatus == IX_QMGR_WARNING)
  1190. {
  1191. /* notification is enabled for a queue
  1192. * which is already empty (the condition is already met)
  1193. * and there will be no more queue event to drain the sw queue
  1194. * move an entry from the sw queue to the hw queue */
  1195. RX_STATS_INC(portId,rxFreeLateNotificationEnabled);
  1196. ixEthAccRxFreeFromSwQ(portId);
  1197. }
  1198. else
  1199. {
  1200. RX_INC(portId,rxUnexpectedError);
  1201. IX_ETH_ACC_FATAL_LOG(
  1202. "ixEthAccRxPortFreeReplenish:Error: %u\n",
  1203. qStatus, 0, 0, 0, 0, 0);
  1204. }
  1205. }
  1206. }
  1207. else
  1208. {
  1209. RX_INC(portId,rxUnexpectedError);
  1210. IX_ETH_ACC_FATAL_LOG(
  1211. "ixEthAccRxPortFreeReplenish:Error: qStatus = %u\n",
  1212. (UINT32)qStatus, 0, 0, 0, 0, 0);
  1213. return(IX_ETH_ACC_FAIL);
  1214. }
  1215. return (IX_ETH_ACC_SUCCESS);
  1216. }
  1217. IX_ETH_ACC_PUBLIC
  1218. IxEthAccStatus ixEthAccTxSchedulingDisciplineSetPriv(IxEthAccPortId portId,
  1219. IxEthAccSchedulerDiscipline
  1220. sched)
  1221. {
  1222. if (!IX_ETH_ACC_IS_PORT_VALID(portId))
  1223. {
  1224. return (IX_ETH_ACC_INVALID_PORT);
  1225. }
  1226. if (IX_ETH_ACC_SUCCESS != ixEthAccSingleEthNpeCheck(portId))
  1227. {
  1228. IX_ETH_ACC_WARNING_LOG("ixEthAccTxSchedulingDisciplineSet: Unavailable Eth %d: Cannot set Tx Scheduling Discipline.\n",(INT32)portId,0,0,0,0,0);
  1229. return IX_ETH_ACC_SUCCESS ;
  1230. }
  1231. if (!IX_ETH_IS_PORT_INITIALIZED(portId))
  1232. {
  1233. return (IX_ETH_ACC_PORT_UNINITIALIZED);
  1234. }
  1235. if (sched != FIFO_PRIORITY && sched != FIFO_NO_PRIORITY)
  1236. {
  1237. return (IX_ETH_ACC_INVALID_ARG);
  1238. }
  1239. ixEthAccPortData[portId].ixEthAccTxData.schDiscipline = sched;
  1240. return (IX_ETH_ACC_SUCCESS);
  1241. }
  1242. IX_ETH_ACC_PUBLIC
  1243. IxEthAccStatus ixEthAccRxSchedulingDisciplineSetPriv(IxEthAccSchedulerDiscipline
  1244. sched)
  1245. {
  1246. if (sched != FIFO_PRIORITY && sched != FIFO_NO_PRIORITY)
  1247. {
  1248. return (IX_ETH_ACC_INVALID_ARG);
  1249. }
  1250. ixEthAccDataInfo.schDiscipline = sched;
  1251. return (IX_ETH_ACC_SUCCESS);
  1252. }
  1253. /**
  1254. * @fn ixEthRxFrameProcess(IxEthAccPortId portId, IX_OSAL_MBUF *mbufPtr)
  1255. *
  1256. * @brief process incoming frame :
  1257. *
  1258. * @param @ref IxQMgrCallback IxQMgrMultiBufferCallback
  1259. *
  1260. * @return none
  1261. *
  1262. * @internal
  1263. *
  1264. */
  1265. IX_ETH_ACC_PRIVATE BOOL
  1266. ixEthRxFrameProcess(IxEthAccPortId portId, IX_OSAL_MBUF *mbufPtr)
  1267. {
  1268. UINT32 flags;
  1269. IxEthDBStatus result;
  1270. #ifndef NDEBUG
  1271. /* Prudent to at least check the port is within range */
  1272. if (portId >= IX_ETH_ACC_NUMBER_OF_PORTS)
  1273. {
  1274. ixEthAccDataStats.unexpectedError++;
  1275. IX_ETH_ACC_FATAL_LOG(
  1276. "ixEthRxFrameProcess: Illegal port: %u\n",
  1277. (UINT32)portId, 0, 0, 0, 0, 0);
  1278. return false;
  1279. }
  1280. #endif
  1281. /* convert fields from mbuf header */
  1282. ixEthAccMbufFromRxQ(mbufPtr);
  1283. /* check about any special processing for this frame */
  1284. flags = IX_ETHACC_NE_FLAGS(mbufPtr);
  1285. if ((flags & (IX_ETHACC_NE_FILTERMASK | IX_ETHACC_NE_NEWSRCMASK)) == 0)
  1286. {
  1287. /* "best case" scenario : nothing special to do for this frame */
  1288. return true;
  1289. }
  1290. #ifdef CONFIG_IXP425_COMPONENT_ETHDB
  1291. /* if a new source MAC address is detected by the NPE,
  1292. * update IxEthDB with the portId and the MAC address.
  1293. */
  1294. if ((flags & IX_ETHACC_NE_NEWSRCMASK & ixEthAccNewSrcMask) != 0)
  1295. {
  1296. result = ixEthDBFilteringDynamicEntryProvision(portId,
  1297. (IxEthDBMacAddr *) IX_ETHACC_NE_SOURCEMAC(mbufPtr));
  1298. if (result != IX_ETH_DB_SUCCESS && result != IX_ETH_DB_FEATURE_UNAVAILABLE)
  1299. {
  1300. if ((ixEthAccMacState[portId].portDisableState == ACTIVE) && (result != IX_ETH_DB_BUSY))
  1301. {
  1302. RX_STATS_INC(portId, rxUnexpectedError);
  1303. IX_ETH_ACC_FATAL_LOG("ixEthRxFrameProcess: Failed to add source MAC \
  1304. to the Learning/Filtering database\n", 0, 0, 0, 0, 0, 0);
  1305. }
  1306. else
  1307. {
  1308. /* we expect this to fail during PortDisable, as EthDB is disabled for
  1309. * that port and will refuse to learn new addresses
  1310. */
  1311. }
  1312. }
  1313. else
  1314. {
  1315. RX_STATS_INC(portId, rxUnlearnedMacAddress);
  1316. }
  1317. }
  1318. #endif
  1319. /* check if this frame should have been filtered
  1320. * by the NPE and take the appropriate action
  1321. */
  1322. if (((flags & IX_ETHACC_NE_FILTERMASK) != 0)
  1323. && (ixEthAccMacState[portId].portDisableState == ACTIVE))
  1324. {
  1325. /* If the mbuf was allocated with a small data size, or the current data pointer is not
  1326. * within the allocated data area, then the buffer is non-standard and has to be
  1327. * replenished with the minimum size only
  1328. */
  1329. if( (IX_OSAL_MBUF_ALLOCATED_BUFF_LEN(mbufPtr) < IX_ETHNPE_ACC_RXFREE_BUFFER_LENGTH_MIN)
  1330. || ((UINT8 *)IX_OSAL_MBUF_ALLOCATED_BUFF_DATA(mbufPtr) > IX_OSAL_MBUF_MDATA(mbufPtr))
  1331. || ((UINT8 *)(IX_OSAL_MBUF_ALLOCATED_BUFF_DATA(mbufPtr) +
  1332. IX_OSAL_MBUF_ALLOCATED_BUFF_LEN(mbufPtr))
  1333. < IX_OSAL_MBUF_MDATA(mbufPtr)) )
  1334. {
  1335. /* set to minimum length */
  1336. IX_OSAL_MBUF_MLEN(mbufPtr) = IX_OSAL_MBUF_PKT_LEN(mbufPtr) =
  1337. IX_ETHNPE_ACC_RXFREE_BUFFER_LENGTH_MIN;
  1338. }
  1339. else
  1340. {
  1341. /* restore original length */
  1342. IX_OSAL_MBUF_MLEN(mbufPtr) = IX_OSAL_MBUF_PKT_LEN(mbufPtr) =
  1343. ( IX_OSAL_MBUF_ALLOCATED_BUFF_LEN(mbufPtr) -
  1344. (IX_OSAL_MBUF_MDATA(mbufPtr) - (UINT8 *)IX_OSAL_MBUF_ALLOCATED_BUFF_DATA(mbufPtr)) );
  1345. }
  1346. /* replenish from here */
  1347. if (ixEthAccPortRxFreeReplenish(portId, mbufPtr) != IX_ETH_ACC_SUCCESS)
  1348. {
  1349. IX_ETH_ACC_FATAL_LOG("ixEthRxFrameProcess: Failed to replenish with filtered frame\
  1350. on port %d\n", portId, 0, 0, 0, 0, 0);
  1351. }
  1352. RX_STATS_INC(portId, rxFiltered);
  1353. /* indicate that frame should not be subjected to further processing */
  1354. return false;
  1355. }
  1356. return true;
  1357. }
  1358. /**
  1359. * @fn ixEthRxFrameQMCallback
  1360. *
  1361. * @brief receive callback for Frame receive Q from NPE
  1362. *
  1363. * Frames are passed one-at-a-time to the user
  1364. *
  1365. * @param @ref IxQMgrCallback
  1366. *
  1367. * @return none
  1368. *
  1369. * @internal
  1370. *
  1371. * Design note : while processing the entry X, entry X+1 is preloaded
  1372. * into memory to reduce the number of stall cycles
  1373. *
  1374. */
  1375. void ixEthRxFrameQMCallback(IxQMgrQId qId, IxQMgrCallbackId callbackId)
  1376. {
  1377. IX_OSAL_MBUF *mbufPtr;
  1378. IX_OSAL_MBUF *nextMbufPtr;
  1379. UINT32 qEntry;
  1380. UINT32 nextQEntry;
  1381. UINT32 *qEntryPtr;
  1382. UINT32 portId;
  1383. UINT32 destPortId;
  1384. UINT32 npeId;
  1385. UINT32 rxQReadStatus;
  1386. /*
  1387. * Design note : entries are read in a buffer, This buffer contains
  1388. * an extra zeroed entry so the loop will
  1389. * always terminate on a null entry, whatever the result of Burst read is.
  1390. */
  1391. UINT32 rxQEntry[IX_ETH_ACC_MAX_RX_FRAME_CONSUME_PER_CALLBACK + 1];
  1392. /*
  1393. * Indication of the number of times the callback is used.
  1394. */
  1395. IX_ETH_ACC_STATS_INC(ixEthAccDataStats.rxCallbackCounter);
  1396. do
  1397. {
  1398. /*
  1399. * Indication of the number of times the queue is drained
  1400. */
  1401. IX_ETH_ACC_STATS_INC(ixEthAccDataStats.rxCallbackBurstRead);
  1402. /* ensure the last entry of the array contains a zeroed value */
  1403. qEntryPtr = rxQEntry;
  1404. qEntryPtr[IX_ETH_ACC_MAX_RX_FRAME_CONSUME_PER_CALLBACK] = 0;
  1405. rxQReadStatus = ixQMgrQBurstRead(qId,
  1406. IX_ETH_ACC_MAX_RX_FRAME_CONSUME_PER_CALLBACK,
  1407. qEntryPtr);
  1408. #ifndef NDEBUG
  1409. if ((rxQReadStatus != IX_QMGR_Q_UNDERFLOW)
  1410. && (rxQReadStatus != IX_SUCCESS))
  1411. {
  1412. ixEthAccDataStats.unexpectedError++;
  1413. /*major error*/
  1414. IX_ETH_ACC_FATAL_LOG(
  1415. "ixEthRxFrameQMCallback:Error: %u\n",
  1416. (UINT32)rxQReadStatus, 0, 0, 0, 0, 0);
  1417. return;
  1418. }
  1419. #endif
  1420. /* convert and preload the next entry
  1421. * (the conversion function takes care about null pointers which
  1422. * are used to mark the end of the loop)
  1423. */
  1424. nextQEntry = *qEntryPtr;
  1425. nextMbufPtr = ixEthAccEntryFromQConvert(nextQEntry,
  1426. IX_ETHNPE_QM_Q_RXENET_ADDR_MASK);
  1427. while(nextQEntry != 0)
  1428. {
  1429. /* get the next entry */
  1430. qEntry = nextQEntry;
  1431. mbufPtr = nextMbufPtr;
  1432. #ifndef NDEBUG
  1433. if (mbufPtr == NULL)
  1434. {
  1435. ixEthAccDataStats.unexpectedError++;
  1436. IX_ETH_ACC_FATAL_LOG(
  1437. "ixEthRxFrameQMCallback: Null Mbuf Ptr\n",
  1438. 0, 0, 0, 0, 0, 0);
  1439. return;
  1440. }
  1441. #endif
  1442. /* convert the next entry
  1443. * (the conversion function takes care about null pointers which
  1444. * are used to mark the end of the loop)
  1445. */
  1446. nextQEntry = *(++qEntryPtr);
  1447. nextMbufPtr = ixEthAccEntryFromQConvert(nextQEntry,
  1448. IX_ETHNPE_QM_Q_RXENET_ADDR_MASK);
  1449. /*
  1450. * Get Port and Npe ID from message.
  1451. */
  1452. npeId = ((IX_ETHNPE_QM_Q_RXENET_NPEID_MASK &
  1453. qEntry) >> IX_ETHNPE_QM_Q_FIELD_NPEID_R);
  1454. portId = IX_ETH_ACC_NPE_TO_PORT_ID(npeId);
  1455. /* process frame, check the return code and skip the remaining of
  1456. * the loop if the frame is to be filtered out
  1457. */
  1458. if (ixEthRxFrameProcess(portId, mbufPtr))
  1459. {
  1460. /* destination portId for this packet */
  1461. destPortId = IX_ETHACC_NE_DESTPORTID(mbufPtr);
  1462. if (destPortId != IX_ETH_DB_UNKNOWN_PORT)
  1463. {
  1464. destPortId = IX_ETH_DB_NPE_LOGICAL_ID_TO_PORT_ID(destPortId);
  1465. }
  1466. /* test if QoS is enabled in ethAcc
  1467. */
  1468. if (ixEthAccDataInfo.schDiscipline == FIFO_PRIORITY)
  1469. {
  1470. /* check if there is a higher priority queue
  1471. * which may require processing and then process it.
  1472. */
  1473. if (ixEthAccDataInfo.higherPriorityQueue[qId] < IX_QMGR_MAX_NUM_QUEUES)
  1474. {
  1475. ixEthRxFrameQMCallback(ixEthAccDataInfo.higherPriorityQueue[qId],
  1476. callbackId);
  1477. }
  1478. }
  1479. /*
  1480. * increment priority stats
  1481. */
  1482. RX_STATS_INC(portId,rxPriority[IX_ETHACC_NE_QOS(mbufPtr)]);
  1483. /*
  1484. * increment callback count stats
  1485. */
  1486. RX_STATS_INC(portId,rxFrameClientCallback);
  1487. /*
  1488. * Call user level callback.
  1489. */
  1490. ixEthAccPortData[portId].ixEthAccRxData.rxCallbackFn(
  1491. ixEthAccPortData[portId].ixEthAccRxData.rxCallbackTag,
  1492. mbufPtr,
  1493. destPortId);
  1494. }
  1495. }
  1496. } while (rxQReadStatus == IX_SUCCESS);
  1497. }
  1498. /**
  1499. * @fn ixEthRxMultiBufferQMCallback
  1500. *
  1501. * @brief receive callback for Frame receive Q from NPE
  1502. *
  1503. * Frames are passed as an array to the user
  1504. *
  1505. * @param @ref IxQMgrCallback
  1506. *
  1507. * @return none
  1508. *
  1509. * @internal
  1510. *
  1511. * Design note : while processing the entry X, entry X+1 is preloaded
  1512. * into memory to reduce the number of stall cycles
  1513. *
  1514. */
  1515. void ixEthRxMultiBufferQMCallback(IxQMgrQId qId, IxQMgrCallbackId callbackId)
  1516. {
  1517. IX_OSAL_MBUF *mbufPtr;
  1518. IX_OSAL_MBUF *nextMbufPtr;
  1519. UINT32 qEntry;
  1520. UINT32 nextQEntry;
  1521. UINT32 *qEntryPtr;
  1522. UINT32 portId;
  1523. UINT32 npeId;
  1524. UINT32 rxQReadStatus;
  1525. /*
  1526. * Design note : entries are read in a static buffer, This buffer contains
  1527. * an extra zeroed entry so the loop will
  1528. * always terminate on a null entry, whatever the result of Burst read is.
  1529. */
  1530. static UINT32 rxQEntry[IX_ETH_ACC_MAX_RX_FRAME_CONSUME_PER_CALLBACK + 1];
  1531. static IX_OSAL_MBUF *rxMbufPortArray[IX_ETH_ACC_NUMBER_OF_PORTS][IX_ETH_ACC_MAX_RX_FRAME_CONSUME_PER_CALLBACK + 1];
  1532. IX_OSAL_MBUF **rxMbufPtr[IX_ETH_ACC_NUMBER_OF_PORTS];
  1533. for (portId = 0; portId < IX_ETH_ACC_NUMBER_OF_PORTS; portId++)
  1534. {
  1535. rxMbufPtr[portId] = rxMbufPortArray[portId];
  1536. }
  1537. /*
  1538. * Indication of the number of times the callback is used.
  1539. */
  1540. IX_ETH_ACC_STATS_INC(ixEthAccDataStats.rxCallbackCounter);
  1541. do
  1542. {
  1543. /*
  1544. * Indication of the number of times the queue is drained
  1545. */
  1546. IX_ETH_ACC_STATS_INC(ixEthAccDataStats.rxCallbackBurstRead);
  1547. /* ensure the last entry of the array contains a zeroed value */
  1548. qEntryPtr = rxQEntry;
  1549. qEntryPtr[IX_ETH_ACC_MAX_RX_FRAME_CONSUME_PER_CALLBACK] = 0;
  1550. rxQReadStatus = ixQMgrQBurstRead(qId,
  1551. IX_ETH_ACC_MAX_RX_FRAME_CONSUME_PER_CALLBACK,
  1552. qEntryPtr);
  1553. #ifndef NDEBUG
  1554. if ((rxQReadStatus != IX_QMGR_Q_UNDERFLOW)
  1555. && (rxQReadStatus != IX_SUCCESS))
  1556. {
  1557. ixEthAccDataStats.unexpectedError++;
  1558. /*major error*/
  1559. IX_ETH_ACC_FATAL_LOG(
  1560. "ixEthRxFrameMultiBufferQMCallback:Error: %u\n",
  1561. (UINT32)rxQReadStatus, 0, 0, 0, 0, 0);
  1562. return;
  1563. }
  1564. #endif
  1565. /* convert and preload the next entry
  1566. * (the conversion function takes care about null pointers which
  1567. * are used to mark the end of the loop)
  1568. */
  1569. nextQEntry = *qEntryPtr;
  1570. nextMbufPtr = ixEthAccEntryFromQConvert(nextQEntry,
  1571. IX_ETHNPE_QM_Q_RXENET_ADDR_MASK);
  1572. while(nextQEntry != 0)
  1573. {
  1574. /* get the next entry */
  1575. qEntry = nextQEntry;
  1576. mbufPtr = nextMbufPtr;
  1577. #ifndef NDEBUG
  1578. if (mbufPtr == NULL)
  1579. {
  1580. ixEthAccDataStats.unexpectedError++;
  1581. IX_ETH_ACC_FATAL_LOG(
  1582. "ixEthRxFrameMultiBufferQMCallback:Error: Null Mbuf Ptr\n",
  1583. 0, 0, 0, 0, 0, 0);
  1584. return;
  1585. }
  1586. #endif
  1587. /* convert the next entry
  1588. * (the conversion function takes care about null pointers which
  1589. * are used to mark the end of the loop)
  1590. */
  1591. nextQEntry = *(++qEntryPtr);
  1592. nextMbufPtr = ixEthAccEntryFromQConvert(nextQEntry,
  1593. IX_ETHNPE_QM_Q_RXENET_ADDR_MASK);
  1594. /*
  1595. * Get Port and Npe ID from message.
  1596. */
  1597. npeId = ((IX_ETHNPE_QM_Q_RXENET_NPEID_MASK &
  1598. qEntry) >>
  1599. IX_ETHNPE_QM_Q_FIELD_NPEID_R);
  1600. portId = IX_ETH_ACC_NPE_TO_PORT_ID(npeId);
  1601. /* skip the remaining of the loop if the frame is
  1602. * to be filtered out
  1603. */
  1604. if (ixEthRxFrameProcess(portId, mbufPtr))
  1605. {
  1606. /* store a mbuf pointer in an array */
  1607. *rxMbufPtr[portId]++ = mbufPtr;
  1608. /*
  1609. * increment priority stats
  1610. */
  1611. RX_STATS_INC(portId,rxPriority[IX_ETHACC_NE_QOS(mbufPtr)]);
  1612. }
  1613. /* test for QoS enabled in ethAcc */
  1614. if (ixEthAccDataInfo.schDiscipline == FIFO_PRIORITY)
  1615. {
  1616. /* check if there is a higher priority queue
  1617. * which may require processing and then process it.
  1618. */
  1619. if (ixEthAccDataInfo.higherPriorityQueue[qId] < IX_QMGR_MAX_NUM_QUEUES)
  1620. {
  1621. ixEthRxMultiBufferQMCallback(ixEthAccDataInfo.higherPriorityQueue[qId],
  1622. callbackId);
  1623. }
  1624. }
  1625. }
  1626. /* check if any of the the arrays contains any entry */
  1627. for (portId = 0; portId < IX_ETH_ACC_NUMBER_OF_PORTS; portId++)
  1628. {
  1629. if (rxMbufPtr[portId] != rxMbufPortArray[portId])
  1630. {
  1631. /* add a last NULL pointer at the end of the
  1632. * array of mbuf pointers
  1633. */
  1634. *rxMbufPtr[portId] = NULL;
  1635. /*
  1636. * increment callback count stats
  1637. */
  1638. RX_STATS_INC(portId,rxFrameClientCallback);
  1639. /*
  1640. * Call user level callback with an array of
  1641. * buffers (NULL terminated)
  1642. */
  1643. ixEthAccPortData[portId].ixEthAccRxData.
  1644. rxMultiBufferCallbackFn(
  1645. ixEthAccPortData[portId].ixEthAccRxData.
  1646. rxMultiBufferCallbackTag,
  1647. rxMbufPortArray[portId]);
  1648. /* reset the buffer pointer to the beginning of
  1649. * the array
  1650. */
  1651. rxMbufPtr[portId] = rxMbufPortArray[portId];
  1652. }
  1653. }
  1654. } while (rxQReadStatus == IX_SUCCESS);
  1655. }
  1656. /**
  1657. * @brief rxFree low event handler
  1658. *
  1659. */
  1660. void ixEthRxFreeQMCallback(IxQMgrQId qId, IxQMgrCallbackId callbackId)
  1661. {
  1662. IxEthAccPortId portId = (IxEthAccPortId) callbackId;
  1663. int lockVal;
  1664. UINT32 maxQWritesToPerform = IX_ETH_ACC_MAX_RX_FREE_BUFFERS_LOAD;
  1665. IX_STATUS qStatus = IX_SUCCESS;
  1666. /*
  1667. * We have reached a low threshold on one of the Rx Free Qs
  1668. */
  1669. /*note that due to the fact that we are working off an Empty threshold, this callback
  1670. need only write a single entry to the Rx Free queue in order to re-arm the notification
  1671. */
  1672. RX_STATS_INC(portId,rxFreeLowCallback);
  1673. /*
  1674. * Get buffers from approprite S/W Rx freeBufferList Q.
  1675. */
  1676. #ifndef NDEBUG
  1677. if (!IX_ETH_ACC_IS_PORT_VALID(portId))
  1678. {
  1679. ixEthAccDataStats.unexpectedError++;
  1680. IX_ETH_ACC_FATAL_LOG(
  1681. "ixEthRxFreeQMCallback:Error: Invalid Port 0x%08X\n",
  1682. portId, 0, 0, 0, 0, 0);
  1683. return;
  1684. }
  1685. #endif
  1686. IX_ETH_ACC_DATA_PLANE_LOCK(lockVal);
  1687. if (IX_ETH_ACC_DATAPLANE_IS_Q_EMPTY(ixEthAccPortData[portId].
  1688. ixEthAccRxData.freeBufferList))
  1689. {
  1690. /*
  1691. * Turn off Q callback notification for Q in Question.
  1692. */
  1693. qStatus = ixQMgrNotificationDisable(
  1694. IX_ETH_ACC_PORT_TO_RX_FREE_Q_ID(portId));
  1695. IX_ETH_ACC_DATA_PLANE_UNLOCK(lockVal);
  1696. if (qStatus != IX_SUCCESS)
  1697. {
  1698. RX_INC(portId,rxUnexpectedError);
  1699. IX_ETH_ACC_FATAL_LOG(
  1700. "ixEthRxFreeQMCallback:Error: unexpected QM status 0x%08X\n",
  1701. qStatus, 0, 0, 0, 0, 0);
  1702. return;
  1703. }
  1704. }
  1705. else
  1706. {
  1707. IX_ETH_ACC_DATA_PLANE_UNLOCK(lockVal);
  1708. /*
  1709. * Load the H/W Q with buffers from the s/w Q.
  1710. */
  1711. do
  1712. {
  1713. /*
  1714. * Consume Q entries. - Note Q contains Physical addresss,
  1715. * and have already been flushed to memory,
  1716. * And endianess converted if required.
  1717. */
  1718. if (ixEthAccRxFreeFromSwQ(portId) != IX_SUCCESS)
  1719. {
  1720. /*
  1721. * No more entries in s/w Q.
  1722. * Turn off Q callback indication
  1723. */
  1724. IX_ETH_ACC_DATA_PLANE_LOCK(lockVal);
  1725. if (IX_ETH_ACC_DATAPLANE_IS_Q_EMPTY(ixEthAccPortData[portId].
  1726. ixEthAccRxData.freeBufferList))
  1727. {
  1728. qStatus = ixQMgrNotificationDisable(
  1729. IX_ETH_ACC_PORT_TO_RX_FREE_Q_ID(portId));
  1730. }
  1731. IX_ETH_ACC_DATA_PLANE_UNLOCK(lockVal);
  1732. break;
  1733. }
  1734. }
  1735. while (--maxQWritesToPerform);
  1736. }
  1737. }
  1738. /**
  1739. * @fn Tx queue low event handler
  1740. *
  1741. */
  1742. void
  1743. ixEthTxFrameQMCallback(IxQMgrQId qId, IxQMgrCallbackId callbackId)
  1744. {
  1745. IxEthAccPortId portId = (IxEthAccPortId) callbackId;
  1746. int lockVal;
  1747. UINT32 maxQWritesToPerform = IX_ETH_ACC_MAX_TX_FRAME_TX_CONSUME_PER_CALLBACK;
  1748. IX_STATUS qStatus = IX_SUCCESS;
  1749. IxEthAccTxPriority highestPriority;
  1750. /*
  1751. * We have reached a low threshold on the Tx Q, and are being asked to
  1752. * supply a buffer for transmission from our S/W TX queues
  1753. */
  1754. TX_STATS_INC(portId,txLowThreshCallback);
  1755. /*
  1756. * Get buffers from approprite Q.
  1757. */
  1758. #ifndef NDEBUG
  1759. if (!IX_ETH_ACC_IS_PORT_VALID(portId))
  1760. {
  1761. ixEthAccDataStats.unexpectedError++;
  1762. IX_ETH_ACC_FATAL_LOG(
  1763. "ixEthTxFrameQMCallback:Error: Invalid Port 0x%08X\n",
  1764. portId, 0, 0, 0, 0, 0);
  1765. return;
  1766. }
  1767. #endif
  1768. do
  1769. {
  1770. /*
  1771. * Consume Q entries. - Note Q contains Physical addresss,
  1772. * and have already been flushed to memory,
  1773. * and endianess already sone if required.
  1774. */
  1775. IX_ETH_ACC_DATA_PLANE_LOCK(lockVal);
  1776. if(ixEthAccTxSwQHighestPriorityGet(portId, &highestPriority) ==
  1777. IX_ETH_ACC_FAIL)
  1778. {
  1779. /*
  1780. * No more entries in s/w Q.
  1781. * Turn off Q callback indication
  1782. */
  1783. qStatus = ixQMgrNotificationDisable(
  1784. IX_ETH_ACC_PORT_TO_TX_Q_ID(portId));
  1785. IX_ETH_ACC_DATA_PLANE_UNLOCK(lockVal);
  1786. if (qStatus != IX_SUCCESS)
  1787. {
  1788. ixEthAccDataStats.unexpectedError++;
  1789. IX_ETH_ACC_FATAL_LOG(
  1790. "ixEthTxFrameQMCallback:Error: unexpected QM status 0x%08X\n",
  1791. qStatus, 0, 0, 0, 0, 0);
  1792. }
  1793. return;
  1794. }
  1795. else
  1796. {
  1797. IX_ETH_ACC_DATA_PLANE_UNLOCK(lockVal);
  1798. if (ixEthAccTxFromSwQ(portId,highestPriority)!=IX_SUCCESS)
  1799. {
  1800. /* nothing left in the sw queue or the hw queues are
  1801. * full. There is no point to continue to drain the
  1802. * sw queues
  1803. */
  1804. return;
  1805. }
  1806. }
  1807. }
  1808. while (--maxQWritesToPerform);
  1809. }
  1810. /**
  1811. * @brief TxDone event handler
  1812. *
  1813. * Design note : while processing the entry X, entry X+1 is preloaded
  1814. * into memory to reduce the number of stall cycles
  1815. *
  1816. */
  1817. void
  1818. ixEthTxFrameDoneQMCallback(IxQMgrQId qId, IxQMgrCallbackId callbackId)
  1819. {
  1820. IX_OSAL_MBUF *mbufPtr;
  1821. UINT32 qEntry;
  1822. UINT32 *qEntryPtr;
  1823. UINT32 txDoneQReadStatus;
  1824. UINT32 portId;
  1825. UINT32 npeId;
  1826. /*
  1827. * Design note : entries are read in a static buffer, This buffer contains
  1828. * an extra entyry (which is zeroed by the compiler), so the loop will
  1829. * always terminate on a null entry, whatever the result of Burst read is.
  1830. */
  1831. static UINT32 txDoneQEntry[IX_ETH_ACC_MAX_TX_FRAME_DONE_CONSUME_PER_CALLBACK + 1];
  1832. /*
  1833. * Indication that Tx frames have been transmitted from the NPE.
  1834. */
  1835. IX_ETH_ACC_STATS_INC(ixEthAccDataStats.txDoneCallbackCounter);
  1836. do{
  1837. qEntryPtr = txDoneQEntry;
  1838. txDoneQReadStatus = ixQMgrQBurstRead(IX_ETH_ACC_TX_FRAME_DONE_ETH_Q,
  1839. IX_ETH_ACC_MAX_TX_FRAME_DONE_CONSUME_PER_CALLBACK,
  1840. qEntryPtr);
  1841. #ifndef NDEBUG
  1842. if (txDoneQReadStatus != IX_QMGR_Q_UNDERFLOW
  1843. && (txDoneQReadStatus != IX_SUCCESS))
  1844. {
  1845. /*major error*/
  1846. ixEthAccDataStats.unexpectedError++;
  1847. IX_ETH_ACC_FATAL_LOG(
  1848. "ixEthTxFrameDoneQMCallback:Error: %u\n",
  1849. (UINT32)txDoneQReadStatus, 0, 0, 0, 0, 0);
  1850. return;
  1851. }
  1852. #endif
  1853. qEntry = *qEntryPtr;
  1854. while(qEntry != 0)
  1855. {
  1856. mbufPtr = ixEthAccEntryFromQConvert(qEntry,
  1857. IX_ETHNPE_QM_Q_TXENET_ADDR_MASK);
  1858. #ifndef NDEBUG
  1859. if (mbufPtr == NULL)
  1860. {
  1861. ixEthAccDataStats.unexpectedError++;
  1862. IX_ETH_ACC_FATAL_LOG(
  1863. "ixEthTxFrameDoneQMCallback:Error: Null Mbuf Ptr\n",
  1864. 0, 0, 0, 0, 0, 0);
  1865. return;
  1866. }
  1867. #endif
  1868. /* endianness conversions and stats updates */
  1869. ixEthAccMbufFromTxQ(mbufPtr);
  1870. /*
  1871. * Get NPE id from message, then convert to portId.
  1872. */
  1873. npeId = ((IX_ETHNPE_QM_Q_TXENETDONE_NPEID_MASK &
  1874. qEntry) >>
  1875. IX_ETHNPE_QM_Q_FIELD_NPEID_R);
  1876. portId = IX_ETH_ACC_NPE_TO_PORT_ID(npeId);
  1877. #ifndef NDEBUG
  1878. /* Prudent to at least check the port is within range */
  1879. if (portId >= IX_ETH_ACC_NUMBER_OF_PORTS)
  1880. {
  1881. ixEthAccDataStats.unexpectedError++;
  1882. IX_ETH_ACC_FATAL_LOG(
  1883. "ixEthTxFrameDoneQMCallback: Illegal port: %u\n",
  1884. (UINT32)portId, 0, 0, 0, 0, 0);
  1885. return;
  1886. }
  1887. #endif
  1888. TX_STATS_INC(portId,txDoneClientCallback);
  1889. /*
  1890. * Call user level callback.
  1891. */
  1892. ixEthAccPortData[portId].ixEthAccTxData.txBufferDoneCallbackFn(
  1893. ixEthAccPortData[portId].ixEthAccTxData.txCallbackTag,
  1894. mbufPtr);
  1895. /* move to next queue entry */
  1896. qEntry = *(++qEntryPtr);
  1897. }
  1898. } while( txDoneQReadStatus == IX_SUCCESS );
  1899. }
  1900. IX_ETH_ACC_PUBLIC
  1901. void ixEthAccDataPlaneShow(void)
  1902. {
  1903. UINT32 numTx0Entries;
  1904. UINT32 numTx1Entries;
  1905. UINT32 numTxDoneEntries;
  1906. UINT32 numRxEntries;
  1907. UINT32 numRxFree0Entries;
  1908. UINT32 numRxFree1Entries;
  1909. UINT32 portId;
  1910. #ifdef __ixp46X
  1911. UINT32 numTx2Entries;
  1912. UINT32 numRxFree2Entries;
  1913. #endif
  1914. #ifndef NDEBUG
  1915. UINT32 priority;
  1916. UINT32 numBuffersInRx=0;
  1917. UINT32 numBuffersInTx=0;
  1918. UINT32 numBuffersInSwQ=0;
  1919. UINT32 totalBuffers=0;
  1920. UINT32 rxFreeCallbackCounter = 0;
  1921. UINT32 txCallbackCounter = 0;
  1922. #endif
  1923. UINT32 key;
  1924. /* snapshot of stats */
  1925. IxEthAccTxDataStats tx[IX_ETH_ACC_NUMBER_OF_PORTS];
  1926. IxEthAccRxDataStats rx[IX_ETH_ACC_NUMBER_OF_PORTS];
  1927. IxEthAccDataPlaneStats stats;
  1928. if (!IX_ETH_ACC_IS_SERVICE_INITIALIZED())
  1929. {
  1930. return;
  1931. }
  1932. /* get a reliable snapshot */
  1933. key = ixOsalIrqLock();
  1934. numTx0Entries = 0;
  1935. ixQMgrQNumEntriesGet(IX_ETH_ACC_TX_FRAME_ENET0_Q, &numTx0Entries);
  1936. numTx1Entries = 0;
  1937. ixQMgrQNumEntriesGet(IX_ETH_ACC_TX_FRAME_ENET1_Q, &numTx1Entries);
  1938. numTxDoneEntries = 0;
  1939. ixQMgrQNumEntriesGet( IX_ETH_ACC_TX_FRAME_DONE_ETH_Q, &numTxDoneEntries);
  1940. numRxEntries = 0;
  1941. ixEthAccQMgrRxQEntryGet(&numRxEntries);
  1942. numRxFree0Entries = 0;
  1943. ixQMgrQNumEntriesGet(IX_ETH_ACC_RX_FREE_BUFF_ENET0_Q, &numRxFree0Entries);
  1944. numRxFree1Entries = 0;
  1945. ixQMgrQNumEntriesGet(IX_ETH_ACC_RX_FREE_BUFF_ENET1_Q, &numRxFree1Entries);
  1946. #ifdef __ixp46X
  1947. numTx2Entries = 0;
  1948. ixQMgrQNumEntriesGet(IX_ETH_ACC_TX_FRAME_ENET2_Q, &numTx2Entries);
  1949. numRxFree2Entries = 0;
  1950. ixQMgrQNumEntriesGet(IX_ETH_ACC_RX_FREE_BUFF_ENET2_Q, &numRxFree2Entries);
  1951. #endif
  1952. for(portId=IX_ETH_PORT_1; portId < IX_ETH_ACC_NUMBER_OF_PORTS; portId++)
  1953. {
  1954. memcpy(&tx[portId],
  1955. &ixEthAccPortData[portId].ixEthAccTxData.stats,
  1956. sizeof(tx[portId]));
  1957. memcpy(&rx[portId],
  1958. &ixEthAccPortData[portId].ixEthAccRxData.stats,
  1959. sizeof(rx[portId]));
  1960. }
  1961. memcpy(&stats, &ixEthAccDataStats, sizeof(stats));
  1962. ixOsalIrqUnlock(key);
  1963. #ifdef NDEBUG
  1964. printf("Detailed statistics collection not supported in this load\n");
  1965. #endif
  1966. /* print snapshot */
  1967. for(portId=0; portId < IX_ETH_ACC_NUMBER_OF_PORTS; portId++)
  1968. {
  1969. /* If not IXP42X A0 stepping, proceed to check for existence of coprocessors */
  1970. if ((IX_FEATURE_CTRL_SILICON_TYPE_A0 !=
  1971. (ixFeatureCtrlProductIdRead() & IX_FEATURE_CTRL_SILICON_STEPPING_MASK))
  1972. || (IX_FEATURE_CTRL_DEVICE_TYPE_IXP42X != ixFeatureCtrlDeviceRead ()))
  1973. {
  1974. if ((IX_ETH_PORT_1 == portId) &&
  1975. (ixFeatureCtrlComponentCheck(IX_FEATURECTRL_ETH0) ==
  1976. IX_FEATURE_CTRL_COMPONENT_DISABLED))
  1977. {
  1978. continue ;
  1979. }
  1980. if ((IX_ETH_PORT_2 == portId) &&
  1981. (ixFeatureCtrlComponentCheck(IX_FEATURECTRL_ETH1) ==
  1982. IX_FEATURE_CTRL_COMPONENT_DISABLED))
  1983. {
  1984. continue ;
  1985. }
  1986. if ((IX_ETH_PORT_3 == portId) &&
  1987. (ixFeatureCtrlComponentCheck(IX_FEATURECTRL_NPEA_ETH) ==
  1988. IX_FEATURE_CTRL_COMPONENT_DISABLED))
  1989. {
  1990. continue ;
  1991. }
  1992. }
  1993. printf("PORT %u --------------------------------\n",
  1994. portId);
  1995. #ifndef NDEBUG
  1996. printf("Tx Done Frames : %u\n",
  1997. tx[portId].txDoneClientCallback +
  1998. tx[portId].txDoneSwQDuringDisable +
  1999. tx[portId].txDoneDuringDisable);
  2000. printf("Tx Frames : %u\n",
  2001. tx[portId].txQOK + tx[portId].txQDelayed);
  2002. printf("Tx H/W Q Added OK : %u\n",
  2003. tx[portId].txQOK);
  2004. printf("Tx H/W Q Delayed : %u\n",
  2005. tx[portId].txQDelayed);
  2006. printf("Tx From S/W Q Added OK : %u\n",
  2007. tx[portId].txFromSwQOK);
  2008. printf("Tx From S/W Q Delayed : %u\n",
  2009. tx[portId].txFromSwQDelayed);
  2010. printf("Tx Overflow : %u\n",
  2011. tx[portId].txOverflow);
  2012. printf("Tx Mutual Lock : %u\n",
  2013. tx[portId].txLock);
  2014. printf("Tx Late Ntf Enabled : %u\n",
  2015. tx[portId].txLateNotificationEnabled);
  2016. printf("Tx Low Thresh CB : %u\n",
  2017. tx[portId].txLowThreshCallback);
  2018. printf("Tx Done from H/W Q (Disable) : %u\n",
  2019. tx[portId].txDoneDuringDisable);
  2020. printf("Tx Done from S/W Q (Disable) : %u\n",
  2021. tx[portId].txDoneSwQDuringDisable);
  2022. for (priority = IX_ETH_ACC_TX_PRIORITY_0;
  2023. priority <= IX_ETH_ACC_TX_PRIORITY_7;
  2024. priority++)
  2025. {
  2026. if (tx[portId].txPriority[priority])
  2027. {
  2028. printf("Tx Priority %u : %u\n",
  2029. priority,
  2030. tx[portId].txPriority[priority]);
  2031. }
  2032. }
  2033. #endif
  2034. printf("Tx unexpected errors : %u (should be 0)\n",
  2035. tx[portId].txUnexpectedError);
  2036. #ifndef NDEBUG
  2037. printf("Rx Frames : %u\n",
  2038. rx[portId].rxFrameClientCallback +
  2039. rx[portId].rxSwQDuringDisable+
  2040. rx[portId].rxDuringDisable);
  2041. printf("Rx Free Replenish : %u\n",
  2042. rx[portId].rxFreeRepOK + rx[portId].rxFreeRepDelayed);
  2043. printf("Rx Free H/W Q Added OK : %u\n",
  2044. rx[portId].rxFreeRepOK);
  2045. printf("Rx Free H/W Q Delayed : %u\n",
  2046. rx[portId].rxFreeRepDelayed);
  2047. printf("Rx Free From S/W Q Added OK : %u\n",
  2048. rx[portId].rxFreeRepFromSwQOK);
  2049. printf("Rx Free From S/W Q Delayed : %u\n",
  2050. rx[portId].rxFreeRepFromSwQDelayed);
  2051. printf("Rx Free Overflow : %u\n",
  2052. rx[portId].rxFreeOverflow);
  2053. printf("Rx Free Mutual Lock : %u\n",
  2054. rx[portId].rxFreeLock);
  2055. printf("Rx Free Late Ntf Enabled : %u\n",
  2056. rx[portId].rxFreeLateNotificationEnabled);
  2057. printf("Rx Free Low CB : %u\n",
  2058. rx[portId].rxFreeLowCallback);
  2059. printf("Rx From H/W Q (Disable) : %u\n",
  2060. rx[portId].rxDuringDisable);
  2061. printf("Rx From S/W Q (Disable) : %u\n",
  2062. rx[portId].rxSwQDuringDisable);
  2063. printf("Rx unlearned Mac Address : %u\n",
  2064. rx[portId].rxUnlearnedMacAddress);
  2065. printf("Rx Filtered (Rx => RxFree) : %u\n",
  2066. rx[portId].rxFiltered);
  2067. for (priority = IX_ETH_ACC_TX_PRIORITY_0;
  2068. priority <= IX_ETH_ACC_TX_PRIORITY_7;
  2069. priority++)
  2070. {
  2071. if (rx[portId].rxPriority[priority])
  2072. {
  2073. printf("Rx Priority %u : %u\n",
  2074. priority,
  2075. rx[portId].rxPriority[priority]);
  2076. }
  2077. }
  2078. #endif
  2079. printf("Rx unexpected errors : %u (should be 0)\n",
  2080. rx[portId].rxUnexpectedError);
  2081. #ifndef NDEBUG
  2082. numBuffersInTx = tx[portId].txQOK +
  2083. tx[portId].txQDelayed -
  2084. tx[portId].txDoneClientCallback -
  2085. tx[portId].txDoneSwQDuringDisable -
  2086. tx[portId].txDoneDuringDisable;
  2087. printf("# Tx Buffers currently for transmission : %u\n",
  2088. numBuffersInTx);
  2089. numBuffersInRx = rx[portId].rxFreeRepOK +
  2090. rx[portId].rxFreeRepDelayed -
  2091. rx[portId].rxFrameClientCallback -
  2092. rx[portId].rxSwQDuringDisable -
  2093. rx[portId].rxDuringDisable;
  2094. printf("# Rx Buffers currently for reception : %u\n",
  2095. numBuffersInRx);
  2096. totalBuffers += numBuffersInRx + numBuffersInTx;
  2097. #endif
  2098. }
  2099. printf("---------------------------------------\n");
  2100. #ifndef NDEBUG
  2101. printf("\n");
  2102. printf("Mbufs :\n");
  2103. printf("Tx Unchained mbufs : %u\n",
  2104. stats.unchainedTxMBufs);
  2105. printf("Tx Chained bufs : %u\n",
  2106. stats.chainedTxMBufs);
  2107. printf("TxDone Unchained mbufs : %u\n",
  2108. stats.unchainedTxDoneMBufs);
  2109. printf("TxDone Chained bufs : %u\n",
  2110. stats.chainedTxDoneMBufs);
  2111. printf("RxFree Unchained mbufs : %u\n",
  2112. stats.unchainedRxFreeMBufs);
  2113. printf("RxFree Chained bufs : %u\n",
  2114. stats.chainedRxFreeMBufs);
  2115. printf("Rx Unchained mbufs : %u\n",
  2116. stats.unchainedRxMBufs);
  2117. printf("Rx Chained bufs : %u\n",
  2118. stats.chainedRxMBufs);
  2119. printf("\n");
  2120. printf("Software queue usage :\n");
  2121. printf("Buffers added to S/W Q : %u\n",
  2122. stats.addToSwQ);
  2123. printf("Buffers removed from S/W Q : %u\n",
  2124. stats.removeFromSwQ);
  2125. printf("\n");
  2126. printf("Hardware queues callbacks :\n");
  2127. for(portId=0; portId < IX_ETH_ACC_NUMBER_OF_PORTS; portId++)
  2128. {
  2129. rxFreeCallbackCounter += rx[portId].rxFreeLowCallback;
  2130. txCallbackCounter += tx[portId].txLowThreshCallback;
  2131. }
  2132. printf("Tx Done QM Callback invoked : %u\n",
  2133. stats.txDoneCallbackCounter);
  2134. printf("Tx QM Callback invoked : %u\n",
  2135. txCallbackCounter);
  2136. printf("Rx QM Callback invoked : %u\n",
  2137. stats.rxCallbackCounter);
  2138. printf("Rx QM Callback burst read : %u\n",
  2139. stats.rxCallbackBurstRead);
  2140. printf("Rx Free QM Callback invoked : %u\n",
  2141. rxFreeCallbackCounter);
  2142. #endif
  2143. printf("Unexpected errors in CB : %u (should be 0)\n",
  2144. stats.unexpectedError);
  2145. printf("\n");
  2146. printf("Hardware queues levels :\n");
  2147. printf("Transmit Port 1 Q : %u \n",numTx0Entries);
  2148. printf("Transmit Port 2 Q : %u \n",numTx1Entries);
  2149. #ifdef __ixp46X
  2150. printf("Transmit Port 3 Q : %u \n",numTx2Entries);
  2151. #endif
  2152. printf("Transmit Done Q : %u \n",numTxDoneEntries);
  2153. printf("Receive Q : %u \n",numRxEntries);
  2154. printf("Receive Free Port 1 Q : %u \n",numRxFree0Entries);
  2155. printf("Receive Free Port 2 Q : %u \n",numRxFree1Entries);
  2156. #ifdef __ixp46X
  2157. printf("Receive Free Port 3 Q : %u \n",numRxFree2Entries);
  2158. #endif
  2159. #ifndef NDEBUG
  2160. printf("\n");
  2161. printf("# Total Buffers accounted for : %u\n",
  2162. totalBuffers);
  2163. numBuffersInSwQ = ixEthAccDataStats.addToSwQ -
  2164. ixEthAccDataStats.removeFromSwQ;
  2165. printf(" Buffers in S/W Qs : %u\n",
  2166. numBuffersInSwQ);
  2167. printf(" Buffers in H/W Qs or NPEs : %u\n",
  2168. totalBuffers - numBuffersInSwQ);
  2169. #endif
  2170. printf("Rx QoS Discipline : %s\n",
  2171. (ixEthAccDataInfo.schDiscipline ==
  2172. FIFO_PRIORITY ) ? "Enabled" : "Disabled");
  2173. for(portId=0; portId < IX_ETH_ACC_NUMBER_OF_PORTS; portId++)
  2174. {
  2175. printf("Tx QoS Discipline port %u : %s\n",
  2176. portId,
  2177. (ixEthAccPortData[portId].ixEthAccTxData.schDiscipline ==
  2178. FIFO_PRIORITY ) ? "Enabled" : "Disabled");
  2179. }
  2180. printf("\n");
  2181. }