aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base/sys.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/base/sys.c')
-rw-r--r--drivers/base/sys.c8
1 files changed, 7 insertions, 1 deletions
diff --git a/drivers/base/sys.c b/drivers/base/sys.c
index 9742a78c9fe4..79a9ae5238ac 100644
--- a/drivers/base/sys.c
+++ b/drivers/base/sys.c
@@ -131,6 +131,8 @@ static struct kset *system_kset;
131 131
132int sysdev_class_register(struct sysdev_class *cls) 132int sysdev_class_register(struct sysdev_class *cls)
133{ 133{
134 int retval;
135
134 pr_debug("Registering sysdev class '%s'\n", cls->name); 136 pr_debug("Registering sysdev class '%s'\n", cls->name);
135 137
136 INIT_LIST_HEAD(&cls->drivers); 138 INIT_LIST_HEAD(&cls->drivers);
@@ -138,7 +140,11 @@ int sysdev_class_register(struct sysdev_class *cls)
138 cls->kset.kobj.parent = &system_kset->kobj; 140 cls->kset.kobj.parent = &system_kset->kobj;
139 cls->kset.kobj.ktype = &ktype_sysdev_class; 141 cls->kset.kobj.ktype = &ktype_sysdev_class;
140 cls->kset.kobj.kset = system_kset; 142 cls->kset.kobj.kset = system_kset;
141 kobject_set_name(&cls->kset.kobj, cls->name); 143
144 retval = kobject_set_name(&cls->kset.kobj, "%s", cls->name);
145 if (retval)
146 return retval;
147
142 return kset_register(&cls->kset); 148 return kset_register(&cls->kset);
143} 149}
144 150
='#n356'>356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742





















































































































































































                                                                                     
                                                          






































































                                                                                
                                                                              
































































































































































































































































                                                                                      
                                                                              




































































































































































































































                                                                                
/******************************************************************************
 *
 * 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 useful
                */
                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 regarding 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);
}