Fixed kernel oops concerning slave configuration detaching.
--- a/documentation/graphs/fsm_slave_conf.dot Tue Nov 25 12:31:53 2008 +0000
+++ b/documentation/graphs/fsm_slave_conf.dot Tue Nov 25 13:31:58 2008 +0000
@@ -5,7 +5,10 @@
size="3,5"
start [fontname="Helvetica"]
- start -> init [weight=10]
+ start -> enter_init [weight=10]
+
+ enter_init [shape=point, label=""]
+ enter_init -> init [weight=10]
init [fontname="Helvetica"]
init -> enter_mbox_sync [fontname="Helvetica", label="No FMMUs"]
@@ -32,12 +35,14 @@
enter_sdo_conf -> sdo_conf [weight=10]
sdo_conf [fontname="Helvetica"]
+ sdo_conf -> enter_init [fontname="Helvetica", label="Config\ndetached"]
sdo_conf -> enter_pdo_conf [weight=10]
enter_pdo_conf [shape=point, label=""]
enter_pdo_conf -> pdo_conf [weight=10]
pdo_conf [fontname="Helvetica"]
+ pdo_conf -> enter_init [fontname="Helvetica", label="Config\ndetached"]
pdo_conf -> enter_pdo_sync [weight=10]
enter_pdo_sync [shape=point, label=""]
@@ -45,6 +50,7 @@
enter_pdo_sync -> pdo_sync [weight=10]
pdo_sync [fontname="Helvetica"]
+ pdo_sync -> enter_init [fontname="Helvetica", label="Config\ndetached"]
pdo_sync -> enter_fmmu [weight=10]
enter_fmmu [shape=point,label=""]
--- a/master/fsm_pdo.c Tue Nov 25 12:31:53 2008 +0000
+++ b/master/fsm_pdo.c Tue Nov 25 13:31:58 2008 +0000
@@ -402,6 +402,11 @@
fsm->sync_index++;
for (; fsm->sync_index < EC_MAX_SYNC_MANAGERS; fsm->sync_index++) {
+ if (!fsm->slave->config) { // slave configuration removed in the meantime
+ fsm->state = ec_fsm_pdo_state_error;
+ return;
+ }
+
if (ec_pdo_list_copy(&fsm->pdos,
&fsm->slave->config->sync_configs[fsm->sync_index].pdos)) {
fsm->state = ec_fsm_pdo_state_error;
--- a/master/fsm_slave_config.c Tue Nov 25 12:31:53 2008 +0000
+++ b/master/fsm_slave_config.c Tue Nov 25 13:31:58 2008 +0000
@@ -58,6 +58,7 @@
void ec_fsm_slave_config_state_safeop(ec_fsm_slave_config_t *);
void ec_fsm_slave_config_state_op(ec_fsm_slave_config_t *);
+void ec_fsm_slave_config_enter_init(ec_fsm_slave_config_t *);
void ec_fsm_slave_config_enter_mbox_sync(ec_fsm_slave_config_t *);
void ec_fsm_slave_config_enter_preop(ec_fsm_slave_config_t *);
void ec_fsm_slave_config_enter_sdo_conf(ec_fsm_slave_config_t *);
@@ -69,6 +70,8 @@
void ec_fsm_slave_config_state_end(ec_fsm_slave_config_t *);
void ec_fsm_slave_config_state_error(ec_fsm_slave_config_t *);
+void ec_fsm_slave_config_reconfigure(ec_fsm_slave_config_t *);
+
/*****************************************************************************/
/** Constructor.
@@ -81,6 +84,8 @@
ec_fsm_pdo_t *fsm_pdo /**< Pdo configuration state machine to use. */
)
{
+ ec_sdo_request_init(&fsm->request_copy);
+
fsm->datagram = datagram;
fsm->fsm_change = fsm_change;
fsm->fsm_coe = fsm_coe;
@@ -95,6 +100,7 @@
ec_fsm_slave_config_t *fsm /**< slave state machine */
)
{
+ ec_sdo_request_clear(&fsm->request_copy);
}
/*****************************************************************************/
@@ -172,6 +178,17 @@
EC_DBG("Configuring slave %u...\n", fsm->slave->ring_position);
}
+ ec_fsm_slave_config_enter_init(fsm);
+}
+
+/*****************************************************************************/
+
+/** Start state change to INIT.
+ */
+void ec_fsm_slave_config_enter_init(
+ ec_fsm_slave_config_t *fsm /**< slave state machine */
+ )
+{
ec_fsm_change_start(fsm->fsm_change, fsm->slave, EC_SLAVE_STATE_INIT);
ec_fsm_change_exec(fsm->fsm_change);
fsm->state = ec_fsm_slave_config_state_init;
@@ -445,8 +462,9 @@
fsm->state = ec_fsm_slave_config_state_sdo_conf;
fsm->request = list_entry(fsm->slave->config->sdo_configs.next,
ec_sdo_request_t, list);
- ecrt_sdo_request_write(fsm->request);
- ec_fsm_coe_transfer(fsm->fsm_coe, fsm->slave, fsm->request);
+ ec_sdo_request_copy(&fsm->request_copy, fsm->request);
+ ecrt_sdo_request_write(&fsm->request_copy);
+ ec_fsm_coe_transfer(fsm->fsm_coe, fsm->slave, &fsm->request_copy);
ec_fsm_coe_exec(fsm->fsm_coe); // execute immediately
}
@@ -468,12 +486,18 @@
return;
}
+ if (!fsm->slave->config) { // config removed in the meantime
+ ec_fsm_slave_config_reconfigure(fsm);
+ return;
+ }
+
// Another Sdo to configure?
if (fsm->request->list.next != &fsm->slave->config->sdo_configs) {
- fsm->request = list_entry(fsm->request->list.next, ec_sdo_request_t,
- list);
- ecrt_sdo_request_write(fsm->request);
- ec_fsm_coe_transfer(fsm->fsm_coe, fsm->slave, fsm->request);
+ fsm->request = list_entry(fsm->request->list.next,
+ ec_sdo_request_t, list);
+ ec_sdo_request_copy(&fsm->request_copy, fsm->request);
+ ecrt_sdo_request_write(&fsm->request_copy);
+ ec_fsm_coe_transfer(fsm->fsm_coe, fsm->slave, &fsm->request_copy);
ec_fsm_coe_exec(fsm->fsm_coe); // execute immediately
return;
}
@@ -507,6 +531,11 @@
if (ec_fsm_pdo_exec(fsm->fsm_pdo))
return;
+ if (!fsm->slave->config) { // config removed in the meantime
+ ec_fsm_slave_config_reconfigure(fsm);
+ return;
+ }
+
if (!ec_fsm_pdo_success(fsm->fsm_pdo)) {
EC_WARN("Pdo configuration failed on slave %u.\n",
fsm->slave->ring_position);
@@ -595,6 +624,11 @@
return;
}
+ if (!fsm->slave->config) { // config removed in the meantime
+ ec_fsm_slave_config_reconfigure(fsm);
+ return;
+ }
+
ec_fsm_slave_config_enter_fmmu(fsm);
}
@@ -765,6 +799,22 @@
fsm->state = ec_fsm_slave_config_state_end; // successful
}
+/*****************************************************************************/
+
+/** Reconfigure the slave starting at INIT.
+ */
+void ec_fsm_slave_config_reconfigure(
+ ec_fsm_slave_config_t *fsm /**< slave state machine */
+ )
+{
+ if (fsm->slave->master->debug_level) {
+ EC_DBG("Slave configuration for slave %u detached during "
+ "configuration. Reconfiguring.", fsm->slave->ring_position);
+ }
+
+ ec_fsm_slave_config_enter_init(fsm); // reconfigure
+}
+
/******************************************************************************
* Common state functions
*****************************************************************************/
--- a/master/fsm_slave_config.h Tue Nov 25 12:31:53 2008 +0000
+++ b/master/fsm_slave_config.h Tue Nov 25 13:31:58 2008 +0000
@@ -68,6 +68,7 @@
void (*state)(ec_fsm_slave_config_t *); /**< State function. */
unsigned int retries; /**< Retries on datagram timeout. */
ec_sdo_request_t *request; /**< Sdo request for Sdo configuration. */
+ ec_sdo_request_t request_copy; /**< Copied Sdo request. */
};
/*****************************************************************************/