| /****************************************************************************** |
| * |
| * Name: skdim.c |
| * Project: GEnesis, PCI Gigabit Ethernet Adapter |
| * Version: $Revision: 1.5 $ |
| * Date: $Date: 2003/11/28 12:55:40 $ |
| * Purpose: All functions to maintain interrupt moderation |
| * |
| ******************************************************************************/ |
| |
| /****************************************************************************** |
| * |
| * (C)Copyright 1998-2002 SysKonnect GmbH. |
| * (C)Copyright 2002-2003 Marvell. |
| * |
| * This program is free software; you can redistribute it and/or modify |
| * it under the terms of the GNU General Public License as published by |
| * the Free Software Foundation; either version 2 of the License, or |
| * (at your option) any later version. |
| * |
| * The information in this file is provided "AS IS" without warranty. |
| * |
| ******************************************************************************/ |
| |
| /****************************************************************************** |
| * |
| * Description: |
| * |
| * This module is intended to manage the dynamic interrupt moderation on both |
| * GEnesis and Yukon adapters. |
| * |
| * Include File Hierarchy: |
| * |
| * "skdrv1st.h" |
| * "skdrv2nd.h" |
| * |
| ******************************************************************************/ |
| |
| #ifndef lint |
| static const char SysKonnectFileId[] = |
| "@(#) $Id: skdim.c,v 1.5 2003/11/28 12:55:40 rroesler Exp $ (C) SysKonnect."; |
| #endif |
| |
| #define __SKADDR_C |
| |
| #ifdef __cplusplus |
| #error C++ is not yet supported. |
| extern "C" { |
| #endif |
| |
| /******************************************************************************* |
| ** |
| ** Includes |
| ** |
| *******************************************************************************/ |
| |
| #ifndef __INC_SKDRV1ST_H |
| #include "h/skdrv1st.h" |
| #endif |
| |
| #ifndef __INC_SKDRV2ND_H |
| #include "h/skdrv2nd.h" |
| #endif |
| |
| #include <linux/kernel_stat.h> |
| |
| /******************************************************************************* |
| ** |
| ** Defines |
| ** |
| *******************************************************************************/ |
| |
| /******************************************************************************* |
| ** |
| ** Typedefs |
| ** |
| *******************************************************************************/ |
| |
| /******************************************************************************* |
| ** |
| ** Local function prototypes |
| ** |
| *******************************************************************************/ |
| |
| static unsigned int GetCurrentSystemLoad(SK_AC *pAC); |
| static SK_U64 GetIsrCalls(SK_AC *pAC); |
| static SK_BOOL IsIntModEnabled(SK_AC *pAC); |
| static void SetCurrIntCtr(SK_AC *pAC); |
| static void EnableIntMod(SK_AC *pAC); |
| static void DisableIntMod(SK_AC *pAC); |
| static void ResizeDimTimerDuration(SK_AC *pAC); |
| static void DisplaySelectedModerationType(SK_AC *pAC); |
| static void DisplaySelectedModerationMask(SK_AC *pAC); |
| static void DisplayDescrRatio(SK_AC *pAC); |
| |
| /******************************************************************************* |
| ** |
| ** Global variables |
| ** |
| *******************************************************************************/ |
| |
| /******************************************************************************* |
| ** |
| ** Local variables |
| ** |
| *******************************************************************************/ |
| |
| /******************************************************************************* |
| ** |
| ** Global functions |
| ** |
| *******************************************************************************/ |
| |
| /******************************************************************************* |
| ** Function : SkDimModerate |
| ** Description : Called in every ISR to check if moderation is to be applied |
| ** or not for the current number of interrupts |
| ** Programmer : Ralph Roesler |
| ** Last Modified: 22-mar-03 |
| ** Returns : void (!) |
| ** Notes : - |
| *******************************************************************************/ |
| |
| void |
| SkDimModerate(SK_AC *pAC) { |
| unsigned int CurrSysLoad = 0; /* expressed in percent */ |
| unsigned int LoadIncrease = 0; /* expressed in percent */ |
| SK_U64 ThresholdInts = 0; |
| SK_U64 IsrCallsPerSec = 0; |
| |
| #define M_DIMINFO pAC->DynIrqModInfo |
| |
| if (!IsIntModEnabled(pAC)) { |
| if (M_DIMINFO.IntModTypeSelect == C_INT_MOD_DYNAMIC) { |
| CurrSysLoad = GetCurrentSystemLoad(pAC); |
| if (CurrSysLoad > 75) { |
| /* |
| ** More than 75% total system load! Enable the moderation |
| ** to shield the system against too many interrupts. |
| */ |
| EnableIntMod(pAC); |
| } else if (CurrSysLoad > M_DIMINFO.PrevSysLoad) { |
| LoadIncrease = (CurrSysLoad - M_DIMINFO.PrevSysLoad); |
| if (LoadIncrease > ((M_DIMINFO.PrevSysLoad * |
| C_INT_MOD_ENABLE_PERCENTAGE) / 100)) { |
| if (CurrSysLoad > 10) { |
| /* |
| ** More than 50% increase with respect to the |
| ** previous load of the system. Most likely this |
| ** is due to our ISR-proc... |
| */ |
| EnableIntMod(pAC); |
| } |
| } |
| } else { |
| /* |
| ** Neither too much system load at all nor too much increase |
| ** with respect to the previous system load. Hence, we can leave |
| ** the ISR-handling like it is without enabling moderation. |
| */ |
| } |
| M_DIMINFO.PrevSysLoad = CurrSysLoad; |
| } |
| } else { |
| if (M_DIMINFO.IntModTypeSelect == C_INT_MOD_DYNAMIC) { |
| ThresholdInts = ((M_DIMINFO.MaxModIntsPerSec * |
| C_INT_MOD_DISABLE_PERCENTAGE) / 100); |
| IsrCallsPerSec = GetIsrCalls(pAC); |
| if (IsrCallsPerSec <= ThresholdInts) { |
| /* |
| ** The number of interrupts within the last second is |
| ** lower than the disable_percentage of the desried |
| ** maxrate. Therefore we can disable the moderation. |
| */ |
| DisableIntMod(pAC); |
| M_DIMINFO.MaxModIntsPerSec = |
| (M_DIMINFO.MaxModIntsPerSecUpperLimit + |
| M_DIMINFO.MaxModIntsPerSecLowerLimit) / 2; |
| } else { |
| /* |
| ** The number of interrupts per sec is the same as expected. |
| ** Evalulate the descriptor-ratio. If it has changed, a resize |
| ** in the moderation timer might be usefull |
| */ |
| if (M_DIMINFO.AutoSizing) { |
| ResizeDimTimerDuration(pAC); |
| } |
| } |
| } |
| } |
| |
| /* |
| ** Some information to the log... |
| */ |
| if (M_DIMINFO.DisplayStats) { |
| DisplaySelectedModerationType(pAC); |
| DisplaySelectedModerationMask(pAC); |
| DisplayDescrRatio(pAC); |
| } |
| |
| M_DIMINFO.NbrProcessedDescr = 0; |
| SetCurrIntCtr(pAC); |
| } |
| |
| /******************************************************************************* |
| ** Function : SkDimStartModerationTimer |
| ** Description : Starts the audit-timer for the dynamic interrupt moderation |
| ** Programmer : Ralph Roesler |
| ** Last Modified: 22-mar-03 |
| ** Returns : void (!) |
| ** Notes : - |
| *******************************************************************************/ |
| |
| void |
| SkDimStartModerationTimer(SK_AC *pAC) { |
| SK_EVPARA EventParam; /* Event struct for timer event */ |
| |
| SK_MEMSET((char *) &EventParam, 0, sizeof(EventParam)); |
| EventParam.Para32[0] = SK_DRV_MODERATION_TIMER; |
| SkTimerStart(pAC, pAC->IoBase, &pAC->DynIrqModInfo.ModTimer, |
| SK_DRV_MODERATION_TIMER_LENGTH, |
| SKGE_DRV, SK_DRV_TIMER, EventParam); |
| } |
| |
| /******************************************************************************* |
| ** Function : SkDimEnableModerationIfNeeded |
| ** Description : Either enables or disables moderation |
| ** Programmer : Ralph Roesler |
| ** Last Modified: 22-mar-03 |
| ** Returns : void (!) |
| ** Notes : This function is called when a particular adapter is opened |
| ** There is no Disable function, because when all interrupts |
| ** might be disable, the moderation timer has no meaning at all |
| ******************************************************************************/ |
| |
| void |
| SkDimEnableModerationIfNeeded(SK_AC *pAC) { |
| |
| if (M_DIMINFO.IntModTypeSelect == C_INT_MOD_STATIC) { |
| EnableIntMod(pAC); /* notification print in this function */ |
| } else if (M_DIMINFO.IntModTypeSelect == C_INT_MOD_DYNAMIC) { |
| SkDimStartModerationTimer(pAC); |
| if (M_DIMINFO.DisplayStats) { |
| printk("Dynamic moderation has been enabled\n"); |
| } |
| } else { |
| if (M_DIMINFO.DisplayStats) { |
| printk("No moderation has been enabled\n"); |
| } |
| } |
| } |
| |
| /******************************************************************************* |
| ** Function : SkDimDisplayModerationSettings |
| ** Description : Displays the current settings regaring interrupt moderation |
| ** Programmer : Ralph Roesler |
| ** Last Modified: 22-mar-03 |
| ** Returns : void (!) |
| ** Notes : - |
| *******************************************************************************/ |
| |
| void |
| SkDimDisplayModerationSettings(SK_AC *pAC) { |
| DisplaySelectedModerationType(pAC); |
| DisplaySelectedModerationMask(pAC); |
| } |
| |
| /******************************************************************************* |
| ** |
| ** Local functions |
| ** |
| *******************************************************************************/ |
| |
| /******************************************************************************* |
| ** Function : GetCurrentSystemLoad |
| ** Description : Retrieves the current system load of the system. This load |
| ** is evaluated for all processors within the system. |
| ** Programmer : Ralph Roesler |
| ** Last Modified: 22-mar-03 |
| ** Returns : unsigned int: load expressed in percentage |
| ** Notes : The possible range being returned is from 0 up to 100. |
| ** Whereas 0 means 'no load at all' and 100 'system fully loaded' |
| ** It is impossible to determine what actually causes the system |
| ** to be in 100%, but maybe that is due to too much interrupts. |
| *******************************************************************************/ |
| |
| static unsigned int |
| GetCurrentSystemLoad(SK_AC *pAC) { |
| unsigned long jif = jiffies; |
| unsigned int UserTime = 0; |
| unsigned int SystemTime = 0; |
| unsigned int NiceTime = 0; |
| unsigned int IdleTime = 0; |
| unsigned int TotalTime = 0; |
| unsigned int UsedTime = 0; |
| unsigned int SystemLoad = 0; |
| |
| /* unsigned int NbrCpu = 0; */ |
| |
| /* |
| ** The following lines have been commented out, because |
| ** from kernel 2.5.44 onwards, the kernel-owned structure |
| ** |
| ** struct kernel_stat kstat |
| ** |
| ** is not marked as an exported symbol in the file |
| ** |
| ** kernel/ksyms.c |
| ** |
| ** As a consequence, using this driver as KLM is not possible |
| ** and any access of the structure kernel_stat via the |
| ** dedicated macros kstat_cpu(i).cpustat.xxx is to be avoided. |
| ** |
| ** The kstat-information might be added again in future |
| ** versions of the 2.5.xx kernel, but for the time being, |
| ** number of interrupts will serve as indication how much |
| ** load we currently have... |
| ** |
| ** for (NbrCpu = 0; NbrCpu < num_online_cpus(); NbrCpu++) { |
| ** UserTime = UserTime + kstat_cpu(NbrCpu).cpustat.user; |
| ** NiceTime = NiceTime + kstat_cpu(NbrCpu).cpustat.nice; |
| ** SystemTime = SystemTime + kstat_cpu(NbrCpu).cpustat.system; |
| ** } |
| */ |
| SK_U64 ThresholdInts = 0; |
| SK_U64 IsrCallsPerSec = 0; |
| |
| ThresholdInts = ((M_DIMINFO.MaxModIntsPerSec * |
| C_INT_MOD_ENABLE_PERCENTAGE) + 100); |
| IsrCallsPerSec = GetIsrCalls(pAC); |
| if (IsrCallsPerSec >= ThresholdInts) { |
| /* |
| ** We do not know how much the real CPU-load is! |
| ** Return 80% as a default in order to activate DIM |
| */ |
| SystemLoad = 80; |
| return (SystemLoad); |
| } |
| |
| UsedTime = UserTime + NiceTime + SystemTime; |
| |
| IdleTime = jif * num_online_cpus() - UsedTime; |
| TotalTime = UsedTime + IdleTime; |
| |
| SystemLoad = ( 100 * (UsedTime - M_DIMINFO.PrevUsedTime) ) / |
| (TotalTime - M_DIMINFO.PrevTotalTime); |
| |
| if (M_DIMINFO.DisplayStats) { |
| printk("Current system load is: %u\n", SystemLoad); |
| } |
| |
| M_DIMINFO.PrevTotalTime = TotalTime; |
| M_DIMINFO.PrevUsedTime = UsedTime; |
| |
| return (SystemLoad); |
| } |
| |
| /******************************************************************************* |
| ** Function : GetIsrCalls |
| ** Description : Depending on the selected moderation mask, this function will |
| ** return the number of interrupts handled in the previous time- |
| ** frame. This evaluated number is based on the current number |
| ** of interrupts stored in PNMI-context and the previous stored |
| ** interrupts. |
| ** Programmer : Ralph Roesler |
| ** Last Modified: 23-mar-03 |
| ** Returns : int: the number of interrupts being executed in the last |
| ** timeframe |
| ** Notes : It makes only sense to call this function, when dynamic |
| ** interrupt moderation is applied |
| *******************************************************************************/ |
| |
| static SK_U64 |
| GetIsrCalls(SK_AC *pAC) { |
| SK_U64 RxPort0IntDiff = 0; |
| SK_U64 RxPort1IntDiff = 0; |
| SK_U64 TxPort0IntDiff = 0; |
| SK_U64 TxPort1IntDiff = 0; |
| |
| if (pAC->DynIrqModInfo.MaskIrqModeration == IRQ_MASK_TX_ONLY) { |
| if (pAC->GIni.GIMacsFound == 2) { |
| TxPort1IntDiff = pAC->Pnmi.Port[1].TxIntrCts - |
| pAC->DynIrqModInfo.PrevPort1TxIntrCts; |
| } |
| TxPort0IntDiff = pAC->Pnmi.Port[0].TxIntrCts - |
| pAC->DynIrqModInfo.PrevPort0TxIntrCts; |
| } else if (pAC->DynIrqModInfo.MaskIrqModeration == IRQ_MASK_RX_ONLY) { |
| if (pAC->GIni.GIMacsFound == 2) { |
| RxPort1IntDiff = pAC->Pnmi.Port[1].RxIntrCts - |
| pAC->DynIrqModInfo.PrevPort1RxIntrCts; |
| } |
| RxPort0IntDiff = pAC->Pnmi.Port[0].RxIntrCts - |
| pAC->DynIrqModInfo.PrevPort0RxIntrCts; |
| } else { |
| if (pAC->GIni.GIMacsFound == 2) { |
| RxPort1IntDiff = pAC->Pnmi.Port[1].RxIntrCts - |
| pAC->DynIrqModInfo.PrevPort1RxIntrCts; |
| TxPort1IntDiff = pAC->Pnmi.Port[1].TxIntrCts - |
| pAC->DynIrqModInfo.PrevPort1TxIntrCts; |
| } |
| RxPort0IntDiff = pAC->Pnmi.Port[0].RxIntrCts - |
| pAC->DynIrqModInfo.PrevPort0RxIntrCts; |
| TxPort0IntDiff = pAC->Pnmi.Port[0].TxIntrCts - |
| pAC->DynIrqModInfo.PrevPort0TxIntrCts; |
| } |
| |
| return (RxPort0IntDiff + RxPort1IntDiff + TxPort0IntDiff + TxPort1IntDiff); |
| } |
| |
| /******************************************************************************* |
| ** Function : GetRxCalls |
| ** Description : This function will return the number of times a receive inter- |
| ** rupt was processed. This is needed to evaluate any resizing |
| ** factor. |
| ** Programmer : Ralph Roesler |
| ** Last Modified: 23-mar-03 |
| ** Returns : SK_U64: the number of RX-ints being processed |
| ** Notes : It makes only sense to call this function, when dynamic |
| ** interrupt moderation is applied |
| *******************************************************************************/ |
| |
| static SK_U64 |
| GetRxCalls(SK_AC *pAC) { |
| SK_U64 RxPort0IntDiff = 0; |
| SK_U64 RxPort1IntDiff = 0; |
| |
| if (pAC->GIni.GIMacsFound == 2) { |
| RxPort1IntDiff = pAC->Pnmi.Port[1].RxIntrCts - |
| pAC->DynIrqModInfo.PrevPort1RxIntrCts; |
| } |
| RxPort0IntDiff = pAC->Pnmi.Port[0].RxIntrCts - |
| pAC->DynIrqModInfo.PrevPort0RxIntrCts; |
| |
| return (RxPort0IntDiff + RxPort1IntDiff); |
| } |
| |
| /******************************************************************************* |
| ** Function : SetCurrIntCtr |
| ** Description : Will store the current number orf occured interrupts in the |
| ** adapter context. This is needed to evaluated the number of |
| ** interrupts within a current timeframe. |
| ** Programmer : Ralph Roesler |
| ** Last Modified: 23-mar-03 |
| ** Returns : void (!) |
| ** Notes : - |
| *******************************************************************************/ |
| |
| static void |
| SetCurrIntCtr(SK_AC *pAC) { |
| if (pAC->GIni.GIMacsFound == 2) { |
| pAC->DynIrqModInfo.PrevPort1RxIntrCts = pAC->Pnmi.Port[1].RxIntrCts; |
| pAC->DynIrqModInfo.PrevPort1TxIntrCts = pAC->Pnmi.Port[1].TxIntrCts; |
| } |
| pAC->DynIrqModInfo.PrevPort0RxIntrCts = pAC->Pnmi.Port[0].RxIntrCts; |
| pAC->DynIrqModInfo.PrevPort0TxIntrCts = pAC->Pnmi.Port[0].TxIntrCts; |
| } |
| |
| /******************************************************************************* |
| ** Function : IsIntModEnabled() |
| ** Description : Retrieves the current value of the interrupts moderation |
| ** command register. Its content determines whether any |
| ** moderation is running or not. |
| ** Programmer : Ralph Roesler |
| ** Last Modified: 23-mar-03 |
| ** Returns : SK_TRUE : if mod timer running |
| ** SK_FALSE : if no moderation is being performed |
| ** Notes : - |
| *******************************************************************************/ |
| |
| static SK_BOOL |
| IsIntModEnabled(SK_AC *pAC) { |
| unsigned long CtrCmd; |
| |
| SK_IN32(pAC->IoBase, B2_IRQM_CTRL, &CtrCmd); |
| if ((CtrCmd & TIM_START) == TIM_START) { |
| return SK_TRUE; |
| } else { |
| return SK_FALSE; |
| } |
| } |
| |
| /******************************************************************************* |
| ** Function : EnableIntMod() |
| ** Description : Enables the interrupt moderation using the values stored in |
| ** in the pAC->DynIntMod data structure |
| ** Programmer : Ralph Roesler |
| ** Last Modified: 22-mar-03 |
| ** Returns : - |
| ** Notes : - |
| *******************************************************************************/ |
| |
| static void |
| EnableIntMod(SK_AC *pAC) { |
| unsigned long ModBase; |
| |
| if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) { |
| ModBase = C_CLK_FREQ_GENESIS / pAC->DynIrqModInfo.MaxModIntsPerSec; |
| } else { |
| ModBase = C_CLK_FREQ_YUKON / pAC->DynIrqModInfo.MaxModIntsPerSec; |
| } |
| |
| SK_OUT32(pAC->IoBase, B2_IRQM_INI, ModBase); |
| SK_OUT32(pAC->IoBase, B2_IRQM_MSK, pAC->DynIrqModInfo.MaskIrqModeration); |
| SK_OUT32(pAC->IoBase, B2_IRQM_CTRL, TIM_START); |
| if (M_DIMINFO.DisplayStats) { |
| printk("Enabled interrupt moderation (%i ints/sec)\n", |
| M_DIMINFO.MaxModIntsPerSec); |
| } |
| } |
| |
| /******************************************************************************* |
| ** Function : DisableIntMod() |
| ** Description : Disbles the interrupt moderation independent of what inter- |
| ** rupts are running or not |
| ** Programmer : Ralph Roesler |
| ** Last Modified: 23-mar-03 |
| ** Returns : - |
| ** Notes : - |
| *******************************************************************************/ |
| |
| static void |
| DisableIntMod(SK_AC *pAC) { |
| |
| SK_OUT32(pAC->IoBase, B2_IRQM_CTRL, TIM_STOP); |
| if (M_DIMINFO.DisplayStats) { |
| printk("Disabled interrupt moderation\n"); |
| } |
| } |
| |
| /******************************************************************************* |
| ** Function : ResizeDimTimerDuration(); |
| ** Description : Checks the current used descriptor ratio and resizes the |
| ** duration timer (longer/smaller) if possible. |
| ** Programmer : Ralph Roesler |
| ** Last Modified: 23-mar-03 |
| ** Returns : - |
| ** Notes : There are both maximum and minimum timer duration value. |
| ** This function assumes that interrupt moderation is already |
| ** enabled! |
| *******************************************************************************/ |
| |
| static void |
| ResizeDimTimerDuration(SK_AC *pAC) { |
| SK_BOOL IncreaseTimerDuration; |
| int TotalMaxNbrDescr; |
| int UsedDescrRatio; |
| int RatioDiffAbs; |
| int RatioDiffRel; |
| int NewMaxModIntsPerSec; |
| int ModAdjValue; |
| long ModBase; |
| |
| /* |
| ** Check first if we are allowed to perform any modification |
| */ |
| if (IsIntModEnabled(pAC)) { |
| if (M_DIMINFO.IntModTypeSelect != C_INT_MOD_DYNAMIC) { |
| return; |
| } else { |
| if (M_DIMINFO.ModJustEnabled) { |
| M_DIMINFO.ModJustEnabled = SK_FALSE; |
| return; |
| } |
| } |
| } |
| |
| /* |
| ** If we got until here, we have to evaluate the amount of the |
| ** descriptor ratio change... |
| */ |
| TotalMaxNbrDescr = pAC->RxDescrPerRing * GetRxCalls(pAC); |
| UsedDescrRatio = (M_DIMINFO.NbrProcessedDescr * 100) / TotalMaxNbrDescr; |
| |
| if (UsedDescrRatio > M_DIMINFO.PrevUsedDescrRatio) { |
| RatioDiffAbs = (UsedDescrRatio - M_DIMINFO.PrevUsedDescrRatio); |
| RatioDiffRel = (RatioDiffAbs * 100) / UsedDescrRatio; |
| M_DIMINFO.PrevUsedDescrRatio = UsedDescrRatio; |
| IncreaseTimerDuration = SK_FALSE; /* in other words: DECREASE */ |
| } else if (UsedDescrRatio < M_DIMINFO.PrevUsedDescrRatio) { |
| RatioDiffAbs = (M_DIMINFO.PrevUsedDescrRatio - UsedDescrRatio); |
| RatioDiffRel = (RatioDiffAbs * 100) / M_DIMINFO.PrevUsedDescrRatio; |
| M_DIMINFO.PrevUsedDescrRatio = UsedDescrRatio; |
| IncreaseTimerDuration = SK_TRUE; /* in other words: INCREASE */ |
| } else { |
| RatioDiffAbs = (M_DIMINFO.PrevUsedDescrRatio - UsedDescrRatio); |
| RatioDiffRel = (RatioDiffAbs * 100) / M_DIMINFO.PrevUsedDescrRatio; |
| M_DIMINFO.PrevUsedDescrRatio = UsedDescrRatio; |
| IncreaseTimerDuration = SK_TRUE; /* in other words: INCREASE */ |
| } |
| |
| /* |
| ** Now we can determine the change in percent |
| */ |
| if ((RatioDiffRel >= 0) && (RatioDiffRel <= 5) ) { |
| ModAdjValue = 1; /* 1% change - maybe some other value in future */ |
| } else if ((RatioDiffRel > 5) && (RatioDiffRel <= 10) ) { |
| ModAdjValue = 1; /* 1% change - maybe some other value in future */ |
| } else if ((RatioDiffRel > 10) && (RatioDiffRel <= 15) ) { |
| ModAdjValue = 1; /* 1% change - maybe some other value in future */ |
| } else { |
| ModAdjValue = 1; /* 1% change - maybe some other value in future */ |
| } |
| |
| if (IncreaseTimerDuration) { |
| NewMaxModIntsPerSec = M_DIMINFO.MaxModIntsPerSec + |
| (M_DIMINFO.MaxModIntsPerSec * ModAdjValue) / 100; |
| } else { |
| NewMaxModIntsPerSec = M_DIMINFO.MaxModIntsPerSec - |
| (M_DIMINFO.MaxModIntsPerSec * ModAdjValue) / 100; |
| } |
| |
| /* |
| ** Check if we exceed boundaries... |
| */ |
| if ( (NewMaxModIntsPerSec > M_DIMINFO.MaxModIntsPerSecUpperLimit) || |
| (NewMaxModIntsPerSec < M_DIMINFO.MaxModIntsPerSecLowerLimit)) { |
| if (M_DIMINFO.DisplayStats) { |
| printk("Cannot change ModTim from %i to %i ints/sec\n", |
| M_DIMINFO.MaxModIntsPerSec, NewMaxModIntsPerSec); |
| } |
| return; |
| } else { |
| if (M_DIMINFO.DisplayStats) { |
| printk("Resized ModTim from %i to %i ints/sec\n", |
| M_DIMINFO.MaxModIntsPerSec, NewMaxModIntsPerSec); |
| } |
| } |
| |
| M_DIMINFO.MaxModIntsPerSec = NewMaxModIntsPerSec; |
| |
| if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) { |
| ModBase = C_CLK_FREQ_GENESIS / pAC->DynIrqModInfo.MaxModIntsPerSec; |
| } else { |
| ModBase = C_CLK_FREQ_YUKON / pAC->DynIrqModInfo.MaxModIntsPerSec; |
| } |
| |
| /* |
| ** We do not need to touch any other registers |
| */ |
| SK_OUT32(pAC->IoBase, B2_IRQM_INI, ModBase); |
| } |
| |
| /******************************************************************************* |
| ** Function : DisplaySelectedModerationType() |
| ** Description : Displays what type of moderation we have |
| ** Programmer : Ralph Roesler |
| ** Last Modified: 23-mar-03 |
| ** Returns : void! |
| ** Notes : - |
| *******************************************************************************/ |
| |
| static void |
| DisplaySelectedModerationType(SK_AC *pAC) { |
| |
| if (pAC->DynIrqModInfo.DisplayStats) { |
| if (pAC->DynIrqModInfo.IntModTypeSelect == C_INT_MOD_STATIC) { |
| printk("Static int moderation runs with %i INTS/sec\n", |
| pAC->DynIrqModInfo.MaxModIntsPerSec); |
| } else if (pAC->DynIrqModInfo.IntModTypeSelect == C_INT_MOD_DYNAMIC) { |
| if (IsIntModEnabled(pAC)) { |
| printk("Dynamic int moderation runs with %i INTS/sec\n", |
| pAC->DynIrqModInfo.MaxModIntsPerSec); |
| } else { |
| printk("Dynamic int moderation currently not applied\n"); |
| } |
| } else { |
| printk("No interrupt moderation selected!\n"); |
| } |
| } |
| } |
| |
| /******************************************************************************* |
| ** Function : DisplaySelectedModerationMask() |
| ** Description : Displays what interrupts are moderated |
| ** Programmer : Ralph Roesler |
| ** Last Modified: 23-mar-03 |
| ** Returns : void! |
| ** Notes : - |
| *******************************************************************************/ |
| |
| static void |
| DisplaySelectedModerationMask(SK_AC *pAC) { |
| |
| if (pAC->DynIrqModInfo.DisplayStats) { |
| if (pAC->DynIrqModInfo.IntModTypeSelect != C_INT_MOD_NONE) { |
| switch (pAC->DynIrqModInfo.MaskIrqModeration) { |
| case IRQ_MASK_TX_ONLY: |
| printk("Only Tx-interrupts are moderated\n"); |
| break; |
| case IRQ_MASK_RX_ONLY: |
| printk("Only Rx-interrupts are moderated\n"); |
| break; |
| case IRQ_MASK_SP_ONLY: |
| printk("Only special-interrupts are moderated\n"); |
| break; |
| case IRQ_MASK_TX_RX: |
| printk("Tx- and Rx-interrupts are moderated\n"); |
| break; |
| case IRQ_MASK_SP_RX: |
| printk("Special- and Rx-interrupts are moderated\n"); |
| break; |
| case IRQ_MASK_SP_TX: |
| printk("Special- and Tx-interrupts are moderated\n"); |
| break; |
| case IRQ_MASK_RX_TX_SP: |
| printk("All Rx-, Tx and special-interrupts are moderated\n"); |
| break; |
| default: |
| printk("Don't know what is moderated\n"); |
| break; |
| } |
| } else { |
| printk("No specific interrupts masked for moderation\n"); |
| } |
| } |
| } |
| |
| /******************************************************************************* |
| ** Function : DisplayDescrRatio |
| ** Description : Like the name states... |
| ** Programmer : Ralph Roesler |
| ** Last Modified: 23-mar-03 |
| ** Returns : void! |
| ** Notes : - |
| *******************************************************************************/ |
| |
| static void |
| DisplayDescrRatio(SK_AC *pAC) { |
| int TotalMaxNbrDescr = 0; |
| |
| if (pAC->DynIrqModInfo.DisplayStats) { |
| TotalMaxNbrDescr = pAC->RxDescrPerRing * GetRxCalls(pAC); |
| printk("Ratio descriptors: %i/%i\n", |
| M_DIMINFO.NbrProcessedDescr, TotalMaxNbrDescr); |
| } |
| } |
| |
| /******************************************************************************* |
| ** |
| ** End of file |
| ** |
| *******************************************************************************/ |