<div>I have just tried the recently reworked RTDM interface of the EtherCAT master with Xenomai 2.6.1 on Linux 3.2.21 with a e1000e network card and I have to say that it works very well!</div><div><br></div><div>However, although the example Xenomai application works without problem, I found that my own Xenomai application did not. After some investigation, I found that this was because I was calling the ecrt_master_activate function from a Xenomai real-time task in primary mode (rather than from a standard Linux process as per the example code). The problem is that activating the master causes the idle thread to be stopped via kthread_stop which cannot be run in a real-time context and causes the kernel to panic with &quot;scheduling while atomic&quot;.</div>
<div><br></div><div>The current implementation uses the same ioctl function for real-time and non real-time callers and does not check the mode of the caller in order to return -ENOSYS to get the caller to try again in the opposite context. I added a check in the ec_rtdm_ioctl() function (in master/rtdm.c) and if rtdm_in_rt_context() returns true and the request is EC_IOCTL_ACTIVATE, return -ENOSYS. This makes the caller switch to secondary mode and try again. On the second occasion, the code continues to the ec_ioctl_rtdm function as normal. This fixes the problem for activate. However, I also noted a similar problem with EC_IOCTL_CREATE_SLAVE_CONFIG if called from a real-time context so I added this case to my check and now it all works perfectly. I suspect that there may be other IOCTLs that cannot be called safely from a (primary mode) real-time context and therefore need adding to this check.</div>
<div><br></div><div>My revised code for ec_rtdm_ioctl() is:</div><div><br></div><blockquote style="margin:0 0 0 40px;border:none;padding:0px"><div><div><font face="courier new, monospace">int ec_rtdm_ioctl(</font></div></div>
<div><div><font face="courier new, monospace">        struct rtdm_dev_context *context, /**&lt; Context. */</font></div></div><div><div><font face="courier new, monospace">        rtdm_user_info_t *user_info, /**&lt; User data. */</font></div>
</div><div><div><font face="courier new, monospace">        unsigned int request, /**&lt; Request. */</font></div></div><div><div><font face="courier new, monospace">        void __user *arg /**&lt; Argument. */</font></div>
</div><div><div><font face="courier new, monospace">        )</font></div></div><div><div><font face="courier new, monospace">{</font></div></div><div><div><font face="courier new, monospace">    ec_rtdm_context_t *ctx = (ec_rtdm_context_t *) context-&gt;dev_private;</font></div>
</div><div><div><font face="courier new, monospace">    ec_rtdm_dev_t *rtdm_dev = (ec_rtdm_dev_t *) context-&gt;device-&gt;device_data;</font></div></div><div><div><font face="courier new, monospace"><br></font></div></div>
<div><div><font face="courier new, monospace"><b style="background-color:rgb(255,255,51)">    if (rtdm_in_rt_context())</b></font></div></div><div><div><font face="courier new, monospace"><b style="background-color:rgb(255,255,51)">    {</b></font></div>
</div><div><div><font face="courier new, monospace"><b style="background-color:rgb(255,255,51)">        switch (request)</b></font></div></div><div><div><font face="courier new, monospace"><b style="background-color:rgb(255,255,51)">        {</b></font></div>
</div><div><div><font face="courier new, monospace"><b style="background-color:rgb(255,255,51)">        case EC_IOCTL_ACTIVATE:</b></font></div></div><div><div><font face="courier new, monospace"><b style="background-color:rgb(255,255,51)">        case EC_IOCTL_CREATE_SLAVE_CONFIG:</b></font></div>
</div><div><div><font face="courier new, monospace"><b style="background-color:rgb(255,255,51)">            return -ENOSYS;</b></font></div></div><div><div><font face="courier new, monospace"><b style="background-color:rgb(255,255,51)">        }</b></font></div>
</div><div><div><font face="courier new, monospace"><b style="background-color:rgb(255,255,51)">    }</b></font></div></div><div><div><font face="courier new, monospace"><br></font></div></div><div><div><font face="courier new, monospace">#if DEBUG</font></div>
</div><div><div><font face="courier new, monospace">    EC_MASTER_INFO(rtdm_dev-&gt;master, &quot;ioctl(request = %u, ctl = %02x)&quot;</font></div></div><div><div><font face="courier new, monospace">            &quot; on RTDM device %s.\n&quot;, request, _IOC_NR(request),</font></div>
</div><div><div><font face="courier new, monospace">            context-&gt;device-&gt;device_name);</font></div></div><div><div><font face="courier new, monospace">#endif</font></div></div><div><div><font face="courier new, monospace">    return ec_ioctl_rtdm(rtdm_dev-&gt;master, &amp;ctx-&gt;ioctl_ctx, request, arg);</font></div>
</div><div><div><font face="courier new, monospace">}</font></div></div></blockquote><div><br></div><div>Note that if using the generic driver, you will have more kernel &quot;complaints&quot; as there are situations where the xmit function cannot be called safely from a real-time context. If you add the EC_IOCTL_SEND case to the above, you will not have hard real-time support as the calling task will always be switching in and out of secondary mode. This may not be an issue depending on the application but it should not be added as standard because it will unnecessarily break hard real-time support when using a ported driver (such as e1000e).</div>
<div><br></div><div><br></div><div><br></div>