📄 skdim.c
字号:
/****************************************************************************** * * 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 lintstatic 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******************************************************************************/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; /* 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*******************************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -