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