Make ecrt_master_reset available in RT context
It takes the master_sem, so calling it from RT context is not an option. The reset is done by a workqueue now, which is triggered in a NMI-safe way. Fixes #103
This commit is contained in:
parent
1226b9d745
commit
d0f4aed39b
|
|
@ -2282,9 +2282,12 @@ static ATTRIBUTES int ec_ioctl_reset(
|
|||
ec_ioctl_context_t *ctx /**< Private data structure of file handle. */
|
||||
)
|
||||
{
|
||||
down(&master->master_sem);
|
||||
ecrt_master_reset(master);
|
||||
up(&master->master_sem);
|
||||
#ifdef EC_IOCTL_RTDM
|
||||
/* Xenomai/LXRT is like NMI context, so we do a two-stage schedule. */
|
||||
irq_work_queue(&master->sc_reset_work_kicker);
|
||||
#else
|
||||
schedule_work(&master->sc_reset_work);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -4720,6 +4723,13 @@ static long ec_ioctl_both(
|
|||
case EC_IOCTL_MASTER_LINK_STATE:
|
||||
ret = ec_ioctl_master_link_state(master, arg, ctx);
|
||||
break;
|
||||
case EC_IOCTL_RESET:
|
||||
if (!ctx->writable) {
|
||||
ret = -EPERM;
|
||||
break;
|
||||
}
|
||||
ret = ec_ioctl_reset(master, arg, ctx);
|
||||
break;
|
||||
case EC_IOCTL_REF_CLOCK_TIME:
|
||||
if (!ctx->writable) {
|
||||
ret = -EPERM;
|
||||
|
|
@ -5204,13 +5214,6 @@ static long ec_ioctl_nrt
|
|||
}
|
||||
ret = ec_ioctl_deactivate(master, arg, ctx);
|
||||
break;
|
||||
case EC_IOCTL_RESET:
|
||||
if (!ctx->writable) {
|
||||
ret = -EPERM;
|
||||
break;
|
||||
}
|
||||
ret = ec_ioctl_reset(master, arg, ctx);
|
||||
break;
|
||||
case EC_IOCTL_SC_SYNC:
|
||||
if (!ctx->writable) {
|
||||
ret = -EPERM;
|
||||
|
|
|
|||
|
|
@ -107,6 +107,8 @@ static int ec_master_eoe_thread(void *);
|
|||
void ec_master_find_dc_ref_clock(ec_master_t *);
|
||||
void ec_master_clear_device_stats(ec_master_t *);
|
||||
void ec_master_update_device_stats(ec_master_t *);
|
||||
static void sc_reset_task_kicker(struct irq_work *work);
|
||||
static void sc_reset_task(struct work_struct *work);
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
|
|
@ -316,6 +318,9 @@ int ec_master_init(ec_master_t *master, /**< EtherCAT master */
|
|||
master->dc_ref_config = NULL;
|
||||
master->dc_ref_clock = NULL;
|
||||
|
||||
INIT_WORK(&master->sc_reset_work, sc_reset_task);
|
||||
init_irq_work(&master->sc_reset_work_kicker, sc_reset_task_kicker);
|
||||
|
||||
// init character device
|
||||
ret = ec_cdev_init(&master->cdev, master, device_number);
|
||||
if (ret)
|
||||
|
|
@ -383,6 +388,9 @@ void ec_master_clear(
|
|||
|
||||
ec_cdev_clear(&master->cdev);
|
||||
|
||||
irq_work_sync(&master->sc_reset_work_kicker);
|
||||
cancel_work_sync(&master->sc_reset_work);
|
||||
|
||||
#ifdef EC_EOE
|
||||
ec_master_clear_eoe_handlers(master);
|
||||
#endif
|
||||
|
|
@ -3257,6 +3265,27 @@ void ecrt_master_reset(ec_master_t *master)
|
|||
|
||||
/****************************************************************************/
|
||||
|
||||
static void sc_reset_task_kicker(struct irq_work *work)
|
||||
{
|
||||
struct ec_master *master =
|
||||
container_of(work, struct ec_master, sc_reset_work_kicker);
|
||||
schedule_work(&master->sc_reset_work);
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
static void sc_reset_task(struct work_struct *work)
|
||||
{
|
||||
struct ec_master *master =
|
||||
container_of(work, struct ec_master, sc_reset_work);
|
||||
|
||||
down(&master->master_sem);
|
||||
ecrt_master_reset(master);
|
||||
up(&master->master_sem);
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
/** \cond */
|
||||
|
||||
EXPORT_SYMBOL(ecrt_master_create_domain);
|
||||
|
|
|
|||
|
|
@ -30,11 +30,13 @@
|
|||
#define __EC_MASTER_H__
|
||||
|
||||
#include <linux/version.h>
|
||||
#include <linux/irq_work.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/rtmutex.h>
|
||||
#include <linux/workqueue.h>
|
||||
|
||||
#include "device.h"
|
||||
#include "domain.h"
|
||||
|
|
@ -294,6 +296,9 @@ struct ec_master {
|
|||
|
||||
wait_queue_head_t request_queue; /**< Wait queue for external requests
|
||||
from user space. */
|
||||
struct work_struct sc_reset_work; /**< Task to reset slave configuration. */
|
||||
struct irq_work sc_reset_work_kicker; /**< NMI-Safe kicker to trigger
|
||||
reset task above. */
|
||||
};
|
||||
|
||||
/****************************************************************************/
|
||||
|
|
|
|||
Loading…
Reference in New Issue