Add lock protection of domain->datagram_pairs

While domain->datagram_pairs was previously partly protected by the
master->master_sem lock (it was not done consistently though), the fix
to protection of master->datagram_queue made it even worse.

This change adds protection of domain->datagram_pairs using a new lock
dedicated to this.  The domain->datagram_pairs_lock is acquired in the actual
functions accessing the domain->datagram_pairs, and this currently means that
it is acquired both in situations where master->master_sem is held and in
situations where master->io_sem is held.
This commit is contained in:
Esben Haabendal 2018-01-17 09:30:50 +01:00 committed by Rasmus Villemoes
parent 2372382259
commit 19b8ddea18
2 changed files with 14 additions and 0 deletions

View File

@ -76,6 +76,7 @@ void ec_domain_init(
domain->data_origin = EC_ORIG_INTERNAL;
domain->logical_base_address = 0x00000000;
INIT_LIST_HEAD(&domain->datagram_pairs);
ec_lock_init(&domain->datagram_pairs_lock);
for (dev_idx = EC_DEVICE_MAIN; dev_idx < ec_master_num_devices(master);
dev_idx++) {
domain->working_counter[dev_idx] = 0x0000;
@ -98,12 +99,14 @@ void ec_domain_clear(ec_domain_t *domain /**< EtherCAT domain */)
{
ec_datagram_pair_t *datagram_pair, *next_pair;
ec_lock_down(&domain->datagram_pairs_lock);
// dequeue and free datagrams
list_for_each_entry_safe(datagram_pair, next_pair,
&domain->datagram_pairs, list) {
ec_datagram_pair_clear(datagram_pair);
kfree(datagram_pair);
}
ec_lock_up(&domain->datagram_pairs_lock);
ec_domain_clear_data(domain);
}
@ -216,7 +219,9 @@ int ec_domain_add_datagram_pair(
datagram_pair->expected_working_counter);
ec_lock_down(&domain->datagram_pairs_lock);
list_add_tail(&datagram_pair->list, &domain->datagram_pairs);
ec_lock_up(&domain->datagram_pairs_lock);
return 0;
}
@ -389,6 +394,7 @@ int ec_domain_finish(
domain->logical_base_address, domain->data_size,
domain->expected_working_counter);
ec_lock_down(&domain->datagram_pairs_lock);
list_for_each_entry(datagram_pair, &domain->datagram_pairs, list) {
const ec_datagram_t *datagram =
&datagram_pair->datagrams[EC_DEVICE_MAIN];
@ -397,6 +403,7 @@ int ec_domain_finish(
EC_READ_U32(datagram->address), datagram->data_size,
ec_datagram_type_string(datagram), datagram);
}
ec_lock_up(&domain->datagram_pairs_lock);
return 0;
}
@ -551,6 +558,7 @@ void ecrt_domain_process(ec_domain_t *domain)
EC_MASTER_DBG(domain->master, 1, "domain %u process\n", domain->index);
#endif
ec_lock_down(&domain->datagram_pairs_lock);
list_for_each_entry(pair, &domain->datagram_pairs, list) {
#if EC_MAX_NUM_DEVICES > 1
datagram_pair_wc = ec_datagram_pair_process(pair, wc_sum);
@ -638,6 +646,7 @@ void ecrt_domain_process(ec_domain_t *domain)
}
#endif // EC_MAX_NUM_DEVICES > 1
}
ec_lock_up(&domain->datagram_pairs_lock);
#if EC_MAX_NUM_DEVICES > 1
redundant_wc = 0;
@ -726,6 +735,7 @@ void ecrt_domain_queue(ec_domain_t *domain)
ec_datagram_pair_t *datagram_pair;
ec_device_index_t dev_idx;
ec_lock_down(&domain->datagram_pairs_lock);
list_for_each_entry(datagram_pair, &domain->datagram_pairs, list) {
#if EC_MAX_NUM_DEVICES > 1
@ -747,6 +757,7 @@ void ecrt_domain_queue(ec_domain_t *domain)
&datagram_pair->datagrams[dev_idx]);
}
}
ec_lock_up(&domain->datagram_pairs_lock);
}
/*****************************************************************************/

View File

@ -43,6 +43,7 @@
#include "datagram.h"
#include "master.h"
#include "fmmu_config.h"
#include "locks.h"
/*****************************************************************************/
@ -65,6 +66,8 @@ struct ec_domain
process data. */
struct list_head datagram_pairs; /**< Datagrams pairs (main/backup) for
process data exchange. */
ec_lock_t datagram_pairs_lock; /**< Semaphore protecting the
datagram_pairs. */
uint16_t working_counter[EC_MAX_NUM_DEVICES]; /**< Last working counter
values. */
uint16_t expected_working_counter; /**< Expected working counter. */