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