use rt_mutex instead of semaphore for mutual exclusion (use --enable-mutex)
This commit is contained in:
parent
f2131608f1
commit
c059ec6f49
25
configure.ac
25
configure.ac
|
|
@ -536,6 +536,31 @@ if test "x${regalias}" = "x1"; then
|
|||
AC_DEFINE([EC_REGALIAS], [1], [Read alias adresses from register])
|
||||
fi
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# use mutexes instead of semaphores
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
AC_ARG_ENABLE([mutex],
|
||||
AS_HELP_STRING([--enable-mutex],
|
||||
[Use mutex instead of semaphores for mutual exclusion (default: no)]),
|
||||
[
|
||||
case "${enableval}" in
|
||||
yes) mutex=1
|
||||
;;
|
||||
no) mutex=0
|
||||
;;
|
||||
*) AC_MSG_ERROR([Invalid value for --enable-mutex])
|
||||
;;
|
||||
esac
|
||||
],
|
||||
[mutex=0]
|
||||
)
|
||||
|
||||
if test "x${mutex}" = "x1"; then
|
||||
AC_DEFINE([EC_USE_MUTEX], [1], [Use mutex for mutual exclusion])
|
||||
fi
|
||||
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Command-line tool
|
||||
#-----------------------------------------------------------------------------
|
||||
|
|
|
|||
456
master/cdev.c
456
master/cdev.c
File diff suppressed because it is too large
Load Diff
|
|
@ -501,9 +501,9 @@ void ecdev_withdraw(ec_device_t *device /**< EtherCAT device */)
|
|||
ec_mac_print(device->dev->dev_addr, str);
|
||||
EC_MASTER_INFO(master, "Releasing main device %s.\n", str);
|
||||
|
||||
down(&master->device_sem);
|
||||
ec_mutex_lock(&master->device_mutex);
|
||||
ec_device_detach(device);
|
||||
up(&master->device_sem);
|
||||
ec_mutex_unlock(&master->device_mutex);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
|
|||
|
|
@ -381,14 +381,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_mutex_lock(&domain->master->master_mutex);
|
||||
|
||||
ec_domain_clear_data(domain);
|
||||
|
||||
domain->data = mem;
|
||||
domain->data_origin = EC_ORIG_EXTERNAL;
|
||||
|
||||
up(&domain->master->master_sem);
|
||||
ec_mutex_unlock(&domain->master->master_mutex);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
|
|||
|
|
@ -122,7 +122,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_mutex_init(&eoe->tx_queue_mutex);
|
||||
eoe->tx_frame_number = 0xFF;
|
||||
memset(&eoe->stats, 0, sizeof(struct net_device_stats));
|
||||
|
||||
|
|
@ -231,7 +231,7 @@ void ec_eoe_flush(ec_eoe_t *eoe /**< EoE handler */)
|
|||
{
|
||||
ec_eoe_frame_t *frame, *next;
|
||||
|
||||
down(&eoe->tx_queue_sem);
|
||||
ec_mutex_lock(&eoe->tx_queue_mutex);
|
||||
|
||||
list_for_each_entry_safe(frame, next, &eoe->tx_queue, queue) {
|
||||
list_del(&frame->queue);
|
||||
|
|
@ -240,7 +240,7 @@ void ec_eoe_flush(ec_eoe_t *eoe /**< EoE handler */)
|
|||
}
|
||||
eoe->tx_queued_frames = 0;
|
||||
|
||||
up(&eoe->tx_queue_sem);
|
||||
ec_mutex_unlock(&eoe->tx_queue_mutex);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -621,10 +621,10 @@ void ec_eoe_state_tx_start(ec_eoe_t *eoe /**< EoE handler */)
|
|||
return;
|
||||
}
|
||||
|
||||
down(&eoe->tx_queue_sem);
|
||||
ec_mutex_lock(&eoe->tx_queue_mutex);
|
||||
|
||||
if (!eoe->tx_queued_frames || list_empty(&eoe->tx_queue)) {
|
||||
up(&eoe->tx_queue_sem);
|
||||
ec_mutex_unlock(&eoe->tx_queue_mutex);
|
||||
eoe->tx_idle = 1;
|
||||
// no data available.
|
||||
// start a new receive immediately.
|
||||
|
|
@ -645,7 +645,7 @@ void ec_eoe_state_tx_start(ec_eoe_t *eoe /**< EoE handler */)
|
|||
}
|
||||
|
||||
eoe->tx_queued_frames--;
|
||||
up(&eoe->tx_queue_sem);
|
||||
ec_mutex_unlock(&eoe->tx_queue_mutex);
|
||||
|
||||
eoe->tx_idle = 0;
|
||||
|
||||
|
|
@ -813,14 +813,14 @@ int ec_eoedev_tx(struct sk_buff *skb, /**< transmit socket buffer */
|
|||
|
||||
frame->skb = skb;
|
||||
|
||||
down(&eoe->tx_queue_sem);
|
||||
ec_mutex_lock(&eoe->tx_queue_mutex);
|
||||
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_mutex_unlock(&eoe->tx_queue_mutex);
|
||||
|
||||
#if EOE_DEBUG_LEVEL >= 2
|
||||
EC_SLAVE_DBG(eoe->slave, 0, "EoE %s TX queued frame"
|
||||
|
|
|
|||
|
|
@ -92,7 +92,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. */
|
||||
struct ec_mutex_t tx_queue_mutex; /**< Mutex 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 */
|
||||
|
|
|
|||
|
|
@ -238,12 +238,12 @@ void ec_fsm_master_state_broadcast(
|
|||
}
|
||||
|
||||
if (fsm->rescan_required) {
|
||||
down(&master->scan_sem);
|
||||
ec_mutex_lock(&master->scan_mutex);
|
||||
if (!master->allow_scan) {
|
||||
up(&master->scan_sem);
|
||||
ec_mutex_unlock(&master->scan_mutex);
|
||||
} else {
|
||||
master->scan_busy = 1;
|
||||
up(&master->scan_sem);
|
||||
ec_mutex_unlock(&master->scan_mutex);
|
||||
|
||||
// clear all slaves and scan the bus
|
||||
fsm->rescan_required = 0;
|
||||
|
|
@ -570,12 +570,12 @@ void ec_fsm_master_action_configure(
|
|||
|| slave->force_config) && !slave->error_flag) {
|
||||
|
||||
// Start slave configuration, if it is allowed.
|
||||
down(&master->config_sem);
|
||||
ec_mutex_lock(&master->config_mutex);
|
||||
if (!master->allow_config) {
|
||||
up(&master->config_sem);
|
||||
ec_mutex_unlock(&master->config_mutex);
|
||||
} else {
|
||||
master->config_busy = 1;
|
||||
up(&master->config_sem);
|
||||
ec_mutex_unlock(&master->config_mutex);
|
||||
|
||||
if (master->debug_level) {
|
||||
char old_state[EC_STATE_STRING_SIZE],
|
||||
|
|
|
|||
|
|
@ -39,6 +39,12 @@
|
|||
#include "../globals.h"
|
||||
#include "../include/ecrt.h"
|
||||
|
||||
#ifdef __KERNEL__
|
||||
#ifdef EC_USE_MUTEX
|
||||
#include <linux/rtmutex.h>
|
||||
#endif // EC_USE_MUTEX
|
||||
#endif // __KERNEL__
|
||||
|
||||
/******************************************************************************
|
||||
* EtherCAT master
|
||||
*****************************************************************************/
|
||||
|
|
@ -305,4 +311,60 @@ typedef struct ec_slave ec_slave_t; /**< \see ec_slave. */
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
/** Mutual exclusion helpers.
|
||||
*
|
||||
*/
|
||||
#ifdef EC_USE_MUTEX
|
||||
#define ec_mutex_t rt_mutex
|
||||
static inline void ec_mutex_init(struct ec_mutex_t *mutex)
|
||||
{
|
||||
rt_mutex_init(mutex);
|
||||
}
|
||||
static inline void ec_mutex_lock(struct ec_mutex_t *mutex)
|
||||
{
|
||||
rt_mutex_lock(mutex);
|
||||
}
|
||||
static inline int ec_mutex_trylock(struct ec_mutex_t *mutex)
|
||||
{
|
||||
return rt_mutex_trylock(mutex);
|
||||
}
|
||||
static inline int ec_mutex_lock_interruptible(struct ec_mutex_t *mutex)
|
||||
{
|
||||
return rt_mutex_lock_interruptible(mutex,0);
|
||||
}
|
||||
static inline void ec_mutex_unlock(struct ec_mutex_t *mutex)
|
||||
{
|
||||
rt_mutex_unlock(mutex);
|
||||
}
|
||||
#else // EC_USE_MUTEX
|
||||
#define ec_mutex_t semaphore
|
||||
static inline void ec_mutex_init(struct ec_mutex_t *sem)
|
||||
{
|
||||
sema_init(sem, 1);
|
||||
}
|
||||
static inline void ec_mutex_lock(struct ec_mutex_t *sem)
|
||||
{
|
||||
down(sem);
|
||||
}
|
||||
static inline int ec_mutex_trylock(struct ec_mutex_t *sem)
|
||||
{
|
||||
down(sem);
|
||||
return 1;
|
||||
}
|
||||
static inline int ec_mutex_lock_interruptible(struct ec_mutex_t *sem)
|
||||
{
|
||||
return down_interruptible(sem);
|
||||
}
|
||||
static inline void ec_mutex_unlock(struct ec_mutex_t *sem)
|
||||
{
|
||||
up(sem);
|
||||
}
|
||||
|
||||
#endif // EC_USE_MUTEX
|
||||
#endif // __KERNEL__
|
||||
|
||||
#endif
|
||||
|
|
|
|||
103
master/master.c
103
master/master.c
|
|
@ -130,12 +130,12 @@ int ec_master_init(ec_master_t *master, /**< EtherCAT master */
|
|||
master->index = index;
|
||||
master->reserved = 0;
|
||||
|
||||
sema_init(&master->master_sem, 1);
|
||||
ec_mutex_init(&master->master_mutex);
|
||||
|
||||
master->main_mac = main_mac;
|
||||
master->backup_mac = backup_mac;
|
||||
|
||||
sema_init(&master->device_sem, 1);
|
||||
ec_mutex_init(&master->device_mutex);
|
||||
|
||||
master->phase = EC_ORPHANED;
|
||||
master->active = 0;
|
||||
|
|
@ -158,18 +158,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_mutex_init(&master->scan_mutex);
|
||||
init_waitqueue_head(&master->scan_queue);
|
||||
|
||||
master->config_busy = 0;
|
||||
master->allow_config = 1;
|
||||
sema_init(&master->config_sem, 1);
|
||||
ec_mutex_init(&master->config_mutex);
|
||||
init_waitqueue_head(&master->config_queue);
|
||||
|
||||
INIT_LIST_HEAD(&master->datagram_queue);
|
||||
master->datagram_index = 0;
|
||||
|
||||
sema_init(&master->fsm_queue_sem, 1);
|
||||
ec_mutex_init(&master->fsm_queue_mutex);
|
||||
INIT_LIST_HEAD(&master->fsm_datagram_queue);
|
||||
|
||||
// send interval in IDLE phase
|
||||
|
|
@ -190,7 +190,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_mutex_init(&master->io_mutex);
|
||||
master->fsm_queue_lock_cb = NULL;
|
||||
master->fsm_queue_unlock_cb = NULL;
|
||||
master->fsm_queue_locking_data = NULL;
|
||||
|
|
@ -447,10 +447,10 @@ void ec_master_clear_config(
|
|||
ec_master_t *master /**< EtherCAT master. */
|
||||
)
|
||||
{
|
||||
down(&master->master_sem);
|
||||
ec_mutex_lock(&master->master_mutex);
|
||||
ec_master_clear_domains(master);
|
||||
ec_master_clear_slave_configs(master);
|
||||
up(&master->master_sem);
|
||||
ec_mutex_unlock(&master->master_mutex);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -545,9 +545,9 @@ void ec_master_leave_idle_phase(ec_master_t *master /**< EtherCAT master */)
|
|||
|
||||
ec_master_thread_stop(master);
|
||||
|
||||
down(&master->master_sem);
|
||||
ec_mutex_lock(&master->master_mutex);
|
||||
ec_master_clear_slaves(master);
|
||||
up(&master->master_sem);
|
||||
ec_mutex_unlock(&master->master_mutex);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -564,10 +564,10 @@ int ec_master_enter_operation_phase(ec_master_t *master /**< EtherCAT master */)
|
|||
|
||||
EC_MASTER_DBG(master, 1, "IDLE -> OPERATION.\n");
|
||||
|
||||
down(&master->config_sem);
|
||||
ec_mutex_lock(&master->config_mutex);
|
||||
master->allow_config = 0; // temporarily disable slave configuration
|
||||
if (master->config_busy) {
|
||||
up(&master->config_sem);
|
||||
ec_mutex_unlock(&master->config_mutex);
|
||||
|
||||
// wait for slave configuration to complete
|
||||
ret = wait_event_interruptible(master->config_queue,
|
||||
|
|
@ -581,15 +581,15 @@ int ec_master_enter_operation_phase(ec_master_t *master /**< EtherCAT master */)
|
|||
EC_MASTER_DBG(master, 1, "Waiting for pending slave"
|
||||
" configuration returned.\n");
|
||||
} else {
|
||||
up(&master->config_sem);
|
||||
ec_mutex_unlock(&master->config_mutex);
|
||||
}
|
||||
|
||||
down(&master->scan_sem);
|
||||
ec_mutex_lock(&master->scan_mutex);
|
||||
master->allow_scan = 0; // 'lock' the slave list
|
||||
if (!master->scan_busy) {
|
||||
up(&master->scan_sem);
|
||||
ec_mutex_unlock(&master->scan_mutex);
|
||||
} else {
|
||||
up(&master->scan_sem);
|
||||
ec_mutex_unlock(&master->scan_mutex);
|
||||
|
||||
// wait for slave scan to complete
|
||||
ret = wait_event_interruptible(master->scan_queue, !master->scan_busy);
|
||||
|
|
@ -662,9 +662,10 @@ void ec_master_inject_fsm_datagrams(
|
|||
|
||||
if (master->fsm_queue_lock_cb)
|
||||
master->fsm_queue_lock_cb(master->fsm_queue_locking_data);
|
||||
down(&master->fsm_queue_sem);
|
||||
if (ec_mutex_trylock(&master->fsm_queue_mutex) == 0)
|
||||
return;
|
||||
if (list_empty(&master->fsm_datagram_queue)) {
|
||||
up(&master->fsm_queue_sem);
|
||||
ec_mutex_unlock(&master->fsm_queue_mutex);
|
||||
if (master->fsm_queue_unlock_cb)
|
||||
master->fsm_queue_unlock_cb(master->fsm_queue_locking_data);
|
||||
return;
|
||||
|
|
@ -736,7 +737,7 @@ void ec_master_inject_fsm_datagrams(
|
|||
}
|
||||
}
|
||||
}
|
||||
up(&master->fsm_queue_sem);
|
||||
ec_mutex_unlock(&master->fsm_queue_mutex);
|
||||
if (master->fsm_queue_unlock_cb)
|
||||
master->fsm_queue_unlock_cb(master->fsm_queue_locking_data);
|
||||
}
|
||||
|
|
@ -783,14 +784,14 @@ void ec_master_queue_fsm_datagram(
|
|||
|
||||
if (master->fsm_queue_lock_cb)
|
||||
master->fsm_queue_lock_cb(master->fsm_queue_locking_data);
|
||||
down(&master->fsm_queue_sem);
|
||||
ec_mutex_lock(&master->fsm_queue_mutex);
|
||||
|
||||
// check, if the datagram is already queued
|
||||
list_for_each_entry(queued_datagram, &master->fsm_datagram_queue,
|
||||
queue) {
|
||||
if (queued_datagram == datagram) {
|
||||
datagram->state = EC_DATAGRAM_QUEUED;
|
||||
up(&master->fsm_queue_sem);
|
||||
ec_mutex_unlock(&master->fsm_queue_mutex);
|
||||
if (master->fsm_queue_unlock_cb)
|
||||
master->fsm_queue_unlock_cb(master->fsm_queue_locking_data);
|
||||
return;
|
||||
|
|
@ -809,7 +810,7 @@ void ec_master_queue_fsm_datagram(
|
|||
#endif
|
||||
datagram->jiffies_sent = jiffies;
|
||||
|
||||
up(&master->fsm_queue_sem);
|
||||
ec_mutex_unlock(&master->fsm_queue_mutex);
|
||||
if (master->fsm_queue_unlock_cb)
|
||||
master->fsm_queue_unlock_cb(master->fsm_queue_locking_data);
|
||||
}
|
||||
|
|
@ -1252,12 +1253,12 @@ static int ec_master_idle_thread(void *priv_data)
|
|||
ec_datagram_output_stats(&master->fsm_datagram);
|
||||
|
||||
// receive
|
||||
down(&master->io_sem);
|
||||
ec_mutex_lock(&master->io_mutex);
|
||||
ecrt_master_receive(master);
|
||||
up(&master->io_sem);
|
||||
ec_mutex_unlock(&master->io_mutex);
|
||||
|
||||
// execute master & slave state machines
|
||||
if (down_interruptible(&master->master_sem))
|
||||
if (ec_mutex_lock_interruptible(&master->master_mutex))
|
||||
break;
|
||||
if (ec_fsm_master_exec(&master->fsm)) {
|
||||
ec_master_queue_fsm_datagram(master, &master->fsm_datagram);
|
||||
|
|
@ -1271,14 +1272,14 @@ static int ec_master_idle_thread(void *priv_data)
|
|||
if (!ec_master_eoe_processing(master))
|
||||
master->fsm.idle = 0; // pump the bus as fast as possible
|
||||
#endif
|
||||
up(&master->master_sem);
|
||||
ec_mutex_unlock(&master->master_mutex);
|
||||
|
||||
// queue and send
|
||||
down(&master->io_sem);
|
||||
ec_mutex_lock(&master->io_mutex);
|
||||
ecrt_master_send(master);
|
||||
sent_bytes = master->main_device.tx_skb[
|
||||
master->main_device.tx_ring_index]->len;
|
||||
up(&master->io_sem);
|
||||
ec_mutex_unlock(&master->io_mutex);
|
||||
|
||||
if (ec_fsm_master_idle(&master->fsm)) {
|
||||
#ifdef EC_USE_HRTIMER
|
||||
|
|
@ -1321,7 +1322,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_mutex_lock_interruptible(&master->master_mutex))
|
||||
break;
|
||||
if (ec_fsm_master_exec(&master->fsm))
|
||||
ec_master_queue_fsm_datagram(master, &master->fsm_datagram);
|
||||
|
|
@ -1333,7 +1334,7 @@ static int ec_master_operation_thread(void *priv_data)
|
|||
#if defined(EC_EOE)
|
||||
ec_master_eoe_processing(master);
|
||||
#endif
|
||||
up(&master->master_sem);
|
||||
ec_mutex_unlock(&master->master_mutex);
|
||||
|
||||
#ifdef EC_USE_HRTIMER
|
||||
// the op thread should not work faster than the sending RT thread
|
||||
|
|
@ -1858,7 +1859,7 @@ ec_domain_t *ecrt_master_create_domain_err(
|
|||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
down(&master->master_sem);
|
||||
ec_mutex_lock(&master->master_mutex);
|
||||
|
||||
if (list_empty(&master->domains)) {
|
||||
index = 0;
|
||||
|
|
@ -1870,7 +1871,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_mutex_unlock(&master->master_mutex);
|
||||
|
||||
EC_MASTER_DBG(master, 1, "Created domain %u.\n", domain->index);
|
||||
|
||||
|
|
@ -1902,21 +1903,21 @@ int ecrt_master_activate(ec_master_t *master)
|
|||
return 0;
|
||||
}
|
||||
|
||||
down(&master->master_sem);
|
||||
ec_mutex_lock(&master->master_mutex);
|
||||
|
||||
// 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_mutex_unlock(&master->master_mutex);
|
||||
EC_MASTER_ERR(master, "Failed to finish domain 0x%p!\n", domain);
|
||||
return ret;
|
||||
}
|
||||
domain_offset += domain->data_size;
|
||||
}
|
||||
|
||||
up(&master->master_sem);
|
||||
ec_mutex_unlock(&master->master_mutex);
|
||||
|
||||
// restart EoE process and master thread with new locking
|
||||
|
||||
|
|
@ -2128,14 +2129,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_mutex_lock(&master->master_mutex);
|
||||
|
||||
// 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_mutex_unlock(&master->master_mutex);
|
||||
}
|
||||
|
||||
return sc;
|
||||
|
|
@ -2173,7 +2174,7 @@ int ecrt_master_get_slave(ec_master_t *master, uint16_t slave_position,
|
|||
{
|
||||
const ec_slave_t *slave;
|
||||
|
||||
if (down_interruptible(&master->master_sem)) {
|
||||
if (ec_mutex_lock_interruptible(&master->master_mutex)) {
|
||||
return -EINTR;
|
||||
}
|
||||
|
||||
|
|
@ -2196,7 +2197,7 @@ int ecrt_master_get_slave(ec_master_t *master, uint16_t slave_position,
|
|||
slave_info->name[0] = 0;
|
||||
}
|
||||
|
||||
up(&master->master_sem);
|
||||
ec_mutex_unlock(&master->master_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -2325,12 +2326,12 @@ int ecrt_master_write_idn(ec_master_t *master, uint16_t slave_position,
|
|||
request.req.data_size = data_size;
|
||||
ec_soe_request_write(&request.req);
|
||||
|
||||
if (down_interruptible(&master->master_sem))
|
||||
if (ec_mutex_lock_interruptible(&master->master_mutex))
|
||||
return -EINTR;
|
||||
|
||||
if (!(request.slave = ec_master_find_slave(
|
||||
master, 0, slave_position))) {
|
||||
up(&master->master_sem);
|
||||
ec_mutex_unlock(&master->master_mutex);
|
||||
EC_MASTER_ERR(master, "Slave %u does not exist!\n",
|
||||
slave_position);
|
||||
ec_soe_request_clear(&request.req);
|
||||
|
|
@ -2342,21 +2343,21 @@ int ecrt_master_write_idn(ec_master_t *master, uint16_t slave_position,
|
|||
// schedule SoE write request.
|
||||
list_add_tail(&request.list, &request.slave->soe_requests);
|
||||
|
||||
up(&master->master_sem);
|
||||
ec_mutex_unlock(&master->master_mutex);
|
||||
|
||||
// wait for processing through FSM
|
||||
if (wait_event_interruptible(request.slave->soe_queue,
|
||||
request.req.state != EC_INT_REQUEST_QUEUED)) {
|
||||
// interrupted by signal
|
||||
down(&master->master_sem);
|
||||
ec_mutex_lock(&master->master_mutex);
|
||||
if (request.req.state == EC_INT_REQUEST_QUEUED) {
|
||||
// abort request
|
||||
list_del(&request.list);
|
||||
up(&master->master_sem);
|
||||
ec_mutex_unlock(&master->master_mutex);
|
||||
ec_soe_request_clear(&request.req);
|
||||
return -EINTR;
|
||||
}
|
||||
up(&master->master_sem);
|
||||
ec_mutex_unlock(&master->master_mutex);
|
||||
}
|
||||
|
||||
// wait until master FSM has finished processing
|
||||
|
|
@ -2391,11 +2392,11 @@ int ecrt_master_read_idn(ec_master_t *master, uint16_t slave_position,
|
|||
ec_soe_request_set_idn(&request.req, idn);
|
||||
ec_soe_request_read(&request.req);
|
||||
|
||||
if (down_interruptible(&master->master_sem))
|
||||
if (ec_mutex_lock_interruptible(&master->master_mutex))
|
||||
return -EINTR;
|
||||
|
||||
if (!(request.slave = ec_master_find_slave(master, 0, slave_position))) {
|
||||
up(&master->master_sem);
|
||||
ec_mutex_unlock(&master->master_mutex);
|
||||
ec_soe_request_clear(&request.req);
|
||||
EC_MASTER_ERR(master, "Slave %u does not exist!\n", slave_position);
|
||||
return -EINVAL;
|
||||
|
|
@ -2404,7 +2405,7 @@ int ecrt_master_read_idn(ec_master_t *master, uint16_t slave_position,
|
|||
// schedule request.
|
||||
list_add_tail(&request.list, &request.slave->soe_requests);
|
||||
|
||||
up(&master->master_sem);
|
||||
ec_mutex_unlock(&master->master_mutex);
|
||||
|
||||
EC_SLAVE_DBG(request.slave, 1, "Scheduled SoE read request.\n");
|
||||
|
||||
|
|
@ -2412,15 +2413,15 @@ int ecrt_master_read_idn(ec_master_t *master, uint16_t slave_position,
|
|||
if (wait_event_interruptible(request.slave->soe_queue,
|
||||
request.req.state != EC_INT_REQUEST_QUEUED)) {
|
||||
// interrupted by signal
|
||||
down(&master->master_sem);
|
||||
ec_mutex_lock(&master->master_mutex);
|
||||
if (request.req.state == EC_INT_REQUEST_QUEUED) {
|
||||
list_del(&request.list);
|
||||
up(&master->master_sem);
|
||||
ec_mutex_unlock(&master->master_mutex);
|
||||
ec_soe_request_clear(&request.req);
|
||||
return -EINTR;
|
||||
}
|
||||
// request already processing: interrupt not possible.
|
||||
up(&master->master_sem);
|
||||
ec_mutex_unlock(&master->master_mutex);
|
||||
}
|
||||
|
||||
// wait until master FSM has finished processing
|
||||
|
|
|
|||
|
|
@ -43,18 +43,13 @@
|
|||
#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 "cdev.h"
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/** Convenience macro for printing master-specific information to syslog.
|
||||
|
|
@ -152,13 +147,13 @@ struct ec_master {
|
|||
struct class_device *class_device; /**< Master class device. */
|
||||
#endif
|
||||
|
||||
struct semaphore master_sem; /**< Master semaphore. */
|
||||
struct ec_mutex_t master_mutex; /**< Master mutex. */
|
||||
|
||||
ec_device_t main_device; /**< EtherCAT main device. */
|
||||
const uint8_t *main_mac; /**< MAC address of main device. */
|
||||
ec_device_t backup_device; /**< EtherCAT backup device. */
|
||||
const uint8_t *backup_mac; /**< MAC address of backup device. */
|
||||
struct semaphore device_sem; /**< Device semaphore. */
|
||||
struct ec_mutex_t device_mutex; /**< Device mutex. */
|
||||
|
||||
ec_fsm_master_t fsm; /**< Master state machine. */
|
||||
ec_datagram_t fsm_datagram; /**< Datagram used for state machines. */
|
||||
|
|
@ -194,7 +189,7 @@ struct ec_master {
|
|||
ecrt_master_sync() call.*/
|
||||
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
|
||||
struct ec_mutex_t scan_mutex; /**< Mutex 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. */
|
||||
|
|
@ -202,7 +197,7 @@ struct ec_master {
|
|||
unsigned int config_busy; /**< State of slave configuration. */
|
||||
unsigned int allow_config; /**< \a True, if slave configuration is
|
||||
allowed. */
|
||||
struct semaphore config_sem; /**< Semaphore protecting the \a config_busy
|
||||
struct ec_mutex_t config_mutex; /**< Mutex 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. */
|
||||
|
|
@ -210,7 +205,7 @@ struct ec_master {
|
|||
struct list_head datagram_queue; /**< Datagram queue. */
|
||||
uint8_t datagram_index; /**< Current datagram index. */
|
||||
|
||||
struct semaphore fsm_queue_sem; /**< Semaphore protecting the \a
|
||||
struct ec_mutex_t fsm_queue_mutex; /**< Mutex protecting the \a
|
||||
fsm_datagram_queue. */
|
||||
struct list_head fsm_datagram_queue; /**< External Datagram queue. */
|
||||
|
||||
|
|
@ -227,7 +222,7 @@ struct ec_master {
|
|||
struct list_head eoe_handlers; /**< Ethernet over EtherCAT handlers. */
|
||||
#endif
|
||||
|
||||
struct semaphore io_sem; /**< Semaphore used in \a IDLE phase. */
|
||||
struct ec_mutex_t io_mutex; /**< Mutex used in \a IDLE phase. */
|
||||
|
||||
void (*fsm_queue_lock_cb)(void *); /**< FSM queue lock callback. */
|
||||
void (*fsm_queue_unlock_cb)(void *); /**< FSM queue unlock callback. */
|
||||
|
|
|
|||
|
|
@ -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 struct ec_mutex_t master_mutex; /**< Master mutex. */
|
||||
|
||||
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_mutex_init(&master_mutex);
|
||||
|
||||
if (master_count) {
|
||||
if (alloc_chrdev_region(&device_number,
|
||||
|
|
@ -468,9 +468,9 @@ ec_device_t *ecdev_offer(
|
|||
for (i = 0; i < master_count; i++) {
|
||||
master = &masters[i];
|
||||
|
||||
down(&master->device_sem);
|
||||
ec_mutex_lock(&master->device_mutex);
|
||||
if (master->main_device.dev) { // master already has a device
|
||||
up(&master->device_sem);
|
||||
ec_mutex_unlock(&master->device_mutex);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -481,14 +481,14 @@ ec_device_t *ecdev_offer(
|
|||
str, master->index);
|
||||
|
||||
ec_device_attach(&master->main_device, net_dev, poll, module);
|
||||
up(&master->device_sem);
|
||||
ec_mutex_unlock(&master->device_mutex);
|
||||
|
||||
snprintf(net_dev->name, IFNAMSIZ, "ec%u", master->index);
|
||||
|
||||
return &master->main_device; // offer accepted
|
||||
}
|
||||
else {
|
||||
up(&master->device_sem);
|
||||
ec_mutex_unlock(&master->device_mutex);
|
||||
|
||||
if (master->debug_level) {
|
||||
ec_mac_print(net_dev->dev_addr, str);
|
||||
|
|
@ -524,40 +524,40 @@ ec_master_t *ecrt_request_master_err(
|
|||
}
|
||||
master = &masters[master_index];
|
||||
|
||||
if (down_interruptible(&master_sem)) {
|
||||
if (ec_mutex_lock_interruptible(&master_mutex)) {
|
||||
errptr = ERR_PTR(-EINTR);
|
||||
goto out_return;
|
||||
}
|
||||
|
||||
if (master->reserved) {
|
||||
up(&master_sem);
|
||||
ec_mutex_unlock(&master_mutex);
|
||||
EC_MASTER_ERR(master, "Master already in use!\n");
|
||||
errptr = ERR_PTR(-EBUSY);
|
||||
goto out_return;
|
||||
}
|
||||
master->reserved = 1;
|
||||
up(&master_sem);
|
||||
ec_mutex_unlock(&master_mutex);
|
||||
|
||||
if (down_interruptible(&master->device_sem)) {
|
||||
if (ec_mutex_lock_interruptible(&master->device_mutex)) {
|
||||
errptr = ERR_PTR(-EINTR);
|
||||
goto out_release;
|
||||
}
|
||||
|
||||
if (master->phase != EC_IDLE) {
|
||||
up(&master->device_sem);
|
||||
ec_mutex_unlock(&master->device_mutex);
|
||||
EC_MASTER_ERR(master, "Master still waiting for devices!\n");
|
||||
errptr = ERR_PTR(-ENODEV);
|
||||
goto out_release;
|
||||
}
|
||||
|
||||
if (!try_module_get(master->main_device.module)) {
|
||||
up(&master->device_sem);
|
||||
ec_mutex_unlock(&master->device_mutex);
|
||||
EC_ERR("Device module is unloading!\n");
|
||||
errptr = ERR_PTR(-ENODEV);
|
||||
goto out_release;
|
||||
}
|
||||
|
||||
up(&master->device_sem);
|
||||
ec_mutex_unlock(&master->device_mutex);
|
||||
|
||||
if (ec_master_enter_operation_phase(master)) {
|
||||
EC_MASTER_ERR(master, "Failed to enter OPERATION phase!\n");
|
||||
|
|
|
|||
|
|
@ -182,7 +182,7 @@ int ec_slave_config_prepare_fmmu(
|
|||
|
||||
fmmu = &sc->fmmu_configs[sc->used_fmmus];
|
||||
|
||||
down(&sc->master->master_sem);
|
||||
ec_mutex_lock(&sc->master->master_mutex);
|
||||
ec_fmmu_config_init(fmmu, sc, sync_index, dir);
|
||||
fmmu_logical_start_address = domain->tx_size;
|
||||
tx_size = fmmu->data_size;
|
||||
|
|
@ -199,7 +199,7 @@ int ec_slave_config_prepare_fmmu(
|
|||
}
|
||||
}
|
||||
ec_fmmu_config_domain(fmmu,domain,fmmu_logical_start_address,tx_size);
|
||||
up(&sc->master->master_sem);
|
||||
ec_mutex_unlock(&sc->master->master_mutex);
|
||||
|
||||
++sc->used_fmmus;
|
||||
return fmmu->domain_address;
|
||||
|
|
@ -536,18 +536,18 @@ int ecrt_slave_config_pdo_assign_add(ec_slave_config_t *sc,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
down(&sc->master->master_sem);
|
||||
ec_mutex_lock(&sc->master->master_mutex);
|
||||
|
||||
pdo = ec_pdo_list_add_pdo(&sc->sync_configs[sync_index].pdos, pdo_index);
|
||||
if (IS_ERR(pdo)) {
|
||||
up(&sc->master->master_sem);
|
||||
ec_mutex_unlock(&sc->master->master_mutex);
|
||||
return PTR_ERR(pdo);
|
||||
}
|
||||
pdo->sync_index = sync_index;
|
||||
|
||||
ec_slave_config_load_default_mapping(sc, pdo);
|
||||
|
||||
up(&sc->master->master_sem);
|
||||
ec_mutex_unlock(&sc->master->master_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -564,9 +564,9 @@ void ecrt_slave_config_pdo_assign_clear(ec_slave_config_t *sc,
|
|||
return;
|
||||
}
|
||||
|
||||
down(&sc->master->master_sem);
|
||||
ec_mutex_lock(&sc->master->master_mutex);
|
||||
ec_pdo_list_clear_pdos(&sc->sync_configs[sync_index].pdos);
|
||||
up(&sc->master->master_sem);
|
||||
ec_mutex_unlock(&sc->master->master_mutex);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -592,10 +592,10 @@ int ecrt_slave_config_pdo_mapping_add(ec_slave_config_t *sc,
|
|||
break;
|
||||
|
||||
if (pdo) {
|
||||
down(&sc->master->master_sem);
|
||||
ec_mutex_lock(&sc->master->master_mutex);
|
||||
entry = ec_pdo_add_entry(pdo, entry_index, entry_subindex,
|
||||
entry_bit_length);
|
||||
up(&sc->master->master_sem);
|
||||
ec_mutex_unlock(&sc->master->master_mutex);
|
||||
if (IS_ERR(entry))
|
||||
retval = PTR_ERR(entry);
|
||||
} else {
|
||||
|
|
@ -623,9 +623,9 @@ void ecrt_slave_config_pdo_mapping_clear(ec_slave_config_t *sc,
|
|||
break;
|
||||
|
||||
if (pdo) {
|
||||
down(&sc->master->master_sem);
|
||||
ec_mutex_lock(&sc->master->master_mutex);
|
||||
ec_pdo_clear_entries(pdo);
|
||||
up(&sc->master->master_sem);
|
||||
ec_mutex_unlock(&sc->master->master_mutex);
|
||||
} else {
|
||||
EC_CONFIG_WARN(sc, "PDO 0x%04X is not assigned.\n", pdo_index);
|
||||
}
|
||||
|
|
@ -805,9 +805,9 @@ int ecrt_slave_config_sdo(ec_slave_config_t *sc, uint16_t index,
|
|||
return ret;
|
||||
}
|
||||
|
||||
down(&sc->master->master_sem);
|
||||
ec_mutex_lock(&sc->master->master_mutex);
|
||||
list_add_tail(&req->list, &sc->sdo_configs);
|
||||
up(&sc->master->master_sem);
|
||||
ec_mutex_unlock(&sc->master->master_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -890,9 +890,9 @@ int ecrt_slave_config_complete_sdo(ec_slave_config_t *sc, uint16_t index,
|
|||
return ret;
|
||||
}
|
||||
|
||||
down(&sc->master->master_sem);
|
||||
ec_mutex_lock(&sc->master->master_mutex);
|
||||
list_add_tail(&req->list, &sc->sdo_configs);
|
||||
up(&sc->master->master_sem);
|
||||
ec_mutex_unlock(&sc->master->master_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -931,9 +931,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_mutex_lock(&sc->master->master_mutex);
|
||||
list_add_tail(&req->list, &sc->sdo_requests);
|
||||
up(&sc->master->master_sem);
|
||||
ec_mutex_unlock(&sc->master->master_mutex);
|
||||
|
||||
return req;
|
||||
}
|
||||
|
|
@ -973,9 +973,9 @@ ec_voe_handler_t *ecrt_slave_config_create_voe_handler_err(
|
|||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
down(&sc->master->master_sem);
|
||||
ec_mutex_lock(&sc->master->master_mutex);
|
||||
list_add_tail(&voe->list, &sc->voe_handlers);
|
||||
up(&sc->master->master_sem);
|
||||
ec_mutex_unlock(&sc->master->master_mutex);
|
||||
|
||||
return voe;
|
||||
}
|
||||
|
|
@ -1056,9 +1056,9 @@ int ecrt_slave_config_idn(ec_slave_config_t *sc, uint8_t drive_no,
|
|||
return ret;
|
||||
}
|
||||
|
||||
down(&sc->master->master_sem);
|
||||
ec_mutex_lock(&sc->master->master_mutex);
|
||||
list_add_tail(&req->list, &sc->soe_configs);
|
||||
up(&sc->master->master_sem);
|
||||
ec_mutex_unlock(&sc->master->master_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
26
tty/module.c
26
tty/module.c
|
|
@ -65,7 +65,7 @@ unsigned int debug_level = 0;
|
|||
|
||||
static struct tty_driver *tty_driver = NULL;
|
||||
ec_tty_t *ttys[EC_TTY_MAX_DEVICES];
|
||||
struct semaphore tty_sem;
|
||||
struct ec_mutex_t tty_sem;
|
||||
|
||||
void ec_tty_wakeup(unsigned long);
|
||||
|
||||
|
|
@ -111,7 +111,7 @@ struct ec_tty {
|
|||
struct timer_list timer;
|
||||
struct tty_struct *tty;
|
||||
unsigned int open_count;
|
||||
struct semaphore sem;
|
||||
struct ec_mutex_t sem;
|
||||
|
||||
ec_tty_operations_t ops;
|
||||
void *cb_data;
|
||||
|
|
@ -131,7 +131,7 @@ int __init ec_tty_init_module(void)
|
|||
|
||||
printk(KERN_INFO PFX "TTY driver %s\n", EC_MASTER_VERSION);
|
||||
|
||||
sema_init(&tty_sem, 1);
|
||||
ec_mutex_init(&tty_sem);
|
||||
|
||||
for (i = 0; i < EC_TTY_MAX_DEVICES; i++) {
|
||||
ttys[i] = NULL;
|
||||
|
|
@ -202,7 +202,7 @@ int ec_tty_init(ec_tty_t *t, int minor,
|
|||
init_timer(&t->timer);
|
||||
t->tty = NULL;
|
||||
t->open_count = 0;
|
||||
sema_init(&t->sem, 1);
|
||||
ec_mutex_init(&t->sem);
|
||||
t->ops = *ops;
|
||||
t->cb_data = cb_data;
|
||||
|
||||
|
|
@ -391,9 +391,9 @@ static int ec_tty_open(struct tty_struct *tty, struct file *file)
|
|||
tty->driver_data = t;
|
||||
}
|
||||
|
||||
down(&t->sem);
|
||||
ec_mutex_lock(&t->sem);
|
||||
t->open_count++;
|
||||
up(&t->sem);
|
||||
ec_mutex_unlock(&t->sem);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -409,11 +409,11 @@ static void ec_tty_close(struct tty_struct *tty, struct file *file)
|
|||
#endif
|
||||
|
||||
if (t) {
|
||||
down(&t->sem);
|
||||
ec_mutex_lock(&t->sem);
|
||||
if (--t->open_count == 0) {
|
||||
t->tty = NULL;
|
||||
}
|
||||
up(&t->sem);
|
||||
ec_mutex_unlock(&t->sem);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -676,7 +676,7 @@ ec_tty_t *ectty_create(const ec_tty_operations_t *ops, void *cb_data)
|
|||
ec_tty_t *tty;
|
||||
int minor, ret;
|
||||
|
||||
if (down_interruptible(&tty_sem)) {
|
||||
if (ec_mutex_lock_interruptible(&tty_sem)) {
|
||||
return ERR_PTR(-EINTR);
|
||||
}
|
||||
|
||||
|
|
@ -686,25 +686,25 @@ ec_tty_t *ectty_create(const ec_tty_operations_t *ops, void *cb_data)
|
|||
|
||||
tty = kmalloc(sizeof(ec_tty_t), GFP_KERNEL);
|
||||
if (!tty) {
|
||||
up(&tty_sem);
|
||||
ec_mutex_unlock(&tty_sem);
|
||||
printk(KERN_ERR PFX "Failed to allocate memory.\n");
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
ret = ec_tty_init(tty, minor, ops, cb_data);
|
||||
if (ret) {
|
||||
up(&tty_sem);
|
||||
ec_mutex_unlock(&tty_sem);
|
||||
kfree(tty);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
ttys[minor] = tty;
|
||||
up(&tty_sem);
|
||||
ec_mutex_unlock(&tty_sem);
|
||||
return tty;
|
||||
}
|
||||
}
|
||||
|
||||
up(&tty_sem);
|
||||
ec_mutex_unlock(&tty_sem);
|
||||
printk(KERN_ERR PFX "No free interfaces avaliable.\n");
|
||||
return ERR_PTR(-EBUSY);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue