📄 skdim.c
字号:
/****************************************************************************** * * Name: skdim.c * Project: GEnesis, PCI Gigabit Ethernet Adapter * Version: $Revision: 1.1 $ * Date: $Date: 2003/03/21 14:51:50 $ * Purpose: All functions to maintain interrupt moderation * ******************************************************************************//****************************************************************************** * * (C)Copyright 1998-2002 SysKonnect GmbH. * * 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. * ******************************************************************************//****************************************************************************** * * History: * * ******************************************************************************//****************************************************************************** * * 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 lintstatic const char SysKonnectFileId[] = "@(#) $Id: skdim.c,v 1.1 2003/03/21 14:51:50 rroesler Exp $ (C) SysKonnect.";#endif /* !defined(lint) */#define __SKADDR_C#ifdef __cplusplus#error C++ is not yet supported.extern "C" {#endif /* cplusplus *//*********************************************************************************** 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******************************************************************************/voidSkDimEnableModerationIfNeeded(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 intGetCurrentSystemLoad(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; int NbrCpu = 0; for (NbrCpu = 0; NbrCpu < smp_num_cpus; NbrCpu++) { UserTime = UserTime + kstat.per_cpu_user[NbrCpu]; NiceTime = NiceTime + kstat.per_cpu_nice[NbrCpu]; SystemTime = SystemTime + kstat.per_cpu_system[NbrCpu]; } UsedTime = UserTime + NiceTime + SystemTime; IdleTime = jif * smp_num_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_U64GetIsrCalls(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) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -