On Fri, 20 Aug 1999, Maryam Moghaddas wrote:

> So the same as above I replaced the interrupt request function, but
> there are some issues still vague for me.
> My impression from the email above is that I should avoid using skb
> buffers in the RTLinux  interupt handler/receive/transmit  path and
> inanother words discard and change them all in the code. Is this
> correct?

You can use skb buffers, if they are pre-allocated. The memory allocation
routine is not real time. So you should decide what is more convinient for
you - preallocate e.g. 10 skbs of max size (1500B) in init_module, or use
your own buffering scheme. Another idea I just got is to keep a set of free
skbs, but not static - every time you use one skb in RT code or pass it to
the kernel, you allocate new one in the bottom half interrupt handler. 

By the way - my last advice about triggering Linux interrupts from RT tasks
was untested - now I see the problems, fortunately easy to overcome.

>    Tomasz Motylewski had suggested trying :
>    SFREQ |= MASK(WAVELAN_IRQ); /* analog of "mark_bh" */
>    This didn't seem to work though.

First, SFREQ variable should be exported from the kernel in kernel/ksyms.c
like SFIF. Then, the operation to trigger interrupt is simply
SFREQ |= 1 << irq;

Since I did not like to use precious interrupts from range 0-15, I have
patched the RT v1.2 kernel (2.0.38pre1, will work with 2.0.37 and 36) to
allow registration of interrupt in 16-31 range.

It is quite cool to have:

 cat /proc/interrupts 
 0:    1618292   timer
 1:       1655   keyboard
 2:          0   cascade
 4:       6963 + serial
 8:          1 + rtc
10:     172271   3c509
13:          1   math error
14:     243234 + ide0
15:          4 + ide1
20:         44   rt-test

The code is simply:

void test_soft_irq(int irq, void *id, struct pt_regs *regs) {
        printk("test_soft_irq called at %d\n", rt_get_rdtsc());
}

[...]
int init_module() {
[...]
rt_task_make_periodic(&rt_trigger,now+1000,300000);
[...]
request_irq(testirq,&test_soft_irq,0,"rt-test",shd);//shd is my shared mem ptr
return 0;
}

and in rt_trigger() I do:

MARK_IRQ(testirq);

(full code in http://crds.chemie.unibas.ch/PCI-MIO-E/pcontrol-0.4.0.tar.gz)

I would like to ask the RT Linux maintainers to include this or equivalent
patch in v1.3 (if ever released). My approach probably contains too much code
and could be done better with understanding of all the assembler in IRQ
setup. It does not need to be 16 additional interrupts, but at least one
(some pointer array can then be used to distribute the calls). At the very
least I would suggest to export SFREQ to allow triggering of standard 0-15
interrupts from RT tasks and RT interrupt handlers.

BTW. The examples in v1.2 still contain insmod without ".o". The
http://www.rtlinux.org/~rtlinux/body.shtml in the V1.2  Download section
still has a link to ftp://rtlinux.org/pub/rtlinux/v1/rtlinux1.1.tgz 

Patch (tested) follows,
--
Tomasz Motylewski


diff -Nur linux-2.0.38-pl-pre1-sec-rtl12incl/arch/i386/kernel/irq.c 
linux/arch/i386/kernel/irq.c
--- linux-2.0.38-pl-pre1-sec-rtl12incl/arch/i386/kernel/irq.c   Tue Aug 17 10:34:40 
1999
+++ linux/arch/i386/kernel/irq.c        Sun Aug 22 01:54:56 1999
@@ -178,25 +178,53 @@
 #endif
 BUILD_IRQ(SECOND,14,0x40)
 BUILD_IRQ(SECOND,15,0x80)
+#ifdef __RT__
+BUILD_IRQ(NONE,16,0)
+BUILD_IRQ(NONE,17,0)
+BUILD_IRQ(NONE,18,0)
+BUILD_IRQ(NONE,19,0)
+BUILD_IRQ(NONE,20,0)
+BUILD_IRQ(NONE,21,0)
+BUILD_IRQ(NONE,22,0)
+BUILD_IRQ(NONE,23,0)
+BUILD_IRQ(NONE,24,0)
+BUILD_IRQ(NONE,25,0)
+BUILD_IRQ(NONE,26,0)
+BUILD_IRQ(NONE,27,0)
+BUILD_IRQ(NONE,28,0)
+BUILD_IRQ(NONE,29,0)
+BUILD_IRQ(NONE,30,0)
+BUILD_IRQ(NONE,31,0)
+#ifdef __SMP__
+#error SMP can not be used together with Real Time Linux in 2.0 kernel
+#endif
+#else
 #ifdef __SMP__
 BUILD_RESCHEDIRQ(16)
 #endif
+#endif
 
 /*
  * Pointers to the low-level handlers: first the general ones, then the
  * fast ones, then the bad ones.
  */
-static void (*interrupt[17])(void) = {
+static void (*interrupt[NR_IRQS+1])(void) = {
        IRQ0_interrupt, IRQ1_interrupt, IRQ2_interrupt, IRQ3_interrupt,
        IRQ4_interrupt, IRQ5_interrupt, IRQ6_interrupt, IRQ7_interrupt,
        IRQ8_interrupt, IRQ9_interrupt, IRQ10_interrupt, IRQ11_interrupt,
        IRQ12_interrupt, IRQ13_interrupt, IRQ14_interrupt, IRQ15_interrupt      
+#ifdef __RT__
+       ,IRQ16_interrupt, IRQ17_interrupt, IRQ18_interrupt, IRQ19_interrupt,
+       IRQ20_interrupt, IRQ21_interrupt, IRQ22_interrupt, IRQ23_interrupt,
+       IRQ24_interrupt, IRQ25_interrupt, IRQ26_interrupt, IRQ27_interrupt,
+       IRQ28_interrupt, IRQ29_interrupt, IRQ30_interrupt, IRQ31_interrupt      
+#endif
 #ifdef __SMP__ 
        ,IRQ16_interrupt
 #endif
 };
 
-static void (*fast_interrupt[16])(void) = {
+static void (*fast_interrupt[NR_IRQS])(void) = {
        fast_IRQ0_interrupt, fast_IRQ1_interrupt,
        fast_IRQ2_interrupt, fast_IRQ3_interrupt,
        fast_IRQ4_interrupt, fast_IRQ5_interrupt,
@@ -205,9 +233,19 @@
        fast_IRQ10_interrupt, fast_IRQ11_interrupt,
        fast_IRQ12_interrupt, fast_IRQ13_interrupt,
        fast_IRQ14_interrupt, fast_IRQ15_interrupt
+#ifdef __RT__
+       ,fast_IRQ16_interrupt, fast_IRQ17_interrupt,
+       fast_IRQ18_interrupt, fast_IRQ19_interrupt,
+       fast_IRQ20_interrupt, fast_IRQ21_interrupt,
+       fast_IRQ22_interrupt, fast_IRQ23_interrupt,
+       fast_IRQ24_interrupt, fast_IRQ25_interrupt,
+       fast_IRQ26_interrupt, fast_IRQ27_interrupt,
+       fast_IRQ28_interrupt, fast_IRQ29_interrupt,
+       fast_IRQ30_interrupt, fast_IRQ31_interrupt
+#endif
 };
 
-static void (*bad_interrupt[16])(void) = {
+static void (*bad_interrupt[NR_IRQS])(void) = {
        bad_IRQ0_interrupt, bad_IRQ1_interrupt,
        bad_IRQ2_interrupt, bad_IRQ3_interrupt,
        bad_IRQ4_interrupt, bad_IRQ5_interrupt,
@@ -216,11 +254,21 @@
        bad_IRQ10_interrupt, bad_IRQ11_interrupt,
        bad_IRQ12_interrupt, bad_IRQ13_interrupt,
        bad_IRQ14_interrupt, bad_IRQ15_interrupt
+#ifdef __RT__
+       ,bad_IRQ16_interrupt, bad_IRQ17_interrupt,
+       bad_IRQ18_interrupt, bad_IRQ19_interrupt,
+       bad_IRQ20_interrupt, bad_IRQ21_interrupt,
+       bad_IRQ22_interrupt, bad_IRQ23_interrupt,
+       bad_IRQ24_interrupt, bad_IRQ25_interrupt,
+       bad_IRQ26_interrupt, bad_IRQ27_interrupt,
+       bad_IRQ28_interrupt, bad_IRQ29_interrupt,
+       bad_IRQ30_interrupt, bad_IRQ31_interrupt
+#endif
 };
 
 
 #ifdef __RT__
-static void (*linux_interrupt[16])(void) = {
+static void (*linux_interrupt[NR_IRQS])(void) = {
        linux_IRQ0_interrupt, linux_IRQ1_interrupt,
        linux_IRQ2_interrupt, linux_IRQ3_interrupt,
        linux_IRQ4_interrupt, linux_IRQ5_interrupt,
@@ -229,6 +277,16 @@
        linux_IRQ10_interrupt, linux_IRQ11_interrupt,
        linux_IRQ12_interrupt, linux_IRQ13_interrupt,
        linux_IRQ14_interrupt, linux_IRQ15_interrupt
+#ifdef __RT__
+       ,linux_IRQ16_interrupt, linux_IRQ17_interrupt,
+       linux_IRQ18_interrupt, linux_IRQ19_interrupt,
+       linux_IRQ20_interrupt, linux_IRQ21_interrupt,
+       linux_IRQ22_interrupt, linux_IRQ23_interrupt,
+       linux_IRQ24_interrupt, linux_IRQ25_interrupt,
+       linux_IRQ26_interrupt, linux_IRQ27_interrupt,
+       linux_IRQ28_interrupt, linux_IRQ29_interrupt,
+       linux_IRQ30_interrupt, linux_IRQ31_interrupt
+#endif
 };
 
 static void (*rt_interrupt[16])(void) = {
@@ -249,7 +307,7 @@
 }
 
 /* software IDT */
-void (*SFIDT[16])(void);
+void (*SFIDT[NR_IRQS])(void);
 
 static int rt_irq_status[16];
 
@@ -370,7 +428,7 @@
  */
 static struct irqaction irq2  = { no_action, 0, 0, "cascade", NULL, NULL};
 
-static struct irqaction *irq_action[16] = {
+static struct irqaction *irq_action[NR_IRQS] = {
        NULL, NULL, NULL, NULL,
        NULL, NULL, NULL, NULL,
        NULL, NULL, NULL, NULL,
@@ -382,7 +440,7 @@
        int i, len = 0;
        struct irqaction * action;
 
-       for (i = 0 ; i < 16 ; i++) {
+       for (i = 0 ; i < NR_IRQS ; i++) {
                action = irq_action[i];
                if (!action) 
                        continue;
@@ -624,7 +682,7 @@
        int retval;
        struct irqaction * action;
 
-       if (irq > 15)
+       if (irq > NR_IRQS-1)
                return -EINVAL;
        if (!handler)
                return -EINVAL;
@@ -652,7 +710,7 @@
        struct irqaction * action, **p;
        unsigned long flags;
 
-       if (irq > 15) {
+       if (irq > NR_IRQS-1) {
                printk("Trying to free IRQ%d\n",irq);
                return;
        }
@@ -737,7 +795,7 @@
        }
 #endif /* __RT__ */
 
-       for (i = 0; i < 16 ; i++)
+       for (i = 0; i < NR_IRQS ; i++)
                set_intr_gate(0x20+i,bad_interrupt[i]);
        /* This bit is a hack because we don't send timer messages to all processors 
yet */
        /* It has to be here .. it doesn't work if you put it down the bottom - 
assembler explodes 8) */
diff -Nur linux-2.0.38-pl-pre1-sec-rtl12incl/arch/i386/kernel/rt_time.c 
linux/arch/i386/kernel/rt_time.c
--- linux-2.0.38-pl-pre1-sec-rtl12incl/arch/i386/kernel/rt_time.c       Tue Aug 17 
10:34:40 1999
+++ linux/arch/i386/kernel/rt_time.c    Sat Aug 21 17:02:58 1999
@@ -90,7 +90,7 @@
 
 static volatile int first_time_mode2;  /* on changing modes from 0 to 2 the 8254 will 
generate an interrupt immediately; we skip this interrupt */
 
-static unsigned long scaler;
+unsigned long scaler;
 
 
 static void rt_set_latch2(int latch)
diff -Nur linux-2.0.38-pl-pre1-sec-rtl12incl/include/asm-i386/irq.h 
linux/include/asm-i386/irq.h
--- linux-2.0.38-pl-pre1-sec-rtl12incl/include/asm-i386/irq.h   Tue Aug 17 10:34:40 
1999
+++ linux/include/asm-i386/irq.h        Sun Aug 22 01:46:43 1999
@@ -13,7 +13,11 @@
 #include <linux/linkage.h>
 #include <asm/segment.h>
 
+#ifdef __RT__
+#define NR_IRQS 32
+#else
 #define NR_IRQS 16
+#endif
 
 #define TIMER_IRQ 0
 
@@ -490,6 +494,11 @@
        "movb $0x20,%al\n\t \
        outb %al,$0x20\n\t \
        outb %al,$0xA0\n\t" \
+
+/* for the "software only" Linux interrupts */
+#define ACK_NONE(mask,nr)
+#define UNBLK_NONE(mask)
+#define EOI_NONE
 
 #define MASK(i) "(1 <<" #i ")"
 
diff -Nur linux-2.0.38-pl-pre1-sec-rtl12incl/include/asm-i386/rt_irq.h 
linux/include/asm-i386/rt_irq.h
--- linux-2.0.38-pl-pre1-sec-rtl12incl/include/asm-i386/rt_irq.h        Tue Aug 17 
10:34:40 1999
+++ linux/include/asm-i386/rt_irq.h     Sun Aug 22 02:51:17 1999
@@ -17,5 +17,6 @@
 extern void s_cli(void);
 extern void s_sti(void);
 
+#define MARK_IRQ(irq) do { SFREQ |= 1<< irq; } while(0)
 
 #endif
diff -Nur linux-2.0.38-pl-pre1-sec-rtl12incl/init/patches/rtlinux.pinfo 
linux/init/patches/rtlinux.pinfo
--- linux-2.0.38-pl-pre1-sec-rtl12incl/init/patches/rtlinux.pinfo       Tue Aug 17 
23:49:58 1999
+++ linux/init/patches/rtlinux.pinfo    Sun Aug 22 00:18:41 1999
@@ -1,2 +1,3 @@
 RT-Linux version 1.2 (Victor Yodaiken, Michael Barabanov)
 RT-Linux includes and schedulers/x86 files (Tomasz Motylewski)
+RT-Linux software interrupts 16-31
diff -Nur linux-2.0.38-pl-pre1-sec-rtl12incl/kernel/ksyms.c linux/kernel/ksyms.c
--- linux-2.0.38-pl-pre1-sec-rtl12incl/kernel/ksyms.c   Tue Aug 17 10:34:40 1999
+++ linux/kernel/ksyms.c        Sun Aug 22 01:49:06 1999
@@ -125,15 +125,17 @@
        X(I8253_make_oneshot),
        X(I8253_channel2_free),
        X(I8253_make_periodic),
+       X(I8253_disable_speaker),
+       X(I8253_enable_speaker),
+       X(scaler),
 
        X(SFIF),
+       X(SFREQ),
        X(s_cli),
        X(s_sti),
        X(request_RTirq),
        X(free_RTirq),
 
-//     X(rt_fifo_get),
-//     X(rt_fifo_put),
 
        X(tq_rt),
 #endif /* __RT__ */


--- [rtl] ---
To unsubscribe:
echo "unsubscribe rtl" | mail [EMAIL PROTECTED] OR
echo "unsubscribe rtl <Your_email>" | mail [EMAIL PROTECTED]
----
For more information on Real-Time Linux see:
http://www.rtlinux.org/~rtlinux/

Reply via email to