Another test mode for irqbench: this patch allows to run the irq loopback ahead 
of
Xenomai in its own domain. Relies on latest ipipe patch which made non-heading 
irq
handlers interruptible, requires CONFIG_XENO_OPT_PIPELINE_HEAD=n (but will 
simply fail
on mode request if not).

I tried to pick up the rthal versions of all ipipe-related stuff, please remark
potential misuse.

Jan

---
 doc/txt/irqbench.txt             |   36 ++++++++++++++++++++++++++-
 include/rtdm/rttesting.h         |    1 
 ksrc/drivers/testing/irqbench.c  |   51 +++++++++++++++++++++++++++++++++++++--
 src/testsuite/irqbench/irqloop.c |    6 +++-
 4 files changed, 89 insertions(+), 5 deletions(-)

Index: xenomai/include/rtdm/rttesting.h
===================================================================
--- xenomai.orig/include/rtdm/rttesting.h
+++ xenomai/include/rtdm/rttesting.h
@@ -97,6 +97,7 @@ typedef struct rttst_tmbench_config {
 #define RTTST_IRQBENCH_USER_TASK    0
 #define RTTST_IRQBENCH_KERNEL_TASK  1
 #define RTTST_IRQBENCH_HANDLER      2
+#define RTTST_IRQBENCH_HARD_IRQ     3
 
 #define RTTST_IRQBENCH_SERPORT      0
 #define RTTST_IRQBENCH_PARPORT      1
Index: xenomai/ksrc/drivers/testing/irqbench.c
===================================================================
--- xenomai.orig/ksrc/drivers/testing/irqbench.c
+++ xenomai/ksrc/drivers/testing/irqbench.c
@@ -56,11 +56,13 @@ struct rt_irqbench_context {
     int                         mode;
     int                         port_type;
     unsigned long               port_ioaddr;
+    unsigned int                port_irq;
     unsigned int                toggle;
     struct rttst_irqbench_stats stats;
     rtdm_irq_t                  irq_handle;
     rtdm_event_t                irq_event;
     rtdm_task_t                 irq_task;
+    rthal_pipeline_stage_t      domain;
     struct semaphore            nrt_mutex;
 };
 
@@ -156,6 +158,25 @@ static int rt_irqbench_direct_irq(rtdm_i
 }
 
 
+static void rt_irqbench_domain_irq(unsigned irq, void *arg)
+{
+    struct rt_irqbench_context *ctx = (struct rt_irqbench_context *)arg;
+
+
+    if (rt_irqbench_check_irq(ctx))
+        rt_irqbench_hwreply(ctx);
+
+    rthal_irq_end(ctx->port_irq);
+}
+
+
+static inline void do_rt_irqbench_domain_entry(void)
+{
+}
+
+RTHAL_DECLARE_DOMAIN(rt_irqbench_domain_entry);
+
+
 static int rt_irqbench_stop(struct rt_irqbench_context *ctx)
 {
     if (ctx->mode < 0)
@@ -172,7 +193,12 @@ static int rt_irqbench_stop(struct rt_ir
             break;
     }
 
-    rtdm_irq_free(&ctx->irq_handle);
+    if (ctx->mode == RTTST_IRQBENCH_HARD_IRQ) {
+        rthal_virtualize_irq(&ctx->domain, ctx->port_irq, NULL, NULL, NULL,
+                             IPIPE_PASS_MASK);
+        rthal_unregister_domain(&ctx->domain);
+    } else
+        rtdm_irq_free(&ctx->irq_handle);
 
     if (ctx->mode == RTTST_IRQBENCH_KERNEL_TASK)
         rtdm_task_destroy(&ctx->irq_task);
@@ -304,6 +330,24 @@ static int rt_irqbench_ioctl_nrt(struct 
                                            "irqbench", ctx);
                     break;
 
+                case RTTST_IRQBENCH_HARD_IRQ:
+                    ret = rthal_register_domain(&ctx->domain, "irqbench",
+                                                0x49525142,
+                                                IPIPE_HEAD_PRIORITY,
+                                                rt_irqbench_domain_entry);
+                    if (ret < 0)
+                        goto unlock_start_out;
+
+                    ctx->port_irq = config->port_irq;
+                    ret = rthal_virtualize_irq(&ctx->domain, config->port_irq,
+                                               rt_irqbench_domain_irq, ctx,
+                                               NULL, IPIPE_HANDLE_MASK |
+                                               IPIPE_WIRED_MASK |
+                                               IPIPE_EXCLUSIVE_MASK);
+                    if (ret < 0)
+                        rthal_unregister_domain(&ctx->domain);
+                    break;
+
                 default:
                     ret = -EINVAL;
                     break;
@@ -315,7 +359,10 @@ static int rt_irqbench_ioctl_nrt(struct 
 
             memset(&ctx->stats, 0, sizeof(ctx->stats));
 
-            rtdm_irq_enable(&ctx->irq_handle);
+            if (ctx->mode == RTTST_IRQBENCH_HARD_IRQ)
+                rthal_irq_enable(ctx->port_irq);
+            else
+                rtdm_irq_enable(&ctx->irq_handle);
 
             /* Arm IRQ */
             switch (ctx->port_type) {
Index: xenomai/src/testsuite/irqbench/irqloop.c
===================================================================
--- xenomai.orig/src/testsuite/irqbench/irqloop.c
+++ xenomai/src/testsuite/irqbench/irqloop.c
@@ -54,7 +54,8 @@ void sighand(int sig)
 int main(int argc, char *argv[])
 {
     const char *mode_name[] =
-        { "user-space task", "kernel-space task", "IRQ handler" };
+        { "user-space task", "kernel-space task",
+          "IRQ handler", "hard-IRQ handler" };
     const char *port_type_name[] = { "serial", "parallel" };
     char devname[RTDM_MAX_DEVNAME_LEN];
     int benchdev_no = 0;
@@ -102,7 +103,8 @@ int main(int argc, char *argv[])
             default:
                 fprintf(stderr, "usage: irqloop [options]\n"
                         "  [-D <testing_device_no>] # number of testing 
device, default=0\n"
-                        "  [-t <test_mode>]         # 0=user task (default), 
1=kernel task, 2=IRQ\n"
+                        "  [-t <test_mode>]         # 0=user task (default), 
1=kernel task,\n"
+                        "                           # 2=IRQ handler, 
3=hard-IRQ handler\n"
                         "  [-P <priority>]          # task priority (test mode 
0 and 1 only)\n"
                         "  [-o <port_type>]         # 0=serial (default), 
1=parallel\n"
                         "  [-a <port_io_address>]   # default=0x3f8\n"
Index: xenomai/doc/txt/irqbench.txt
===================================================================
--- xenomai.orig/doc/txt/irqbench.txt
+++ xenomai/doc/txt/irqbench.txt
@@ -1,6 +1,8 @@
 IRQ Latency Benchmark
 ---------------------
 
+1. Overview
+
 This latency benchmark for external interrupts consists of three parts:
 
 1. xeno_irqbench (ksrc/drivers/testing)
@@ -19,6 +21,9 @@ This latency benchmark for external inte
 
         <gcc-x86-compiler> irqbench.c -o irqbench -O2
 
+
+2. Hardware Setup
+
 To link both test and log system, a null-modem cable between 8250-compatible
 two RS232 ports is required. The infrastructure for parallel port cross-over
 is prepared as well, but yet untested and incomplete. The null-modem cable
@@ -38,6 +43,36 @@ must provide at least the following link
 Test and log system can be started in arbitrary order, they will wait on
 each other.
 
+
+3. Test Scenarios
+
+The xeno_irqbench driver supports four different IRQ handling scenarios,
+selectable via "-t <test_mode>" on irqloop start-up:
+
+Mode 0 - Installs an IRQ handler that wakes up a user-space task. This task
+         is provided by irqloop. Once it is woken up, it will issue an IOCTL
+         to xeno_irqbench in order to generate the reply. This scenario is
+         typical for kernel-based device drivers.
+
+Mode 1 - Same as mode 0, except that the task resides inside the kernel and is
+         provided by xeno_irqbench itself. A typical scenario for kernel-based
+         RT-applications or drivers that handle IRQ requests inside a kernel
+         task.
+
+Mode 2 - Installs an IRQ handler that directly replies to the event. This
+         scenario measures the reactivity of driver IRQ handlers when handling
+         events immediately or taking timestamps.
+
+Mode 3 - In this mode, an additional I-pipe domain is registered on top of
+         Xenomai. The IRQ handler for immediate reply is then assigned to the
+         new domain. By pushing the handling above Xenomai, the IRQ reply
+         latency can widely be decoupled from RT-application-related delays.
+         The drawback is that no direct interaction with the Xenomai scheduler
+         is possible from the higher domain.
+
+
+4. Measuring
+
 The log system runs each single IRQ measurement with local IRQs disabled. It
 will wait up to 100 times the current period on the test system's reply (after
 initial successful synchronisation, which happens with IRQs enabled). Note that
@@ -48,4 +83,3 @@ new IRQ event before the reply on the pr
 Thus the specified test period may be dynamically expended in case of
 overload. But maximum a latency close or above the period will clearly
 indicate this.
-



Attachment: signature.asc
Description: OpenPGP digital signature

_______________________________________________
Xenomai-core mailing list
Xenomai-core@gna.org
https://mail.gna.org/listinfo/xenomai-core

Reply via email to