Applied base-0028-ec_master_exec_slave_fsms-external-datagram-fix

Slaves can fail to correctly read their SII information, leading to
zero or corrupted SII information.  This leads to slaves that remain
in PREOP or SAFEOP.

This is caused by the cached external (slave) datagrams being cycled
through too quickly due to being marked as consumed when they are not.
Datagrams can then be lost or incorrectly shared between multiple slaves
as the ring returns a datagram that is still in use by a read SII call.

This may also occur if multiple services are contending for a slaves
mailbox.

I have not added checks into ec_master_get_external_datagram() to
check that a returned datagram is not currently in use.
This commit is contained in:
Graeme Foot 2019-05-21 18:26:31 +12:00 committed by Knud Baastrup
parent d3e853514f
commit 2c1597231d
1 changed files with 11 additions and 7 deletions

View File

@ -1634,13 +1634,15 @@ void ec_master_exec_slave_fsms(
fsm->slave->ring_position);
#endif
if (ec_fsm_slave_exec(fsm, datagram)) {
// FSM consumed datagram
if (datagram->state != EC_DATAGRAM_INVALID) {
// FSM consumed datagram
#if DEBUG_INJECT
EC_MASTER_DBG(master, 1, "FSM consumed datagram %s\n",
datagram->name);
EC_MASTER_DBG(master, 1, "FSM consumed datagram %s\n",
datagram->name);
#endif
master->ext_ring_idx_fsm =
(master->ext_ring_idx_fsm + 1) % EC_EXT_RING_SIZE;
master->ext_ring_idx_fsm =
(master->ext_ring_idx_fsm + 1) % EC_EXT_RING_SIZE;
}
}
else {
// FSM finished
@ -1660,8 +1662,10 @@ void ec_master_exec_slave_fsms(
datagram = ec_master_get_external_datagram(master);
if (ec_fsm_slave_exec(&master->fsm_slave->fsm, datagram)) {
master->ext_ring_idx_fsm =
(master->ext_ring_idx_fsm + 1) % EC_EXT_RING_SIZE;
if (datagram->state != EC_DATAGRAM_INVALID) {
master->ext_ring_idx_fsm =
(master->ext_ring_idx_fsm + 1) % EC_EXT_RING_SIZE;
}
list_add_tail(&master->fsm_slave->fsm.list,
&master->fsm_exec_list);
master->fsm_exec_count++;