Applied 0016-If-enable-rtmutex-use-rtmutexes-instead-of-semaphore.patch

This commit is contained in:
Florian Pose 2022-06-23 11:21:51 +02:00
parent 667e93284d
commit 9955855f7e
13 changed files with 417 additions and 317 deletions

View File

@ -812,6 +812,35 @@ else
AC_MSG_RESULT([no])
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
#------------------------------------------------------------------------------

View File

@ -57,6 +57,7 @@ noinst_HEADERS = \
fsm_soe.c fsm_soe.h \
globals.h \
ioctl.c ioctl.h \
locks.h \
mailbox.c mailbox.h \
master.c master.h \
module.c \

View File

@ -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);
down(&master->device_sem);
ec_lock_down(&master->device_sem);
ec_device_detach(device);
up(&master->device_sem);
ec_lock_up(&master->device_sem);
}
/*****************************************************************************/

View File

@ -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("
"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);
domain->data = mem;
domain->data_origin = EC_ORIG_EXTERNAL;
up(&domain->master->master_sem);
ec_lock_up(&domain->master->master_sem);
}
/*****************************************************************************/

View File

@ -153,7 +153,7 @@ int ec_eoe_init(
eoe->tx_queue_size = EC_EOE_TX_QUEUE_SIZE;
eoe->tx_queued_frames = 0;
sema_init(&eoe->tx_queue_sem, 1);
ec_lock_init(&eoe->tx_queue_sem);
eoe->tx_frame_number = 0xFF;
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;
down(&eoe->tx_queue_sem);
ec_lock_down(&eoe->tx_queue_sem);
list_for_each_entry_safe(frame, next, &eoe->tx_queue, queue) {
list_del(&frame->queue);
@ -332,7 +332,7 @@ void ec_eoe_flush(ec_eoe_t *eoe /**< EoE handler */)
}
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;
}
down(&eoe->tx_queue_sem);
ec_lock_down(&eoe->tx_queue_sem);
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;
// no data available.
// 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--;
up(&eoe->tx_queue_sem);
ec_lock_up(&eoe->tx_queue_sem);
eoe->tx_idle = 0;
@ -923,14 +923,14 @@ int ec_eoedev_tx(struct sk_buff *skb, /**< transmit socket buffer */
frame->skb = skb;
down(&eoe->tx_queue_sem);
ec_lock_down(&eoe->tx_queue_sem);
list_add_tail(&frame->queue, &eoe->tx_queue);
eoe->tx_queued_frames++;
if (eoe->tx_queued_frames == eoe->tx_queue_size) {
netif_stop_queue(dev);
eoe->tx_queue_active = 0;
}
up(&eoe->tx_queue_sem);
ec_lock_up(&eoe->tx_queue_sem);
#if EOE_DEBUG_LEVEL >= 2
EC_SLAVE_DBG(eoe->slave, 0, "EoE %s TX queued frame"

View File

@ -40,13 +40,8 @@
#include <linux/list.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 "locks.h"
#include "slave.h"
#include "datagram.h"
@ -109,7 +104,7 @@ struct ec_eoe
unsigned int tx_queue_size; /**< Transmit queue size. */
unsigned int tx_queue_active; /**< kernel netif queue started */
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 */
uint8_t tx_frame_number; /**< number of the transmitted frame */
uint8_t tx_fragment_number; /**< number of the fragment */

View File

@ -334,15 +334,15 @@ void ec_fsm_master_state_broadcast(
}
if (fsm->rescan_required) {
down(&master->scan_sem);
ec_lock_down(&master->scan_sem);
if (!master->allow_scan) {
up(&master->scan_sem);
ec_lock_up(&master->scan_sem);
} else {
unsigned int count = 0, next_dev_slave, ring_position;
ec_device_index_t dev_idx;
master->scan_busy = 1;
up(&master->scan_sem);
ec_lock_up(&master->scan_sem);
// clear all slaves and scan the bus
fsm->rescan_required = 0;
@ -826,9 +826,9 @@ void ec_fsm_master_action_configure(
|| slave->force_config) && !slave->error_flag) {
// Start slave configuration
down(&master->config_sem);
ec_lock_down(&master->config_sem);
master->config_busy = 1;
up(&master->config_sem);
ec_lock_up(&master->config_sem);
if (master->debug_level) {
char old_state[EC_STATE_STRING_SIZE],

File diff suppressed because it is too large Load Diff

80
master/locks.h Normal file
View File

@ -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
/*****************************************************************************/

View File

@ -153,7 +153,7 @@ int ec_master_init(ec_master_t *master, /**< EtherCAT master */
master->index = index;
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++) {
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);
sema_init(&master->device_sem, 1);
ec_lock_init(&master->device_sem);
master->phase = EC_ORPHANED;
master->active = 0;
@ -192,18 +192,18 @@ int ec_master_init(ec_master_t *master, /**< EtherCAT master */
master->scan_busy = 0;
master->allow_scan = 1;
sema_init(&master->scan_sem, 1);
ec_lock_init(&master->scan_sem);
init_waitqueue_head(&master->scan_queue);
master->config_busy = 0;
sema_init(&master->config_sem, 1);
ec_lock_init(&master->config_sem);
init_waitqueue_head(&master->config_queue);
INIT_LIST_HEAD(&master->datagram_queue);
master->datagram_index = 0;
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_fsm = 0;
@ -235,7 +235,7 @@ int ec_master_init(ec_master_t *master, /**< EtherCAT master */
INIT_LIST_HEAD(&master->eoe_handlers);
#endif
sema_init(&master->io_sem, 1);
ec_lock_init(&master->io_sem);
master->send_cb = NULL;
master->receive_cb = NULL;
master->cb_data = NULL;
@ -548,10 +548,10 @@ void ec_master_clear_config(
ec_master_t *master /**< EtherCAT master. */
)
{
down(&master->master_sem);
ec_lock_down(&master->master_sem);
ec_master_clear_domains(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;
down(&master->io_sem);
ec_lock_down(&master->io_sem);
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;
down(&master->io_sem);
ec_lock_down(&master->io_sem);
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
ec_master_thread_stop(master);
down(&master->master_sem);
ec_lock_down(&master->master_sem);
ec_master_clear_slaves(master);
up(&master->master_sem);
ec_lock_up(&master->master_sem);
ec_fsm_master_reset(&master->fsm);
}
@ -710,9 +710,9 @@ int ec_master_enter_operation_phase(
EC_MASTER_DBG(master, 1, "IDLE -> OPERATION.\n");
down(&master->config_sem);
ec_lock_down(&master->config_sem);
if (master->config_busy) {
up(&master->config_sem);
ec_lock_up(&master->config_sem);
// wait for slave configuration to complete
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"
" configuration returned.\n");
} 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
if (!master->scan_busy) {
up(&master->scan_sem);
ec_lock_up(&master->scan_sem);
} else {
up(&master->scan_sem);
ec_lock_up(&master->scan_sem);
// wait for slave scan to complete
ret = wait_event_interruptible(master->scan_queue,
@ -982,9 +982,9 @@ void ec_master_queue_datagram_ext(
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);
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);
// receive
down(&master->io_sem);
ec_lock_down(&master->io_sem);
ecrt_master_receive(master);
up(&master->io_sem);
ec_lock_up(&master->io_sem);
// execute master & slave state machines
if (down_interruptible(&master->master_sem)) {
if (ec_lock_down_interruptible(&master->master_sem)) {
break;
}
@ -1605,15 +1605,15 @@ static int ec_master_idle_thread(void *priv_data)
ec_master_exec_slave_fsms(master);
up(&master->master_sem);
ec_lock_up(&master->master_sem);
// queue and send
down(&master->io_sem);
ec_lock_down(&master->io_sem);
if (fsm_exec) {
ec_master_queue_datagram(master, &master->fsm_datagram);
}
sent_bytes = ecrt_master_send(master);
up(&master->io_sem);
ec_lock_up(&master->io_sem);
if (ec_fsm_master_idle(&master->fsm)) {
#ifdef EC_USE_HRTIMER
@ -1657,7 +1657,7 @@ static int ec_master_operation_thread(void *priv_data)
ec_master_output_stats(master);
// execute master & slave state machines
if (down_interruptible(&master->master_sem)) {
if (ec_lock_down_interruptible(&master->master_sem)) {
break;
}
@ -1669,7 +1669,7 @@ static int ec_master_operation_thread(void *priv_data)
ec_master_exec_slave_fsms(master);
up(&master->master_sem);
ec_lock_up(&master->master_sem);
}
#ifdef EC_USE_HRTIMER
@ -1802,9 +1802,9 @@ static int ec_master_eoe_thread(void *priv_data)
ec_eoe_queue(eoe);
}
// (try to) send datagrams
down(&master->ext_queue_sem);
ec_lock_down(&master->ext_queue_sem);
master->send_cb(master->cb_data);
up(&master->ext_queue_sem);
ec_lock_up(&master->ext_queue_sem);
}
schedule:
@ -2331,7 +2331,7 @@ ec_domain_t *ecrt_master_create_domain_err(
return ERR_PTR(-ENOMEM);
}
down(&master->master_sem);
ec_lock_down(&master->master_sem);
if (list_empty(&master->domains)) {
index = 0;
@ -2343,7 +2343,7 @@ ec_domain_t *ecrt_master_create_domain_err(
ec_domain_init(domain, master, index);
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);
@ -2386,21 +2386,21 @@ int ecrt_master_activate(ec_master_t *master)
return 0;
}
down(&master->master_sem);
ec_lock_down(&master->master_sem);
// finish all domains
domain_offset = 0;
list_for_each_entry(domain, &master->domains, list) {
ret = ec_domain_finish(domain, domain_offset);
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);
return ret;
}
domain_offset += domain->data_size;
}
up(&master->master_sem);
ec_lock_up(&master->master_sem);
// 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,
alias, position, vendor_id, product_code);
down(&master->master_sem);
ec_lock_down(&master->master_sem);
// try to find the addressed slave
ec_slave_config_attach(sc);
ec_slave_config_load_default_sync_config(sc);
list_add_tail(&sc->list, &master->configs);
up(&master->master_sem);
ec_lock_up(&master->master_sem);
}
return sc;
@ -2797,7 +2797,7 @@ int ecrt_master_get_slave(ec_master_t *master, uint16_t slave_position,
unsigned int i;
int ret = 0;
if (down_interruptible(&master->master_sem)) {
if (ec_lock_down_interruptible(&master->master_sem)) {
return -EINTR;
}
@ -2845,7 +2845,7 @@ int ecrt_master_get_slave(ec_master_t *master, uint16_t slave_position,
}
out_get_slave:
up(&master->master_sem);
ec_lock_up(&master->master_sem);
return ret;
}
@ -3055,13 +3055,13 @@ int ecrt_master_sdo_download(ec_master_t *master, uint16_t slave_position,
request.data_size = data_size;
ecrt_sdo_request_write(&request);
if (down_interruptible(&master->master_sem)) {
if (ec_lock_down_interruptible(&master->master_sem)) {
ec_sdo_request_clear(&request);
return -EINTR;
}
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_sdo_request_clear(&request);
return -EINVAL;
@ -3072,21 +3072,21 @@ int ecrt_master_sdo_download(ec_master_t *master, uint16_t slave_position,
// schedule request.
list_add_tail(&request.list, &slave->sdo_requests);
up(&master->master_sem);
ec_lock_up(&master->master_sem);
// wait for processing through FSM
if (wait_event_interruptible(master->request_queue,
request.state != EC_INT_REQUEST_QUEUED)) {
// interrupted by signal
down(&master->master_sem);
ec_lock_down(&master->master_sem);
if (request.state == EC_INT_REQUEST_QUEUED) {
list_del(&request.list);
up(&master->master_sem);
ec_lock_up(&master->master_sem);
ec_sdo_request_clear(&request);
return -EINTR;
}
// request already processing: interrupt not possible.
up(&master->master_sem);
ec_lock_up(&master->master_sem);
}
// 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;
ecrt_sdo_request_write(&request);
if (down_interruptible(&master->master_sem)) {
if (ec_lock_down_interruptible(&master->master_sem)) {
ec_sdo_request_clear(&request);
return -EINTR;
}
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_sdo_request_clear(&request);
return -EINVAL;
@ -3158,21 +3158,21 @@ int ecrt_master_sdo_download_complete(ec_master_t *master,
// schedule request.
list_add_tail(&request.list, &slave->sdo_requests);
up(&master->master_sem);
ec_lock_up(&master->master_sem);
// wait for processing through FSM
if (wait_event_interruptible(master->request_queue,
request.state != EC_INT_REQUEST_QUEUED)) {
// interrupted by signal
down(&master->master_sem);
ec_lock_down(&master->master_sem);
if (request.state == EC_INT_REQUEST_QUEUED) {
list_del(&request.list);
up(&master->master_sem);
ec_lock_up(&master->master_sem);
ec_sdo_request_clear(&request);
return -EINTR;
}
// request already processing: interrupt not possible.
up(&master->master_sem);
ec_lock_up(&master->master_sem);
}
// 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_read(&request);
if (down_interruptible(&master->master_sem)) {
if (ec_lock_down_interruptible(&master->master_sem)) {
ec_sdo_request_clear(&request);
return -EINTR;
}
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_MASTER_ERR(master, "Slave %u does not exist!\n", slave_position);
return -EINVAL;
@ -3230,21 +3230,21 @@ int ecrt_master_sdo_upload(ec_master_t *master, uint16_t slave_position,
// schedule request.
list_add_tail(&request.list, &slave->sdo_requests);
up(&master->master_sem);
ec_lock_up(&master->master_sem);
// wait for processing through FSM
if (wait_event_interruptible(master->request_queue,
request.state != EC_INT_REQUEST_QUEUED)) {
// interrupted by signal
down(&master->master_sem);
ec_lock_down(&master->master_sem);
if (request.state == EC_INT_REQUEST_QUEUED) {
list_del(&request.list);
up(&master->master_sem);
ec_lock_up(&master->master_sem);
ec_sdo_request_clear(&request);
return -EINTR;
}
// request already processing: interrupt not possible.
up(&master->master_sem);
ec_lock_up(&master->master_sem);
}
// 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;
ec_soe_request_write(&request);
if (down_interruptible(&master->master_sem)) {
if (ec_lock_down_interruptible(&master->master_sem)) {
ec_soe_request_clear(&request);
return -EINTR;
}
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_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.
list_add_tail(&request.list, &slave->soe_requests);
up(&master->master_sem);
ec_lock_up(&master->master_sem);
// wait for processing through FSM
if (wait_event_interruptible(master->request_queue,
request.state != EC_INT_REQUEST_QUEUED)) {
// interrupted by signal
down(&master->master_sem);
ec_lock_down(&master->master_sem);
if (request.state == EC_INT_REQUEST_QUEUED) {
// abort request
list_del(&request.list);
up(&master->master_sem);
ec_lock_up(&master->master_sem);
ec_soe_request_clear(&request);
return -EINTR;
}
up(&master->master_sem);
ec_lock_up(&master->master_sem);
}
// 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_read(&request);
if (down_interruptible(&master->master_sem)) {
if (ec_lock_down_interruptible(&master->master_sem)) {
ec_soe_request_clear(&request);
return -EINTR;
}
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_MASTER_ERR(master, "Slave %u does not exist!\n", slave_position);
return -EINVAL;
@ -3388,21 +3388,21 @@ int ecrt_master_read_idn(ec_master_t *master, uint16_t slave_position,
// schedule request.
list_add_tail(&request.list, &slave->soe_requests);
up(&master->master_sem);
ec_lock_up(&master->master_sem);
// wait for processing through FSM
if (wait_event_interruptible(master->request_queue,
request.state != EC_INT_REQUEST_QUEUED)) {
// interrupted by signal
down(&master->master_sem);
ec_lock_down(&master->master_sem);
if (request.state == EC_INT_REQUEST_QUEUED) {
list_del(&request.list);
up(&master->master_sem);
ec_lock_up(&master->master_sem);
ec_soe_request_clear(&request);
return -EINTR;
}
// request already processing: interrupt not possible.
up(&master->master_sem);
ec_lock_up(&master->master_sem);
}
// wait until master FSM has finished processing

View File

@ -43,16 +43,11 @@
#include <linux/wait.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 "domain.h"
#include "ethernet.h"
#include "fsm_master.h"
#include "locks.h"
#include "cdev.h"
#ifdef EC_RTDM
@ -206,7 +201,7 @@ struct ec_master {
ec_rtdm_dev_t rtdm_dev; /**< RTDM device. */
#endif
struct semaphore master_sem; /**< Master semaphore. */
ec_lock_t master_sem; /**< Master semaphore. */
ec_device_t devices[EC_MAX_NUM_DEVICES]; /**< EtherCAT devices. */
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
optimized! */
#endif
struct semaphore device_sem; /**< Device semaphore. */
ec_lock_t device_sem; /**< Device semaphore. */
ec_device_stats_t device_stats; /**< Device statistics. */
ec_fsm_master_t fsm; /**< Master state machine. */
@ -252,13 +247,13 @@ struct ec_master {
unsigned int scan_busy; /**< Current scan state. */
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. */
wait_queue_head_t scan_queue; /**< Queue for processes that wait for
slave scanning. */
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. */
wait_queue_head_t config_queue; /**< Queue for processes that wait for
slave configuration. */
@ -268,7 +263,7 @@ struct ec_master {
struct list_head ext_datagram_queue; /**< Queue for non-application
datagrams. */
struct semaphore ext_queue_sem; /**< Semaphore protecting the \a
ec_lock_t ext_queue_sem; /**< Semaphore protecting the \a
ext_datagram_queue. */
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. */
#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 (*receive_cb)(void *); /**< Current receive datagrams callback. */

View File

@ -61,7 +61,7 @@ static unsigned int backup_count; /**< Number of backup devices. */
static unsigned int debug_level; /**< Debug level parameter. */
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. */
struct class *class; /**< Device class. */
@ -101,7 +101,7 @@ int __init ec_init_module(void)
EC_INFO("Master driver %s\n", EC_MASTER_VERSION);
sema_init(&master_sem, 1);
ec_lock_init(&master_sem);
if (master_count) {
if (alloc_chrdev_region(&device_number,
@ -484,7 +484,7 @@ ec_device_t *ecdev_offer(
master = &masters[i];
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__);
return NULL;
}
@ -500,7 +500,7 @@ ec_device_t *ecdev_offer(
ec_device_attach(&master->devices[dev_idx],
net_dev, poll, module);
up(&master->device_sem);
ec_lock_up(&master->device_sem);
snprintf(net_dev->name, IFNAMSIZ, "ec%c%u",
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);
}
@ -543,27 +543,27 @@ ec_master_t *ecrt_request_master_err(
}
master = &masters[master_index];
if (down_interruptible(&master_sem)) {
if (ec_lock_down_interruptible(&master_sem)) {
errptr = ERR_PTR(-EINTR);
goto out_return;
}
if (master->reserved) {
up(&master_sem);
ec_lock_up(&master_sem);
EC_MASTER_ERR(master, "Master already in use!\n");
errptr = ERR_PTR(-EBUSY);
goto out_return;
}
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);
goto out_release;
}
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");
errptr = ERR_PTR(-ENODEV);
goto out_release;
@ -572,14 +572,14 @@ ec_master_t *ecrt_request_master_err(
for (; dev_idx < ec_master_num_devices(master); dev_idx++) {
ec_device_t *device = &master->devices[dev_idx];
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");
errptr = ERR_PTR(-ENODEV);
goto out_module_put;
}
}
up(&master->device_sem);
ec_lock_up(&master->device_sem);
if (ec_master_enter_operation_phase(master)) {
EC_MASTER_ERR(master, "Failed to enter OPERATION phase!\n");

View File

@ -202,7 +202,7 @@ int ec_slave_config_prepare_fmmu(
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);
#if 0 //TODO overlapping PDOs
@ -235,7 +235,7 @@ int ec_slave_config_prepare_fmmu(
#endif
sc->used_fmmus++;
up(&sc->master->master_sem);
ec_lock_up(&sc->master->master_sem);
return fmmu->logical_domain_offset;
}
@ -731,18 +731,18 @@ int ecrt_slave_config_pdo_assign_add(ec_slave_config_t *sc,
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);
if (IS_ERR(pdo)) {
up(&sc->master->master_sem);
ec_lock_up(&sc->master->master_sem);
return PTR_ERR(pdo);
}
pdo->sync_index = sync_index;
ec_slave_config_load_default_mapping(sc, pdo);
up(&sc->master->master_sem);
ec_lock_up(&sc->master->master_sem);
return 0;
}
@ -759,9 +759,9 @@ void ecrt_slave_config_pdo_assign_clear(ec_slave_config_t *sc,
return;
}
down(&sc->master->master_sem);
ec_lock_down(&sc->master->master_sem);
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;
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_bit_length);
up(&sc->master->master_sem);
ec_lock_up(&sc->master->master_sem);
if (IS_ERR(entry))
retval = PTR_ERR(entry);
} else {
@ -818,9 +818,9 @@ void ecrt_slave_config_pdo_mapping_clear(ec_slave_config_t *sc,
break;
if (pdo) {
down(&sc->master->master_sem);
ec_lock_down(&sc->master->master_sem);
ec_pdo_clear_entries(pdo);
up(&sc->master->master_sem);
ec_lock_up(&sc->master->master_sem);
} else {
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;
}
down(&sc->master->master_sem);
ec_lock_down(&sc->master->master_sem);
list_add_tail(&req->list, &sc->sdo_configs);
up(&sc->master->master_sem);
ec_lock_up(&sc->master->master_sem);
return 0;
}
@ -1151,9 +1151,9 @@ int ecrt_slave_config_complete_sdo(ec_slave_config_t *sc, uint16_t index,
return ret;
}
down(&sc->master->master_sem);
ec_lock_down(&sc->master->master_sem);
list_add_tail(&req->list, &sc->sdo_configs);
up(&sc->master->master_sem);
ec_lock_up(&sc->master->master_sem);
return 0;
}
@ -1220,9 +1220,9 @@ ec_sdo_request_t *ecrt_slave_config_create_sdo_request_err(
memset(req->data, 0x00, 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);
up(&sc->master->master_sem);
ec_lock_up(&sc->master->master_sem);
return req;
}
@ -1263,9 +1263,9 @@ ec_reg_request_t *ecrt_slave_config_create_reg_request_err(
return ERR_PTR(ret);
}
down(&sc->master->master_sem);
ec_lock_down(&sc->master->master_sem);
list_add_tail(&reg->list, &sc->reg_requests);
up(&sc->master->master_sem);
ec_lock_up(&sc->master->master_sem);
return reg;
}
@ -1305,9 +1305,9 @@ ec_voe_handler_t *ecrt_slave_config_create_voe_handler_err(
return ERR_PTR(ret);
}
down(&sc->master->master_sem);
ec_lock_down(&sc->master->master_sem);
list_add_tail(&voe->list, &sc->voe_handlers);
up(&sc->master->master_sem);
ec_lock_up(&sc->master->master_sem);
return voe;
}
@ -1388,9 +1388,9 @@ int ecrt_slave_config_idn(ec_slave_config_t *sc, uint8_t drive_no,
return ret;
}
down(&sc->master->master_sem);
ec_lock_down(&sc->master->master_sem);
list_add_tail(&req->list, &sc->soe_configs);
up(&sc->master->master_sem);
ec_lock_up(&sc->master->master_sem);
return 0;
}