# HG changeset patch # User Florian Pose # Date 1326366873 -3600 # Node ID 2d36f36a433c4051174bd8a9a9c1e52a20358542 # Parent e3bf5adad75f41d725953dd937a977c990e355ad Devices as array; lock all device modules with module_get(). diff -r e3bf5adad75f -r 2d36f36a433c master/cdev.c --- a/master/cdev.c Wed Nov 09 17:07:33 2011 +0100 +++ b/master/cdev.c Thu Jan 12 12:14:33 2012 +0100 @@ -184,10 +184,11 @@ ) { ec_ioctl_master_t data; - unsigned int i; - - if (down_interruptible(&master->master_sem)) - return -EINTR; + 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 @@ 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]; - } - - 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]; + for (i = 0; i < EC_NUM_DEVICES; i++) { + ec_device_t *device = &master->devices[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; diff -r e3bf5adad75f -r 2d36f36a433c master/device.c --- a/master/device.c Wed Nov 09 17:07:33 2011 +0100 +++ b/master/device.c Thu Jan 12 12:14:33 2012 +0100 @@ -513,9 +513,9 @@ 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 @@ 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"); diff -r e3bf5adad75f -r 2d36f36a433c master/ethernet.c --- a/master/ethernet.c Wed Nov 09 17:07:33 2011 +0100 +++ b/master/ethernet.c Thu Jan 12 12:14:33 2012 +0100 @@ -384,11 +384,13 @@ * * 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 @@ * * 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 @@ #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; diff -r e3bf5adad75f -r 2d36f36a433c master/fsm_master.c --- a/master/fsm_master.c Wed Nov 09 17:07:33 2011 +0100 +++ b/master/fsm_master.c Thu Jan 12 12:14:33 2012 +0100 @@ -207,7 +207,7 @@ 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 @@ 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); diff -r e3bf5adad75f -r 2d36f36a433c master/globals.h --- a/master/globals.h Wed Nov 09 17:07:33 2011 +0100 +++ b/master/globals.h Thu Jan 12 12:14:33 2012 +0100 @@ -216,6 +216,14 @@ 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. diff -r e3bf5adad75f -r 2d36f36a433c master/ioctl.h --- a/master/ioctl.h Wed Nov 09 17:07:33 2011 +0100 +++ b/master/ioctl.h Thu Jan 12 12:14:33 2012 +0100 @@ -174,7 +174,7 @@ 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; diff -r e3bf5adad75f -r 2d36f36a433c master/master.c --- a/master/master.c Wed Nov 09 17:07:33 2011 +0100 +++ b/master/master.c Thu Jan 12 12:14:33 2012 +0100 @@ -109,11 +109,13 @@ { #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 @@ 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 @@ 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 @@ // 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 @@ // 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 @@ 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 @@ 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 @@ /** 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 @@ 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 @@ 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 @@ // 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 @@ // 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 @@ 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 @@ 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 @@ // dequeue the received datagram datagram->state = EC_DATAGRAM_RECEIVED; #ifdef EC_HAVE_CYCLES - datagram->cycles_received = master->main_device.cycles_poll; -#endif - datagram->jiffies_received = master->main_device.jiffies_poll; + datagram->cycles_received = + master->devices[EC_DEVICE_MAIN].cycles_poll; +#endif + datagram->jiffies_received = + master->devices[EC_DEVICE_MAIN].jiffies_poll; list_del_init(&datagram->queue); } } @@ -1230,8 +1241,8 @@ 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 @@ } 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_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 @@ } 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 @@ 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 @@ 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 @@ 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 @@ " 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 @@ { 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; } /*****************************************************************************/ diff -r e3bf5adad75f -r 2d36f36a433c master/master.h --- a/master/master.h Wed Nov 09 17:07:33 2011 +0100 +++ b/master/master.h Thu Jan 12 12:14:33 2012 +0100 @@ -187,10 +187,8 @@ 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. */ diff -r e3bf5adad75f -r 2d36f36a433c master/module.c --- a/master/module.c Wed Nov 09 17:07:33 2011 +0100 +++ b/master/module.c Thu Jan 12 12:14:33 2012 +0100 @@ -229,13 +229,19 @@ /*****************************************************************************/ +/** 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 @@ * 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_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 @@ 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))) { - - EC_INFO("Accepting %s as main device for master %u.\n", - str, master->index); - - ec_device_attach(&master->main_device, net_dev, poll, module); - up(&master->device_sem); - - snprintf(net_dev->name, IFNAMSIZ, "ecm%u", 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); - } + 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 %s device for master %u.\n", + str, ec_device_names[j], master->index); + + ec_device_attach(&master->devices[j], net_dev, poll, module); + up(&master->device_sem); + + snprintf(net_dev->name, IFNAMSIZ, "ec%c%u", + ec_device_names[j][0], master->index); + + 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 *master, *errptr = NULL; + unsigned int i, got_modules = 0; EC_INFO("Requesting master %u...\n", master_index); @@ -558,11 +560,17 @@ 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 @@ 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 @@ 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 @@ 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");