Applied 0016-If-enable-rtmutex-use-rtmutexes-instead-of-semaphore.patch
This commit is contained in:
parent
667e93284d
commit
9955855f7e
29
configure.ac
29
configure.ac
|
|
@ -812,6 +812,35 @@ else
|
||||||
AC_MSG_RESULT([no])
|
AC_MSG_RESULT([no])
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
#------------------------------------------------------------------------------
|
||||||
|
# Realtime Mutex support
|
||||||
|
#------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
AC_MSG_CHECKING([whether to use rtmutexes])
|
||||||
|
|
||||||
|
AC_ARG_ENABLE([rtmutex],
|
||||||
|
AS_HELP_STRING([--enable-rtmutex],
|
||||||
|
[Use rtmutexes for synchronization (default: no)]),
|
||||||
|
[
|
||||||
|
case "${enableval}" in
|
||||||
|
yes) rtmutex=1
|
||||||
|
;;
|
||||||
|
no) rtmutex=0
|
||||||
|
;;
|
||||||
|
*) AC_MSG_ERROR([Invalid value for --enable-rtmutex])
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
],
|
||||||
|
[rtmutex=0]
|
||||||
|
)
|
||||||
|
|
||||||
|
if test "x${rtmutex}" = "x1"; then
|
||||||
|
AC_DEFINE([EC_USE_RTMUTEX], [1], [Use rtmutex for synchronization])
|
||||||
|
AC_MSG_RESULT([yes])
|
||||||
|
else
|
||||||
|
AC_MSG_RESULT([no])
|
||||||
|
fi
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
#------------------------------------------------------------------------------
|
||||||
# High-resolution timer support
|
# High-resolution timer support
|
||||||
#------------------------------------------------------------------------------
|
#------------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
|
@ -57,6 +57,7 @@ noinst_HEADERS = \
|
||||||
fsm_soe.c fsm_soe.h \
|
fsm_soe.c fsm_soe.h \
|
||||||
globals.h \
|
globals.h \
|
||||||
ioctl.c ioctl.h \
|
ioctl.c ioctl.h \
|
||||||
|
locks.h \
|
||||||
mailbox.c mailbox.h \
|
mailbox.c mailbox.h \
|
||||||
master.c master.h \
|
master.c master.h \
|
||||||
module.c \
|
module.c \
|
||||||
|
|
|
||||||
|
|
@ -559,9 +559,9 @@ void ecdev_withdraw(ec_device_t *device /**< EtherCAT device */)
|
||||||
|
|
||||||
EC_MASTER_INFO(master, "Releasing %s device %s.\n", dev_str, mac_str);
|
EC_MASTER_INFO(master, "Releasing %s device %s.\n", dev_str, mac_str);
|
||||||
|
|
||||||
down(&master->device_sem);
|
ec_lock_down(&master->device_sem);
|
||||||
ec_device_detach(device);
|
ec_device_detach(device);
|
||||||
up(&master->device_sem);
|
ec_lock_up(&master->device_sem);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
|
||||||
|
|
@ -512,14 +512,14 @@ void ecrt_domain_external_memory(ec_domain_t *domain, uint8_t *mem)
|
||||||
EC_MASTER_DBG(domain->master, 1, "ecrt_domain_external_memory("
|
EC_MASTER_DBG(domain->master, 1, "ecrt_domain_external_memory("
|
||||||
"domain = 0x%p, mem = 0x%p)\n", domain, mem);
|
"domain = 0x%p, mem = 0x%p)\n", domain, mem);
|
||||||
|
|
||||||
down(&domain->master->master_sem);
|
ec_lock_down(&domain->master->master_sem);
|
||||||
|
|
||||||
ec_domain_clear_data(domain);
|
ec_domain_clear_data(domain);
|
||||||
|
|
||||||
domain->data = mem;
|
domain->data = mem;
|
||||||
domain->data_origin = EC_ORIG_EXTERNAL;
|
domain->data_origin = EC_ORIG_EXTERNAL;
|
||||||
|
|
||||||
up(&domain->master->master_sem);
|
ec_lock_up(&domain->master->master_sem);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
|
||||||
|
|
@ -153,7 +153,7 @@ int ec_eoe_init(
|
||||||
eoe->tx_queue_size = EC_EOE_TX_QUEUE_SIZE;
|
eoe->tx_queue_size = EC_EOE_TX_QUEUE_SIZE;
|
||||||
eoe->tx_queued_frames = 0;
|
eoe->tx_queued_frames = 0;
|
||||||
|
|
||||||
sema_init(&eoe->tx_queue_sem, 1);
|
ec_lock_init(&eoe->tx_queue_sem);
|
||||||
eoe->tx_frame_number = 0xFF;
|
eoe->tx_frame_number = 0xFF;
|
||||||
memset(&eoe->stats, 0, sizeof(struct net_device_stats));
|
memset(&eoe->stats, 0, sizeof(struct net_device_stats));
|
||||||
|
|
||||||
|
|
@ -323,7 +323,7 @@ void ec_eoe_flush(ec_eoe_t *eoe /**< EoE handler */)
|
||||||
{
|
{
|
||||||
ec_eoe_frame_t *frame, *next;
|
ec_eoe_frame_t *frame, *next;
|
||||||
|
|
||||||
down(&eoe->tx_queue_sem);
|
ec_lock_down(&eoe->tx_queue_sem);
|
||||||
|
|
||||||
list_for_each_entry_safe(frame, next, &eoe->tx_queue, queue) {
|
list_for_each_entry_safe(frame, next, &eoe->tx_queue, queue) {
|
||||||
list_del(&frame->queue);
|
list_del(&frame->queue);
|
||||||
|
|
@ -332,7 +332,7 @@ void ec_eoe_flush(ec_eoe_t *eoe /**< EoE handler */)
|
||||||
}
|
}
|
||||||
eoe->tx_queued_frames = 0;
|
eoe->tx_queued_frames = 0;
|
||||||
|
|
||||||
up(&eoe->tx_queue_sem);
|
ec_lock_up(&eoe->tx_queue_sem);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
@ -727,10 +727,10 @@ void ec_eoe_state_tx_start(ec_eoe_t *eoe /**< EoE handler */)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
down(&eoe->tx_queue_sem);
|
ec_lock_down(&eoe->tx_queue_sem);
|
||||||
|
|
||||||
if (!eoe->tx_queued_frames || list_empty(&eoe->tx_queue)) {
|
if (!eoe->tx_queued_frames || list_empty(&eoe->tx_queue)) {
|
||||||
up(&eoe->tx_queue_sem);
|
ec_lock_up(&eoe->tx_queue_sem);
|
||||||
eoe->tx_idle = 1;
|
eoe->tx_idle = 1;
|
||||||
// no data available.
|
// no data available.
|
||||||
// start a new receive immediately.
|
// start a new receive immediately.
|
||||||
|
|
@ -751,7 +751,7 @@ void ec_eoe_state_tx_start(ec_eoe_t *eoe /**< EoE handler */)
|
||||||
}
|
}
|
||||||
|
|
||||||
eoe->tx_queued_frames--;
|
eoe->tx_queued_frames--;
|
||||||
up(&eoe->tx_queue_sem);
|
ec_lock_up(&eoe->tx_queue_sem);
|
||||||
|
|
||||||
eoe->tx_idle = 0;
|
eoe->tx_idle = 0;
|
||||||
|
|
||||||
|
|
@ -923,14 +923,14 @@ int ec_eoedev_tx(struct sk_buff *skb, /**< transmit socket buffer */
|
||||||
|
|
||||||
frame->skb = skb;
|
frame->skb = skb;
|
||||||
|
|
||||||
down(&eoe->tx_queue_sem);
|
ec_lock_down(&eoe->tx_queue_sem);
|
||||||
list_add_tail(&frame->queue, &eoe->tx_queue);
|
list_add_tail(&frame->queue, &eoe->tx_queue);
|
||||||
eoe->tx_queued_frames++;
|
eoe->tx_queued_frames++;
|
||||||
if (eoe->tx_queued_frames == eoe->tx_queue_size) {
|
if (eoe->tx_queued_frames == eoe->tx_queue_size) {
|
||||||
netif_stop_queue(dev);
|
netif_stop_queue(dev);
|
||||||
eoe->tx_queue_active = 0;
|
eoe->tx_queue_active = 0;
|
||||||
}
|
}
|
||||||
up(&eoe->tx_queue_sem);
|
ec_lock_up(&eoe->tx_queue_sem);
|
||||||
|
|
||||||
#if EOE_DEBUG_LEVEL >= 2
|
#if EOE_DEBUG_LEVEL >= 2
|
||||||
EC_SLAVE_DBG(eoe->slave, 0, "EoE %s TX queued frame"
|
EC_SLAVE_DBG(eoe->slave, 0, "EoE %s TX queued frame"
|
||||||
|
|
|
||||||
|
|
@ -40,13 +40,8 @@
|
||||||
#include <linux/list.h>
|
#include <linux/list.h>
|
||||||
#include <linux/netdevice.h>
|
#include <linux/netdevice.h>
|
||||||
|
|
||||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
|
|
||||||
#include <linux/semaphore.h>
|
|
||||||
#else
|
|
||||||
#include <asm/semaphore.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "globals.h"
|
#include "globals.h"
|
||||||
|
#include "locks.h"
|
||||||
#include "slave.h"
|
#include "slave.h"
|
||||||
#include "datagram.h"
|
#include "datagram.h"
|
||||||
|
|
||||||
|
|
@ -109,7 +104,7 @@ struct ec_eoe
|
||||||
unsigned int tx_queue_size; /**< Transmit queue size. */
|
unsigned int tx_queue_size; /**< Transmit queue size. */
|
||||||
unsigned int tx_queue_active; /**< kernel netif queue started */
|
unsigned int tx_queue_active; /**< kernel netif queue started */
|
||||||
unsigned int tx_queued_frames; /**< number of frames in the queue */
|
unsigned int tx_queued_frames; /**< number of frames in the queue */
|
||||||
struct semaphore tx_queue_sem; /**< Semaphore for the send queue. */
|
ec_lock_t tx_queue_sem; /**< Semaphore for the send queue. */
|
||||||
ec_eoe_frame_t *tx_frame; /**< current TX frame */
|
ec_eoe_frame_t *tx_frame; /**< current TX frame */
|
||||||
uint8_t tx_frame_number; /**< number of the transmitted frame */
|
uint8_t tx_frame_number; /**< number of the transmitted frame */
|
||||||
uint8_t tx_fragment_number; /**< number of the fragment */
|
uint8_t tx_fragment_number; /**< number of the fragment */
|
||||||
|
|
|
||||||
|
|
@ -334,15 +334,15 @@ void ec_fsm_master_state_broadcast(
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fsm->rescan_required) {
|
if (fsm->rescan_required) {
|
||||||
down(&master->scan_sem);
|
ec_lock_down(&master->scan_sem);
|
||||||
if (!master->allow_scan) {
|
if (!master->allow_scan) {
|
||||||
up(&master->scan_sem);
|
ec_lock_up(&master->scan_sem);
|
||||||
} else {
|
} else {
|
||||||
unsigned int count = 0, next_dev_slave, ring_position;
|
unsigned int count = 0, next_dev_slave, ring_position;
|
||||||
ec_device_index_t dev_idx;
|
ec_device_index_t dev_idx;
|
||||||
|
|
||||||
master->scan_busy = 1;
|
master->scan_busy = 1;
|
||||||
up(&master->scan_sem);
|
ec_lock_up(&master->scan_sem);
|
||||||
|
|
||||||
// clear all slaves and scan the bus
|
// clear all slaves and scan the bus
|
||||||
fsm->rescan_required = 0;
|
fsm->rescan_required = 0;
|
||||||
|
|
@ -826,9 +826,9 @@ void ec_fsm_master_action_configure(
|
||||||
|| slave->force_config) && !slave->error_flag) {
|
|| slave->force_config) && !slave->error_flag) {
|
||||||
|
|
||||||
// Start slave configuration
|
// Start slave configuration
|
||||||
down(&master->config_sem);
|
ec_lock_down(&master->config_sem);
|
||||||
master->config_busy = 1;
|
master->config_busy = 1;
|
||||||
up(&master->config_sem);
|
ec_lock_up(&master->config_sem);
|
||||||
|
|
||||||
if (master->debug_level) {
|
if (master->debug_level) {
|
||||||
char old_state[EC_STATE_STRING_SIZE],
|
char old_state[EC_STATE_STRING_SIZE],
|
||||||
|
|
|
||||||
350
master/ioctl.c
350
master/ioctl.c
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,80 @@
|
||||||
|
/******************************************************************************
|
||||||
|
*
|
||||||
|
* $Id$
|
||||||
|
*
|
||||||
|
* Copyright (C) 2006-2008 Florian Pose, Ingenieurgemeinschaft IgH
|
||||||
|
*
|
||||||
|
* This file is part of the IgH EtherCAT Master.
|
||||||
|
*
|
||||||
|
* The IgH EtherCAT Master is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License version 2, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* The IgH EtherCAT Master 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.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with the IgH EtherCAT Master; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
* ---
|
||||||
|
*
|
||||||
|
* The license mentioned above concerns the source code only. Using the
|
||||||
|
* EtherCAT technology and brand is only permitted in compliance with the
|
||||||
|
* industrial property and similar rights of Beckhoff Automation GmbH.
|
||||||
|
*
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
\file
|
||||||
|
Abstract locks
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef __EC_LOCKS_H__
|
||||||
|
#define __EC_LOCKS_H__
|
||||||
|
|
||||||
|
#include "globals.h"
|
||||||
|
|
||||||
|
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
|
||||||
|
#include <linux/semaphore.h>
|
||||||
|
#else
|
||||||
|
#include <asm/semaphore.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
#ifdef EC_USE_RTMUTEX
|
||||||
|
|
||||||
|
#include <linux/rtmutex.h>
|
||||||
|
|
||||||
|
typedef struct rt_mutex ec_lock_t;
|
||||||
|
|
||||||
|
static inline void ec_lock_init(ec_lock_t *sem) { rt_mutex_init(sem); }
|
||||||
|
static inline void ec_lock_down(ec_lock_t *sem) { rt_mutex_lock(sem); }
|
||||||
|
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 34)
|
||||||
|
static inline int ec_lock_down_interruptible(ec_lock_t *sem) { return rt_mutex_lock_interruptible(sem); }
|
||||||
|
#else
|
||||||
|
static inline int ec_lock_down_interruptible(ec_lock_t *sem) { return rt_mutex_lock_interruptible(sem, 1); }
|
||||||
|
#endif
|
||||||
|
static inline void ec_lock_up(ec_lock_t *sem) { rt_mutex_unlock(sem); }
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
typedef struct semaphore ec_lock_t;
|
||||||
|
|
||||||
|
static inline void ec_lock_init(ec_lock_t *sem) { sema_init(sem, 1); }
|
||||||
|
static inline void ec_lock_down(ec_lock_t *sem) { down(sem); }
|
||||||
|
static inline int ec_lock_down_interruptible(ec_lock_t *sem) { return down_interruptible(sem); }
|
||||||
|
static inline void ec_lock_up(ec_lock_t *sem) { up(sem); }
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
142
master/master.c
142
master/master.c
|
|
@ -153,7 +153,7 @@ int ec_master_init(ec_master_t *master, /**< EtherCAT master */
|
||||||
master->index = index;
|
master->index = index;
|
||||||
master->reserved = 0;
|
master->reserved = 0;
|
||||||
|
|
||||||
sema_init(&master->master_sem, 1);
|
ec_lock_init(&master->master_sem);
|
||||||
|
|
||||||
for (dev_idx = EC_DEVICE_MAIN; dev_idx < EC_MAX_NUM_DEVICES; dev_idx++) {
|
for (dev_idx = EC_DEVICE_MAIN; dev_idx < EC_MAX_NUM_DEVICES; dev_idx++) {
|
||||||
master->macs[dev_idx] = NULL;
|
master->macs[dev_idx] = NULL;
|
||||||
|
|
@ -172,7 +172,7 @@ int ec_master_init(ec_master_t *master, /**< EtherCAT master */
|
||||||
|
|
||||||
ec_master_clear_device_stats(master);
|
ec_master_clear_device_stats(master);
|
||||||
|
|
||||||
sema_init(&master->device_sem, 1);
|
ec_lock_init(&master->device_sem);
|
||||||
|
|
||||||
master->phase = EC_ORPHANED;
|
master->phase = EC_ORPHANED;
|
||||||
master->active = 0;
|
master->active = 0;
|
||||||
|
|
@ -192,18 +192,18 @@ int ec_master_init(ec_master_t *master, /**< EtherCAT master */
|
||||||
|
|
||||||
master->scan_busy = 0;
|
master->scan_busy = 0;
|
||||||
master->allow_scan = 1;
|
master->allow_scan = 1;
|
||||||
sema_init(&master->scan_sem, 1);
|
ec_lock_init(&master->scan_sem);
|
||||||
init_waitqueue_head(&master->scan_queue);
|
init_waitqueue_head(&master->scan_queue);
|
||||||
|
|
||||||
master->config_busy = 0;
|
master->config_busy = 0;
|
||||||
sema_init(&master->config_sem, 1);
|
ec_lock_init(&master->config_sem);
|
||||||
init_waitqueue_head(&master->config_queue);
|
init_waitqueue_head(&master->config_queue);
|
||||||
|
|
||||||
INIT_LIST_HEAD(&master->datagram_queue);
|
INIT_LIST_HEAD(&master->datagram_queue);
|
||||||
master->datagram_index = 0;
|
master->datagram_index = 0;
|
||||||
|
|
||||||
INIT_LIST_HEAD(&master->ext_datagram_queue);
|
INIT_LIST_HEAD(&master->ext_datagram_queue);
|
||||||
sema_init(&master->ext_queue_sem, 1);
|
ec_lock_init(&master->ext_queue_sem);
|
||||||
|
|
||||||
master->ext_ring_idx_rt = 0;
|
master->ext_ring_idx_rt = 0;
|
||||||
master->ext_ring_idx_fsm = 0;
|
master->ext_ring_idx_fsm = 0;
|
||||||
|
|
@ -235,7 +235,7 @@ int ec_master_init(ec_master_t *master, /**< EtherCAT master */
|
||||||
INIT_LIST_HEAD(&master->eoe_handlers);
|
INIT_LIST_HEAD(&master->eoe_handlers);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
sema_init(&master->io_sem, 1);
|
ec_lock_init(&master->io_sem);
|
||||||
master->send_cb = NULL;
|
master->send_cb = NULL;
|
||||||
master->receive_cb = NULL;
|
master->receive_cb = NULL;
|
||||||
master->cb_data = NULL;
|
master->cb_data = NULL;
|
||||||
|
|
@ -548,10 +548,10 @@ void ec_master_clear_config(
|
||||||
ec_master_t *master /**< EtherCAT master. */
|
ec_master_t *master /**< EtherCAT master. */
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
down(&master->master_sem);
|
ec_lock_down(&master->master_sem);
|
||||||
ec_master_clear_domains(master);
|
ec_master_clear_domains(master);
|
||||||
ec_master_clear_slave_configs(master);
|
ec_master_clear_slave_configs(master);
|
||||||
up(&master->master_sem);
|
ec_lock_up(&master->master_sem);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
@ -563,9 +563,9 @@ void ec_master_internal_send_cb(
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
ec_master_t *master = (ec_master_t *) cb_data;
|
ec_master_t *master = (ec_master_t *) cb_data;
|
||||||
down(&master->io_sem);
|
ec_lock_down(&master->io_sem);
|
||||||
ecrt_master_send_ext(master);
|
ecrt_master_send_ext(master);
|
||||||
up(&master->io_sem);
|
ec_lock_up(&master->io_sem);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
@ -577,9 +577,9 @@ void ec_master_internal_receive_cb(
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
ec_master_t *master = (ec_master_t *) cb_data;
|
ec_master_t *master = (ec_master_t *) cb_data;
|
||||||
down(&master->io_sem);
|
ec_lock_down(&master->io_sem);
|
||||||
ecrt_master_receive(master);
|
ecrt_master_receive(master);
|
||||||
up(&master->io_sem);
|
ec_lock_up(&master->io_sem);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
@ -688,9 +688,9 @@ void ec_master_leave_idle_phase(ec_master_t *master /**< EtherCAT master */)
|
||||||
#endif
|
#endif
|
||||||
ec_master_thread_stop(master);
|
ec_master_thread_stop(master);
|
||||||
|
|
||||||
down(&master->master_sem);
|
ec_lock_down(&master->master_sem);
|
||||||
ec_master_clear_slaves(master);
|
ec_master_clear_slaves(master);
|
||||||
up(&master->master_sem);
|
ec_lock_up(&master->master_sem);
|
||||||
|
|
||||||
ec_fsm_master_reset(&master->fsm);
|
ec_fsm_master_reset(&master->fsm);
|
||||||
}
|
}
|
||||||
|
|
@ -710,9 +710,9 @@ int ec_master_enter_operation_phase(
|
||||||
|
|
||||||
EC_MASTER_DBG(master, 1, "IDLE -> OPERATION.\n");
|
EC_MASTER_DBG(master, 1, "IDLE -> OPERATION.\n");
|
||||||
|
|
||||||
down(&master->config_sem);
|
ec_lock_down(&master->config_sem);
|
||||||
if (master->config_busy) {
|
if (master->config_busy) {
|
||||||
up(&master->config_sem);
|
ec_lock_up(&master->config_sem);
|
||||||
|
|
||||||
// wait for slave configuration to complete
|
// wait for slave configuration to complete
|
||||||
ret = wait_event_interruptible(master->config_queue,
|
ret = wait_event_interruptible(master->config_queue,
|
||||||
|
|
@ -726,15 +726,15 @@ int ec_master_enter_operation_phase(
|
||||||
EC_MASTER_DBG(master, 1, "Waiting for pending slave"
|
EC_MASTER_DBG(master, 1, "Waiting for pending slave"
|
||||||
" configuration returned.\n");
|
" configuration returned.\n");
|
||||||
} else {
|
} else {
|
||||||
up(&master->config_sem);
|
ec_lock_up(&master->config_sem);
|
||||||
}
|
}
|
||||||
|
|
||||||
down(&master->scan_sem);
|
ec_lock_down(&master->scan_sem);
|
||||||
master->allow_scan = 0; // 'lock' the slave list
|
master->allow_scan = 0; // 'lock' the slave list
|
||||||
if (!master->scan_busy) {
|
if (!master->scan_busy) {
|
||||||
up(&master->scan_sem);
|
ec_lock_up(&master->scan_sem);
|
||||||
} else {
|
} else {
|
||||||
up(&master->scan_sem);
|
ec_lock_up(&master->scan_sem);
|
||||||
|
|
||||||
// wait for slave scan to complete
|
// wait for slave scan to complete
|
||||||
ret = wait_event_interruptible(master->scan_queue,
|
ret = wait_event_interruptible(master->scan_queue,
|
||||||
|
|
@ -982,9 +982,9 @@ void ec_master_queue_datagram_ext(
|
||||||
ec_datagram_t *datagram /**< datagram */
|
ec_datagram_t *datagram /**< datagram */
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
down(&master->ext_queue_sem);
|
ec_lock_down(&master->ext_queue_sem);
|
||||||
list_add_tail(&datagram->queue, &master->ext_datagram_queue);
|
list_add_tail(&datagram->queue, &master->ext_datagram_queue);
|
||||||
up(&master->ext_queue_sem);
|
ec_lock_up(&master->ext_queue_sem);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
@ -1592,12 +1592,12 @@ static int ec_master_idle_thread(void *priv_data)
|
||||||
ec_datagram_output_stats(&master->fsm_datagram);
|
ec_datagram_output_stats(&master->fsm_datagram);
|
||||||
|
|
||||||
// receive
|
// receive
|
||||||
down(&master->io_sem);
|
ec_lock_down(&master->io_sem);
|
||||||
ecrt_master_receive(master);
|
ecrt_master_receive(master);
|
||||||
up(&master->io_sem);
|
ec_lock_up(&master->io_sem);
|
||||||
|
|
||||||
// execute master & slave state machines
|
// execute master & slave state machines
|
||||||
if (down_interruptible(&master->master_sem)) {
|
if (ec_lock_down_interruptible(&master->master_sem)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1605,15 +1605,15 @@ static int ec_master_idle_thread(void *priv_data)
|
||||||
|
|
||||||
ec_master_exec_slave_fsms(master);
|
ec_master_exec_slave_fsms(master);
|
||||||
|
|
||||||
up(&master->master_sem);
|
ec_lock_up(&master->master_sem);
|
||||||
|
|
||||||
// queue and send
|
// queue and send
|
||||||
down(&master->io_sem);
|
ec_lock_down(&master->io_sem);
|
||||||
if (fsm_exec) {
|
if (fsm_exec) {
|
||||||
ec_master_queue_datagram(master, &master->fsm_datagram);
|
ec_master_queue_datagram(master, &master->fsm_datagram);
|
||||||
}
|
}
|
||||||
sent_bytes = ecrt_master_send(master);
|
sent_bytes = ecrt_master_send(master);
|
||||||
up(&master->io_sem);
|
ec_lock_up(&master->io_sem);
|
||||||
|
|
||||||
if (ec_fsm_master_idle(&master->fsm)) {
|
if (ec_fsm_master_idle(&master->fsm)) {
|
||||||
#ifdef EC_USE_HRTIMER
|
#ifdef EC_USE_HRTIMER
|
||||||
|
|
@ -1657,7 +1657,7 @@ static int ec_master_operation_thread(void *priv_data)
|
||||||
ec_master_output_stats(master);
|
ec_master_output_stats(master);
|
||||||
|
|
||||||
// execute master & slave state machines
|
// execute master & slave state machines
|
||||||
if (down_interruptible(&master->master_sem)) {
|
if (ec_lock_down_interruptible(&master->master_sem)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1669,7 +1669,7 @@ static int ec_master_operation_thread(void *priv_data)
|
||||||
|
|
||||||
ec_master_exec_slave_fsms(master);
|
ec_master_exec_slave_fsms(master);
|
||||||
|
|
||||||
up(&master->master_sem);
|
ec_lock_up(&master->master_sem);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef EC_USE_HRTIMER
|
#ifdef EC_USE_HRTIMER
|
||||||
|
|
@ -1802,9 +1802,9 @@ static int ec_master_eoe_thread(void *priv_data)
|
||||||
ec_eoe_queue(eoe);
|
ec_eoe_queue(eoe);
|
||||||
}
|
}
|
||||||
// (try to) send datagrams
|
// (try to) send datagrams
|
||||||
down(&master->ext_queue_sem);
|
ec_lock_down(&master->ext_queue_sem);
|
||||||
master->send_cb(master->cb_data);
|
master->send_cb(master->cb_data);
|
||||||
up(&master->ext_queue_sem);
|
ec_lock_up(&master->ext_queue_sem);
|
||||||
}
|
}
|
||||||
|
|
||||||
schedule:
|
schedule:
|
||||||
|
|
@ -2331,7 +2331,7 @@ ec_domain_t *ecrt_master_create_domain_err(
|
||||||
return ERR_PTR(-ENOMEM);
|
return ERR_PTR(-ENOMEM);
|
||||||
}
|
}
|
||||||
|
|
||||||
down(&master->master_sem);
|
ec_lock_down(&master->master_sem);
|
||||||
|
|
||||||
if (list_empty(&master->domains)) {
|
if (list_empty(&master->domains)) {
|
||||||
index = 0;
|
index = 0;
|
||||||
|
|
@ -2343,7 +2343,7 @@ ec_domain_t *ecrt_master_create_domain_err(
|
||||||
ec_domain_init(domain, master, index);
|
ec_domain_init(domain, master, index);
|
||||||
list_add_tail(&domain->list, &master->domains);
|
list_add_tail(&domain->list, &master->domains);
|
||||||
|
|
||||||
up(&master->master_sem);
|
ec_lock_up(&master->master_sem);
|
||||||
|
|
||||||
EC_MASTER_DBG(master, 1, "Created domain %u.\n", domain->index);
|
EC_MASTER_DBG(master, 1, "Created domain %u.\n", domain->index);
|
||||||
|
|
||||||
|
|
@ -2386,21 +2386,21 @@ int ecrt_master_activate(ec_master_t *master)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
down(&master->master_sem);
|
ec_lock_down(&master->master_sem);
|
||||||
|
|
||||||
// finish all domains
|
// finish all domains
|
||||||
domain_offset = 0;
|
domain_offset = 0;
|
||||||
list_for_each_entry(domain, &master->domains, list) {
|
list_for_each_entry(domain, &master->domains, list) {
|
||||||
ret = ec_domain_finish(domain, domain_offset);
|
ret = ec_domain_finish(domain, domain_offset);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
up(&master->master_sem);
|
ec_lock_up(&master->master_sem);
|
||||||
EC_MASTER_ERR(master, "Failed to finish domain 0x%p!\n", domain);
|
EC_MASTER_ERR(master, "Failed to finish domain 0x%p!\n", domain);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
domain_offset += domain->data_size;
|
domain_offset += domain->data_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
up(&master->master_sem);
|
ec_lock_up(&master->master_sem);
|
||||||
|
|
||||||
// restart EoE process and master thread with new locking
|
// restart EoE process and master thread with new locking
|
||||||
|
|
||||||
|
|
@ -2726,14 +2726,14 @@ ec_slave_config_t *ecrt_master_slave_config_err(ec_master_t *master,
|
||||||
ec_slave_config_init(sc, master,
|
ec_slave_config_init(sc, master,
|
||||||
alias, position, vendor_id, product_code);
|
alias, position, vendor_id, product_code);
|
||||||
|
|
||||||
down(&master->master_sem);
|
ec_lock_down(&master->master_sem);
|
||||||
|
|
||||||
// try to find the addressed slave
|
// try to find the addressed slave
|
||||||
ec_slave_config_attach(sc);
|
ec_slave_config_attach(sc);
|
||||||
ec_slave_config_load_default_sync_config(sc);
|
ec_slave_config_load_default_sync_config(sc);
|
||||||
list_add_tail(&sc->list, &master->configs);
|
list_add_tail(&sc->list, &master->configs);
|
||||||
|
|
||||||
up(&master->master_sem);
|
ec_lock_up(&master->master_sem);
|
||||||
}
|
}
|
||||||
|
|
||||||
return sc;
|
return sc;
|
||||||
|
|
@ -2797,7 +2797,7 @@ int ecrt_master_get_slave(ec_master_t *master, uint16_t slave_position,
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
if (down_interruptible(&master->master_sem)) {
|
if (ec_lock_down_interruptible(&master->master_sem)) {
|
||||||
return -EINTR;
|
return -EINTR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2845,7 +2845,7 @@ int ecrt_master_get_slave(ec_master_t *master, uint16_t slave_position,
|
||||||
}
|
}
|
||||||
|
|
||||||
out_get_slave:
|
out_get_slave:
|
||||||
up(&master->master_sem);
|
ec_lock_up(&master->master_sem);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
@ -3055,13 +3055,13 @@ int ecrt_master_sdo_download(ec_master_t *master, uint16_t slave_position,
|
||||||
request.data_size = data_size;
|
request.data_size = data_size;
|
||||||
ecrt_sdo_request_write(&request);
|
ecrt_sdo_request_write(&request);
|
||||||
|
|
||||||
if (down_interruptible(&master->master_sem)) {
|
if (ec_lock_down_interruptible(&master->master_sem)) {
|
||||||
ec_sdo_request_clear(&request);
|
ec_sdo_request_clear(&request);
|
||||||
return -EINTR;
|
return -EINTR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(slave = ec_master_find_slave(master, 0, slave_position))) {
|
if (!(slave = ec_master_find_slave(master, 0, slave_position))) {
|
||||||
up(&master->master_sem);
|
ec_lock_up(&master->master_sem);
|
||||||
EC_MASTER_ERR(master, "Slave %u does not exist!\n", slave_position);
|
EC_MASTER_ERR(master, "Slave %u does not exist!\n", slave_position);
|
||||||
ec_sdo_request_clear(&request);
|
ec_sdo_request_clear(&request);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
@ -3072,21 +3072,21 @@ int ecrt_master_sdo_download(ec_master_t *master, uint16_t slave_position,
|
||||||
// schedule request.
|
// schedule request.
|
||||||
list_add_tail(&request.list, &slave->sdo_requests);
|
list_add_tail(&request.list, &slave->sdo_requests);
|
||||||
|
|
||||||
up(&master->master_sem);
|
ec_lock_up(&master->master_sem);
|
||||||
|
|
||||||
// wait for processing through FSM
|
// wait for processing through FSM
|
||||||
if (wait_event_interruptible(master->request_queue,
|
if (wait_event_interruptible(master->request_queue,
|
||||||
request.state != EC_INT_REQUEST_QUEUED)) {
|
request.state != EC_INT_REQUEST_QUEUED)) {
|
||||||
// interrupted by signal
|
// interrupted by signal
|
||||||
down(&master->master_sem);
|
ec_lock_down(&master->master_sem);
|
||||||
if (request.state == EC_INT_REQUEST_QUEUED) {
|
if (request.state == EC_INT_REQUEST_QUEUED) {
|
||||||
list_del(&request.list);
|
list_del(&request.list);
|
||||||
up(&master->master_sem);
|
ec_lock_up(&master->master_sem);
|
||||||
ec_sdo_request_clear(&request);
|
ec_sdo_request_clear(&request);
|
||||||
return -EINTR;
|
return -EINTR;
|
||||||
}
|
}
|
||||||
// request already processing: interrupt not possible.
|
// request already processing: interrupt not possible.
|
||||||
up(&master->master_sem);
|
ec_lock_up(&master->master_sem);
|
||||||
}
|
}
|
||||||
|
|
||||||
// wait until master FSM has finished processing
|
// wait until master FSM has finished processing
|
||||||
|
|
@ -3140,13 +3140,13 @@ int ecrt_master_sdo_download_complete(ec_master_t *master,
|
||||||
request.data_size = data_size;
|
request.data_size = data_size;
|
||||||
ecrt_sdo_request_write(&request);
|
ecrt_sdo_request_write(&request);
|
||||||
|
|
||||||
if (down_interruptible(&master->master_sem)) {
|
if (ec_lock_down_interruptible(&master->master_sem)) {
|
||||||
ec_sdo_request_clear(&request);
|
ec_sdo_request_clear(&request);
|
||||||
return -EINTR;
|
return -EINTR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(slave = ec_master_find_slave(master, 0, slave_position))) {
|
if (!(slave = ec_master_find_slave(master, 0, slave_position))) {
|
||||||
up(&master->master_sem);
|
ec_lock_up(&master->master_sem);
|
||||||
EC_MASTER_ERR(master, "Slave %u does not exist!\n", slave_position);
|
EC_MASTER_ERR(master, "Slave %u does not exist!\n", slave_position);
|
||||||
ec_sdo_request_clear(&request);
|
ec_sdo_request_clear(&request);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
@ -3158,21 +3158,21 @@ int ecrt_master_sdo_download_complete(ec_master_t *master,
|
||||||
// schedule request.
|
// schedule request.
|
||||||
list_add_tail(&request.list, &slave->sdo_requests);
|
list_add_tail(&request.list, &slave->sdo_requests);
|
||||||
|
|
||||||
up(&master->master_sem);
|
ec_lock_up(&master->master_sem);
|
||||||
|
|
||||||
// wait for processing through FSM
|
// wait for processing through FSM
|
||||||
if (wait_event_interruptible(master->request_queue,
|
if (wait_event_interruptible(master->request_queue,
|
||||||
request.state != EC_INT_REQUEST_QUEUED)) {
|
request.state != EC_INT_REQUEST_QUEUED)) {
|
||||||
// interrupted by signal
|
// interrupted by signal
|
||||||
down(&master->master_sem);
|
ec_lock_down(&master->master_sem);
|
||||||
if (request.state == EC_INT_REQUEST_QUEUED) {
|
if (request.state == EC_INT_REQUEST_QUEUED) {
|
||||||
list_del(&request.list);
|
list_del(&request.list);
|
||||||
up(&master->master_sem);
|
ec_lock_up(&master->master_sem);
|
||||||
ec_sdo_request_clear(&request);
|
ec_sdo_request_clear(&request);
|
||||||
return -EINTR;
|
return -EINTR;
|
||||||
}
|
}
|
||||||
// request already processing: interrupt not possible.
|
// request already processing: interrupt not possible.
|
||||||
up(&master->master_sem);
|
ec_lock_up(&master->master_sem);
|
||||||
}
|
}
|
||||||
|
|
||||||
// wait until master FSM has finished processing
|
// wait until master FSM has finished processing
|
||||||
|
|
@ -3213,13 +3213,13 @@ int ecrt_master_sdo_upload(ec_master_t *master, uint16_t slave_position,
|
||||||
ecrt_sdo_request_index(&request, index, subindex);
|
ecrt_sdo_request_index(&request, index, subindex);
|
||||||
ecrt_sdo_request_read(&request);
|
ecrt_sdo_request_read(&request);
|
||||||
|
|
||||||
if (down_interruptible(&master->master_sem)) {
|
if (ec_lock_down_interruptible(&master->master_sem)) {
|
||||||
ec_sdo_request_clear(&request);
|
ec_sdo_request_clear(&request);
|
||||||
return -EINTR;
|
return -EINTR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(slave = ec_master_find_slave(master, 0, slave_position))) {
|
if (!(slave = ec_master_find_slave(master, 0, slave_position))) {
|
||||||
up(&master->master_sem);
|
ec_lock_up(&master->master_sem);
|
||||||
ec_sdo_request_clear(&request);
|
ec_sdo_request_clear(&request);
|
||||||
EC_MASTER_ERR(master, "Slave %u does not exist!\n", slave_position);
|
EC_MASTER_ERR(master, "Slave %u does not exist!\n", slave_position);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
@ -3230,21 +3230,21 @@ int ecrt_master_sdo_upload(ec_master_t *master, uint16_t slave_position,
|
||||||
// schedule request.
|
// schedule request.
|
||||||
list_add_tail(&request.list, &slave->sdo_requests);
|
list_add_tail(&request.list, &slave->sdo_requests);
|
||||||
|
|
||||||
up(&master->master_sem);
|
ec_lock_up(&master->master_sem);
|
||||||
|
|
||||||
// wait for processing through FSM
|
// wait for processing through FSM
|
||||||
if (wait_event_interruptible(master->request_queue,
|
if (wait_event_interruptible(master->request_queue,
|
||||||
request.state != EC_INT_REQUEST_QUEUED)) {
|
request.state != EC_INT_REQUEST_QUEUED)) {
|
||||||
// interrupted by signal
|
// interrupted by signal
|
||||||
down(&master->master_sem);
|
ec_lock_down(&master->master_sem);
|
||||||
if (request.state == EC_INT_REQUEST_QUEUED) {
|
if (request.state == EC_INT_REQUEST_QUEUED) {
|
||||||
list_del(&request.list);
|
list_del(&request.list);
|
||||||
up(&master->master_sem);
|
ec_lock_up(&master->master_sem);
|
||||||
ec_sdo_request_clear(&request);
|
ec_sdo_request_clear(&request);
|
||||||
return -EINTR;
|
return -EINTR;
|
||||||
}
|
}
|
||||||
// request already processing: interrupt not possible.
|
// request already processing: interrupt not possible.
|
||||||
up(&master->master_sem);
|
ec_lock_up(&master->master_sem);
|
||||||
}
|
}
|
||||||
|
|
||||||
// wait until master FSM has finished processing
|
// wait until master FSM has finished processing
|
||||||
|
|
@ -3304,13 +3304,13 @@ int ecrt_master_write_idn(ec_master_t *master, uint16_t slave_position,
|
||||||
request.data_size = data_size;
|
request.data_size = data_size;
|
||||||
ec_soe_request_write(&request);
|
ec_soe_request_write(&request);
|
||||||
|
|
||||||
if (down_interruptible(&master->master_sem)) {
|
if (ec_lock_down_interruptible(&master->master_sem)) {
|
||||||
ec_soe_request_clear(&request);
|
ec_soe_request_clear(&request);
|
||||||
return -EINTR;
|
return -EINTR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(slave = ec_master_find_slave(master, 0, slave_position))) {
|
if (!(slave = ec_master_find_slave(master, 0, slave_position))) {
|
||||||
up(&master->master_sem);
|
ec_lock_up(&master->master_sem);
|
||||||
EC_MASTER_ERR(master, "Slave %u does not exist!\n",
|
EC_MASTER_ERR(master, "Slave %u does not exist!\n",
|
||||||
slave_position);
|
slave_position);
|
||||||
ec_soe_request_clear(&request);
|
ec_soe_request_clear(&request);
|
||||||
|
|
@ -3322,21 +3322,21 @@ int ecrt_master_write_idn(ec_master_t *master, uint16_t slave_position,
|
||||||
// schedule SoE write request.
|
// schedule SoE write request.
|
||||||
list_add_tail(&request.list, &slave->soe_requests);
|
list_add_tail(&request.list, &slave->soe_requests);
|
||||||
|
|
||||||
up(&master->master_sem);
|
ec_lock_up(&master->master_sem);
|
||||||
|
|
||||||
// wait for processing through FSM
|
// wait for processing through FSM
|
||||||
if (wait_event_interruptible(master->request_queue,
|
if (wait_event_interruptible(master->request_queue,
|
||||||
request.state != EC_INT_REQUEST_QUEUED)) {
|
request.state != EC_INT_REQUEST_QUEUED)) {
|
||||||
// interrupted by signal
|
// interrupted by signal
|
||||||
down(&master->master_sem);
|
ec_lock_down(&master->master_sem);
|
||||||
if (request.state == EC_INT_REQUEST_QUEUED) {
|
if (request.state == EC_INT_REQUEST_QUEUED) {
|
||||||
// abort request
|
// abort request
|
||||||
list_del(&request.list);
|
list_del(&request.list);
|
||||||
up(&master->master_sem);
|
ec_lock_up(&master->master_sem);
|
||||||
ec_soe_request_clear(&request);
|
ec_soe_request_clear(&request);
|
||||||
return -EINTR;
|
return -EINTR;
|
||||||
}
|
}
|
||||||
up(&master->master_sem);
|
ec_lock_up(&master->master_sem);
|
||||||
}
|
}
|
||||||
|
|
||||||
// wait until master FSM has finished processing
|
// wait until master FSM has finished processing
|
||||||
|
|
@ -3371,13 +3371,13 @@ int ecrt_master_read_idn(ec_master_t *master, uint16_t slave_position,
|
||||||
ec_soe_request_set_idn(&request, idn);
|
ec_soe_request_set_idn(&request, idn);
|
||||||
ec_soe_request_read(&request);
|
ec_soe_request_read(&request);
|
||||||
|
|
||||||
if (down_interruptible(&master->master_sem)) {
|
if (ec_lock_down_interruptible(&master->master_sem)) {
|
||||||
ec_soe_request_clear(&request);
|
ec_soe_request_clear(&request);
|
||||||
return -EINTR;
|
return -EINTR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(slave = ec_master_find_slave(master, 0, slave_position))) {
|
if (!(slave = ec_master_find_slave(master, 0, slave_position))) {
|
||||||
up(&master->master_sem);
|
ec_lock_up(&master->master_sem);
|
||||||
ec_soe_request_clear(&request);
|
ec_soe_request_clear(&request);
|
||||||
EC_MASTER_ERR(master, "Slave %u does not exist!\n", slave_position);
|
EC_MASTER_ERR(master, "Slave %u does not exist!\n", slave_position);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
@ -3388,21 +3388,21 @@ int ecrt_master_read_idn(ec_master_t *master, uint16_t slave_position,
|
||||||
// schedule request.
|
// schedule request.
|
||||||
list_add_tail(&request.list, &slave->soe_requests);
|
list_add_tail(&request.list, &slave->soe_requests);
|
||||||
|
|
||||||
up(&master->master_sem);
|
ec_lock_up(&master->master_sem);
|
||||||
|
|
||||||
// wait for processing through FSM
|
// wait for processing through FSM
|
||||||
if (wait_event_interruptible(master->request_queue,
|
if (wait_event_interruptible(master->request_queue,
|
||||||
request.state != EC_INT_REQUEST_QUEUED)) {
|
request.state != EC_INT_REQUEST_QUEUED)) {
|
||||||
// interrupted by signal
|
// interrupted by signal
|
||||||
down(&master->master_sem);
|
ec_lock_down(&master->master_sem);
|
||||||
if (request.state == EC_INT_REQUEST_QUEUED) {
|
if (request.state == EC_INT_REQUEST_QUEUED) {
|
||||||
list_del(&request.list);
|
list_del(&request.list);
|
||||||
up(&master->master_sem);
|
ec_lock_up(&master->master_sem);
|
||||||
ec_soe_request_clear(&request);
|
ec_soe_request_clear(&request);
|
||||||
return -EINTR;
|
return -EINTR;
|
||||||
}
|
}
|
||||||
// request already processing: interrupt not possible.
|
// request already processing: interrupt not possible.
|
||||||
up(&master->master_sem);
|
ec_lock_up(&master->master_sem);
|
||||||
}
|
}
|
||||||
|
|
||||||
// wait until master FSM has finished processing
|
// wait until master FSM has finished processing
|
||||||
|
|
|
||||||
|
|
@ -43,16 +43,11 @@
|
||||||
#include <linux/wait.h>
|
#include <linux/wait.h>
|
||||||
#include <linux/kthread.h>
|
#include <linux/kthread.h>
|
||||||
|
|
||||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
|
|
||||||
#include <linux/semaphore.h>
|
|
||||||
#else
|
|
||||||
#include <asm/semaphore.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "device.h"
|
#include "device.h"
|
||||||
#include "domain.h"
|
#include "domain.h"
|
||||||
#include "ethernet.h"
|
#include "ethernet.h"
|
||||||
#include "fsm_master.h"
|
#include "fsm_master.h"
|
||||||
|
#include "locks.h"
|
||||||
#include "cdev.h"
|
#include "cdev.h"
|
||||||
|
|
||||||
#ifdef EC_RTDM
|
#ifdef EC_RTDM
|
||||||
|
|
@ -206,7 +201,7 @@ struct ec_master {
|
||||||
ec_rtdm_dev_t rtdm_dev; /**< RTDM device. */
|
ec_rtdm_dev_t rtdm_dev; /**< RTDM device. */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct semaphore master_sem; /**< Master semaphore. */
|
ec_lock_t master_sem; /**< Master semaphore. */
|
||||||
|
|
||||||
ec_device_t devices[EC_MAX_NUM_DEVICES]; /**< EtherCAT devices. */
|
ec_device_t devices[EC_MAX_NUM_DEVICES]; /**< EtherCAT devices. */
|
||||||
const uint8_t *macs[EC_MAX_NUM_DEVICES]; /**< Device MAC addresses. */
|
const uint8_t *macs[EC_MAX_NUM_DEVICES]; /**< Device MAC addresses. */
|
||||||
|
|
@ -215,7 +210,7 @@ struct ec_master {
|
||||||
ec_master_num_devices(), because it may be
|
ec_master_num_devices(), because it may be
|
||||||
optimized! */
|
optimized! */
|
||||||
#endif
|
#endif
|
||||||
struct semaphore device_sem; /**< Device semaphore. */
|
ec_lock_t device_sem; /**< Device semaphore. */
|
||||||
ec_device_stats_t device_stats; /**< Device statistics. */
|
ec_device_stats_t device_stats; /**< Device statistics. */
|
||||||
|
|
||||||
ec_fsm_master_t fsm; /**< Master state machine. */
|
ec_fsm_master_t fsm; /**< Master state machine. */
|
||||||
|
|
@ -252,13 +247,13 @@ struct ec_master {
|
||||||
|
|
||||||
unsigned int scan_busy; /**< Current scan state. */
|
unsigned int scan_busy; /**< Current scan state. */
|
||||||
unsigned int allow_scan; /**< \a True, if slave scanning is allowed. */
|
unsigned int allow_scan; /**< \a True, if slave scanning is allowed. */
|
||||||
struct semaphore scan_sem; /**< Semaphore protecting the \a scan_busy
|
ec_lock_t scan_sem; /**< Semaphore protecting the \a scan_busy
|
||||||
variable and the \a allow_scan flag. */
|
variable and the \a allow_scan flag. */
|
||||||
wait_queue_head_t scan_queue; /**< Queue for processes that wait for
|
wait_queue_head_t scan_queue; /**< Queue for processes that wait for
|
||||||
slave scanning. */
|
slave scanning. */
|
||||||
|
|
||||||
unsigned int config_busy; /**< State of slave configuration. */
|
unsigned int config_busy; /**< State of slave configuration. */
|
||||||
struct semaphore config_sem; /**< Semaphore protecting the \a config_busy
|
ec_lock_t config_sem; /**< Semaphore protecting the \a config_busy
|
||||||
variable and the allow_config flag. */
|
variable and the allow_config flag. */
|
||||||
wait_queue_head_t config_queue; /**< Queue for processes that wait for
|
wait_queue_head_t config_queue; /**< Queue for processes that wait for
|
||||||
slave configuration. */
|
slave configuration. */
|
||||||
|
|
@ -268,7 +263,7 @@ struct ec_master {
|
||||||
|
|
||||||
struct list_head ext_datagram_queue; /**< Queue for non-application
|
struct list_head ext_datagram_queue; /**< Queue for non-application
|
||||||
datagrams. */
|
datagrams. */
|
||||||
struct semaphore ext_queue_sem; /**< Semaphore protecting the \a
|
ec_lock_t ext_queue_sem; /**< Semaphore protecting the \a
|
||||||
ext_datagram_queue. */
|
ext_datagram_queue. */
|
||||||
|
|
||||||
ec_datagram_t ext_datagram_ring[EC_EXT_RING_SIZE]; /**< External datagram
|
ec_datagram_t ext_datagram_ring[EC_EXT_RING_SIZE]; /**< External datagram
|
||||||
|
|
@ -295,7 +290,7 @@ struct ec_master {
|
||||||
struct list_head eoe_handlers; /**< Ethernet over EtherCAT handlers. */
|
struct list_head eoe_handlers; /**< Ethernet over EtherCAT handlers. */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct semaphore io_sem; /**< Semaphore used in \a IDLE phase. */
|
ec_lock_t io_sem; /**< Semaphore used in \a IDLE phase. */
|
||||||
|
|
||||||
void (*send_cb)(void *); /**< Current send datagrams callback. */
|
void (*send_cb)(void *); /**< Current send datagrams callback. */
|
||||||
void (*receive_cb)(void *); /**< Current receive datagrams callback. */
|
void (*receive_cb)(void *); /**< Current receive datagrams callback. */
|
||||||
|
|
|
||||||
|
|
@ -61,7 +61,7 @@ static unsigned int backup_count; /**< Number of backup devices. */
|
||||||
static unsigned int debug_level; /**< Debug level parameter. */
|
static unsigned int debug_level; /**< Debug level parameter. */
|
||||||
|
|
||||||
static ec_master_t *masters; /**< Array of masters. */
|
static ec_master_t *masters; /**< Array of masters. */
|
||||||
static struct semaphore master_sem; /**< Master semaphore. */
|
static ec_lock_t master_sem; /**< Master semaphore. */
|
||||||
|
|
||||||
dev_t device_number; /**< Device number for master cdevs. */
|
dev_t device_number; /**< Device number for master cdevs. */
|
||||||
struct class *class; /**< Device class. */
|
struct class *class; /**< Device class. */
|
||||||
|
|
@ -101,7 +101,7 @@ int __init ec_init_module(void)
|
||||||
|
|
||||||
EC_INFO("Master driver %s\n", EC_MASTER_VERSION);
|
EC_INFO("Master driver %s\n", EC_MASTER_VERSION);
|
||||||
|
|
||||||
sema_init(&master_sem, 1);
|
ec_lock_init(&master_sem);
|
||||||
|
|
||||||
if (master_count) {
|
if (master_count) {
|
||||||
if (alloc_chrdev_region(&device_number,
|
if (alloc_chrdev_region(&device_number,
|
||||||
|
|
@ -484,7 +484,7 @@ ec_device_t *ecdev_offer(
|
||||||
master = &masters[i];
|
master = &masters[i];
|
||||||
ec_mac_print(net_dev->dev_addr, str);
|
ec_mac_print(net_dev->dev_addr, str);
|
||||||
|
|
||||||
if (down_interruptible(&master->device_sem)) {
|
if (ec_lock_down_interruptible(&master->device_sem)) {
|
||||||
EC_MASTER_WARN(master, "%s() interrupted!\n", __func__);
|
EC_MASTER_WARN(master, "%s() interrupted!\n", __func__);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
@ -500,7 +500,7 @@ ec_device_t *ecdev_offer(
|
||||||
|
|
||||||
ec_device_attach(&master->devices[dev_idx],
|
ec_device_attach(&master->devices[dev_idx],
|
||||||
net_dev, poll, module);
|
net_dev, poll, module);
|
||||||
up(&master->device_sem);
|
ec_lock_up(&master->device_sem);
|
||||||
|
|
||||||
snprintf(net_dev->name, IFNAMSIZ, "ec%c%u",
|
snprintf(net_dev->name, IFNAMSIZ, "ec%c%u",
|
||||||
ec_device_names[dev_idx != 0][0], master->index);
|
ec_device_names[dev_idx != 0][0], master->index);
|
||||||
|
|
@ -509,7 +509,7 @@ ec_device_t *ecdev_offer(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
up(&master->device_sem);
|
ec_lock_up(&master->device_sem);
|
||||||
|
|
||||||
EC_MASTER_DBG(master, 1, "Master declined device %s.\n", str);
|
EC_MASTER_DBG(master, 1, "Master declined device %s.\n", str);
|
||||||
}
|
}
|
||||||
|
|
@ -543,27 +543,27 @@ ec_master_t *ecrt_request_master_err(
|
||||||
}
|
}
|
||||||
master = &masters[master_index];
|
master = &masters[master_index];
|
||||||
|
|
||||||
if (down_interruptible(&master_sem)) {
|
if (ec_lock_down_interruptible(&master_sem)) {
|
||||||
errptr = ERR_PTR(-EINTR);
|
errptr = ERR_PTR(-EINTR);
|
||||||
goto out_return;
|
goto out_return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (master->reserved) {
|
if (master->reserved) {
|
||||||
up(&master_sem);
|
ec_lock_up(&master_sem);
|
||||||
EC_MASTER_ERR(master, "Master already in use!\n");
|
EC_MASTER_ERR(master, "Master already in use!\n");
|
||||||
errptr = ERR_PTR(-EBUSY);
|
errptr = ERR_PTR(-EBUSY);
|
||||||
goto out_return;
|
goto out_return;
|
||||||
}
|
}
|
||||||
master->reserved = 1;
|
master->reserved = 1;
|
||||||
up(&master_sem);
|
ec_lock_up(&master_sem);
|
||||||
|
|
||||||
if (down_interruptible(&master->device_sem)) {
|
if (ec_lock_down_interruptible(&master->device_sem)) {
|
||||||
errptr = ERR_PTR(-EINTR);
|
errptr = ERR_PTR(-EINTR);
|
||||||
goto out_release;
|
goto out_release;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (master->phase != EC_IDLE) {
|
if (master->phase != EC_IDLE) {
|
||||||
up(&master->device_sem);
|
ec_lock_up(&master->device_sem);
|
||||||
EC_MASTER_ERR(master, "Master still waiting for devices!\n");
|
EC_MASTER_ERR(master, "Master still waiting for devices!\n");
|
||||||
errptr = ERR_PTR(-ENODEV);
|
errptr = ERR_PTR(-ENODEV);
|
||||||
goto out_release;
|
goto out_release;
|
||||||
|
|
@ -572,14 +572,14 @@ ec_master_t *ecrt_request_master_err(
|
||||||
for (; dev_idx < ec_master_num_devices(master); dev_idx++) {
|
for (; dev_idx < ec_master_num_devices(master); dev_idx++) {
|
||||||
ec_device_t *device = &master->devices[dev_idx];
|
ec_device_t *device = &master->devices[dev_idx];
|
||||||
if (!try_module_get(device->module)) {
|
if (!try_module_get(device->module)) {
|
||||||
up(&master->device_sem);
|
ec_lock_up(&master->device_sem);
|
||||||
EC_MASTER_ERR(master, "Device module is unloading!\n");
|
EC_MASTER_ERR(master, "Device module is unloading!\n");
|
||||||
errptr = ERR_PTR(-ENODEV);
|
errptr = ERR_PTR(-ENODEV);
|
||||||
goto out_module_put;
|
goto out_module_put;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
up(&master->device_sem);
|
ec_lock_up(&master->device_sem);
|
||||||
|
|
||||||
if (ec_master_enter_operation_phase(master)) {
|
if (ec_master_enter_operation_phase(master)) {
|
||||||
EC_MASTER_ERR(master, "Failed to enter OPERATION phase!\n");
|
EC_MASTER_ERR(master, "Failed to enter OPERATION phase!\n");
|
||||||
|
|
|
||||||
|
|
@ -202,7 +202,7 @@ int ec_slave_config_prepare_fmmu(
|
||||||
|
|
||||||
fmmu = &sc->fmmu_configs[sc->used_fmmus];
|
fmmu = &sc->fmmu_configs[sc->used_fmmus];
|
||||||
|
|
||||||
down(&sc->master->master_sem);
|
ec_lock_down(&sc->master->master_sem);
|
||||||
ec_fmmu_config_init(fmmu, sc, domain, sync_index, dir);
|
ec_fmmu_config_init(fmmu, sc, domain, sync_index, dir);
|
||||||
|
|
||||||
#if 0 //TODO overlapping PDOs
|
#if 0 //TODO overlapping PDOs
|
||||||
|
|
@ -235,7 +235,7 @@ int ec_slave_config_prepare_fmmu(
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
sc->used_fmmus++;
|
sc->used_fmmus++;
|
||||||
up(&sc->master->master_sem);
|
ec_lock_up(&sc->master->master_sem);
|
||||||
|
|
||||||
return fmmu->logical_domain_offset;
|
return fmmu->logical_domain_offset;
|
||||||
}
|
}
|
||||||
|
|
@ -731,18 +731,18 @@ int ecrt_slave_config_pdo_assign_add(ec_slave_config_t *sc,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
down(&sc->master->master_sem);
|
ec_lock_down(&sc->master->master_sem);
|
||||||
|
|
||||||
pdo = ec_pdo_list_add_pdo(&sc->sync_configs[sync_index].pdos, pdo_index);
|
pdo = ec_pdo_list_add_pdo(&sc->sync_configs[sync_index].pdos, pdo_index);
|
||||||
if (IS_ERR(pdo)) {
|
if (IS_ERR(pdo)) {
|
||||||
up(&sc->master->master_sem);
|
ec_lock_up(&sc->master->master_sem);
|
||||||
return PTR_ERR(pdo);
|
return PTR_ERR(pdo);
|
||||||
}
|
}
|
||||||
pdo->sync_index = sync_index;
|
pdo->sync_index = sync_index;
|
||||||
|
|
||||||
ec_slave_config_load_default_mapping(sc, pdo);
|
ec_slave_config_load_default_mapping(sc, pdo);
|
||||||
|
|
||||||
up(&sc->master->master_sem);
|
ec_lock_up(&sc->master->master_sem);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -759,9 +759,9 @@ void ecrt_slave_config_pdo_assign_clear(ec_slave_config_t *sc,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
down(&sc->master->master_sem);
|
ec_lock_down(&sc->master->master_sem);
|
||||||
ec_pdo_list_clear_pdos(&sc->sync_configs[sync_index].pdos);
|
ec_pdo_list_clear_pdos(&sc->sync_configs[sync_index].pdos);
|
||||||
up(&sc->master->master_sem);
|
ec_lock_up(&sc->master->master_sem);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
@ -787,10 +787,10 @@ int ecrt_slave_config_pdo_mapping_add(ec_slave_config_t *sc,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (pdo) {
|
if (pdo) {
|
||||||
down(&sc->master->master_sem);
|
ec_lock_down(&sc->master->master_sem);
|
||||||
entry = ec_pdo_add_entry(pdo, entry_index, entry_subindex,
|
entry = ec_pdo_add_entry(pdo, entry_index, entry_subindex,
|
||||||
entry_bit_length);
|
entry_bit_length);
|
||||||
up(&sc->master->master_sem);
|
ec_lock_up(&sc->master->master_sem);
|
||||||
if (IS_ERR(entry))
|
if (IS_ERR(entry))
|
||||||
retval = PTR_ERR(entry);
|
retval = PTR_ERR(entry);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -818,9 +818,9 @@ void ecrt_slave_config_pdo_mapping_clear(ec_slave_config_t *sc,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (pdo) {
|
if (pdo) {
|
||||||
down(&sc->master->master_sem);
|
ec_lock_down(&sc->master->master_sem);
|
||||||
ec_pdo_clear_entries(pdo);
|
ec_pdo_clear_entries(pdo);
|
||||||
up(&sc->master->master_sem);
|
ec_lock_up(&sc->master->master_sem);
|
||||||
} else {
|
} else {
|
||||||
EC_CONFIG_WARN(sc, "PDO 0x%04X is not assigned.\n", pdo_index);
|
EC_CONFIG_WARN(sc, "PDO 0x%04X is not assigned.\n", pdo_index);
|
||||||
}
|
}
|
||||||
|
|
@ -1066,9 +1066,9 @@ int ecrt_slave_config_sdo(ec_slave_config_t *sc, uint16_t index,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
down(&sc->master->master_sem);
|
ec_lock_down(&sc->master->master_sem);
|
||||||
list_add_tail(&req->list, &sc->sdo_configs);
|
list_add_tail(&req->list, &sc->sdo_configs);
|
||||||
up(&sc->master->master_sem);
|
ec_lock_up(&sc->master->master_sem);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1151,9 +1151,9 @@ int ecrt_slave_config_complete_sdo(ec_slave_config_t *sc, uint16_t index,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
down(&sc->master->master_sem);
|
ec_lock_down(&sc->master->master_sem);
|
||||||
list_add_tail(&req->list, &sc->sdo_configs);
|
list_add_tail(&req->list, &sc->sdo_configs);
|
||||||
up(&sc->master->master_sem);
|
ec_lock_up(&sc->master->master_sem);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1220,9 +1220,9 @@ ec_sdo_request_t *ecrt_slave_config_create_sdo_request_err(
|
||||||
memset(req->data, 0x00, size);
|
memset(req->data, 0x00, size);
|
||||||
req->data_size = size;
|
req->data_size = size;
|
||||||
|
|
||||||
down(&sc->master->master_sem);
|
ec_lock_down(&sc->master->master_sem);
|
||||||
list_add_tail(&req->list, &sc->sdo_requests);
|
list_add_tail(&req->list, &sc->sdo_requests);
|
||||||
up(&sc->master->master_sem);
|
ec_lock_up(&sc->master->master_sem);
|
||||||
|
|
||||||
return req;
|
return req;
|
||||||
}
|
}
|
||||||
|
|
@ -1263,9 +1263,9 @@ ec_reg_request_t *ecrt_slave_config_create_reg_request_err(
|
||||||
return ERR_PTR(ret);
|
return ERR_PTR(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
down(&sc->master->master_sem);
|
ec_lock_down(&sc->master->master_sem);
|
||||||
list_add_tail(®->list, &sc->reg_requests);
|
list_add_tail(®->list, &sc->reg_requests);
|
||||||
up(&sc->master->master_sem);
|
ec_lock_up(&sc->master->master_sem);
|
||||||
|
|
||||||
return reg;
|
return reg;
|
||||||
}
|
}
|
||||||
|
|
@ -1305,9 +1305,9 @@ ec_voe_handler_t *ecrt_slave_config_create_voe_handler_err(
|
||||||
return ERR_PTR(ret);
|
return ERR_PTR(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
down(&sc->master->master_sem);
|
ec_lock_down(&sc->master->master_sem);
|
||||||
list_add_tail(&voe->list, &sc->voe_handlers);
|
list_add_tail(&voe->list, &sc->voe_handlers);
|
||||||
up(&sc->master->master_sem);
|
ec_lock_up(&sc->master->master_sem);
|
||||||
|
|
||||||
return voe;
|
return voe;
|
||||||
}
|
}
|
||||||
|
|
@ -1388,9 +1388,9 @@ int ecrt_slave_config_idn(ec_slave_config_t *sc, uint8_t drive_no,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
down(&sc->master->master_sem);
|
ec_lock_down(&sc->master->master_sem);
|
||||||
list_add_tail(&req->list, &sc->soe_configs);
|
list_add_tail(&req->list, &sc->soe_configs);
|
||||||
up(&sc->master->master_sem);
|
ec_lock_up(&sc->master->master_sem);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue