[linux-audio-dev] [PATCH+DATAPOINT] LinuxPPC IRQ Latency

New Message Reply About this list Date view Thread view Subject view Author view Other groups

Subject: [linux-audio-dev] [PATCH+DATAPOINT] LinuxPPC IRQ Latency
From: Iain Sandoe (iain_AT_sandoe.co.uk)
Date: Wed Jul 05 2000 - 16:50:11 EEST


Hi List(s),

This is cross-posted to linuxppc-dev - apologies to any of you who sit on
both.

Here is a patch to install an option to profile the LinuxPPC kernel wrt IRQ
latency.

All the clever stuff is courtesy of Jun Sun see:
http://www.mvista.com/realtime/latency/ and...
http://www.mvista.com/realtime/rtsched_wp.html

All the mistakes are, undoubtedly, *mine* ;-)

It installs code to measure the amount of time for which interrupts are
blocked. An x86 version is also available via the links IIRC.

You will need "perfview.c" to start/stop & examine the profiling. I've
attached a (slightly) modified version of this - small changes in formatting
of output only.

The patch is against linuxcare rsync 2.2.17pre7 (two days ago).

====

I have tested the patch with/without the option and with/without modules on
a G3/300 (beige).

The worst I've seen is 6.3ms IRQ blocking during the transition between
single and init 5 (bmac.c - eth0 start-up). Probably not relevant to
general usage. The rest of the time IRQ latency <= 600 us - well that's two
midi bytes but not that dramtic.

What I've tried is a simple configuration:
G3 minitower - no extraneous options, no USB, SCSI Xpmac rev 9 (IIRC).
no particular structure to stressing the system - kernel compiles, pings,
xmms etc.

I will test G3 Lombard, G4 (when I get to grips with yaboot - the machine
only arrived yesterday) and I'm about to put a USB PCI card in the G3.

The patch is conservative about machines - it only appears for CONFIG_PMAC
or CONFIG_PPC_ALL.

I would expect that it will work for other machine types - and welcome
feedback on results with different configs.

happy testing,
Iain.

/***********************************************************************
 * <one line to give the program's name and an idea of what it does.>
 * Copyright (C) 2000 Monta Vista Software Inc.
 *
 * Author : Jun Sun, jsun@mvista.com
 *
 * 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.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 **********************************************************************/

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <assert.h>

/****************** CONFIG ****************/
#define NUM_LOG_ENTRY 8
#define CLOCK_FREQUENCY 300 /* cycles per microsecond */
#define SYSCALL_NUMBER 191

/****************** END OF CONFIG ***************/

#define CMD_EXIT 0
#define CMD_DISPLAY 1
#define CMD_START 2
#define CMD_STOP 3
#define CMD_CONTINUE 4
#define CMD_SET_RANGE 5
#define CMD_LAST 6

struct IntrData {
    /* count interrupt and iret */
    int breakCount;

    /* the test name */
    const char * testName;

    /* flag to control logging */
    unsigned logFlag; /* 0 - no logging; 1 - logging */

    /* panic flag - set to 1 if something is realy wrong */
    unsigned panicFlag;

    /* for synchro between start and end */
    unsigned syncFlag;

    /* we only log interrupts within certain range */
    unsigned rangeLow;
    unsigned rangeHigh;

    /* count the total number interrupts and intrs in range*/
    unsigned numIntrs;
    unsigned numInRangeIntrs;

    /* error accounting */
    unsigned skipSti;
    unsigned skipCli;
    unsigned syncStiError;
    unsigned syncCliError;
    unsigned stiBreakError;
    unsigned restoreSti;
    unsigned restoreCli;

    struct {
        /* worst blocking time */
        unsigned blockingTime;

        const char * startFileName;
        unsigned startFileLine;
        unsigned startCount;
        
        const char *endFileName;
        unsigned endFileLine;
        unsigned endCount;
    } count[NUM_LOG_ENTRY];
};

unsigned pData;
struct IntrData data;
int kmem;
char buf[81];

unsigned int GetInt(const char *prompt)
{
    unsigned int i;
    printf("%s", prompt);
    scanf("%d", &i);
    return i;
}

unsigned int GetHex(const char *prompt)
{
    unsigned int i;
    printf("%s", prompt);
    scanf("%x", &i);
    return i;
}

unsigned GetCommand()
{
    for(;;) {
        unsigned cmd;
        printf("\n");
        printf("Command Menu \n");
        printf("=============\n");
        printf("0-Exit 1-Display 2-Start logging 3-Stop logging 4-Continue ");
        printf("5-Set range\n");
        printf("\n");
        printf("Your choice : ");
        scanf("%u", &cmd);
        if ((cmd >= 0) && (cmd < CMD_LAST)) {
            return cmd;
        } else {
            printf("Invalid choice!!!!\n\n");
        }
    }
}

unsigned GetKmemInt(unsigned offset)
{
    off_t seekError;
    ssize_t size;
    unsigned num=0;

    assert((offset & 3) == 0);
            
    seekError = lseek(kmem, offset, SEEK_SET);
    assert(seekError != (off_t)-1);
    
    size = read(kmem, &num, sizeof(num));
    assert(sizeof(num) == 4);
    assert(size == 4);
    return num;
}

char * GetKmemString(unsigned offset)
{
    off_t seekError;
    ssize_t size;

    buf[80]=0;
    buf[0]=0;

    if (offset == 0) return buf;

    seekError = lseek(kmem, offset, SEEK_SET);
    assert(seekError != (off_t)-1);
    
    size = read(kmem, buf, 80);
    assert(size == 80);
    return buf;
}

void GetKmemBlock(unsigned offset, void * buf, unsigned bufSize)
{
    off_t seekError;
    ssize_t size;

    seekError = lseek(kmem, offset, SEEK_SET);
    assert(seekError != (off_t)-1);
    
    size = read(kmem, buf, bufSize);
    assert(size == bufSize);
}

void SetKmemBlock(unsigned offset, void *buf, unsigned bufSize)
{
    off_t seekError;
    ssize_t size;

    seekError = lseek(kmem, offset, SEEK_SET);
    assert(seekError != (off_t)-1);
    
    size = write(kmem, buf, bufSize);
    assert(size == bufSize);
}

void SetKmemInt(unsigned offset, unsigned x)
{
    off_t seekError;
    ssize_t size;

    seekError = lseek(kmem, offset, SEEK_SET);
    assert(seekError != (off_t)-1);
    
    size = write(kmem, &x, sizeof(x));
    assert(size == sizeof(x));
}

void Display()
{
    unsigned i;

    GetKmemBlock(pData, &data, sizeof(data));
    printf("%s : \n", GetKmemString((unsigned)data.testName));
    printf("breakCount : %7d\n", data.breakCount);
    printf("logFlag : %d ", data.logFlag);
    printf("panicFlag : %d ", data.panicFlag);
    printf("syncFlag : %d\n", data.syncFlag);

    printf("range : [%u(0x%x) : %u(0x%x)]\n",
           data.rangeLow, data.rangeLow,
           data.rangeHigh, data.rangeHigh);

    printf("numIntrs : %u\n", data.numIntrs);
    printf("numInRangeInts: %u\n", data.numInRangeIntrs);

    printf("skipSti skipCli syncSti syncCli stiBreak restSti restCli\n");
    printf("%d\t%d\t%d\t%d\t%d\t%d\t%d\t\n",
           data.skipSti,
           data.skipCli,
           data.syncStiError,
           data.syncCliError,
           data.stiBreakError,
           data.restoreSti,
           data.restoreCli);

    for (i=0; i< NUM_LOG_ENTRY; i++) {
        printf("log entry : %d\n", i);
        printf("\tblockingTime : %u (%u us)\n",
                data.count[i].blockingTime,
                data.count[i].blockingTime / CLOCK_FREQUENCY);
        printf("\tstartFileName : %-30s Line :",
               GetKmemString((unsigned)data.count[i].startFileName));
        printf(" %-5u\n", data.count[i].startFileLine);
 /* printf("\tstartCount : %u\n", data.count[i].startCount);*/
        printf("\tendFileName : %-30s Line :",
               GetKmemString((unsigned)data.count[i].endFileName));
        printf(" %-5u\n", data.count[i].endFileLine);
 /* printf("\tendCount : %u\n", data.count[i].endCount);*/
    }
    printf("\n");
}

void StartLogging()
{
    unsigned i;

    /* init first */
    data.breakCount = 0;
    data.logFlag = 0;
    data.panicFlag = 0;
    data.syncFlag = 0;

    data.numIntrs = 0;
    data.numInRangeIntrs = 0;

    data.skipSti =
        data.skipCli =
        data.syncStiError =
        data.syncCliError =
        data.stiBreakError =
        data.restoreSti =
        data.restoreCli = 0;

    for (i=0; i< NUM_LOG_ENTRY; i++) {
        data.count[i].blockingTime = 0;
        data.count[i].startFileName = 0;
        data.count[i].startFileLine = 0;
        data.count[i].startCount = 0;
        data.count[i].endFileName = 0;
        data.count[i].endFileLine = 0;
        data.count[i].endCount = 0;
    }

    SetKmemBlock(pData, &data, sizeof(data));

    /* turn the logging flag */
    SetKmemInt(pData + ((unsigned)&data.logFlag - (unsigned)&data), 1);
}

void EndLogging()
{
    /* turn the logging flag */
    SetKmemInt(pData + ((unsigned)&data.logFlag - (unsigned)&data), 0);
}

void ContinueLoggin()
{
    /* turn the logging flag */
    SetKmemInt(pData + ((unsigned)&data.logFlag - (unsigned)&data), 1);
}

void SetRange()
{
    data.rangeLow = GetInt("Input lower bound (decimal) : ");
    printf("\tlower bound is %u(0x%x)\n", data.rangeLow, data.rangeLow);

    data.rangeHigh = GetInt("Input upper bound (decimal) : ");
    printf("\tupper bound is %u(0x%x)\n", data.rangeHigh, data.rangeHigh);
    
    SetKmemInt(pData + ((unsigned)&data.rangeLow - (unsigned)&data),
               data.rangeLow);
    SetKmemInt(pData + ((unsigned)&data.rangeHigh - (unsigned)&data),
               data.rangeHigh);
}

main()
{
    unsigned int cmd;
    unsigned long offset;

    kmem = open("/dev/kmem", O_RDWR);
    assert(kmem > 0);

    if (syscall(SYSCALL_NUMBER, &pData) != 0) {
        printf("failed to get jsunData address through syscall 191!\n");
        pData = GetHex("Input manually the address of jsunData : ");
    }

    GetKmemBlock(pData, &data, sizeof(data));

    for(;;) {
        cmd = GetCommand();

        switch (cmd) {
         case CMD_DISPLAY:
            Display();
            break;

         case CMD_START:
            StartLogging();
            break;

         case CMD_STOP:
            EndLogging();
            break;

         case CMD_CONTINUE:
            ContinueLoggin();
            break;

         case CMD_SET_RANGE:
            SetRange();
            break;

         case CMD_EXIT:
            close(kmem);
            return;

         default:
            assert(0 == 1);
        }
    }
}

        

diff -urbBwP linux-pmac-stable/Documentation/Configure.help stable-intlat/Documentation/Configure.help
--- linux-pmac-stable/Documentation/Configure.help Sun Jun 25 23:57:39 2000
+++ stable-intlat/Documentation/Configure.help Wed Jul 5 13:26:55 2000
@@ -12372,6 +12372,11 @@
   This will use DMA if possible to reduce CPU usage. If in doubt,
   say Y here.
    
+Interupt Latency Measurement
+CONFIG_IRQ_LATENCY
+ This will install Jun Sun's IRQ latency measurement code into the kernel and
+ modules. Not many people are likely to use it... If in doubt answer N.
+
 #
 # A couple of things I keep forgetting:
 # capitalize: AppleTalk, Ethernet, DOS, DMA, FAT, FTP, Internet,
diff -urbBwP linux-pmac-stable/Makefile stable-intlat/Makefile
--- linux-pmac-stable/Makefile Sun Jun 25 23:51:14 2000
+++ stable-intlat/Makefile Wed Jul 5 13:02:01 2000
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 2
 SUBLEVEL = 17
-EXTRAVERSION = pre7
+EXTRAVERSION = p7int
 
 ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/)
 
Only in linux-pmac-stable/arch/ppc/boot: ramdisk.image.gz
Only in linux-pmac-stable/arch/ppc/chrpboot: ramdisk.image.gz
diff -urbBwP linux-pmac-stable/arch/ppc/config.in stable-intlat/arch/ppc/config.in
--- linux-pmac-stable/arch/ppc/config.in Fri Jun 9 12:54:50 2000
+++ stable-intlat/arch/ppc/config.in Wed Jul 5 13:02:27 2000
@@ -63,6 +63,9 @@
 bool 'Backward-compatible /proc/pci' CONFIG_PCI_OLD_PROC
 bool 'Networking support' CONFIG_NET
 bool 'Sysctl support' CONFIG_SYSCTL
+if [ "$CONFIG_PMAC" = "y" -o "$CONFIG_ALL_PPC" = "y" ]; then
+bool 'IRQ Latency Profiling' CONFIG_IRQ_LATENCY
+fi
 bool 'System V IPC' CONFIG_SYSVIPC
 bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT
 
diff -urbBwP linux-pmac-stable/arch/ppc/kernel/Makefile stable-intlat/arch/ppc/kernel/Makefile
--- linux-pmac-stable/arch/ppc/kernel/Makefile Sat Jun 17 01:12:30 2000
+++ stable-intlat/arch/ppc/kernel/Makefile Wed Jul 5 13:19:27 2000
@@ -16,11 +16,16 @@
 #endif
 
 O_TARGET := kernel.o
-OX_OBJS := ppc_ksyms.o setup.o
 
+OX_OBJS := ppc_ksyms.o setup.o
 
 O_OBJS := traps.o irq.o idle.o time.o process.o signal.o syscalls.o misc.o \
           bitops.o ptrace.o align.o ppc_htab.o
+
+ifeq ($(CONFIG_IRQ_LATENCY),y)
+O_OBJS += intr_blocking.o
+endif
+
 ifdef CONFIG_PCI
 O_OBJS += pci.o
 endif
diff -urbBwP linux-pmac-stable/arch/ppc/kernel/head.S stable-intlat/arch/ppc/kernel/head.S
--- linux-pmac-stable/arch/ppc/kernel/head.S Sat May 27 21:41:39 2000
+++ stable-intlat/arch/ppc/kernel/head.S Tue Jul 4 19:50:23 2000
@@ -312,7 +312,7 @@
         mtspr IBAT2L,r18
         mtspr IBAT2U,r21
 #endif /* ndef CONFIG_GEMINI */
-#endif
+#endif /* CONFIG_APUS */
         mtspr DBAT0L,r8 /* N.B. 6xx (not 601) have valid */
         mtspr DBAT0U,r11 /* bit in upper BAT register */
         mtspr IBAT0L,r8
diff -urbBwP linux-pmac-stable/arch/ppc/kernel/intr_blocking.c stable-intlat/arch/ppc/kernel/intr_blocking.c
--- linux-pmac-stable/arch/ppc/kernel/intr_blocking.c Thu Jan 1 01:00:00 1970
+++ stable-intlat/arch/ppc/kernel/intr_blocking.c Tue Jul 4 09:16:57 2000
@@ -0,0 +1,328 @@
+#include <asm/system.h>
+
+
+/**** platform ****/
+#define readclock(low) \
+ __asm__ __volatile__ ("mftb %0" : "=r" (low) :)
+
+#define __intr_save_flags(x) __save_flags(x)
+
+/**** configure ****/
+#define NUM_LOG_ENTRY 8
+#define INTR_IENABLE MSR_EE
+
+/**** data structure ****/
+struct IntrData {
+ /* count interrupt and iret */
+ int breakCount;
+
+ /* the test name */
+ const char * testName;
+
+ /* flag to control logging */
+ unsigned logFlag; /* 0 - no logging; 1 - logging */
+
+ /* panic flag - set to 1 if something is realy wrong */
+ unsigned panicFlag;
+
+ /* for synchro between start and end */
+ unsigned syncFlag;
+
+ /* we only log interrupts within certain range */
+ unsigned rangeLow;
+ unsigned rangeHigh;
+
+ /* count the total number interrupts and intrs in range*/
+ unsigned numIntrs;
+ unsigned numInRangeIntrs;
+
+
+ /* error accounting */
+ unsigned skipSti;
+ unsigned skipCli;
+ unsigned syncStiError;
+ unsigned syncCliError;
+ unsigned stiBreakError;
+ unsigned restoreSti;
+ unsigned restoreCli;
+
+ struct {
+ /* worst blocking time */
+ unsigned blockingTime;
+
+ const char * startFileName;
+ unsigned startFileLine;
+ unsigned startCount;
+
+ const char *endFileName;
+ unsigned endFileLine;
+ unsigned endCount;
+ } count[NUM_LOG_ENTRY];
+};
+
+struct IntrData intrData = {
+ 0,
+ "interrupt latency test for PPC (8 distinctive entries)",
+ 0,
+ 0,
+ 0,
+
+ 1,
+ 0xffffffff,
+
+ 0,
+ 0,
+
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+};
+
+
+/**** functions ****/
+#if 0
+void intr_check_int(int x)
+{
+
+ unsigned flag;
+ __intr_save_flags(flag);
+
+ if ((flag & INTR_IENABLE) != 0) {
+ switch(x) {
+ case 0 :
+ intrData.count[0].blockingTime ++;
+ break;
+ case 1 :
+ intrData.count[0].startFileLine ++;
+ break;
+ case 2 :
+ intrData.count[0].startCount ++;
+ break;
+ case 3 :
+ intrData.count[0].endFileLine ++;
+ break;
+ case 4 :
+ intrData.count[0].endCount ++;
+ break;
+ default :
+ intrData.count[0].startFileName = "Wrong check number";
+ break;
+ }
+ } else {
+ switch(x) {
+ case 0 :
+ intrData.count[1].blockingTime ++;
+ break;
+ case 1 :
+ intrData.count[1].startFileLine ++;
+ break;
+ case 2 :
+ intrData.count[1].startCount ++;
+ break;
+ case 3 :
+ intrData.count[1].endFileLine ++;
+ break;
+ case 4 :
+ intrData.count[1].endCount ++;
+ break;
+ default :
+ intrData.count[1].startFileName = "Wrong check number";
+ break;
+ }
+ }
+}
+
+#endif
+
+
+static inline void intr_SetPanic(unsigned x, const char *fname, unsigned l)
+{
+ if (intrData.panicFlag != 0) {
+ /* double error; impossible */
+ intrData.panicFlag = 99;
+ return;
+ }
+ intrData.panicFlag = x;
+ intrData.count[0].startFileName = fname;
+ intrData.count[0].startFileLine = l;
+}
+
+static const char *intrStartFileName;
+static unsigned intrStartFileLine;
+static unsigned intrStartCount;
+
+/* strategy :
+ * if it is true "cli", i.e., clearing the IF, we remember
+ * everything, and clear breakCount.
+ */
+int intr_cli(const char *fname, unsigned lineno)
+{
+ unsigned flag;
+ int retValue;
+
+ __intr_save_flags(flag);
+
+ retValue = __intr_cli();
+
+ /* if we are not logging or we have an error, do nothing */
+ if ((intrData.logFlag == 0) || ( intrData.panicFlag != 0)) {
+ return retValue;
+ }
+
+ /* do nothing we had IF cleared before we call this function */
+ if ((flag & INTR_IENABLE) == 0) {
+ intrData.skipCli ++;
+ return retValue;
+ }
+
+ /* debug */
+ if (intrData.syncFlag == 1) {
+ intrData.syncCliError ++;
+ }
+ intrData.syncFlag = 1;
+
+ intrData.breakCount = 0;
+
+ /* Read the Time Stamp Counter */
+ intrStartFileName = fname;
+ intrStartFileLine = lineno;
+ readclock(intrStartCount);
+
+ return retValue;
+}
+
+
+/* strategy:
+ * we do a count only if
+ * 1. syncFlag is 1 (a valid cli() was called)
+ * 2. breakCount is 0 (no iret is called between cli() and this sti()
+ */
+void intr_sti(const char *fname, unsigned lineno)
+{
+ unsigned flag;
+ unsigned endCount;
+ unsigned diff;
+ int i;
+
+ __intr_save_flags(flag);
+
+ /* if we are not logging or we have an error, do nothing */
+ if ((intrData.logFlag == 0) || ( intrData.panicFlag != 0)) {
+ __intr_sti();
+ return;
+ }
+
+
+ /* check if this is a real sti() */
+ if ((flag & INTR_IENABLE) != 0) {
+ intrData.skipSti ++;
+ __intr_sti();
+ return;
+ }
+
+ /* check 1*/
+ if (intrData.syncFlag != 1) {
+ intrData.syncStiError ++;
+ __intr_sti();
+ return;
+ }
+
+ /* check 2 */
+ if (intrData.breakCount != 0) {
+ intrData.stiBreakError ++;
+ __intr_sti();
+ return;
+ }
+
+ /* read count again */
+ readclock(endCount);
+
+ intrData.syncFlag = 0;
+
+ diff = endCount - intrStartCount;
+
+ if ((diff >= intrData.rangeLow) && (diff <= intrData.rangeHigh)) {
+ unsigned lowest=0xffffffff;
+ unsigned lowestIndex;
+ unsigned sameIndex = 0xffffffff;
+
+ intrData.numInRangeIntrs++;
+
+ /* check if we need to log this event */
+ for (i=0; i< NUM_LOG_ENTRY; i++) {
+
+ if (lowest > intrData.count[i].blockingTime) {
+ lowest = intrData.count[i].blockingTime;
+ lowestIndex = i;
+ }
+
+ if ( (lineno == intrData.count[i].endFileLine) &&
+ (intrStartFileLine == intrData.count[i].startFileLine) &&
+ (fname[0] == intrData.count[i].endFileName[0]) &&
+ (intrStartFileName[0] == intrData.count[i].startFileName[0]) ) {
+ /* if the line numbers are same, the first chars in
+ * both file names are same, we consider it is the same
+ * entry. */
+ sameIndex = i;
+ }
+ }
+
+ if (sameIndex == 0xffffffff) {
+ i = lowestIndex;
+ } else {
+ i = sameIndex;
+ }
+
+ if (diff > intrData.count[i].blockingTime) {
+ intrData.count[i].blockingTime = diff;
+ intrData.count[i].endFileName = fname;
+ intrData.count[i].endFileLine = lineno;
+ intrData.count[i].endCount = endCount;
+ intrData.count[i].startFileName = intrStartFileName;
+ intrData.count[i].startFileLine = intrStartFileLine;
+ intrData.count[i].startCount = intrStartCount;
+ }
+ }
+
+ intrData.numIntrs++;
+ __intr_sti();
+}
+
+
+void intr_restore_flags(const char *fname, unsigned lineno, unsigned x)
+{
+ unsigned flag;
+
+ /* if we are not logging or we have an error, do nothing */
+ if ((intrData.logFlag == 0) || ( intrData.panicFlag != 0)) {
+ __intr_restore_flags(x);
+ return;
+ }
+
+ __intr_save_flags(flag);
+
+ if (((flag & INTR_IENABLE) == 0) &&
+ ((x & INTR_IENABLE) != 0) ) {
+ intrData.restoreSti ++;
+ intr_sti(fname, lineno);
+ }
+
+ if ( ((flag & INTR_IENABLE) != 0) &&
+ ((x & INTR_IENABLE) == 0) ) {
+ intrData.restoreCli ++;
+ intr_cli(fname, lineno);
+ }
+
+ __intr_restore_flags(x);
+}
+
+#include <asm/uaccess.h>
+
+asmlinkage int sys_get_intrData(void ** ptr)
+{
+ return put_user(&intrData, ptr);
+}
diff -urbBwP linux-pmac-stable/arch/ppc/kernel/misc.S stable-intlat/arch/ppc/kernel/misc.S
--- linux-pmac-stable/arch/ppc/kernel/misc.S Tue Mar 28 05:08:46 2000
+++ stable-intlat/arch/ppc/kernel/misc.S Tue Jul 4 20:03:19 2000
@@ -52,9 +52,15 @@
  * Disable interrupts
  * rc = _disable_interrupts()
  */
+#ifdef CONFIG_IRQ_LATENCY
+_GLOBAL(_intr_disable_interrupts)
+_GLOBAL(__intr_cli)
+_GLOBAL(_intr_hard_cli)
+#else
 _GLOBAL(_disable_interrupts)
 _GLOBAL(__cli)
 _GLOBAL(_hard_cli)
+#endif
         mfmsr r0 /* Get current interrupt state */
         rlwinm r3,r0,16+1,32-1,31 /* Extract old value of 'EE' */
         li r4,0 /* Need [unsigned] value of MSR_EE */
@@ -72,8 +78,13 @@
 _GLOBAL(_enable_interrupts)
         cmpi 0,r3,0 /* turning them on? */
         beqlr /* nothing to do if state == 0 */
+#ifdef CONFIG_IRQ_LATENCY
+_GLOBAL(__intr_sti)
+_GLOBAL(_intr_hard_sti)
+#else
 _GLOBAL(__sti)
 _GLOBAL(_hard_sti)
+#endif
         lis r4,ppc_n_lost_interrupts@ha
         lwz r4,ppc_n_lost_interrupts@l(r4)
         mfmsr r3 /* Get current state */
@@ -493,7 +504,6 @@
         mtspr ICTC,r3
         blr
 
-
 /*
         L2CR functions
         Copyright © 1997-1998 by PowerLogix R & D, Inc.
@@ -961,4 +971,8 @@
         .long sys_ni_syscall /* streams1 */
         .long sys_ni_syscall /* streams2 */
         .long sys_vfork
+#ifdef CONFIG_IRQ_LATENCY
+ .long sys_get_intrData /* 190 */
+ .long sys_get_intrData /* 191 */
+#endif
         .space (NR_syscalls-183)*4
diff -urbBwP linux-pmac-stable/arch/ppc/kernel/ppc_ksyms.c stable-intlat/arch/ppc/kernel/ppc_ksyms.c
--- linux-pmac-stable/arch/ppc/kernel/ppc_ksyms.c Sat Jun 24 03:06:00 2000
+++ stable-intlat/arch/ppc/kernel/ppc_ksyms.c Tue Jul 4 22:53:51 2000
@@ -160,11 +160,19 @@
 EXPORT_SYMBOL(kernel_thread);
 EXPORT_SYMBOL(init_mm);
 
+#ifdef CONFIG_IRQ_LATENCY
+EXPORT_SYMBOL(intr_cli);
+EXPORT_SYMBOL(intr_restore_flags);
+EXPORT_SYMBOL(intr_sti) ;
+#else
 EXPORT_SYMBOL(__cli);
 EXPORT_SYMBOL(__sti);
+#endif
 /*EXPORT_SYMBOL(__restore_flags);*/
+#ifndef CONFIG_IRQ_LATENCY
 EXPORT_SYMBOL(_disable_interrupts);
 EXPORT_SYMBOL(_enable_interrupts);
+#endif
 EXPORT_SYMBOL(flush_instruction_cache);
 EXPORT_SYMBOL(_get_PVR);
 EXPORT_SYMBOL(giveup_fpu);
diff -urbBwP linux-pmac-stable/include/asm-ppc/system.h stable-intlat/include/asm-ppc/system.h
--- linux-pmac-stable/include/asm-ppc/system.h Sat Jun 24 02:49:58 2000
+++ stable-intlat/include/asm-ppc/system.h Wed Jul 5 13:45:14 2000
@@ -39,7 +39,11 @@
         asm("dcbf %0,%1; sync" : : "r" (line), "r" (0));
 }
 
+#ifdef CONFIG_IRQ_LATENCY
+extern __inline__ void __intr_restore_flags(unsigned long flags)
+#else
 extern __inline__ void __restore_flags(unsigned long flags)
+#endif
 {
         extern atomic_t ppc_n_lost_interrupts;
         extern void do_lost_interrupts(unsigned long);
@@ -52,11 +56,30 @@
         }
 }
 
-
+#ifdef CONFIG_IRQ_LATENCY
+/* jsun's IRQ latency measurement stuff */
+extern void __intr_sti(void);
+extern int __intr_cli(void);
+#else
 extern void __sti(void);
 extern void __cli(void);
+#endif
+
+#ifdef CONFIG_IRQ_LATENCY
+extern int intr_cli(const char*, unsigned);
+extern void intr_sti(const char *, unsigned);
+extern void intr_restore_flags(const char *, unsigned, unsigned);
+#define __cli() intr_cli(__FILE__, __LINE__)
+#define __sti() intr_sti(__FILE__, __LINE__)
+#define __restore_flags(x) intr_restore_flags(__FILE__, __LINE__, x)
+#define _disable_interrupts() __cli()
+#define _enable_interrupts(x) { if (x != 0) __sti(); }
+#else
+extern void _sti(void);
+extern void _cli(void);
 extern int _disable_interrupts(void);
 extern void _enable_interrupts(int);
+#endif
 
 extern void print_backtrace(unsigned long *);
 extern void show_regs(struct pt_regs * regs);


New Message Reply About this list Date view Thread view Subject view Author view Other groups

This archive was generated by hypermail 2b28 : Wed Jul 05 2000 - 17:26:59 EEST