skdim.c 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742
  1. /******************************************************************************
  2. *
  3. * Name: skdim.c
  4. * Project: GEnesis, PCI Gigabit Ethernet Adapter
  5. * Version: $Revision: 1.5 $
  6. * Date: $Date: 2003/11/28 12:55:40 $
  7. * Purpose: All functions to maintain interrupt moderation
  8. *
  9. ******************************************************************************/
  10. /******************************************************************************
  11. *
  12. * (C)Copyright 1998-2002 SysKonnect GmbH.
  13. * (C)Copyright 2002-2003 Marvell.
  14. *
  15. * This program is free software; you can redistribute it and/or modify
  16. * it under the terms of the GNU General Public License as published by
  17. * the Free Software Foundation; either version 2 of the License, or
  18. * (at your option) any later version.
  19. *
  20. * The information in this file is provided "AS IS" without warranty.
  21. *
  22. ******************************************************************************/
  23. /******************************************************************************
  24. *
  25. * Description:
  26. *
  27. * This module is intended to manage the dynamic interrupt moderation on both
  28. * GEnesis and Yukon adapters.
  29. *
  30. * Include File Hierarchy:
  31. *
  32. * "skdrv1st.h"
  33. * "skdrv2nd.h"
  34. *
  35. ******************************************************************************/
  36. #ifndef lint
  37. static const char SysKonnectFileId[] =
  38. "@(#) $Id: skdim.c,v 1.5 2003/11/28 12:55:40 rroesler Exp $ (C) SysKonnect.";
  39. #endif
  40. #define __SKADDR_C
  41. #ifdef __cplusplus
  42. #error C++ is not yet supported.
  43. extern "C" {
  44. #endif
  45. /*******************************************************************************
  46. **
  47. ** Includes
  48. **
  49. *******************************************************************************/
  50. #ifndef __INC_SKDRV1ST_H
  51. #include "h/skdrv1st.h"
  52. #endif
  53. #ifndef __INC_SKDRV2ND_H
  54. #include "h/skdrv2nd.h"
  55. #endif
  56. #include <linux/kernel_stat.h>
  57. /*******************************************************************************
  58. **
  59. ** Defines
  60. **
  61. *******************************************************************************/
  62. /*******************************************************************************
  63. **
  64. ** Typedefs
  65. **
  66. *******************************************************************************/
  67. /*******************************************************************************
  68. **
  69. ** Local function prototypes
  70. **
  71. *******************************************************************************/
  72. static unsigned int GetCurrentSystemLoad(SK_AC *pAC);
  73. static SK_U64 GetIsrCalls(SK_AC *pAC);
  74. static SK_BOOL IsIntModEnabled(SK_AC *pAC);
  75. static void SetCurrIntCtr(SK_AC *pAC);
  76. static void EnableIntMod(SK_AC *pAC);
  77. static void DisableIntMod(SK_AC *pAC);
  78. static void ResizeDimTimerDuration(SK_AC *pAC);
  79. static void DisplaySelectedModerationType(SK_AC *pAC);
  80. static void DisplaySelectedModerationMask(SK_AC *pAC);
  81. static void DisplayDescrRatio(SK_AC *pAC);
  82. /*******************************************************************************
  83. **
  84. ** Global variables
  85. **
  86. *******************************************************************************/
  87. /*******************************************************************************
  88. **
  89. ** Local variables
  90. **
  91. *******************************************************************************/
  92. /*******************************************************************************
  93. **
  94. ** Global functions
  95. **
  96. *******************************************************************************/
  97. /*******************************************************************************
  98. ** Function : SkDimModerate
  99. ** Description : Called in every ISR to check if moderation is to be applied
  100. ** or not for the current number of interrupts
  101. ** Programmer : Ralph Roesler
  102. ** Last Modified: 22-mar-03
  103. ** Returns : void (!)
  104. ** Notes : -
  105. *******************************************************************************/
  106. void
  107. SkDimModerate(SK_AC *pAC) {
  108. unsigned int CurrSysLoad = 0; /* expressed in percent */
  109. unsigned int LoadIncrease = 0; /* expressed in percent */
  110. SK_U64 ThresholdInts = 0;
  111. SK_U64 IsrCallsPerSec = 0;
  112. #define M_DIMINFO pAC->DynIrqModInfo
  113. if (!IsIntModEnabled(pAC)) {
  114. if (M_DIMINFO.IntModTypeSelect == C_INT_MOD_DYNAMIC) {
  115. CurrSysLoad = GetCurrentSystemLoad(pAC);
  116. if (CurrSysLoad > 75) {
  117. /*
  118. ** More than 75% total system load! Enable the moderation
  119. ** to shield the system against too many interrupts.
  120. */
  121. EnableIntMod(pAC);
  122. } else if (CurrSysLoad > M_DIMINFO.PrevSysLoad) {
  123. LoadIncrease = (CurrSysLoad - M_DIMINFO.PrevSysLoad);
  124. if (LoadIncrease > ((M_DIMINFO.PrevSysLoad *
  125. C_INT_MOD_ENABLE_PERCENTAGE) / 100)) {
  126. if (CurrSysLoad > 10) {
  127. /*
  128. ** More than 50% increase with respect to the
  129. ** previous load of the system. Most likely this
  130. ** is due to our ISR-proc...
  131. */
  132. EnableIntMod(pAC);
  133. }
  134. }
  135. } else {
  136. /*
  137. ** Neither too much system load at all nor too much increase
  138. ** with respect to the previous system load. Hence, we can leave
  139. ** the ISR-handling like it is without enabling moderation.
  140. */
  141. }
  142. M_DIMINFO.PrevSysLoad = CurrSysLoad;
  143. }
  144. } else {
  145. if (M_DIMINFO.IntModTypeSelect == C_INT_MOD_DYNAMIC) {
  146. ThresholdInts = ((M_DIMINFO.MaxModIntsPerSec *
  147. C_INT_MOD_DISABLE_PERCENTAGE) / 100);
  148. IsrCallsPerSec = GetIsrCalls(pAC);
  149. if (IsrCallsPerSec <= ThresholdInts) {
  150. /*
  151. ** The number of interrupts within the last second is
  152. ** lower than the disable_percentage of the desried
  153. ** maxrate. Therefore we can disable the moderation.
  154. */
  155. DisableIntMod(pAC);
  156. M_DIMINFO.MaxModIntsPerSec =
  157. (M_DIMINFO.MaxModIntsPerSecUpperLimit +
  158. M_DIMINFO.MaxModIntsPerSecLowerLimit) / 2;
  159. } else {
  160. /*
  161. ** The number of interrupts per sec is the same as expected.
  162. ** Evalulate the descriptor-ratio. If it has changed, a resize
  163. ** in the moderation timer might be useful
  164. */
  165. if (M_DIMINFO.AutoSizing) {
  166. ResizeDimTimerDuration(pAC);
  167. }
  168. }
  169. }
  170. }
  171. /*
  172. ** Some information to the log...
  173. */
  174. if (M_DIMINFO.DisplayStats) {
  175. DisplaySelectedModerationType(pAC);
  176. DisplaySelectedModerationMask(pAC);
  177. DisplayDescrRatio(pAC);
  178. }
  179. M_DIMINFO.NbrProcessedDescr = 0;
  180. SetCurrIntCtr(pAC);
  181. }
  182. /*******************************************************************************
  183. ** Function : SkDimStartModerationTimer
  184. ** Description : Starts the audit-timer for the dynamic interrupt moderation
  185. ** Programmer : Ralph Roesler
  186. ** Last Modified: 22-mar-03
  187. ** Returns : void (!)
  188. ** Notes : -
  189. *******************************************************************************/
  190. void
  191. SkDimStartModerationTimer(SK_AC *pAC) {
  192. SK_EVPARA EventParam; /* Event struct for timer event */
  193. SK_MEMSET((char *) &EventParam, 0, sizeof(EventParam));
  194. EventParam.Para32[0] = SK_DRV_MODERATION_TIMER;
  195. SkTimerStart(pAC, pAC->IoBase, &pAC->DynIrqModInfo.ModTimer,
  196. SK_DRV_MODERATION_TIMER_LENGTH,
  197. SKGE_DRV, SK_DRV_TIMER, EventParam);
  198. }
  199. /*******************************************************************************
  200. ** Function : SkDimEnableModerationIfNeeded
  201. ** Description : Either enables or disables moderation
  202. ** Programmer : Ralph Roesler
  203. ** Last Modified: 22-mar-03
  204. ** Returns : void (!)
  205. ** Notes : This function is called when a particular adapter is opened
  206. ** There is no Disable function, because when all interrupts
  207. ** might be disable, the moderation timer has no meaning at all
  208. ******************************************************************************/
  209. void
  210. SkDimEnableModerationIfNeeded(SK_AC *pAC) {
  211. if (M_DIMINFO.IntModTypeSelect == C_INT_MOD_STATIC) {
  212. EnableIntMod(pAC); /* notification print in this function */
  213. } else if (M_DIMINFO.IntModTypeSelect == C_INT_MOD_DYNAMIC) {
  214. SkDimStartModerationTimer(pAC);
  215. if (M_DIMINFO.DisplayStats) {
  216. printk("Dynamic moderation has been enabled\n");
  217. }
  218. } else {
  219. if (M_DIMINFO.DisplayStats) {
  220. printk("No moderation has been enabled\n");
  221. }
  222. }
  223. }
  224. /*******************************************************************************
  225. ** Function : SkDimDisplayModerationSettings
  226. ** Description : Displays the current settings regaring interrupt moderation
  227. ** Programmer : Ralph Roesler
  228. ** Last Modified: 22-mar-03
  229. ** Returns : void (!)
  230. ** Notes : -
  231. *******************************************************************************/
  232. void
  233. SkDimDisplayModerationSettings(SK_AC *pAC) {
  234. DisplaySelectedModerationType(pAC);
  235. DisplaySelectedModerationMask(pAC);
  236. }
  237. /*******************************************************************************
  238. **
  239. ** Local functions
  240. **
  241. *******************************************************************************/
  242. /*******************************************************************************
  243. ** Function : GetCurrentSystemLoad
  244. ** Description : Retrieves the current system load of the system. This load
  245. ** is evaluated for all processors within the system.
  246. ** Programmer : Ralph Roesler
  247. ** Last Modified: 22-mar-03
  248. ** Returns : unsigned int: load expressed in percentage
  249. ** Notes : The possible range being returned is from 0 up to 100.
  250. ** Whereas 0 means 'no load at all' and 100 'system fully loaded'
  251. ** It is impossible to determine what actually causes the system
  252. ** to be in 100%, but maybe that is due to too much interrupts.
  253. *******************************************************************************/
  254. static unsigned int
  255. GetCurrentSystemLoad(SK_AC *pAC) {
  256. unsigned long jif = jiffies;
  257. unsigned int UserTime = 0;
  258. unsigned int SystemTime = 0;
  259. unsigned int NiceTime = 0;
  260. unsigned int IdleTime = 0;
  261. unsigned int TotalTime = 0;
  262. unsigned int UsedTime = 0;
  263. unsigned int SystemLoad = 0;
  264. /* unsigned int NbrCpu = 0; */
  265. /*
  266. ** The following lines have been commented out, because
  267. ** from kernel 2.5.44 onwards, the kernel-owned structure
  268. **
  269. ** struct kernel_stat kstat
  270. **
  271. ** is not marked as an exported symbol in the file
  272. **
  273. ** kernel/ksyms.c
  274. **
  275. ** As a consequence, using this driver as KLM is not possible
  276. ** and any access of the structure kernel_stat via the
  277. ** dedicated macros kstat_cpu(i).cpustat.xxx is to be avoided.
  278. **
  279. ** The kstat-information might be added again in future
  280. ** versions of the 2.5.xx kernel, but for the time being,
  281. ** number of interrupts will serve as indication how much
  282. ** load we currently have...
  283. **
  284. ** for (NbrCpu = 0; NbrCpu < num_online_cpus(); NbrCpu++) {
  285. ** UserTime = UserTime + kstat_cpu(NbrCpu).cpustat.user;
  286. ** NiceTime = NiceTime + kstat_cpu(NbrCpu).cpustat.nice;
  287. ** SystemTime = SystemTime + kstat_cpu(NbrCpu).cpustat.system;
  288. ** }
  289. */
  290. SK_U64 ThresholdInts = 0;
  291. SK_U64 IsrCallsPerSec = 0;
  292. ThresholdInts = ((M_DIMINFO.MaxModIntsPerSec *
  293. C_INT_MOD_ENABLE_PERCENTAGE) + 100);
  294. IsrCallsPerSec = GetIsrCalls(pAC);
  295. if (IsrCallsPerSec >= ThresholdInts) {
  296. /*
  297. ** We do not know how much the real CPU-load is!
  298. ** Return 80% as a default in order to activate DIM
  299. */
  300. SystemLoad = 80;
  301. return (SystemLoad);
  302. }
  303. UsedTime = UserTime + NiceTime + SystemTime;
  304. IdleTime = jif * num_online_cpus() - UsedTime;
  305. TotalTime = UsedTime + IdleTime;
  306. SystemLoad = ( 100 * (UsedTime - M_DIMINFO.PrevUsedTime) ) /
  307. (TotalTime - M_DIMINFO.PrevTotalTime);
  308. if (M_DIMINFO.DisplayStats) {
  309. printk("Current system load is: %u\n", SystemLoad);
  310. }
  311. M_DIMINFO.PrevTotalTime = TotalTime;
  312. M_DIMINFO.PrevUsedTime = UsedTime;
  313. return (SystemLoad);
  314. }
  315. /*******************************************************************************
  316. ** Function : GetIsrCalls
  317. ** Description : Depending on the selected moderation mask, this function will
  318. ** return the number of interrupts handled in the previous time-
  319. ** frame. This evaluated number is based on the current number
  320. ** of interrupts stored in PNMI-context and the previous stored
  321. ** interrupts.
  322. ** Programmer : Ralph Roesler
  323. ** Last Modified: 23-mar-03
  324. ** Returns : int: the number of interrupts being executed in the last
  325. ** timeframe
  326. ** Notes : It makes only sense to call this function, when dynamic
  327. ** interrupt moderation is applied
  328. *******************************************************************************/
  329. static SK_U64
  330. GetIsrCalls(SK_AC *pAC) {
  331. SK_U64 RxPort0IntDiff = 0;
  332. SK_U64 RxPort1IntDiff = 0;
  333. SK_U64 TxPort0IntDiff = 0;
  334. SK_U64 TxPort1IntDiff = 0;
  335. if (pAC->DynIrqModInfo.MaskIrqModeration == IRQ_MASK_TX_ONLY) {
  336. if (pAC->GIni.GIMacsFound == 2) {
  337. TxPort1IntDiff = pAC->Pnmi.Port[1].TxIntrCts -
  338. pAC->DynIrqModInfo.PrevPort1TxIntrCts;
  339. }
  340. TxPort0IntDiff = pAC->Pnmi.Port[0].TxIntrCts -
  341. pAC->DynIrqModInfo.PrevPort0TxIntrCts;
  342. } else if (pAC->DynIrqModInfo.MaskIrqModeration == IRQ_MASK_RX_ONLY) {
  343. if (pAC->GIni.GIMacsFound == 2) {
  344. RxPort1IntDiff = pAC->Pnmi.Port[1].RxIntrCts -
  345. pAC->DynIrqModInfo.PrevPort1RxIntrCts;
  346. }
  347. RxPort0IntDiff = pAC->Pnmi.Port[0].RxIntrCts -
  348. pAC->DynIrqModInfo.PrevPort0RxIntrCts;
  349. } else {
  350. if (pAC->GIni.GIMacsFound == 2) {
  351. RxPort1IntDiff = pAC->Pnmi.Port[1].RxIntrCts -
  352. pAC->DynIrqModInfo.PrevPort1RxIntrCts;
  353. TxPort1IntDiff = pAC->Pnmi.Port[1].TxIntrCts -
  354. pAC->DynIrqModInfo.PrevPort1TxIntrCts;
  355. }
  356. RxPort0IntDiff = pAC->Pnmi.Port[0].RxIntrCts -
  357. pAC->DynIrqModInfo.PrevPort0RxIntrCts;
  358. TxPort0IntDiff = pAC->Pnmi.Port[0].TxIntrCts -
  359. pAC->DynIrqModInfo.PrevPort0TxIntrCts;
  360. }
  361. return (RxPort0IntDiff + RxPort1IntDiff + TxPort0IntDiff + TxPort1IntDiff);
  362. }
  363. /*******************************************************************************
  364. ** Function : GetRxCalls
  365. ** Description : This function will return the number of times a receive inter-
  366. ** rupt was processed. This is needed to evaluate any resizing
  367. ** factor.
  368. ** Programmer : Ralph Roesler
  369. ** Last Modified: 23-mar-03
  370. ** Returns : SK_U64: the number of RX-ints being processed
  371. ** Notes : It makes only sense to call this function, when dynamic
  372. ** interrupt moderation is applied
  373. *******************************************************************************/
  374. static SK_U64
  375. GetRxCalls(SK_AC *pAC) {
  376. SK_U64 RxPort0IntDiff = 0;
  377. SK_U64 RxPort1IntDiff = 0;
  378. if (pAC->GIni.GIMacsFound == 2) {
  379. RxPort1IntDiff = pAC->Pnmi.Port[1].RxIntrCts -
  380. pAC->DynIrqModInfo.PrevPort1RxIntrCts;
  381. }
  382. RxPort0IntDiff = pAC->Pnmi.Port[0].RxIntrCts -
  383. pAC->DynIrqModInfo.PrevPort0RxIntrCts;
  384. return (RxPort0IntDiff + RxPort1IntDiff);
  385. }
  386. /*******************************************************************************
  387. ** Function : SetCurrIntCtr
  388. ** Description : Will store the current number orf occured interrupts in the
  389. ** adapter context. This is needed to evaluated the number of
  390. ** interrupts within a current timeframe.
  391. ** Programmer : Ralph Roesler
  392. ** Last Modified: 23-mar-03
  393. ** Returns : void (!)
  394. ** Notes : -
  395. *******************************************************************************/
  396. static void
  397. SetCurrIntCtr(SK_AC *pAC) {
  398. if (pAC->GIni.GIMacsFound == 2) {
  399. pAC->DynIrqModInfo.PrevPort1RxIntrCts = pAC->Pnmi.Port[1].RxIntrCts;
  400. pAC->DynIrqModInfo.PrevPort1TxIntrCts = pAC->Pnmi.Port[1].TxIntrCts;
  401. }
  402. pAC->DynIrqModInfo.PrevPort0RxIntrCts = pAC->Pnmi.Port[0].RxIntrCts;
  403. pAC->DynIrqModInfo.PrevPort0TxIntrCts = pAC->Pnmi.Port[0].TxIntrCts;
  404. }
  405. /*******************************************************************************
  406. ** Function : IsIntModEnabled()
  407. ** Description : Retrieves the current value of the interrupts moderation
  408. ** command register. Its content determines whether any
  409. ** moderation is running or not.
  410. ** Programmer : Ralph Roesler
  411. ** Last Modified: 23-mar-03
  412. ** Returns : SK_TRUE : if mod timer running
  413. ** SK_FALSE : if no moderation is being performed
  414. ** Notes : -
  415. *******************************************************************************/
  416. static SK_BOOL
  417. IsIntModEnabled(SK_AC *pAC) {
  418. unsigned long CtrCmd;
  419. SK_IN32(pAC->IoBase, B2_IRQM_CTRL, &CtrCmd);
  420. if ((CtrCmd & TIM_START) == TIM_START) {
  421. return SK_TRUE;
  422. } else {
  423. return SK_FALSE;
  424. }
  425. }
  426. /*******************************************************************************
  427. ** Function : EnableIntMod()
  428. ** Description : Enables the interrupt moderation using the values stored in
  429. ** in the pAC->DynIntMod data structure
  430. ** Programmer : Ralph Roesler
  431. ** Last Modified: 22-mar-03
  432. ** Returns : -
  433. ** Notes : -
  434. *******************************************************************************/
  435. static void
  436. EnableIntMod(SK_AC *pAC) {
  437. unsigned long ModBase;
  438. if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) {
  439. ModBase = C_CLK_FREQ_GENESIS / pAC->DynIrqModInfo.MaxModIntsPerSec;
  440. } else {
  441. ModBase = C_CLK_FREQ_YUKON / pAC->DynIrqModInfo.MaxModIntsPerSec;
  442. }
  443. SK_OUT32(pAC->IoBase, B2_IRQM_INI, ModBase);
  444. SK_OUT32(pAC->IoBase, B2_IRQM_MSK, pAC->DynIrqModInfo.MaskIrqModeration);
  445. SK_OUT32(pAC->IoBase, B2_IRQM_CTRL, TIM_START);
  446. if (M_DIMINFO.DisplayStats) {
  447. printk("Enabled interrupt moderation (%i ints/sec)\n",
  448. M_DIMINFO.MaxModIntsPerSec);
  449. }
  450. }
  451. /*******************************************************************************
  452. ** Function : DisableIntMod()
  453. ** Description : Disbles the interrupt moderation independent of what inter-
  454. ** rupts are running or not
  455. ** Programmer : Ralph Roesler
  456. ** Last Modified: 23-mar-03
  457. ** Returns : -
  458. ** Notes : -
  459. *******************************************************************************/
  460. static void
  461. DisableIntMod(SK_AC *pAC) {
  462. SK_OUT32(pAC->IoBase, B2_IRQM_CTRL, TIM_STOP);
  463. if (M_DIMINFO.DisplayStats) {
  464. printk("Disabled interrupt moderation\n");
  465. }
  466. }
  467. /*******************************************************************************
  468. ** Function : ResizeDimTimerDuration();
  469. ** Description : Checks the current used descriptor ratio and resizes the
  470. ** duration timer (longer/smaller) if possible.
  471. ** Programmer : Ralph Roesler
  472. ** Last Modified: 23-mar-03
  473. ** Returns : -
  474. ** Notes : There are both maximum and minimum timer duration value.
  475. ** This function assumes that interrupt moderation is already
  476. ** enabled!
  477. *******************************************************************************/
  478. static void
  479. ResizeDimTimerDuration(SK_AC *pAC) {
  480. SK_BOOL IncreaseTimerDuration;
  481. int TotalMaxNbrDescr;
  482. int UsedDescrRatio;
  483. int RatioDiffAbs;
  484. int RatioDiffRel;
  485. int NewMaxModIntsPerSec;
  486. int ModAdjValue;
  487. long ModBase;
  488. /*
  489. ** Check first if we are allowed to perform any modification
  490. */
  491. if (IsIntModEnabled(pAC)) {
  492. if (M_DIMINFO.IntModTypeSelect != C_INT_MOD_DYNAMIC) {
  493. return;
  494. } else {
  495. if (M_DIMINFO.ModJustEnabled) {
  496. M_DIMINFO.ModJustEnabled = SK_FALSE;
  497. return;
  498. }
  499. }
  500. }
  501. /*
  502. ** If we got until here, we have to evaluate the amount of the
  503. ** descriptor ratio change...
  504. */
  505. TotalMaxNbrDescr = pAC->RxDescrPerRing * GetRxCalls(pAC);
  506. UsedDescrRatio = (M_DIMINFO.NbrProcessedDescr * 100) / TotalMaxNbrDescr;
  507. if (UsedDescrRatio > M_DIMINFO.PrevUsedDescrRatio) {
  508. RatioDiffAbs = (UsedDescrRatio - M_DIMINFO.PrevUsedDescrRatio);
  509. RatioDiffRel = (RatioDiffAbs * 100) / UsedDescrRatio;
  510. M_DIMINFO.PrevUsedDescrRatio = UsedDescrRatio;
  511. IncreaseTimerDuration = SK_FALSE; /* in other words: DECREASE */
  512. } else if (UsedDescrRatio < M_DIMINFO.PrevUsedDescrRatio) {
  513. RatioDiffAbs = (M_DIMINFO.PrevUsedDescrRatio - UsedDescrRatio);
  514. RatioDiffRel = (RatioDiffAbs * 100) / M_DIMINFO.PrevUsedDescrRatio;
  515. M_DIMINFO.PrevUsedDescrRatio = UsedDescrRatio;
  516. IncreaseTimerDuration = SK_TRUE; /* in other words: INCREASE */
  517. } else {
  518. RatioDiffAbs = (M_DIMINFO.PrevUsedDescrRatio - UsedDescrRatio);
  519. RatioDiffRel = (RatioDiffAbs * 100) / M_DIMINFO.PrevUsedDescrRatio;
  520. M_DIMINFO.PrevUsedDescrRatio = UsedDescrRatio;
  521. IncreaseTimerDuration = SK_TRUE; /* in other words: INCREASE */
  522. }
  523. /*
  524. ** Now we can determine the change in percent
  525. */
  526. if ((RatioDiffRel >= 0) && (RatioDiffRel <= 5) ) {
  527. ModAdjValue = 1; /* 1% change - maybe some other value in future */
  528. } else if ((RatioDiffRel > 5) && (RatioDiffRel <= 10) ) {
  529. ModAdjValue = 1; /* 1% change - maybe some other value in future */
  530. } else if ((RatioDiffRel > 10) && (RatioDiffRel <= 15) ) {
  531. ModAdjValue = 1; /* 1% change - maybe some other value in future */
  532. } else {
  533. ModAdjValue = 1; /* 1% change - maybe some other value in future */
  534. }
  535. if (IncreaseTimerDuration) {
  536. NewMaxModIntsPerSec = M_DIMINFO.MaxModIntsPerSec +
  537. (M_DIMINFO.MaxModIntsPerSec * ModAdjValue) / 100;
  538. } else {
  539. NewMaxModIntsPerSec = M_DIMINFO.MaxModIntsPerSec -
  540. (M_DIMINFO.MaxModIntsPerSec * ModAdjValue) / 100;
  541. }
  542. /*
  543. ** Check if we exceed boundaries...
  544. */
  545. if ( (NewMaxModIntsPerSec > M_DIMINFO.MaxModIntsPerSecUpperLimit) ||
  546. (NewMaxModIntsPerSec < M_DIMINFO.MaxModIntsPerSecLowerLimit)) {
  547. if (M_DIMINFO.DisplayStats) {
  548. printk("Cannot change ModTim from %i to %i ints/sec\n",
  549. M_DIMINFO.MaxModIntsPerSec, NewMaxModIntsPerSec);
  550. }
  551. return;
  552. } else {
  553. if (M_DIMINFO.DisplayStats) {
  554. printk("Resized ModTim from %i to %i ints/sec\n",
  555. M_DIMINFO.MaxModIntsPerSec, NewMaxModIntsPerSec);
  556. }
  557. }
  558. M_DIMINFO.MaxModIntsPerSec = NewMaxModIntsPerSec;
  559. if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) {
  560. ModBase = C_CLK_FREQ_GENESIS / pAC->DynIrqModInfo.MaxModIntsPerSec;
  561. } else {
  562. ModBase = C_CLK_FREQ_YUKON / pAC->DynIrqModInfo.MaxModIntsPerSec;
  563. }
  564. /*
  565. ** We do not need to touch any other registers
  566. */
  567. SK_OUT32(pAC->IoBase, B2_IRQM_INI, ModBase);
  568. }
  569. /*******************************************************************************
  570. ** Function : DisplaySelectedModerationType()
  571. ** Description : Displays what type of moderation we have
  572. ** Programmer : Ralph Roesler
  573. ** Last Modified: 23-mar-03
  574. ** Returns : void!
  575. ** Notes : -
  576. *******************************************************************************/
  577. static void
  578. DisplaySelectedModerationType(SK_AC *pAC) {
  579. if (pAC->DynIrqModInfo.DisplayStats) {
  580. if (pAC->DynIrqModInfo.IntModTypeSelect == C_INT_MOD_STATIC) {
  581. printk("Static int moderation runs with %i INTS/sec\n",
  582. pAC->DynIrqModInfo.MaxModIntsPerSec);
  583. } else if (pAC->DynIrqModInfo.IntModTypeSelect == C_INT_MOD_DYNAMIC) {
  584. if (IsIntModEnabled(pAC)) {
  585. printk("Dynamic int moderation runs with %i INTS/sec\n",
  586. pAC->DynIrqModInfo.MaxModIntsPerSec);
  587. } else {
  588. printk("Dynamic int moderation currently not applied\n");
  589. }
  590. } else {
  591. printk("No interrupt moderation selected!\n");
  592. }
  593. }
  594. }
  595. /*******************************************************************************
  596. ** Function : DisplaySelectedModerationMask()
  597. ** Description : Displays what interrupts are moderated
  598. ** Programmer : Ralph Roesler
  599. ** Last Modified: 23-mar-03
  600. ** Returns : void!
  601. ** Notes : -
  602. *******************************************************************************/
  603. static void
  604. DisplaySelectedModerationMask(SK_AC *pAC) {
  605. if (pAC->DynIrqModInfo.DisplayStats) {
  606. if (pAC->DynIrqModInfo.IntModTypeSelect != C_INT_MOD_NONE) {
  607. switch (pAC->DynIrqModInfo.MaskIrqModeration) {
  608. case IRQ_MASK_TX_ONLY:
  609. printk("Only Tx-interrupts are moderated\n");
  610. break;
  611. case IRQ_MASK_RX_ONLY:
  612. printk("Only Rx-interrupts are moderated\n");
  613. break;
  614. case IRQ_MASK_SP_ONLY:
  615. printk("Only special-interrupts are moderated\n");
  616. break;
  617. case IRQ_MASK_TX_RX:
  618. printk("Tx- and Rx-interrupts are moderated\n");
  619. break;
  620. case IRQ_MASK_SP_RX:
  621. printk("Special- and Rx-interrupts are moderated\n");
  622. break;
  623. case IRQ_MASK_SP_TX:
  624. printk("Special- and Tx-interrupts are moderated\n");
  625. break;
  626. case IRQ_MASK_RX_TX_SP:
  627. printk("All Rx-, Tx and special-interrupts are moderated\n");
  628. break;
  629. default:
  630. printk("Don't know what is moderated\n");
  631. break;
  632. }
  633. } else {
  634. printk("No specific interrupts masked for moderation\n");
  635. }
  636. }
  637. }
  638. /*******************************************************************************
  639. ** Function : DisplayDescrRatio
  640. ** Description : Like the name states...
  641. ** Programmer : Ralph Roesler
  642. ** Last Modified: 23-mar-03
  643. ** Returns : void!
  644. ** Notes : -
  645. *******************************************************************************/
  646. static void
  647. DisplayDescrRatio(SK_AC *pAC) {
  648. int TotalMaxNbrDescr = 0;
  649. if (pAC->DynIrqModInfo.DisplayStats) {
  650. TotalMaxNbrDescr = pAC->RxDescrPerRing * GetRxCalls(pAC);
  651. printk("Ratio descriptors: %i/%i\n",
  652. M_DIMINFO.NbrProcessedDescr, TotalMaxNbrDescr);
  653. }
  654. }
  655. /*******************************************************************************
  656. **
  657. ** End of file
  658. **
  659. *******************************************************************************/