Devices as array; lock all device modules with module_get().
This commit is contained in:
parent
2bb6c33d4e
commit
6d932e88d5
|
|
@ -184,10 +184,11 @@ int ec_cdev_ioctl_master(
|
|||
)
|
||||
{
|
||||
ec_ioctl_master_t data;
|
||||
unsigned int i;
|
||||
unsigned int i, j;
|
||||
|
||||
if (down_interruptible(&master->master_sem))
|
||||
return -EINTR;
|
||||
|
||||
data.slave_count = master->slave_count;
|
||||
data.config_count = ec_master_config_count(master);
|
||||
data.domain_count = ec_master_domain_count(master);
|
||||
|
|
@ -197,57 +198,38 @@ int ec_cdev_ioctl_master(
|
|||
data.phase = (uint8_t) master->phase;
|
||||
data.active = (uint8_t) master->active;
|
||||
data.scan_busy = master->scan_busy;
|
||||
|
||||
up(&master->master_sem);
|
||||
|
||||
if (down_interruptible(&master->device_sem))
|
||||
return -EINTR;
|
||||
|
||||
if (master->main_device.dev) {
|
||||
memcpy(data.devices[0].address,
|
||||
master->main_device.dev->dev_addr, ETH_ALEN);
|
||||
} else {
|
||||
memcpy(data.devices[0].address, master->main_mac, ETH_ALEN);
|
||||
}
|
||||
data.devices[0].attached = master->main_device.dev ? 1 : 0;
|
||||
data.devices[0].link_state = master->main_device.link_state ? 1 : 0;
|
||||
data.devices[0].tx_count = master->main_device.tx_count;
|
||||
data.devices[0].rx_count = master->main_device.rx_count;
|
||||
data.devices[0].tx_bytes = master->main_device.tx_bytes;
|
||||
data.devices[0].rx_bytes = master->main_device.rx_bytes;
|
||||
data.devices[0].tx_errors = master->main_device.tx_errors;
|
||||
for (i = 0; i < EC_RATE_COUNT; i++) {
|
||||
data.devices[0].tx_frame_rates[i] =
|
||||
master->main_device.tx_frame_rates[i];
|
||||
data.devices[0].rx_frame_rates[i] =
|
||||
master->main_device.rx_frame_rates[i];
|
||||
data.devices[0].tx_byte_rates[i] =
|
||||
master->main_device.tx_byte_rates[i];
|
||||
data.devices[0].rx_byte_rates[i] =
|
||||
master->main_device.rx_byte_rates[i];
|
||||
}
|
||||
for (i = 0; i < EC_NUM_DEVICES; i++) {
|
||||
ec_device_t *device = &master->devices[i];
|
||||
|
||||
if (master->backup_device.dev) {
|
||||
memcpy(data.devices[1].address,
|
||||
master->backup_device.dev->dev_addr, ETH_ALEN);
|
||||
} else {
|
||||
memcpy(data.devices[1].address, master->backup_mac, ETH_ALEN);
|
||||
}
|
||||
data.devices[1].attached = master->backup_device.dev ? 1 : 0;
|
||||
data.devices[1].link_state = master->backup_device.link_state ? 1 : 0;
|
||||
data.devices[1].tx_count = master->backup_device.tx_count;
|
||||
data.devices[1].rx_count = master->backup_device.rx_count;
|
||||
data.devices[1].tx_bytes = master->backup_device.tx_bytes;
|
||||
data.devices[1].rx_bytes = master->backup_device.rx_bytes;
|
||||
data.devices[1].tx_errors = master->backup_device.tx_errors;
|
||||
for (i = 0; i < EC_RATE_COUNT; i++) {
|
||||
data.devices[1].tx_frame_rates[i] =
|
||||
master->backup_device.tx_frame_rates[i];
|
||||
data.devices[1].rx_frame_rates[i] =
|
||||
master->backup_device.rx_frame_rates[i];
|
||||
data.devices[1].tx_byte_rates[i] =
|
||||
master->backup_device.tx_byte_rates[i];
|
||||
data.devices[1].rx_byte_rates[i] =
|
||||
master->backup_device.rx_byte_rates[i];
|
||||
if (device->dev) {
|
||||
memcpy(data.devices[i].address,
|
||||
device->dev->dev_addr, ETH_ALEN);
|
||||
} else {
|
||||
memcpy(data.devices[i].address, master->macs[i], ETH_ALEN);
|
||||
}
|
||||
data.devices[i].attached = device->dev ? 1 : 0;
|
||||
data.devices[i].link_state = device->link_state ? 1 : 0;
|
||||
data.devices[i].tx_count = device->tx_count;
|
||||
data.devices[i].rx_count = device->rx_count;
|
||||
data.devices[i].tx_bytes = device->tx_bytes;
|
||||
data.devices[i].rx_bytes = device->rx_bytes;
|
||||
data.devices[i].tx_errors = device->tx_errors;
|
||||
for (j = 0; j < EC_RATE_COUNT; j++) {
|
||||
data.devices[i].tx_frame_rates[j] =
|
||||
device->tx_frame_rates[j];
|
||||
data.devices[i].rx_frame_rates[j] =
|
||||
device->rx_frame_rates[j];
|
||||
data.devices[i].tx_byte_rates[j] =
|
||||
device->tx_byte_rates[j];
|
||||
data.devices[i].rx_byte_rates[j] =
|
||||
device->rx_byte_rates[j];
|
||||
}
|
||||
}
|
||||
|
||||
data.tx_count = master->device_stats.tx_count;
|
||||
|
|
|
|||
|
|
@ -513,9 +513,9 @@ void ecdev_withdraw(ec_device_t *device /**< EtherCAT device */)
|
|||
|
||||
ec_mac_print(device->dev->dev_addr, mac_str);
|
||||
|
||||
if (device == &master->main_device) {
|
||||
if (device == &master->devices[EC_DEVICE_MAIN]) {
|
||||
sprintf(dev_str, "main");
|
||||
} else if (device == &master->backup_device) {
|
||||
} else if (device == &master->devices[EC_DEVICE_BACKUP]) {
|
||||
sprintf(dev_str, "backup");
|
||||
} else {
|
||||
EC_MASTER_WARN(master, "%s() called with unknown device %s!\n",
|
||||
|
|
@ -548,9 +548,9 @@ int ecdev_open(ec_device_t *device /**< EtherCAT device */)
|
|||
return ret;
|
||||
}
|
||||
|
||||
if (master->main_device.open &&
|
||||
(ec_mac_is_zero(master->backup_mac) ||
|
||||
master->backup_device.open)) {
|
||||
if (master->devices[EC_DEVICE_MAIN].open &&
|
||||
(ec_mac_is_zero(master->macs[EC_DEVICE_BACKUP]) ||
|
||||
master->devices[EC_DEVICE_BACKUP].open)) {
|
||||
ret = ec_master_enter_idle_phase(device->master);
|
||||
if (ret) {
|
||||
EC_MASTER_ERR(device->master, "Failed to enter IDLE phase!\n");
|
||||
|
|
|
|||
|
|
@ -384,11 +384,13 @@ int ec_eoe_is_idle(const ec_eoe_t *eoe /**< EoE handler */)
|
|||
*
|
||||
* Starts a new receiving sequence by queueing a datagram that checks the
|
||||
* slave's mailbox for a new EoE datagram.
|
||||
*
|
||||
* \fixme Use both devices.
|
||||
*/
|
||||
void ec_eoe_state_rx_start(ec_eoe_t *eoe /**< EoE handler */)
|
||||
{
|
||||
if (eoe->slave->error_flag ||
|
||||
!eoe->slave->master->main_device.link_state) {
|
||||
!eoe->slave->master->devices[EC_DEVICE_MAIN].link_state) {
|
||||
eoe->rx_idle = 1;
|
||||
eoe->tx_idle = 1;
|
||||
return;
|
||||
|
|
@ -606,6 +608,8 @@ void ec_eoe_state_rx_fetch(ec_eoe_t *eoe /**< EoE handler */)
|
|||
*
|
||||
* Starts a new transmit sequence. If no data is available, a new receive
|
||||
* sequence is started instead.
|
||||
*
|
||||
* \fixme Use both devices.
|
||||
*/
|
||||
void ec_eoe_state_tx_start(ec_eoe_t *eoe /**< EoE handler */)
|
||||
{
|
||||
|
|
@ -614,7 +618,7 @@ void ec_eoe_state_tx_start(ec_eoe_t *eoe /**< EoE handler */)
|
|||
#endif
|
||||
|
||||
if (eoe->slave->error_flag ||
|
||||
!eoe->slave->master->main_device.link_state) {
|
||||
!eoe->slave->master->devices[EC_DEVICE_MAIN].link_state) {
|
||||
eoe->rx_idle = 1;
|
||||
eoe->tx_idle = 1;
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -207,7 +207,7 @@ void ec_fsm_master_state_broadcast(
|
|||
fsm->slaves_responding);
|
||||
}
|
||||
|
||||
if (fsm->link_state && !master->main_device.link_state) {
|
||||
if (fsm->link_state && !master->devices[EC_DEVICE_MAIN].link_state) {
|
||||
// link went down
|
||||
EC_MASTER_DBG(master, 1, "Master state machine detected "
|
||||
"link down. Clearing slave list.\n");
|
||||
|
|
@ -219,7 +219,7 @@ void ec_fsm_master_state_broadcast(
|
|||
ec_master_clear_slaves(master);
|
||||
fsm->slave_states = 0x00;
|
||||
}
|
||||
fsm->link_state = master->main_device.link_state;
|
||||
fsm->link_state = master->devices[EC_DEVICE_MAIN].link_state;
|
||||
|
||||
if (datagram->state != EC_DATAGRAM_RECEIVED) {
|
||||
ec_fsm_master_restart(fsm);
|
||||
|
|
|
|||
|
|
@ -216,6 +216,14 @@ enum {
|
|||
EC_SDO_ENTRY_ACCESS_COUNT /**< Number of states. */
|
||||
};
|
||||
|
||||
/** Master devices.
|
||||
*/
|
||||
enum {
|
||||
EC_DEVICE_MAIN, /**< Main device. */
|
||||
EC_DEVICE_BACKUP, /**< Backup device */
|
||||
EC_NUM_DEVICES /**< Number of devices. */
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/** Convenience macro for printing EtherCAT-specific information to syslog.
|
||||
|
|
|
|||
|
|
@ -174,7 +174,7 @@ typedef struct {
|
|||
uint32_t rx_frame_rates[EC_RATE_COUNT];
|
||||
uint32_t tx_byte_rates[EC_RATE_COUNT];
|
||||
uint32_t rx_byte_rates[EC_RATE_COUNT];
|
||||
} devices[2];
|
||||
} devices[EC_NUM_DEVICES];
|
||||
uint64_t tx_count;
|
||||
uint64_t rx_count;
|
||||
uint64_t tx_bytes;
|
||||
|
|
|
|||
|
|
@ -109,11 +109,13 @@ void ec_master_init_static(void)
|
|||
{
|
||||
#ifdef EC_HAVE_CYCLES
|
||||
timeout_cycles = (cycles_t) EC_IO_TIMEOUT /* us */ * (cpu_khz / 1000);
|
||||
ext_injection_timeout_cycles = (cycles_t) EC_SDO_INJECTION_TIMEOUT /* us */ * (cpu_khz / 1000);
|
||||
ext_injection_timeout_cycles =
|
||||
(cycles_t) EC_SDO_INJECTION_TIMEOUT /* us */ * (cpu_khz / 1000);
|
||||
#else
|
||||
// one jiffy may always elapse between time measurement
|
||||
timeout_jiffies = max(EC_IO_TIMEOUT * HZ / 1000000, 1);
|
||||
ext_injection_timeout_jiffies = max(EC_SDO_INJECTION_TIMEOUT * HZ / 1000000, 1);
|
||||
ext_injection_timeout_jiffies =
|
||||
max(EC_SDO_INJECTION_TIMEOUT * HZ / 1000000, 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
@ -140,8 +142,8 @@ int ec_master_init(ec_master_t *master, /**< EtherCAT master */
|
|||
|
||||
sema_init(&master->master_sem, 1);
|
||||
|
||||
master->main_mac = main_mac;
|
||||
master->backup_mac = backup_mac;
|
||||
master->macs[EC_DEVICE_MAIN] = main_mac;
|
||||
master->macs[EC_DEVICE_BACKUP] = backup_mac;
|
||||
ec_master_clear_device_stats(master);
|
||||
|
||||
sema_init(&master->device_sem, 1);
|
||||
|
|
@ -211,11 +213,11 @@ int ec_master_init(ec_master_t *master, /**< EtherCAT master */
|
|||
init_waitqueue_head(&master->reg_queue);
|
||||
|
||||
// init devices
|
||||
ret = ec_device_init(&master->main_device, master);
|
||||
ret = ec_device_init(&master->devices[EC_DEVICE_MAIN], master);
|
||||
if (ret < 0)
|
||||
goto out_return;
|
||||
|
||||
ret = ec_device_init(&master->backup_device, master);
|
||||
ret = ec_device_init(&master->devices[EC_DEVICE_BACKUP], master);
|
||||
if (ret < 0)
|
||||
goto out_clear_main;
|
||||
|
||||
|
|
@ -234,7 +236,8 @@ int ec_master_init(ec_master_t *master, /**< EtherCAT master */
|
|||
|
||||
// init reference sync datagram
|
||||
ec_datagram_init(&master->ref_sync_datagram);
|
||||
snprintf(master->ref_sync_datagram.name, EC_DATAGRAM_NAME_SIZE, "refsync");
|
||||
snprintf(master->ref_sync_datagram.name, EC_DATAGRAM_NAME_SIZE,
|
||||
"refsync");
|
||||
ret = ec_datagram_apwr(&master->ref_sync_datagram, 0, 0x0910, 8);
|
||||
if (ret < 0) {
|
||||
ec_datagram_clear(&master->ref_sync_datagram);
|
||||
|
|
@ -256,7 +259,8 @@ int ec_master_init(ec_master_t *master, /**< EtherCAT master */
|
|||
|
||||
// init sync monitor datagram
|
||||
ec_datagram_init(&master->sync_mon_datagram);
|
||||
snprintf(master->sync_mon_datagram.name, EC_DATAGRAM_NAME_SIZE, "syncmon");
|
||||
snprintf(master->sync_mon_datagram.name, EC_DATAGRAM_NAME_SIZE,
|
||||
"syncmon");
|
||||
ret = ec_datagram_brd(&master->sync_mon_datagram, 0x092c, 4);
|
||||
if (ret < 0) {
|
||||
ec_datagram_clear(&master->sync_mon_datagram);
|
||||
|
|
@ -309,9 +313,9 @@ out_clear_fsm:
|
|||
ec_fsm_master_clear(&master->fsm);
|
||||
ec_datagram_clear(&master->fsm_datagram);
|
||||
out_clear_backup:
|
||||
ec_device_clear(&master->backup_device);
|
||||
ec_device_clear(&master->devices[EC_DEVICE_BACKUP]);
|
||||
out_clear_main:
|
||||
ec_device_clear(&master->main_device);
|
||||
ec_device_clear(&master->devices[EC_DEVICE_MAIN]);
|
||||
out_return:
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -344,8 +348,8 @@ void ec_master_clear(
|
|||
ec_datagram_clear(&master->ref_sync_datagram);
|
||||
ec_fsm_master_clear(&master->fsm);
|
||||
ec_datagram_clear(&master->fsm_datagram);
|
||||
ec_device_clear(&master->backup_device);
|
||||
ec_device_clear(&master->main_device);
|
||||
ec_device_clear(&master->devices[EC_DEVICE_BACKUP]);
|
||||
ec_device_clear(&master->devices[EC_DEVICE_MAIN]);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -591,7 +595,9 @@ void ec_master_leave_idle_phase(ec_master_t *master /**< EtherCAT master */)
|
|||
|
||||
/** Transition function from IDLE to OPERATION phase.
|
||||
*/
|
||||
int ec_master_enter_operation_phase(ec_master_t *master /**< EtherCAT master */)
|
||||
int ec_master_enter_operation_phase(
|
||||
ec_master_t *master /**< EtherCAT master */
|
||||
)
|
||||
{
|
||||
int ret = 0;
|
||||
ec_slave_t *slave;
|
||||
|
|
@ -628,7 +634,8 @@ int ec_master_enter_operation_phase(ec_master_t *master /**< EtherCAT master */)
|
|||
up(&master->scan_sem);
|
||||
|
||||
// wait for slave scan to complete
|
||||
ret = wait_event_interruptible(master->scan_queue, !master->scan_busy);
|
||||
ret = wait_event_interruptible(master->scan_queue,
|
||||
!master->scan_busy);
|
||||
if (ret) {
|
||||
EC_MASTER_INFO(master, "Waiting for slave scan"
|
||||
" interrupted by signal.\n");
|
||||
|
|
@ -908,7 +915,7 @@ void ec_master_send_datagrams(ec_master_t *master /**< EtherCAT master */)
|
|||
|
||||
do {
|
||||
// fetch pointer to transmit socket buffer
|
||||
frame_data = ec_device_tx_data(&master->main_device);
|
||||
frame_data = ec_device_tx_data(&master->devices[EC_DEVICE_MAIN]);
|
||||
cur_data = frame_data + EC_FRAME_HEADER_SIZE;
|
||||
follows_word = NULL;
|
||||
more_datagrams_waiting = 0;
|
||||
|
|
@ -933,7 +940,8 @@ void ec_master_send_datagrams(ec_master_t *master /**< EtherCAT master */)
|
|||
|
||||
// set "datagram following" flag in previous frame
|
||||
if (follows_word)
|
||||
EC_WRITE_U16(follows_word, EC_READ_U16(follows_word) | 0x8000);
|
||||
EC_WRITE_U16(follows_word,
|
||||
EC_READ_U16(follows_word) | 0x8000);
|
||||
|
||||
// EtherCAT datagram header
|
||||
EC_WRITE_U8 (cur_data, datagram->type);
|
||||
|
|
@ -960,7 +968,7 @@ void ec_master_send_datagrams(ec_master_t *master /**< EtherCAT master */)
|
|||
|
||||
// EtherCAT frame header
|
||||
EC_WRITE_U16(frame_data, ((cur_data - frame_data
|
||||
- EC_FRAME_HEADER_SIZE) & 0x7FF) | 0x1000);
|
||||
- EC_FRAME_HEADER_SIZE) & 0x7FF) | 0x1000);
|
||||
|
||||
// pad frame
|
||||
while (cur_data - frame_data < ETH_ZLEN - ETH_HLEN)
|
||||
|
|
@ -969,7 +977,8 @@ void ec_master_send_datagrams(ec_master_t *master /**< EtherCAT master */)
|
|||
EC_MASTER_DBG(master, 2, "frame size: %zu\n", cur_data - frame_data);
|
||||
|
||||
// send frame
|
||||
ec_device_send(&master->main_device, cur_data - frame_data);
|
||||
ec_device_send(&master->devices[EC_DEVICE_MAIN],
|
||||
cur_data - frame_data);
|
||||
#ifdef EC_HAVE_CYCLES
|
||||
cycles_sent = get_cycles();
|
||||
#endif
|
||||
|
|
@ -1092,7 +1101,7 @@ void ec_master_receive_datagrams(ec_master_t *master, /**< EtherCAT master */
|
|||
EC_DATAGRAM_HEADER_SIZE + data_size
|
||||
+ EC_DATAGRAM_FOOTER_SIZE);
|
||||
#ifdef EC_DEBUG_RING
|
||||
ec_device_debug_ring_print(&master->main_device);
|
||||
ec_device_debug_ring_print(&master->devices[EC_DEVICE_MAIN]);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
@ -1117,9 +1126,11 @@ void ec_master_receive_datagrams(ec_master_t *master, /**< EtherCAT master */
|
|||
// dequeue the received datagram
|
||||
datagram->state = EC_DATAGRAM_RECEIVED;
|
||||
#ifdef EC_HAVE_CYCLES
|
||||
datagram->cycles_received = master->main_device.cycles_poll;
|
||||
datagram->cycles_received =
|
||||
master->devices[EC_DEVICE_MAIN].cycles_poll;
|
||||
#endif
|
||||
datagram->jiffies_received = master->main_device.jiffies_poll;
|
||||
datagram->jiffies_received =
|
||||
master->devices[EC_DEVICE_MAIN].jiffies_poll;
|
||||
list_del_init(&datagram->queue);
|
||||
}
|
||||
}
|
||||
|
|
@ -1230,8 +1241,8 @@ void ec_master_update_device_stats(
|
|||
s->last_tx_bytes = s->tx_bytes;
|
||||
s->last_rx_bytes = s->rx_bytes;
|
||||
|
||||
ec_device_update_stats(&master->main_device);
|
||||
ec_device_update_stats(&master->backup_device);
|
||||
ec_device_update_stats(&master->devices[EC_DEVICE_MAIN]);
|
||||
ec_device_update_stats(&master->devices[EC_DEVICE_BACKUP]);
|
||||
|
||||
s->jiffies = jiffies;
|
||||
}
|
||||
|
|
@ -1356,8 +1367,8 @@ static int ec_master_idle_thread(void *priv_data)
|
|||
}
|
||||
ec_master_inject_external_datagrams(master);
|
||||
ecrt_master_send(master);
|
||||
sent_bytes = master->main_device.tx_skb[
|
||||
master->main_device.tx_ring_index]->len;
|
||||
sent_bytes = master->devices[EC_DEVICE_MAIN].tx_skb[
|
||||
master->devices[EC_DEVICE_MAIN].tx_ring_index]->len;
|
||||
up(&master->io_sem);
|
||||
|
||||
if (ec_fsm_master_idle(&master->fsm)) {
|
||||
|
|
@ -2000,7 +2011,8 @@ ec_domain_t *ecrt_master_create_domain_err(
|
|||
EC_MASTER_DBG(master, 1, "ecrt_master_create_domain(master = 0x%p)\n",
|
||||
master);
|
||||
|
||||
if (!(domain = (ec_domain_t *) kmalloc(sizeof(ec_domain_t), GFP_KERNEL))) {
|
||||
if (!(domain =
|
||||
(ec_domain_t *) kmalloc(sizeof(ec_domain_t), GFP_KERNEL))) {
|
||||
EC_MASTER_ERR(master, "Error allocating domain memory!\n");
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
|
@ -2186,18 +2198,19 @@ void ecrt_master_send(ec_master_t *master)
|
|||
}
|
||||
ec_master_inject_external_datagrams(master);
|
||||
|
||||
if (unlikely(!master->main_device.link_state)) {
|
||||
if (unlikely(!master->devices[EC_DEVICE_MAIN].link_state)) {
|
||||
// link is down, no datagram can be sent
|
||||
list_for_each_entry_safe(datagram, n, &master->datagram_queue, queue) {
|
||||
list_for_each_entry_safe(datagram, n,
|
||||
&master->datagram_queue, queue) {
|
||||
datagram->state = EC_DATAGRAM_ERROR;
|
||||
list_del_init(&datagram->queue);
|
||||
}
|
||||
|
||||
// query link state
|
||||
ec_device_poll(&master->main_device);
|
||||
ec_device_poll(&master->devices[EC_DEVICE_MAIN]);
|
||||
|
||||
// clear frame statistics
|
||||
ec_device_clear_stats(&master->main_device);
|
||||
ec_device_clear_stats(&master->devices[EC_DEVICE_MAIN]);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -2212,9 +2225,9 @@ void ecrt_master_receive(ec_master_t *master)
|
|||
ec_datagram_t *datagram, *next;
|
||||
|
||||
// receive datagrams
|
||||
ec_device_poll(&master->main_device);
|
||||
if (master->backup_device.dev) {
|
||||
ec_device_poll(&master->backup_device);
|
||||
ec_device_poll(&master->devices[EC_DEVICE_MAIN]);
|
||||
if (master->devices[EC_DEVICE_BACKUP].dev) {
|
||||
ec_device_poll(&master->devices[EC_DEVICE_BACKUP]);
|
||||
}
|
||||
ec_master_update_device_stats(master);
|
||||
|
||||
|
|
@ -2223,11 +2236,11 @@ void ecrt_master_receive(ec_master_t *master)
|
|||
if (datagram->state != EC_DATAGRAM_SENT) continue;
|
||||
|
||||
#ifdef EC_HAVE_CYCLES
|
||||
if (master->main_device.cycles_poll - datagram->cycles_sent
|
||||
> timeout_cycles) {
|
||||
if (master->devices[EC_DEVICE_MAIN].cycles_poll -
|
||||
datagram->cycles_sent > timeout_cycles) {
|
||||
#else
|
||||
if (master->main_device.jiffies_poll - datagram->jiffies_sent
|
||||
> timeout_jiffies) {
|
||||
if (master->devices[EC_DEVICE_MAIN].jiffies_poll -
|
||||
datagram->jiffies_sent > timeout_jiffies) {
|
||||
#endif
|
||||
list_del_init(&datagram->queue);
|
||||
datagram->state = EC_DATAGRAM_TIMED_OUT;
|
||||
|
|
@ -2237,10 +2250,12 @@ void ecrt_master_receive(ec_master_t *master)
|
|||
if (unlikely(master->debug_level > 0)) {
|
||||
unsigned int time_us;
|
||||
#ifdef EC_HAVE_CYCLES
|
||||
time_us = (unsigned int) (master->main_device.cycles_poll -
|
||||
time_us = (unsigned int)
|
||||
(master->devices[EC_DEVICE_MAIN].cycles_poll -
|
||||
datagram->cycles_sent) * 1000 / cpu_khz;
|
||||
#else
|
||||
time_us = (unsigned int) ((master->main_device.jiffies_poll -
|
||||
time_us = (unsigned int)
|
||||
((master->devices[EC_DEVICE_MAIN].jiffies_poll -
|
||||
datagram->jiffies_sent) * 1000000 / HZ);
|
||||
#endif
|
||||
EC_MASTER_DBG(master, 0, "TIMED OUT datagram %p,"
|
||||
|
|
@ -2345,7 +2360,7 @@ int ecrt_master(ec_master_t *master, ec_master_info_t *master_info)
|
|||
" master_info = 0x%p)\n", master, master_info);
|
||||
|
||||
master_info->slave_count = master->slave_count;
|
||||
master_info->link_up = master->main_device.link_state;
|
||||
master_info->link_up = master->devices[EC_DEVICE_MAIN].link_state;
|
||||
master_info->scan_busy = master->scan_busy;
|
||||
master_info->app_time = master->app_time;
|
||||
return 0;
|
||||
|
|
@ -2406,7 +2421,7 @@ void ecrt_master_state(const ec_master_t *master, ec_master_state_t *state)
|
|||
{
|
||||
state->slaves_responding = master->fsm.slaves_responding;
|
||||
state->al_states = master->fsm.slave_states;
|
||||
state->link_up = master->main_device.link_state;
|
||||
state->link_up = master->devices[EC_DEVICE_MAIN].link_state;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
|
|||
|
|
@ -187,10 +187,8 @@ struct ec_master {
|
|||
|
||||
struct semaphore master_sem; /**< Master semaphore. */
|
||||
|
||||
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. */
|
||||
ec_device_t devices[EC_NUM_DEVICES]; /**< EtherCAT devices. */
|
||||
const uint8_t *macs[EC_NUM_DEVICES]; /**< Device MAC addresses. */
|
||||
struct semaphore device_sem; /**< Device semaphore. */
|
||||
ec_device_stats_t device_stats; /**< Device statistics. */
|
||||
|
||||
|
|
|
|||
|
|
@ -229,13 +229,19 @@ int ec_mac_equal(
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
/** Maximum MAC string size.
|
||||
*/
|
||||
#define EC_MAX_MAC_STRING_SIZE (3 * ETH_ALEN)
|
||||
|
||||
/** Print a MAC address to a buffer.
|
||||
*
|
||||
* The buffer size must be at least EC_MAX_MAC_STRING_SIZE.
|
||||
*
|
||||
* \return number of bytes written.
|
||||
*/
|
||||
ssize_t ec_mac_print(
|
||||
const uint8_t *mac, /**< MAC address */
|
||||
char *buffer /**< target buffer */
|
||||
char *buffer /**< Target buffer. */
|
||||
)
|
||||
{
|
||||
off_t off = 0;
|
||||
|
|
@ -445,6 +451,13 @@ size_t ec_state_string(uint8_t states, /**< slave states */
|
|||
* Device interface
|
||||
*****************************************************************************/
|
||||
|
||||
/** Device names.
|
||||
*/
|
||||
static const char *ec_device_names[EC_NUM_DEVICES] = {
|
||||
"main",
|
||||
"backup"
|
||||
};
|
||||
|
||||
/** Offers an EtherCAT device to a certain master.
|
||||
*
|
||||
* The master decides, if it wants to use the device for EtherCAT operation,
|
||||
|
|
@ -462,8 +475,8 @@ ec_device_t *ecdev_offer(
|
|||
)
|
||||
{
|
||||
ec_master_t *master;
|
||||
char str[20];
|
||||
unsigned int i;
|
||||
char str[EC_MAX_MAC_STRING_SIZE];
|
||||
unsigned int i, j;
|
||||
|
||||
for (i = 0; i < master_count; i++) {
|
||||
master = &masters[i];
|
||||
|
|
@ -471,39 +484,27 @@ ec_device_t *ecdev_offer(
|
|||
|
||||
down(&master->device_sem);
|
||||
|
||||
if (!master->main_device.dev
|
||||
&& (ec_mac_equal(master->main_mac, net_dev->dev_addr)
|
||||
|| ec_mac_is_broadcast(master->main_mac))) {
|
||||
for (j = 0; j < EC_NUM_DEVICES; j++) {
|
||||
if (!master->devices[j].dev
|
||||
&& (ec_mac_equal(master->macs[j], net_dev->dev_addr)
|
||||
|| ec_mac_is_broadcast(master->macs[j]))) {
|
||||
|
||||
EC_INFO("Accepting %s as main device for master %u.\n",
|
||||
str, master->index);
|
||||
EC_INFO("Accepting %s as %s device for master %u.\n",
|
||||
str, ec_device_names[j], master->index);
|
||||
|
||||
ec_device_attach(&master->main_device, net_dev, poll, module);
|
||||
up(&master->device_sem);
|
||||
ec_device_attach(&master->devices[j], net_dev, poll, module);
|
||||
up(&master->device_sem);
|
||||
|
||||
snprintf(net_dev->name, IFNAMSIZ, "ecm%u", master->index);
|
||||
snprintf(net_dev->name, IFNAMSIZ, "ec%c%u",
|
||||
ec_device_names[j][0], master->index);
|
||||
|
||||
return &master->main_device; // offer accepted
|
||||
|
||||
} else if (!master->backup_device.dev
|
||||
&& ec_mac_equal(master->backup_mac, net_dev->dev_addr)) {
|
||||
|
||||
EC_INFO("Accepting %s as backup device for master %u.\n",
|
||||
str, master->index);
|
||||
|
||||
ec_device_attach(&master->backup_device, net_dev, poll, module);
|
||||
up(&master->device_sem);
|
||||
|
||||
snprintf(net_dev->name, IFNAMSIZ, "ecb%u", master->index);
|
||||
|
||||
return &master->backup_device; // offer accepted
|
||||
|
||||
} else {
|
||||
|
||||
up(&master->device_sem);
|
||||
|
||||
EC_MASTER_DBG(master, 1, "Master declined device %s.\n", str);
|
||||
return &master->devices[j]; // offer accepted
|
||||
}
|
||||
}
|
||||
|
||||
up(&master->device_sem);
|
||||
|
||||
EC_MASTER_DBG(master, 1, "Master declined device %s.\n", str);
|
||||
}
|
||||
|
||||
return NULL; // offer declined
|
||||
|
|
@ -522,6 +523,7 @@ ec_master_t *ecrt_request_master_err(
|
|||
)
|
||||
{
|
||||
ec_master_t *master, *errptr = NULL;
|
||||
unsigned int i, got_modules = 0;
|
||||
|
||||
EC_INFO("Requesting master %u...\n", master_index);
|
||||
|
||||
|
|
@ -558,11 +560,17 @@ ec_master_t *ecrt_request_master_err(
|
|||
goto out_release;
|
||||
}
|
||||
|
||||
if (!try_module_get(master->main_device.module)) {
|
||||
up(&master->device_sem);
|
||||
EC_ERR("Device module is unloading!\n");
|
||||
errptr = ERR_PTR(-ENODEV);
|
||||
goto out_release;
|
||||
for (i = 0; i < EC_NUM_DEVICES; i++) {
|
||||
ec_device_t *device = &master->devices[i];
|
||||
if (device->dev) {
|
||||
if (!try_module_get(device->module)) {
|
||||
up(&master->device_sem);
|
||||
EC_MASTER_ERR(master, "Device module is unloading!\n");
|
||||
errptr = ERR_PTR(-ENODEV);
|
||||
goto out_module_put;
|
||||
}
|
||||
}
|
||||
got_modules++;
|
||||
}
|
||||
|
||||
up(&master->device_sem);
|
||||
|
|
@ -577,7 +585,12 @@ ec_master_t *ecrt_request_master_err(
|
|||
return master;
|
||||
|
||||
out_module_put:
|
||||
module_put(master->main_device.module);
|
||||
for (; got_modules > 0; got_modules--) {
|
||||
ec_device_t *device = &master->devices[i - 1];
|
||||
if (device->dev) {
|
||||
module_put(device->module);
|
||||
}
|
||||
}
|
||||
out_release:
|
||||
master->reserved = 0;
|
||||
out_return:
|
||||
|
|
@ -596,6 +609,8 @@ ec_master_t *ecrt_request_master(unsigned int master_index)
|
|||
|
||||
void ecrt_release_master(ec_master_t *master)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
EC_MASTER_INFO(master, "Releasing master...\n");
|
||||
|
||||
if (!master->reserved) {
|
||||
|
|
@ -606,7 +621,12 @@ void ecrt_release_master(ec_master_t *master)
|
|||
|
||||
ec_master_leave_operation_phase(master);
|
||||
|
||||
module_put(master->main_device.module);
|
||||
for (i = 0; i < EC_NUM_DEVICES; i++) {
|
||||
if (master->devices[i].dev) {
|
||||
module_put(master->devices[i].module);
|
||||
}
|
||||
}
|
||||
|
||||
master->reserved = 0;
|
||||
|
||||
EC_MASTER_INFO(master, "Released.\n");
|
||||
|
|
|
|||
Loading…
Reference in New Issue