# HG changeset patch # User Florian Pose # Date 1214926700 0 # Node ID 94c6e36e0f8dac467601b372da1131fda51ff806 # Parent a82793a6d1a03469e349b9bdf3f358275240621d Implemented master semaphore to secure concurrent access from ioctls, state machine and realtime interface. diff -r a82793a6d1a0 -r 94c6e36e0f8d master/cdev.c --- a/master/cdev.c Mon Jun 30 15:51:46 2008 +0000 +++ b/master/cdev.c Tue Jul 01 15:38:20 2008 +0000 @@ -138,8 +138,8 @@ EC_DBG("ioctl(filp = %x, cmd = %u (%u), arg = %x)\n", (u32) filp, (u32) cmd, (u32) _IOC_NR(cmd), (u32) arg); - // FIXME lock - + down(&master->master_sem); + switch (cmd) { case EC_IOCTL_MASTER: { @@ -1012,6 +1012,7 @@ retval = -ENOTTY; } + up(&master->master_sem); return retval; } diff -r a82793a6d1a0 -r 94c6e36e0f8d master/domain.c --- a/master/domain.c Mon Jun 30 15:51:46 2008 +0000 +++ b/master/domain.c Tue Jul 01 15:38:20 2008 +0000 @@ -344,10 +344,14 @@ void ecrt_domain_external_memory(ec_domain_t *domain, uint8_t *mem) { + down(&domain->master->master_sem); + ec_domain_clear_data(domain); domain->data = mem; domain->data_origin = EC_ORIG_EXTERNAL; + + up(&domain->master->master_sem); } /*****************************************************************************/ diff -r a82793a6d1a0 -r 94c6e36e0f8d master/master.c --- a/master/master.c Mon Jun 30 15:51:46 2008 +0000 +++ b/master/master.c Tue Jul 01 15:38:20 2008 +0000 @@ -85,6 +85,8 @@ master->index = index; master->reserved = 0; + init_MUTEX(&master->master_sem); + master->main_mac = main_mac; master->backup_mac = backup_mac; init_MUTEX(&master->device_sem); @@ -360,13 +362,13 @@ ec_master_t *master /**< EtherCAT master */ ) { + if (master->debug_level) + EC_DBG("ORPHANED -> IDLE.\n"); + master->request_cb = ec_master_request_cb; master->release_cb = ec_master_release_cb; master->cb_data = master; - if (master->debug_level) - EC_DBG("ORPHANED -> IDLE.\n"); - master->phase = EC_IDLE; if (ec_master_thread_start(master, ec_master_idle_thread)) { master->phase = EC_ORPHANED; @@ -391,7 +393,10 @@ ec_master_eoe_stop(master); #endif ec_master_thread_stop(master); + + down(&master->master_sem); ec_master_clear_slaves(master); + up(&master->master_sem); } /*****************************************************************************/ @@ -457,9 +462,6 @@ } #endif - if (master->debug_level) - EC_DBG("Switching to operation phase.\n"); - master->phase = EC_OPERATION; master->ext_request_cb = NULL; master->ext_release_cb = NULL; @@ -498,8 +500,10 @@ master->release_cb = ec_master_release_cb; master->cb_data = master; + down(&master->master_sem); ec_master_clear_domains(master); ec_master_clear_slave_configs(master); + up(&master->master_sem); // set states for all slaves for (slave = master->slaves; @@ -826,7 +830,9 @@ goto schedule; // execute master state machine + down(&master->master_sem); ec_fsm_master_exec(&master->fsm); + up(&master->master_sem); // queue and send spin_lock_bh(&master->internal_lock); @@ -870,7 +876,9 @@ ec_master_output_stats(master); // execute master state machine + down(&master->master_sem); ec_fsm_master_exec(&master->fsm); + up(&master->master_sem); // inject datagram master->injection_seq_fsm++; @@ -1146,6 +1154,8 @@ return NULL; } + down(&master->master_sem); + if (list_empty(&master->domains)) { index = 0; } else { @@ -1156,6 +1166,8 @@ ec_domain_init(domain, master, index); list_add_tail(&domain->list, &master->domains); + up(&master->master_sem); + return domain; } @@ -1166,6 +1178,8 @@ uint32_t domain_offset; ec_domain_t *domain; + down(&master->master_sem); + // finish all domains domain_offset = 0; list_for_each_entry(domain, &master->domains, list) { @@ -1175,6 +1189,8 @@ } domain_offset += domain->data_size; } + + up(&master->master_sem); // restart EoE process and master thread with new locking #ifdef EC_EOE @@ -1327,11 +1343,15 @@ ec_slave_config_init(sc, master, alias, position, vendor_id, product_code); + + 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); } return sc; diff -r a82793a6d1a0 -r 94c6e36e0f8d master/master.h --- a/master/master.h Mon Jun 30 15:51:46 2008 +0000 +++ b/master/master.h Tue Jul 01 15:38:20 2008 +0000 @@ -88,6 +88,7 @@ ec_cdev_t cdev; /**< Master character device. */ struct class_device *class_device; /**< Master class device. */ + struct semaphore master_sem; /**< Master semaphore. */ ec_device_t main_device; /**< EtherCAT main device. */ const uint8_t *main_mac; /**< MAC address of main device. */ diff -r a82793a6d1a0 -r 94c6e36e0f8d master/slave_config.c --- a/master/slave_config.c Mon Jun 30 15:51:46 2008 +0000 +++ b/master/slave_config.c Tue Jul 01 15:38:20 2008 +0000 @@ -151,7 +151,11 @@ } fmmu = &sc->fmmu_configs[sc->used_fmmus++]; + + down(&sc->master->master_sem); ec_fmmu_config_init(fmmu, sc, domain, sync_index, dir); + up(&sc->master->master_sem); + return fmmu->logical_start_address; } @@ -388,11 +392,18 @@ return -1; } - if (!(pdo = ec_pdo_list_add_pdo(&sc->sync_configs[sync_index].pdos, pdo_index))) - return -1; + down(&sc->master->master_sem); + + if (!(pdo = ec_pdo_list_add_pdo(&sc->sync_configs[sync_index].pdos, + pdo_index))) { + up(&sc->master->master_sem); + return -1; + } pdo->sync_index = sync_index; ec_slave_config_load_default_mapping(sc, pdo); + + up(&sc->master->master_sem); return 0; } @@ -410,7 +421,9 @@ return; } + down(&sc->master->master_sem); ec_pdo_list_clear_pdos(&sc->sync_configs[sync_index].pdos); + up(&sc->master->master_sem); } /*****************************************************************************/ @@ -421,6 +434,7 @@ { uint8_t sync_index; ec_pdo_t *pdo = NULL; + int retval = -1; if (sc->master->debug_level) EC_DBG("ecrt_slave_config_pdo_mapping_add(sc = 0x%x, " @@ -434,14 +448,17 @@ &sc->sync_configs[sync_index].pdos, pdo_index))) break; - if (!pdo) { + if (pdo) { + down(&sc->master->master_sem); + retval = ec_pdo_add_entry(pdo, entry_index, entry_subindex, + entry_bit_length) ? 0 : -1; + up(&sc->master->master_sem); + } else { EC_ERR("Pdo 0x%04X is not assigned in config %u:%u.\n", pdo_index, sc->alias, sc->position); - return -1; - } - - return ec_pdo_add_entry(pdo, entry_index, entry_subindex, - entry_bit_length) ? 0 : -1; + } + + return retval; } /*****************************************************************************/ @@ -461,13 +478,14 @@ &sc->sync_configs[sync_index].pdos, pdo_index))) break; - if (!pdo) { + if (pdo) { + down(&sc->master->master_sem); + ec_pdo_clear_entries(pdo); + up(&sc->master->master_sem); + } else { EC_WARN("Pdo 0x%04X is not assigned in config %u:%u.\n", pdo_index, sc->alias, sc->position); - return; - } - - ec_pdo_clear_entries(pdo); + } } /*****************************************************************************/ @@ -563,11 +581,6 @@ if (entry->index != index || entry->subindex != subindex) { bit_offset += entry->bit_length; } else { - sync_offset = ec_slave_config_prepare_fmmu( - sc, domain, sync_index, sync_config->dir); - if (sync_offset < 0) - return -2; - bit_pos = bit_offset % 8; if (bit_position) { *bit_position = bit_pos; @@ -578,6 +591,11 @@ return -3; } + sync_offset = ec_slave_config_prepare_fmmu( + sc, domain, sync_index, sync_config->dir); + if (sync_offset < 0) + return -2; + return sync_offset + bit_offset / 8; } } @@ -618,7 +636,10 @@ return -1; } + down(&sc->master->master_sem); list_add_tail(&req->list, &sc->sdo_configs); + up(&sc->master->master_sem); + return 0; } @@ -678,7 +699,10 @@ memset(req->data, 0x00, size); req->data_size = size; + down(&sc->master->master_sem); list_add_tail(&req->list, &sc->sdo_requests); + up(&sc->master->master_sem); + return req; }