IxQMgrDispatcher.c 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320
  1. /**
  2. * @file IxQMgrDispatcher.c
  3. *
  4. * @author Intel Corporation
  5. * @date 20-Dec-2001
  6. *
  7. * @brief This file contains the implementation of the Dispatcher sub component
  8. *
  9. *
  10. * @par
  11. * IXP400 SW Release version 2.0
  12. *
  13. * -- Copyright Notice --
  14. *
  15. * @par
  16. * Copyright 2001-2005, Intel Corporation.
  17. * All rights reserved.
  18. *
  19. * @par
  20. * SPDX-License-Identifier: BSD-3-Clause
  21. * @par
  22. * -- End of Copyright Notice --
  23. */
  24. /*
  25. * User defined include files.
  26. */
  27. #include "IxQMgr.h"
  28. #include "IxQMgrAqmIf_p.h"
  29. #include "IxQMgrQCfg_p.h"
  30. #include "IxQMgrDispatcher_p.h"
  31. #include "IxQMgrLog_p.h"
  32. #include "IxQMgrDefines_p.h"
  33. #include "IxFeatureCtrl.h"
  34. #include "IxOsal.h"
  35. /*
  36. * #defines and macros used in this file.
  37. */
  38. /*
  39. * This constant is used to indicate the number of priority levels supported
  40. */
  41. #define IX_QMGR_NUM_PRIORITY_LEVELS 3
  42. /*
  43. * This constant is used to set the size of the array of status words
  44. */
  45. #define MAX_Q_STATUS_WORDS 4
  46. /*
  47. * This macro is used to check if a given priority is valid
  48. */
  49. #define IX_QMGR_DISPATCHER_PRIORITY_CHECK(priority) \
  50. (((priority) >= IX_QMGR_Q_PRIORITY_0) && ((priority) <= IX_QMGR_Q_PRIORITY_2))
  51. /*
  52. * This macto is used to check that a given interrupt source is valid
  53. */
  54. #define IX_QMGR_DISPATCHER_SOURCE_ID_CHECK(srcSel) \
  55. (((srcSel) >= IX_QMGR_Q_SOURCE_ID_E) && ((srcSel) <= IX_QMGR_Q_SOURCE_ID_NOT_F))
  56. /*
  57. * Number of times a dummy callback is called before logging a trace
  58. * message
  59. */
  60. #define LOG_THROTTLE_COUNT 1000000
  61. /* Priority tables limits */
  62. #define IX_QMGR_MIN_LOW_QUE_PRIORITY_TABLE_INDEX (0)
  63. #define IX_QMGR_MID_LOW_QUE_PRIORITY_TABLE_INDEX (16)
  64. #define IX_QMGR_MAX_LOW_QUE_PRIORITY_TABLE_INDEX (31)
  65. #define IX_QMGR_MIN_UPP_QUE_PRIORITY_TABLE_INDEX (32)
  66. #define IX_QMGR_MID_UPP_QUE_PRIORITY_TABLE_INDEX (48)
  67. #define IX_QMGR_MAX_UPP_QUE_PRIORITY_TABLE_INDEX (63)
  68. /*
  69. * This macro is used to check if a given callback type is valid
  70. */
  71. #define IX_QMGR_DISPATCHER_CALLBACK_TYPE_CHECK(type) \
  72. (((type) >= IX_QMGR_TYPE_REALTIME_OTHER) && \
  73. ((type) <= IX_QMGR_TYPE_REALTIME_SPORADIC))
  74. /*
  75. * define max index in lower queue to use in loops
  76. */
  77. #define IX_QMGR_MAX_LOW_QUE_TABLE_INDEX (31)
  78. /*
  79. * Typedefs whose scope is limited to this file.
  80. */
  81. /*
  82. * Information on a queue needed by the Dispatcher
  83. */
  84. typedef struct
  85. {
  86. IxQMgrCallback callback; /* Notification callback */
  87. IxQMgrCallbackId callbackId; /* Notification callback identifier */
  88. unsigned dummyCallbackCount; /* Number of times runs of dummy callback */
  89. IxQMgrPriority priority; /* Dispatch priority */
  90. unsigned int statusWordOffset; /* Offset to the status word to check */
  91. UINT32 statusMask; /* Status mask */
  92. UINT32 statusCheckValue; /* Status check value */
  93. UINT32 intRegCheckMask; /* Interrupt register check mask */
  94. } IxQMgrQInfo;
  95. /*
  96. * Variable declarations global to this file. Externs are followed by
  97. * statics.
  98. */
  99. /*
  100. * Flag to keep record of what dispatcher set in featureCtrl when ixQMgrInit()
  101. * is called. This is needed because it is possible that a client might
  102. * change whether the live lock prevention dispatcher is used between
  103. * calls to ixQMgrInit() and ixQMgrDispatcherLoopGet().
  104. */
  105. PRIVATE IX_STATUS ixQMgrOrigB0Dispatcher = IX_FEATURE_CTRL_COMPONENT_ENABLED;
  106. /*
  107. * keep record of Q types - not in IxQMgrQInfo for performance as
  108. * it is only used with ixQMgrDispatcherLoopRunB0LLP()
  109. */
  110. PRIVATE IxQMgrType ixQMgrQTypes[IX_QMGR_MAX_NUM_QUEUES];
  111. /*
  112. * This array contains a list of queue identifiers ordered by priority. The table
  113. * is split logically between queue identifiers 0-31 and 32-63.
  114. */
  115. static IxQMgrQId priorityTable[IX_QMGR_MAX_NUM_QUEUES];
  116. /*
  117. * This flag indicates to the dispatcher that the priority table needs to be rebuilt.
  118. */
  119. static BOOL rebuildTable = false;
  120. /* Dispatcher statistics */
  121. static IxQMgrDispatcherStats dispatcherStats;
  122. /* Table of queue information */
  123. static IxQMgrQInfo dispatchQInfo[IX_QMGR_MAX_NUM_QUEUES];
  124. /* Masks use to identify the first queues in the priority tables
  125. * when comparing with the interrupt register
  126. */
  127. static unsigned int lowPriorityTableFirstHalfMask;
  128. static unsigned int uppPriorityTableFirstHalfMask;
  129. /*
  130. * Static function prototypes
  131. */
  132. /*
  133. * This function is the default callback for all queues
  134. */
  135. PRIVATE void
  136. dummyCallback (IxQMgrQId qId,
  137. IxQMgrCallbackId cbId);
  138. PRIVATE void
  139. ixQMgrDispatcherReBuildPriorityTable (void);
  140. /*
  141. * Function definitions.
  142. */
  143. void
  144. ixQMgrDispatcherInit (void)
  145. {
  146. int i;
  147. IxFeatureCtrlProductId productId = 0;
  148. IxFeatureCtrlDeviceId deviceId = 0;
  149. BOOL stickyIntSilicon = true;
  150. /* Set default priorities */
  151. for (i=0; i< IX_QMGR_MAX_NUM_QUEUES; i++)
  152. {
  153. dispatchQInfo[i].callback = dummyCallback;
  154. dispatchQInfo[i].callbackId = 0;
  155. dispatchQInfo[i].dummyCallbackCount = 0;
  156. dispatchQInfo[i].priority = IX_QMGR_Q_PRIORITY_2;
  157. dispatchQInfo[i].statusWordOffset = 0;
  158. dispatchQInfo[i].statusCheckValue = 0;
  159. dispatchQInfo[i].statusMask = 0;
  160. /*
  161. * There are two interrupt registers, 32 bits each. One for the lower
  162. * queues(0-31) and one for the upper queues(32-63). Therefore need to
  163. * mod by 32 i.e the min upper queue identifier.
  164. */
  165. dispatchQInfo[i].intRegCheckMask = (1<<(i%(IX_QMGR_MIN_QUEUPP_QID)));
  166. /*
  167. * Set the Q types - will only be used with livelock
  168. */
  169. ixQMgrQTypes[i] = IX_QMGR_TYPE_REALTIME_OTHER;
  170. /* Reset queue statistics */
  171. dispatcherStats.queueStats[i].callbackCnt = 0;
  172. dispatcherStats.queueStats[i].priorityChangeCnt = 0;
  173. dispatcherStats.queueStats[i].intNoCallbackCnt = 0;
  174. dispatcherStats.queueStats[i].intLostCallbackCnt = 0;
  175. dispatcherStats.queueStats[i].notificationEnabled = false;
  176. dispatcherStats.queueStats[i].srcSel = 0;
  177. }
  178. /* Priority table. Order the table from queue 0 to 63 */
  179. ixQMgrDispatcherReBuildPriorityTable();
  180. /* Reset statistics */
  181. dispatcherStats.loopRunCnt = 0;
  182. /* Get the device ID for the underlying silicon */
  183. deviceId = ixFeatureCtrlDeviceRead();
  184. /* Get the product ID for the underlying silicon */
  185. productId = ixFeatureCtrlProductIdRead();
  186. /*
  187. * Check featureCtrl to see if Livelock prevention is required
  188. */
  189. ixQMgrOrigB0Dispatcher = ixFeatureCtrlSwConfigurationCheck(
  190. IX_FEATURECTRL_ORIGB0_DISPATCHER);
  191. /*
  192. * Check if the silicon supports the sticky interrupt feature.
  193. * IF (IXP42X AND A0) -> No sticky interrupt feature supported
  194. */
  195. if ((IX_FEATURE_CTRL_DEVICE_TYPE_IXP42X ==
  196. (IX_FEATURE_CTRL_DEVICE_TYPE_MASK & deviceId)) &&
  197. (IX_FEATURE_CTRL_SILICON_TYPE_A0 ==
  198. (IX_FEATURE_CTRL_SILICON_STEPPING_MASK & productId)))
  199. {
  200. stickyIntSilicon = false;
  201. }
  202. /*
  203. * IF user wants livelock prev option AND silicon supports sticky interrupt
  204. * feature -> enable the sticky interrupt bit
  205. */
  206. if ((IX_FEATURE_CTRL_SWCONFIG_DISABLED == ixQMgrOrigB0Dispatcher) &&
  207. stickyIntSilicon)
  208. {
  209. ixQMgrStickyInterruptRegEnable();
  210. }
  211. }
  212. IX_STATUS
  213. ixQMgrDispatcherPrioritySet (IxQMgrQId qId,
  214. IxQMgrPriority priority)
  215. {
  216. int ixQMgrLockKey;
  217. if (!ixQMgrQIsConfigured(qId))
  218. {
  219. return IX_QMGR_Q_NOT_CONFIGURED;
  220. }
  221. if (!IX_QMGR_DISPATCHER_PRIORITY_CHECK(priority))
  222. {
  223. return IX_QMGR_Q_INVALID_PRIORITY;
  224. }
  225. ixQMgrLockKey = ixOsalIrqLock();
  226. /* Change priority */
  227. dispatchQInfo[qId].priority = priority;
  228. /* Set flag */
  229. rebuildTable = true;
  230. ixOsalIrqUnlock(ixQMgrLockKey);
  231. #ifndef NDEBUG
  232. /* Update statistics */
  233. dispatcherStats.queueStats[qId].priorityChangeCnt++;
  234. #endif
  235. return IX_SUCCESS;
  236. }
  237. IX_STATUS
  238. ixQMgrNotificationCallbackSet (IxQMgrQId qId,
  239. IxQMgrCallback callback,
  240. IxQMgrCallbackId callbackId)
  241. {
  242. if (!ixQMgrQIsConfigured(qId))
  243. {
  244. return IX_QMGR_Q_NOT_CONFIGURED;
  245. }
  246. if (NULL == callback)
  247. {
  248. /* Reset to dummy callback */
  249. dispatchQInfo[qId].callback = dummyCallback;
  250. dispatchQInfo[qId].dummyCallbackCount = 0;
  251. dispatchQInfo[qId].callbackId = 0;
  252. }
  253. else
  254. {
  255. dispatchQInfo[qId].callback = callback;
  256. dispatchQInfo[qId].callbackId = callbackId;
  257. }
  258. return IX_SUCCESS;
  259. }
  260. IX_STATUS
  261. ixQMgrNotificationEnable (IxQMgrQId qId,
  262. IxQMgrSourceId srcSel)
  263. {
  264. IxQMgrQStatus qStatusOnEntry;/* The queue status on entry/exit */
  265. IxQMgrQStatus qStatusOnExit; /* to this function */
  266. int ixQMgrLockKey;
  267. #ifndef NDEBUG
  268. if (!ixQMgrQIsConfigured (qId))
  269. {
  270. return IX_QMGR_Q_NOT_CONFIGURED;
  271. }
  272. if ((qId < IX_QMGR_MIN_QUEUPP_QID) &&
  273. !IX_QMGR_DISPATCHER_SOURCE_ID_CHECK(srcSel))
  274. {
  275. /* QId 0-31 source id invalid */
  276. return IX_QMGR_INVALID_INT_SOURCE_ID;
  277. }
  278. if ((IX_QMGR_Q_SOURCE_ID_NE != srcSel) &&
  279. (qId >= IX_QMGR_MIN_QUEUPP_QID))
  280. {
  281. /*
  282. * For queues 32-63 the interrupt source is fixed to the Nearly
  283. * Empty status flag and therefore should have a srcSel of NE.
  284. */
  285. return IX_QMGR_INVALID_INT_SOURCE_ID;
  286. }
  287. #endif
  288. #ifndef NDEBUG
  289. dispatcherStats.queueStats[qId].notificationEnabled = true;
  290. dispatcherStats.queueStats[qId].srcSel = srcSel;
  291. #endif
  292. /* Get the current queue status */
  293. ixQMgrAqmIfQueStatRead (qId, &qStatusOnEntry);
  294. /*
  295. * Enabling interrupts results in Read-Modify-Write
  296. * so need critical section
  297. */
  298. ixQMgrLockKey = ixOsalIrqLock();
  299. /* Calculate the checkMask and checkValue for this q */
  300. ixQMgrAqmIfQStatusCheckValsCalc (qId,
  301. srcSel,
  302. &dispatchQInfo[qId].statusWordOffset,
  303. &dispatchQInfo[qId].statusCheckValue,
  304. &dispatchQInfo[qId].statusMask);
  305. /* Set the interrupt source is this queue is in the range 0-31 */
  306. if (qId < IX_QMGR_MIN_QUEUPP_QID)
  307. {
  308. ixQMgrAqmIfIntSrcSelWrite (qId, srcSel);
  309. }
  310. /* Enable the interrupt */
  311. ixQMgrAqmIfQInterruptEnable (qId);
  312. ixOsalIrqUnlock(ixQMgrLockKey);
  313. /* Get the current queue status */
  314. ixQMgrAqmIfQueStatRead (qId, &qStatusOnExit);
  315. /* If the status has changed return a warning */
  316. if (qStatusOnEntry != qStatusOnExit)
  317. {
  318. return IX_QMGR_WARNING;
  319. }
  320. return IX_SUCCESS;
  321. }
  322. IX_STATUS
  323. ixQMgrNotificationDisable (IxQMgrQId qId)
  324. {
  325. int ixQMgrLockKey;
  326. #ifndef NDEBUG
  327. /* Validate parameters */
  328. if (!ixQMgrQIsConfigured (qId))
  329. {
  330. return IX_QMGR_Q_NOT_CONFIGURED;
  331. }
  332. #endif
  333. /*
  334. * Enabling interrupts results in Read-Modify-Write
  335. * so need critical section
  336. */
  337. #ifndef NDEBUG
  338. dispatcherStats.queueStats[qId].notificationEnabled = false;
  339. #endif
  340. ixQMgrLockKey = ixOsalIrqLock();
  341. ixQMgrAqmIfQInterruptDisable (qId);
  342. ixOsalIrqUnlock(ixQMgrLockKey);
  343. return IX_SUCCESS;
  344. }
  345. void
  346. ixQMgrStickyInterruptRegEnable(void)
  347. {
  348. /* Use Aqm If function to set Interrupt Register0 Bit-3 */
  349. ixQMgrAqmIfIntSrcSelReg0Bit3Set ();
  350. }
  351. #if !defined __XSCALE__ || defined __linux
  352. /* Count the number of leading zero bits in a word,
  353. * and return the same value than the CLZ instruction.
  354. *
  355. * word (in) return value (out)
  356. * 0x80000000 0
  357. * 0x40000000 1
  358. * ,,, ,,,
  359. * 0x00000002 30
  360. * 0x00000001 31
  361. * 0x00000000 32
  362. *
  363. * The C version of this function is used as a replacement
  364. * for system not providing the equivalent of the CLZ
  365. * assembly language instruction.
  366. *
  367. * Note that this version is big-endian
  368. */
  369. unsigned int
  370. ixQMgrCountLeadingZeros(UINT32 word)
  371. {
  372. unsigned int leadingZerosCount = 0;
  373. if (word == 0)
  374. {
  375. return 32;
  376. }
  377. /* search the first bit set by testing the MSB and shifting the input word */
  378. while ((word & 0x80000000) == 0)
  379. {
  380. word <<= 1;
  381. leadingZerosCount++;
  382. }
  383. return leadingZerosCount;
  384. }
  385. #endif /* not __XSCALE__ or __linux */
  386. void
  387. ixQMgrDispatcherLoopGet (IxQMgrDispatcherFuncPtr *qDispatcherFuncPtr)
  388. {
  389. IxFeatureCtrlProductId productId = 0;
  390. IxFeatureCtrlDeviceId deviceId = 0;
  391. /* Get the device ID for the underlying silicon */
  392. deviceId = ixFeatureCtrlDeviceRead();
  393. /* Get the product ID for the underlying silicon */
  394. productId = ixFeatureCtrlProductIdRead ();
  395. /* IF (IXP42X AND A0 silicon) -> use ixQMgrDispatcherLoopRunA0 */
  396. if ((IX_FEATURE_CTRL_DEVICE_TYPE_IXP42X ==
  397. (IX_FEATURE_CTRL_DEVICE_TYPE_MASK & deviceId)) &&
  398. (IX_FEATURE_CTRL_SILICON_TYPE_A0 ==
  399. (IX_FEATURE_CTRL_SILICON_STEPPING_MASK & productId)))
  400. {
  401. /*For IXP42X A0 silicon */
  402. *qDispatcherFuncPtr = &ixQMgrDispatcherLoopRunA0 ;
  403. }
  404. else /*For IXP42X B0 or IXP46X silicon*/
  405. {
  406. if (IX_FEATURE_CTRL_SWCONFIG_ENABLED == ixQMgrOrigB0Dispatcher)
  407. {
  408. /* Default for IXP42X B0 and IXP46X silicon */
  409. *qDispatcherFuncPtr = &ixQMgrDispatcherLoopRunB0;
  410. }
  411. else
  412. {
  413. /* FeatureCtrl indicated that livelock dispatcher be used */
  414. *qDispatcherFuncPtr = &ixQMgrDispatcherLoopRunB0LLP;
  415. }
  416. }
  417. }
  418. void
  419. ixQMgrDispatcherLoopRunA0 (IxQMgrDispatchGroup group)
  420. {
  421. UINT32 intRegVal; /* Interrupt reg val */
  422. UINT32 intRegValAfterWrite; /* Interrupt reg val after writing back */
  423. UINT32 intRegCheckMask; /* Mask for checking interrupt bits */
  424. UINT32 qStatusWordsB4Write[MAX_Q_STATUS_WORDS]; /* Status b4 interrupt write */
  425. UINT32 qStatusWordsAfterWrite[MAX_Q_STATUS_WORDS]; /* Status after interrupt write */
  426. IxQMgrQInfo *currDispatchQInfo;
  427. BOOL statusChangeFlag;
  428. int priorityTableIndex;/* Priority table index */
  429. int qIndex; /* Current queue being processed */
  430. int endIndex; /* Index of last queue to process */
  431. #ifndef NDEBUG
  432. IX_OSAL_ASSERT((group == IX_QMGR_QUEUPP_GROUP) ||
  433. (group == IX_QMGR_QUELOW_GROUP));
  434. #endif
  435. /* Read Q status registers before interrupt status read/write */
  436. ixQMgrAqmIfQStatusRegsRead (group, qStatusWordsB4Write);
  437. /* Read the interrupt register */
  438. ixQMgrAqmIfQInterruptRegRead (group, &intRegVal);
  439. /* No bit set : nothing to process (the reaminder of the algorithm is
  440. * based on the fact that the interrupt register value contains at
  441. * least one bit set
  442. */
  443. if (intRegVal == 0)
  444. {
  445. #ifndef NDEBUG
  446. /* Update statistics */
  447. dispatcherStats.loopRunCnt++;
  448. #endif
  449. /* Rebuild the priority table if needed */
  450. if (rebuildTable)
  451. {
  452. ixQMgrDispatcherReBuildPriorityTable ();
  453. }
  454. return;
  455. }
  456. /* Write it back to clear the interrupt */
  457. ixQMgrAqmIfQInterruptRegWrite (group, intRegVal);
  458. /* Read Q status registers after interrupt status read/write */
  459. ixQMgrAqmIfQStatusRegsRead (group, qStatusWordsAfterWrite);
  460. /* get the first queue Id from the interrupt register value */
  461. qIndex = (BITS_PER_WORD - 1) - ixQMgrCountLeadingZeros(intRegVal);
  462. /* check if any change occured during hw register modifications */
  463. if (IX_QMGR_QUELOW_GROUP == group)
  464. {
  465. statusChangeFlag =
  466. (qStatusWordsB4Write[0] != qStatusWordsAfterWrite[0]) ||
  467. (qStatusWordsB4Write[1] != qStatusWordsAfterWrite[1]) ||
  468. (qStatusWordsB4Write[2] != qStatusWordsAfterWrite[2]) ||
  469. (qStatusWordsB4Write[3] != qStatusWordsAfterWrite[3]);
  470. }
  471. else
  472. {
  473. statusChangeFlag =
  474. (qStatusWordsB4Write[0] != qStatusWordsAfterWrite[0]);
  475. /* Set the queue range based on the queue group to proccess */
  476. qIndex += IX_QMGR_MIN_QUEUPP_QID;
  477. }
  478. if (statusChangeFlag == false)
  479. {
  480. /* check if the interrupt register contains
  481. * only 1 bit set (happy day scenario)
  482. */
  483. currDispatchQInfo = &dispatchQInfo[qIndex];
  484. if (intRegVal == currDispatchQInfo->intRegCheckMask)
  485. {
  486. /* only 1 queue event triggered a notification *
  487. * Call the callback function for this queue
  488. */
  489. currDispatchQInfo->callback (qIndex,
  490. currDispatchQInfo->callbackId);
  491. #ifndef NDEBUG
  492. /* Update statistics */
  493. dispatcherStats.queueStats[qIndex].callbackCnt++;
  494. #endif
  495. }
  496. else
  497. {
  498. /* the event is triggered by more than 1 queue,
  499. * the queue search will be starting from the beginning
  500. * or the middle of the priority table
  501. *
  502. * the serach will end when all the bits of the interrupt
  503. * register are cleared. There is no need to maintain
  504. * a seperate value and test it at each iteration.
  505. */
  506. if (IX_QMGR_QUELOW_GROUP == group)
  507. {
  508. /* check if any bit related to queues in the first
  509. * half of the priority table is set
  510. */
  511. if (intRegVal & lowPriorityTableFirstHalfMask)
  512. {
  513. priorityTableIndex = IX_QMGR_MIN_LOW_QUE_PRIORITY_TABLE_INDEX;
  514. }
  515. else
  516. {
  517. priorityTableIndex = IX_QMGR_MID_LOW_QUE_PRIORITY_TABLE_INDEX;
  518. }
  519. }
  520. else
  521. {
  522. /* check if any bit related to queues in the first
  523. * half of the priority table is set
  524. */
  525. if (intRegVal & uppPriorityTableFirstHalfMask)
  526. {
  527. priorityTableIndex = IX_QMGR_MIN_UPP_QUE_PRIORITY_TABLE_INDEX;
  528. }
  529. else
  530. {
  531. priorityTableIndex = IX_QMGR_MID_UPP_QUE_PRIORITY_TABLE_INDEX;
  532. }
  533. }
  534. /* iterate following the priority table until all the bits
  535. * of the interrupt register are cleared.
  536. */
  537. do
  538. {
  539. qIndex = priorityTable[priorityTableIndex++];
  540. currDispatchQInfo = &dispatchQInfo[qIndex];
  541. intRegCheckMask = currDispatchQInfo->intRegCheckMask;
  542. /* If this queue caused this interrupt to be raised */
  543. if (intRegVal & intRegCheckMask)
  544. {
  545. /* Call the callback function for this queue */
  546. currDispatchQInfo->callback (qIndex,
  547. currDispatchQInfo->callbackId);
  548. #ifndef NDEBUG
  549. /* Update statistics */
  550. dispatcherStats.queueStats[qIndex].callbackCnt++;
  551. #endif
  552. /* Clear the interrupt register bit */
  553. intRegVal &= ~intRegCheckMask;
  554. }
  555. }
  556. while(intRegVal);
  557. }
  558. }
  559. else
  560. {
  561. /* A change in queue status occured during the hw interrupt
  562. * register update. To maintain the interrupt consistency, it
  563. * is necessary to iterate through all queues of the queue group.
  564. */
  565. /* Read interrupt status again */
  566. ixQMgrAqmIfQInterruptRegRead (group, &intRegValAfterWrite);
  567. if (IX_QMGR_QUELOW_GROUP == group)
  568. {
  569. priorityTableIndex = IX_QMGR_MIN_LOW_QUE_PRIORITY_TABLE_INDEX;
  570. endIndex = IX_QMGR_MAX_LOW_QUE_PRIORITY_TABLE_INDEX;
  571. }
  572. else
  573. {
  574. priorityTableIndex = IX_QMGR_MIN_UPP_QUE_PRIORITY_TABLE_INDEX;
  575. endIndex = IX_QMGR_MAX_UPP_QUE_PRIORITY_TABLE_INDEX;
  576. }
  577. for ( ; priorityTableIndex<=endIndex; priorityTableIndex++)
  578. {
  579. qIndex = priorityTable[priorityTableIndex];
  580. currDispatchQInfo = &dispatchQInfo[qIndex];
  581. intRegCheckMask = currDispatchQInfo->intRegCheckMask;
  582. /* If this queue caused this interrupt to be raised */
  583. if (intRegVal & intRegCheckMask)
  584. {
  585. /* Call the callback function for this queue */
  586. currDispatchQInfo->callback (qIndex,
  587. currDispatchQInfo->callbackId);
  588. #ifndef NDEBUG
  589. /* Update statistics */
  590. dispatcherStats.queueStats[qIndex].callbackCnt++;
  591. #endif
  592. } /* if (intRegVal .. */
  593. /*
  594. * If interrupt bit is set in intRegValAfterWrite don't
  595. * proceed as this will be caught in next interrupt
  596. */
  597. else if ((intRegValAfterWrite & intRegCheckMask) == 0)
  598. {
  599. /* Check if an interrupt was lost for this Q */
  600. if (ixQMgrAqmIfQStatusCheck(qStatusWordsB4Write,
  601. qStatusWordsAfterWrite,
  602. currDispatchQInfo->statusWordOffset,
  603. currDispatchQInfo->statusCheckValue,
  604. currDispatchQInfo->statusMask))
  605. {
  606. /* Call the callback function for this queue */
  607. currDispatchQInfo->callback (qIndex,
  608. dispatchQInfo[qIndex].callbackId);
  609. #ifndef NDEBUG
  610. /* Update statistics */
  611. dispatcherStats.queueStats[qIndex].callbackCnt++;
  612. dispatcherStats.queueStats[qIndex].intLostCallbackCnt++;
  613. #endif
  614. } /* if ixQMgrAqmIfQStatusCheck(.. */
  615. } /* else if ((intRegValAfterWrite ... */
  616. } /* for (priorityTableIndex=0 ... */
  617. }
  618. /* Rebuild the priority table if needed */
  619. if (rebuildTable)
  620. {
  621. ixQMgrDispatcherReBuildPriorityTable ();
  622. }
  623. #ifndef NDEBUG
  624. /* Update statistics */
  625. dispatcherStats.loopRunCnt++;
  626. #endif
  627. }
  628. void
  629. ixQMgrDispatcherLoopRunB0 (IxQMgrDispatchGroup group)
  630. {
  631. UINT32 intRegVal; /* Interrupt reg val */
  632. UINT32 intRegCheckMask; /* Mask for checking interrupt bits */
  633. IxQMgrQInfo *currDispatchQInfo;
  634. int priorityTableIndex; /* Priority table index */
  635. int qIndex; /* Current queue being processed */
  636. #ifndef NDEBUG
  637. IX_OSAL_ASSERT((group == IX_QMGR_QUEUPP_GROUP) ||
  638. (group == IX_QMGR_QUELOW_GROUP));
  639. IX_OSAL_ASSERT((group == IX_QMGR_QUEUPP_GROUP) ||
  640. (group == IX_QMGR_QUELOW_GROUP));
  641. #endif
  642. /* Read the interrupt register */
  643. ixQMgrAqmIfQInterruptRegRead (group, &intRegVal);
  644. /* No queue has interrupt register set */
  645. if (intRegVal != 0)
  646. {
  647. /* Write it back to clear the interrupt */
  648. ixQMgrAqmIfQInterruptRegWrite (group, intRegVal);
  649. /* get the first queue Id from the interrupt register value */
  650. qIndex = (BITS_PER_WORD - 1) - ixQMgrCountLeadingZeros(intRegVal);
  651. if (IX_QMGR_QUEUPP_GROUP == group)
  652. {
  653. /* Set the queue range based on the queue group to proccess */
  654. qIndex += IX_QMGR_MIN_QUEUPP_QID;
  655. }
  656. /* check if the interrupt register contains
  657. * only 1 bit set
  658. * For example:
  659. * intRegVal = 0x0010
  660. * currDispatchQInfo->intRegCheckMask = 0x0010
  661. * intRegVal == currDispatchQInfo->intRegCheckMask is true.
  662. */
  663. currDispatchQInfo = &dispatchQInfo[qIndex];
  664. if (intRegVal == currDispatchQInfo->intRegCheckMask)
  665. {
  666. /* only 1 queue event triggered a notification *
  667. * Call the callback function for this queue
  668. */
  669. currDispatchQInfo->callback (qIndex,
  670. currDispatchQInfo->callbackId);
  671. #ifndef NDEBUG
  672. /* Update statistics */
  673. dispatcherStats.queueStats[qIndex].callbackCnt++;
  674. #endif
  675. }
  676. else
  677. {
  678. /* the event is triggered by more than 1 queue,
  679. * the queue search will be starting from the beginning
  680. * or the middle of the priority table
  681. *
  682. * the serach will end when all the bits of the interrupt
  683. * register are cleared. There is no need to maintain
  684. * a seperate value and test it at each iteration.
  685. */
  686. if (IX_QMGR_QUELOW_GROUP == group)
  687. {
  688. /* check if any bit related to queues in the first
  689. * half of the priority table is set
  690. */
  691. if (intRegVal & lowPriorityTableFirstHalfMask)
  692. {
  693. priorityTableIndex = IX_QMGR_MIN_LOW_QUE_PRIORITY_TABLE_INDEX;
  694. }
  695. else
  696. {
  697. priorityTableIndex = IX_QMGR_MID_LOW_QUE_PRIORITY_TABLE_INDEX;
  698. }
  699. }
  700. else
  701. {
  702. /* check if any bit related to queues in the first
  703. * half of the priority table is set
  704. */
  705. if (intRegVal & uppPriorityTableFirstHalfMask)
  706. {
  707. priorityTableIndex = IX_QMGR_MIN_UPP_QUE_PRIORITY_TABLE_INDEX;
  708. }
  709. else
  710. {
  711. priorityTableIndex = IX_QMGR_MID_UPP_QUE_PRIORITY_TABLE_INDEX;
  712. }
  713. }
  714. /* iterate following the priority table until all the bits
  715. * of the interrupt register are cleared.
  716. */
  717. do
  718. {
  719. qIndex = priorityTable[priorityTableIndex++];
  720. currDispatchQInfo = &dispatchQInfo[qIndex];
  721. intRegCheckMask = currDispatchQInfo->intRegCheckMask;
  722. /* If this queue caused this interrupt to be raised */
  723. if (intRegVal & intRegCheckMask)
  724. {
  725. /* Call the callback function for this queue */
  726. currDispatchQInfo->callback (qIndex,
  727. currDispatchQInfo->callbackId);
  728. #ifndef NDEBUG
  729. /* Update statistics */
  730. dispatcherStats.queueStats[qIndex].callbackCnt++;
  731. #endif
  732. /* Clear the interrupt register bit */
  733. intRegVal &= ~intRegCheckMask;
  734. }
  735. }
  736. while(intRegVal);
  737. } /*End of intRegVal == currDispatchQInfo->intRegCheckMask */
  738. } /* End of intRegVal != 0 */
  739. #ifndef NDEBUG
  740. /* Update statistics */
  741. dispatcherStats.loopRunCnt++;
  742. #endif
  743. /* Rebuild the priority table if needed */
  744. if (rebuildTable)
  745. {
  746. ixQMgrDispatcherReBuildPriorityTable ();
  747. }
  748. }
  749. void
  750. ixQMgrDispatcherLoopRunB0LLP (IxQMgrDispatchGroup group)
  751. {
  752. UINT32 intRegVal =0; /* Interrupt reg val */
  753. UINT32 intRegCheckMask; /* Mask for checking interrupt bits */
  754. IxQMgrQInfo *currDispatchQInfo;
  755. int priorityTableIndex; /* Priority table index */
  756. int qIndex; /* Current queue being processed */
  757. UINT32 intRegValCopy = 0;
  758. UINT32 intEnableRegVal = 0;
  759. UINT8 i = 0;
  760. #ifndef NDEBUG
  761. IX_OSAL_ASSERT((group == IX_QMGR_QUEUPP_GROUP) ||
  762. (group == IX_QMGR_QUELOW_GROUP));
  763. #endif
  764. /* Read the interrupt register */
  765. ixQMgrAqmIfQInterruptRegRead (group, &intRegVal);
  766. /*
  767. * mask any interrupts that are not enabled
  768. */
  769. ixQMgrAqmIfQInterruptEnableRegRead (group, &intEnableRegVal);
  770. intRegVal &= intEnableRegVal;
  771. /* No queue has interrupt register set */
  772. if (intRegVal != 0)
  773. {
  774. if (IX_QMGR_QUELOW_GROUP == group)
  775. {
  776. /*
  777. * As the sticky bit is set, the interrupt register will
  778. * not clear if write back at this point because the condition
  779. * has not been cleared. Take a copy and write back later after
  780. * the condition has been cleared
  781. */
  782. intRegValCopy = intRegVal;
  783. }
  784. else
  785. {
  786. /* no sticky for upper Q's, so write back now */
  787. ixQMgrAqmIfQInterruptRegWrite (group, intRegVal);
  788. }
  789. /* get the first queue Id from the interrupt register value */
  790. qIndex = (BITS_PER_WORD - 1) - ixQMgrCountLeadingZeros(intRegVal);
  791. if (IX_QMGR_QUEUPP_GROUP == group)
  792. {
  793. /* Set the queue range based on the queue group to proccess */
  794. qIndex += IX_QMGR_MIN_QUEUPP_QID;
  795. }
  796. /* check if the interrupt register contains
  797. * only 1 bit set
  798. * For example:
  799. * intRegVal = 0x0010
  800. * currDispatchQInfo->intRegCheckMask = 0x0010
  801. * intRegVal == currDispatchQInfo->intRegCheckMask is true.
  802. */
  803. currDispatchQInfo = &dispatchQInfo[qIndex];
  804. if (intRegVal == currDispatchQInfo->intRegCheckMask)
  805. {
  806. /*
  807. * check if Q type periodic - only lower queues can
  808. * have there type set to periodic
  809. */
  810. if (IX_QMGR_TYPE_REALTIME_PERIODIC == ixQMgrQTypes[qIndex])
  811. {
  812. /*
  813. * Disable the notifications on any sporadics
  814. */
  815. for (i=0; i <= IX_QMGR_MAX_LOW_QUE_TABLE_INDEX; i++)
  816. {
  817. if (IX_QMGR_TYPE_REALTIME_SPORADIC == ixQMgrQTypes[i])
  818. {
  819. ixQMgrNotificationDisable(i);
  820. #ifndef NDEBUG
  821. /* Update statistics */
  822. dispatcherStats.queueStats[i].disableCount++;
  823. #endif
  824. }
  825. }
  826. }
  827. currDispatchQInfo->callback (qIndex,
  828. currDispatchQInfo->callbackId);
  829. #ifndef NDEBUG
  830. /* Update statistics */
  831. dispatcherStats.queueStats[qIndex].callbackCnt++;
  832. #endif
  833. }
  834. else
  835. {
  836. /* the event is triggered by more than 1 queue,
  837. * the queue search will be starting from the beginning
  838. * or the middle of the priority table
  839. *
  840. * the serach will end when all the bits of the interrupt
  841. * register are cleared. There is no need to maintain
  842. * a seperate value and test it at each iteration.
  843. */
  844. if (IX_QMGR_QUELOW_GROUP == group)
  845. {
  846. /* check if any bit related to queues in the first
  847. * half of the priority table is set
  848. */
  849. if (intRegVal & lowPriorityTableFirstHalfMask)
  850. {
  851. priorityTableIndex =
  852. IX_QMGR_MIN_LOW_QUE_PRIORITY_TABLE_INDEX;
  853. }
  854. else
  855. {
  856. priorityTableIndex =
  857. IX_QMGR_MID_LOW_QUE_PRIORITY_TABLE_INDEX;
  858. }
  859. }
  860. else
  861. {
  862. /* check if any bit related to queues in the first
  863. * half of the priority table is set
  864. */
  865. if (intRegVal & uppPriorityTableFirstHalfMask)
  866. {
  867. priorityTableIndex =
  868. IX_QMGR_MIN_UPP_QUE_PRIORITY_TABLE_INDEX;
  869. }
  870. else
  871. {
  872. priorityTableIndex =
  873. IX_QMGR_MID_UPP_QUE_PRIORITY_TABLE_INDEX;
  874. }
  875. }
  876. /* iterate following the priority table until all the bits
  877. * of the interrupt register are cleared.
  878. */
  879. do
  880. {
  881. qIndex = priorityTable[priorityTableIndex++];
  882. currDispatchQInfo = &dispatchQInfo[qIndex];
  883. intRegCheckMask = currDispatchQInfo->intRegCheckMask;
  884. /* If this queue caused this interrupt to be raised */
  885. if (intRegVal & intRegCheckMask)
  886. {
  887. /*
  888. * check if Q type periodic - only lower queues can
  889. * have there type set to periodic. There can only be one
  890. * periodic queue, so the sporadics are only disabled once.
  891. */
  892. if (IX_QMGR_TYPE_REALTIME_PERIODIC == ixQMgrQTypes[qIndex])
  893. {
  894. /*
  895. * Disable the notifications on any sporadics
  896. */
  897. for (i=0; i <= IX_QMGR_MAX_LOW_QUE_TABLE_INDEX; i++)
  898. {
  899. if (IX_QMGR_TYPE_REALTIME_SPORADIC ==
  900. ixQMgrQTypes[i])
  901. {
  902. ixQMgrNotificationDisable(i);
  903. /*
  904. * remove from intRegVal as we don't want
  905. * to service any sporadics now
  906. */
  907. intRegVal &= ~dispatchQInfo[i].intRegCheckMask;
  908. #ifndef NDEBUG
  909. /* Update statistics */
  910. dispatcherStats.queueStats[i].disableCount++;
  911. #endif
  912. }
  913. }
  914. }
  915. currDispatchQInfo->callback (qIndex,
  916. currDispatchQInfo->callbackId);
  917. #ifndef NDEBUG
  918. /* Update statistics */
  919. dispatcherStats.queueStats[qIndex].callbackCnt++;
  920. #endif
  921. /* Clear the interrupt register bit */
  922. intRegVal &= ~intRegCheckMask;
  923. }
  924. }
  925. while(intRegVal);
  926. } /*End of intRegVal == currDispatchQInfo->intRegCheckMask */
  927. } /* End of intRegVal != 0 */
  928. #ifndef NDEBUG
  929. /* Update statistics */
  930. dispatcherStats.loopRunCnt++;
  931. #endif
  932. if ((intRegValCopy != 0) && (IX_QMGR_QUELOW_GROUP == group))
  933. {
  934. /*
  935. * lower groups (therefore sticky) AND at least one enabled interrupt
  936. * Write back to clear the interrupt
  937. */
  938. ixQMgrAqmIfQInterruptRegWrite (IX_QMGR_QUELOW_GROUP, intRegValCopy);
  939. }
  940. /* Rebuild the priority table if needed */
  941. if (rebuildTable)
  942. {
  943. ixQMgrDispatcherReBuildPriorityTable ();
  944. }
  945. }
  946. PRIVATE void
  947. ixQMgrDispatcherReBuildPriorityTable (void)
  948. {
  949. UINT32 qIndex;
  950. UINT32 priority;
  951. int lowQuePriorityTableIndex = IX_QMGR_MIN_LOW_QUE_PRIORITY_TABLE_INDEX;
  952. int uppQuePriorityTableIndex = IX_QMGR_MIN_UPP_QUE_PRIORITY_TABLE_INDEX;
  953. /* Reset the rebuild flag */
  954. rebuildTable = false;
  955. /* initialize the mak used to identify the queues in the first half
  956. * of the priority table
  957. */
  958. lowPriorityTableFirstHalfMask = 0;
  959. uppPriorityTableFirstHalfMask = 0;
  960. /* For each priority level */
  961. for(priority=0; priority<IX_QMGR_NUM_PRIORITY_LEVELS; priority++)
  962. {
  963. /* Foreach low queue in this priority */
  964. for(qIndex=0; qIndex<IX_QMGR_MIN_QUEUPP_QID; qIndex++)
  965. {
  966. if (dispatchQInfo[qIndex].priority == priority)
  967. {
  968. /* build the priority table bitmask which match the
  969. * queues of the first half of the priority table
  970. */
  971. if (lowQuePriorityTableIndex < IX_QMGR_MID_LOW_QUE_PRIORITY_TABLE_INDEX)
  972. {
  973. lowPriorityTableFirstHalfMask |= dispatchQInfo[qIndex].intRegCheckMask;
  974. }
  975. /* build the priority table */
  976. priorityTable[lowQuePriorityTableIndex++] = qIndex;
  977. }
  978. }
  979. /* Foreach upp queue */
  980. for(qIndex=IX_QMGR_MIN_QUEUPP_QID; qIndex<=IX_QMGR_MAX_QID; qIndex++)
  981. {
  982. if (dispatchQInfo[qIndex].priority == priority)
  983. {
  984. /* build the priority table bitmask which match the
  985. * queues of the first half of the priority table
  986. */
  987. if (uppQuePriorityTableIndex < IX_QMGR_MID_UPP_QUE_PRIORITY_TABLE_INDEX)
  988. {
  989. uppPriorityTableFirstHalfMask |= dispatchQInfo[qIndex].intRegCheckMask;
  990. }
  991. /* build the priority table */
  992. priorityTable[uppQuePriorityTableIndex++] = qIndex;
  993. }
  994. }
  995. }
  996. }
  997. IxQMgrDispatcherStats*
  998. ixQMgrDispatcherStatsGet (void)
  999. {
  1000. return &dispatcherStats;
  1001. }
  1002. PRIVATE void
  1003. dummyCallback (IxQMgrQId qId,
  1004. IxQMgrCallbackId cbId)
  1005. {
  1006. /* Throttle the trace message */
  1007. if ((dispatchQInfo[qId].dummyCallbackCount % LOG_THROTTLE_COUNT) == 0)
  1008. {
  1009. IX_QMGR_LOG_WARNING2("--> dummyCallback: qId (%d), callbackId (%d)\n",qId,cbId);
  1010. }
  1011. dispatchQInfo[qId].dummyCallbackCount++;
  1012. #ifndef NDEBUG
  1013. /* Update statistcs */
  1014. dispatcherStats.queueStats[qId].intNoCallbackCnt++;
  1015. #endif
  1016. }
  1017. void
  1018. ixQMgrLLPShow (int resetStats)
  1019. {
  1020. #ifndef NDEBUG
  1021. UINT8 i = 0;
  1022. UINT32 intEnableRegVal = 0;
  1023. printf ("Livelock statistics are printed on the fly.\n");
  1024. printf ("qId Type EnableCnt DisableCnt IntEnableState Callbacks\n");
  1025. printf ("=== ======== ========= ========== ============== =========\n");
  1026. for (i=0; i<= IX_QMGR_MAX_LOW_QUE_TABLE_INDEX; i++)
  1027. {
  1028. if (ixQMgrQTypes[i] != IX_QMGR_TYPE_REALTIME_OTHER)
  1029. {
  1030. printf (" %2d ", i);
  1031. if (ixQMgrQTypes[i] == IX_QMGR_TYPE_REALTIME_SPORADIC)
  1032. {
  1033. printf ("Sporadic");
  1034. }
  1035. else
  1036. {
  1037. printf ("Periodic");
  1038. }
  1039. ixQMgrAqmIfQInterruptEnableRegRead (IX_QMGR_QUELOW_GROUP,
  1040. &intEnableRegVal);
  1041. intEnableRegVal &= dispatchQInfo[i].intRegCheckMask;
  1042. intEnableRegVal = intEnableRegVal >> i;
  1043. printf (" %10d %10d %10d %10d\n",
  1044. dispatcherStats.queueStats[i].enableCount,
  1045. dispatcherStats.queueStats[i].disableCount,
  1046. intEnableRegVal,
  1047. dispatcherStats.queueStats[i].callbackCnt);
  1048. if (resetStats)
  1049. {
  1050. dispatcherStats.queueStats[i].enableCount =
  1051. dispatcherStats.queueStats[i].disableCount =
  1052. dispatcherStats.queueStats[i].callbackCnt = 0;
  1053. }
  1054. }
  1055. }
  1056. #else
  1057. IX_QMGR_LOG0("Livelock Prevention statistics are only collected in debug mode\n");
  1058. #endif
  1059. }
  1060. void
  1061. ixQMgrPeriodicDone (void)
  1062. {
  1063. UINT32 i = 0;
  1064. UINT32 ixQMgrLockKey = 0;
  1065. /*
  1066. * for the lower queues
  1067. */
  1068. for (i=0; i <= IX_QMGR_MAX_LOW_QUE_TABLE_INDEX; i++)
  1069. {
  1070. /*
  1071. * check for sporadics
  1072. */
  1073. if (IX_QMGR_TYPE_REALTIME_SPORADIC == ixQMgrQTypes[i])
  1074. {
  1075. /*
  1076. * enable any sporadics
  1077. */
  1078. ixQMgrLockKey = ixOsalIrqLock();
  1079. ixQMgrAqmIfQInterruptEnable(i);
  1080. ixOsalIrqUnlock(ixQMgrLockKey);
  1081. #ifndef NDEBUG
  1082. /*
  1083. * Update statistics
  1084. */
  1085. dispatcherStats.queueStats[i].enableCount++;
  1086. dispatcherStats.queueStats[i].notificationEnabled = true;
  1087. #endif
  1088. }
  1089. }
  1090. }
  1091. IX_STATUS
  1092. ixQMgrCallbackTypeSet (IxQMgrQId qId,
  1093. IxQMgrType type)
  1094. {
  1095. UINT32 ixQMgrLockKey = 0;
  1096. IxQMgrType ixQMgrOldType =0;
  1097. #ifndef NDEBUG
  1098. if (!ixQMgrQIsConfigured(qId))
  1099. {
  1100. return IX_QMGR_Q_NOT_CONFIGURED;
  1101. }
  1102. if (qId >= IX_QMGR_MIN_QUEUPP_QID)
  1103. {
  1104. return IX_QMGR_PARAMETER_ERROR;
  1105. }
  1106. if(!IX_QMGR_DISPATCHER_CALLBACK_TYPE_CHECK(type))
  1107. {
  1108. return IX_QMGR_PARAMETER_ERROR;
  1109. }
  1110. #endif
  1111. ixQMgrOldType = ixQMgrQTypes[qId];
  1112. ixQMgrQTypes[qId] = type;
  1113. /*
  1114. * check if Q has been changed from type SPORADIC
  1115. */
  1116. if (IX_QMGR_TYPE_REALTIME_SPORADIC == ixQMgrOldType)
  1117. {
  1118. /*
  1119. * previously Q was a SPORADIC, this means that LLP
  1120. * might have had it disabled. enable it now.
  1121. */
  1122. ixQMgrLockKey = ixOsalIrqLock();
  1123. ixQMgrAqmIfQInterruptEnable(qId);
  1124. ixOsalIrqUnlock(ixQMgrLockKey);
  1125. #ifndef NDEBUG
  1126. /*
  1127. * Update statistics
  1128. */
  1129. dispatcherStats.queueStats[qId].enableCount++;
  1130. #endif
  1131. }
  1132. return IX_SUCCESS;
  1133. }
  1134. IX_STATUS
  1135. ixQMgrCallbackTypeGet (IxQMgrQId qId,
  1136. IxQMgrType *type)
  1137. {
  1138. #ifndef NDEBUG
  1139. if (!ixQMgrQIsConfigured(qId))
  1140. {
  1141. return IX_QMGR_Q_NOT_CONFIGURED;
  1142. }
  1143. if (qId >= IX_QMGR_MIN_QUEUPP_QID)
  1144. {
  1145. return IX_QMGR_PARAMETER_ERROR;
  1146. }
  1147. if(type == NULL)
  1148. {
  1149. return IX_QMGR_PARAMETER_ERROR;
  1150. }
  1151. #endif
  1152. *type = ixQMgrQTypes[qId];
  1153. return IX_SUCCESS;
  1154. }