# HG changeset patch # User Florian Pose # Date 1171991743 0 # Node ID 17c6fd3b076e98818816569fe034d0662289b818 # Parent f402b4bd2f4de2c9b32e322303bfcf0044953166 Made master devices persistent; added ec_device_attach() and ec_device_detach(). diff -r f402b4bd2f4d -r 17c6fd3b076e master/device.c --- a/master/device.c Tue Feb 20 13:42:44 2007 +0000 +++ b/master/device.c Tue Feb 20 17:15:43 2007 +0000 @@ -54,73 +54,97 @@ */ int ec_device_init(ec_device_t *device, /**< EtherCAT device */ - ec_master_t *master, /**< master owning the device */ - struct net_device *net_dev, /**< net_device structure */ - ec_pollfunc_t poll, /**< pointer to device's poll function */ - struct module *module /**< the device's module */ - ) -{ - struct ethhdr *eth; - + ec_master_t *master /**< master owning the device */ + ) +{ device->master = master; + +#ifdef EC_DBG_IF + if (ec_debug_init(&device->dbg)) { + EC_ERR("Failed to init debug device!\n"); + goto out_return; + } +#endif + + if (!(device->tx_skb = dev_alloc_skb(ETH_FRAME_LEN))) { + EC_ERR("Error allocating device socket buffer!\n"); +#ifdef EC_DBG_IF + goto out_debug; +#else + goto out_return; +#endif + } + + // add Ethernet-II-header + skb_reserve(device->tx_skb, ETH_HLEN); + device->eth = (struct ethhdr *) skb_push(device->tx_skb, ETH_HLEN); + device->eth->h_proto = htons(0x88A4); + memset(device->eth->h_dest, 0xFF, ETH_ALEN); + + ec_device_detach(device); // resets remaining fields + return 0; + +#ifdef EC_DBG_IF + out_debug: + ec_debug_clear(&device->dbg); +#endif + out_return: + return -1; +} + +/*****************************************************************************/ + +/** + EtherCAT device destuctor. +*/ + +void ec_device_clear(ec_device_t *device /**< EtherCAT device */) +{ + if (device->open) ec_device_close(device); + dev_kfree_skb(device->tx_skb); +#ifdef EC_DBG_IF + ec_debug_clear(&device->dbg); +#endif +} + +/*****************************************************************************/ + +/** + Associate with net_device. +*/ + +void ec_device_attach(ec_device_t *device, /**< EtherCAT device */ + struct net_device *net_dev, /**< net_device structure */ + ec_pollfunc_t poll, /**< pointer to device's poll function */ + struct module *module /**< the device's module */ + ) +{ + ec_device_detach(device); // resets fields + device->dev = net_dev; device->poll = poll; device->module = module; + device->tx_skb->dev = net_dev; + memcpy(device->eth->h_source, net_dev->dev_addr, ETH_ALEN); +} + +/*****************************************************************************/ + +/** + Disconnect from net_device. +*/ + +void ec_device_detach(ec_device_t *device /**< EtherCAT device */) +{ + device->dev = NULL; + device->poll = NULL; + device->module = NULL; device->open = 0; device->link_state = 0; // down - device->tx_count = 0; device->rx_count = 0; - -#ifdef EC_DBG_IF - if (ec_debug_init(&device->dbg)) { - EC_ERR("Failed to init debug device!\n"); - goto out_return; - } -#endif - - if (!(device->tx_skb = dev_alloc_skb(ETH_FRAME_LEN))) { - EC_ERR("Error allocating device socket buffer!\n"); -#ifdef EC_DBG_IF - goto out_debug; -#else - goto out_return; -#endif - } - - device->tx_skb->dev = net_dev; - - // add Ethernet-II-header - skb_reserve(device->tx_skb, ETH_HLEN); - eth = (struct ethhdr *) skb_push(device->tx_skb, ETH_HLEN); - eth->h_proto = htons(0x88A4); - memcpy(eth->h_source, net_dev->dev_addr, net_dev->addr_len); - memset(eth->h_dest, 0xFF, net_dev->addr_len); - - return 0; - -#ifdef EC_DBG_IF - out_debug: - ec_debug_clear(&device->dbg); -#endif - out_return: - return -1; -} - -/*****************************************************************************/ - -/** - EtherCAT device destuctor. -*/ - -void ec_device_clear(ec_device_t *device /**< EtherCAT device */) -{ - if (device->open) ec_device_close(device); - if (device->tx_skb) dev_kfree_skb(device->tx_skb); -#ifdef EC_DBG_IF - ec_debug_clear(&device->dbg); -#endif + device->tx_skb->dev = NULL; } /*****************************************************************************/ diff -r f402b4bd2f4d -r 17c6fd3b076e master/device.h --- a/master/device.h Tue Feb 20 13:42:44 2007 +0000 +++ b/master/device.h Tue Feb 20 17:15:43 2007 +0000 @@ -63,13 +63,14 @@ { ec_master_t *master; /**< EtherCAT master */ struct net_device *dev; /**< pointer to the assigned net_device */ + ec_pollfunc_t poll; /**< pointer to the device's poll function */ + struct module *module; /**< pointer to the device's owning module */ uint8_t open; /**< true, if the net_device has been opened */ + uint8_t link_state; /**< device link state */ struct sk_buff *tx_skb; /**< transmit socket buffer */ - ec_pollfunc_t poll; /**< pointer to the device's poll function */ + struct ethhdr *eth; /**< pointer to ethernet header in socket buffer */ cycles_t cycles_poll; /**< cycles of last poll */ unsigned long jiffies_poll; /**< jiffies of last poll */ - struct module *module; /**< pointer to the device's owning module */ - uint8_t link_state; /**< device link state */ unsigned int tx_count; /**< number of frames sent */ unsigned int rx_count; /**< number of frames received */ #ifdef EC_DBG_IF @@ -79,10 +80,13 @@ /*****************************************************************************/ -int ec_device_init(ec_device_t *, ec_master_t *, struct net_device *, - ec_pollfunc_t, struct module *); +int ec_device_init(ec_device_t *, ec_master_t *); void ec_device_clear(ec_device_t *); +void ec_device_attach(ec_device_t *, struct net_device *, ec_pollfunc_t, + struct module *); +void ec_device_detach(ec_device_t *); + int ec_device_open(ec_device_t *); int ec_device_close(ec_device_t *); diff -r f402b4bd2f4d -r 17c6fd3b076e master/ethernet.c --- a/master/ethernet.c Tue Feb 20 13:42:44 2007 +0000 +++ b/master/ethernet.c Tue Feb 20 17:15:43 2007 +0000 @@ -317,7 +317,7 @@ void ec_eoe_state_rx_start(ec_eoe_t *eoe /**< EoE handler */) { - if (!eoe->slave->online || !eoe->slave->master->device->link_state) + if (!eoe->slave->online || !eoe->slave->master->main_device.link_state) return; ec_slave_mbox_prepare_check(eoe->slave, &eoe->datagram); @@ -518,7 +518,7 @@ unsigned int wakeup = 0; #endif - if (!eoe->slave->online || !eoe->slave->master->device->link_state) + if (!eoe->slave->online || !eoe->slave->master->main_device.link_state) return; spin_lock_bh(&eoe->tx_queue_lock); diff -r f402b4bd2f4d -r 17c6fd3b076e master/master.c --- a/master/master.c Tue Feb 20 13:42:44 2007 +0000 +++ b/master/master.c Tue Feb 20 17:15:43 2007 +0000 @@ -114,9 +114,7 @@ atomic_set(&master->available, 1); master->index = index; - master->device = NULL; master->main_device_id = main_id; - master->backup_device = NULL; master->backup_device_id = backup_id; init_MUTEX(&master->device_sem); @@ -167,6 +165,13 @@ master->sdo_timer.data = (unsigned long) master; init_completion(&master->sdo_complete); + // init devices + if (ec_device_init(&master->main_device, master)) + goto out_return; + + if (ec_device_init(&master->backup_device, master)) + goto out_clear_main; + // create EoE handlers for (i = 0; i < eoeif_count; i++) { if (!(eoe = (ec_eoe_t *) kmalloc(sizeof(ec_eoe_t), GFP_KERNEL))) { @@ -216,6 +221,10 @@ ec_eoe_clear(eoe); kfree(eoe); } + ec_device_clear(&master->backup_device); +out_clear_main: + ec_device_clear(&master->main_device); +out_return: return -1; } @@ -267,6 +276,9 @@ kfree(eoe); } + ec_device_clear(&master->backup_device); + ec_device_clear(&master->main_device); + EC_INFO("Master %i freed.\n", master->index); kfree(master); @@ -594,7 +606,7 @@ do { // fetch pointer to transmit socket buffer - frame_data = ec_device_tx_data(master->device); + frame_data = ec_device_tx_data(&master->main_device); cur_data = frame_data + EC_FRAME_HEADER_SIZE; follows_word = NULL; more_datagrams_waiting = 0; @@ -657,7 +669,7 @@ EC_DBG("frame size: %i\n", cur_data - frame_data); // send frame - ec_device_send(master->device, cur_data - frame_data); + ec_device_send(&master->main_device, cur_data - frame_data); cycles_sent = get_cycles(); jiffies_sent = jiffies; @@ -764,8 +776,8 @@ // dequeue the received datagram datagram->state = EC_DATAGRAM_RECEIVED; - datagram->cycles_received = master->device->cycles_poll; - datagram->jiffies_received = master->device->jiffies_poll; + datagram->cycles_received = master->main_device.cycles_poll; + datagram->jiffies_received = master->main_device.jiffies_poll; list_del_init(&datagram->queue); } } @@ -862,7 +874,7 @@ off += ec_device_id_print(dev_id, buffer + off); - if (device) { + if (device->dev) { off += sprintf(buffer + off, " (connected).\n"); off += sprintf(buffer + off, " Frames sent: %u\n", device->tx_count); @@ -921,10 +933,10 @@ } off += sprintf(buffer + off, " Main: "); - off += ec_master_device_info(master->device, + off += ec_master_device_info(&master->main_device, master->main_device_id, buffer + off); off += sprintf(buffer + off, " Backup: "); - off += ec_master_device_info(master->backup_device, + off += ec_master_device_info(&master->backup_device, master->backup_device_id, buffer + off); up(&master->device_sem); @@ -1465,7 +1477,7 @@ { ec_datagram_t *datagram, *n; - if (unlikely(!master->device->link_state)) { + if (unlikely(!master->main_device.link_state)) { // link is down, no datagram can be sent list_for_each_entry_safe(datagram, n, &master->datagram_queue, queue) { datagram->state = EC_DATAGRAM_ERROR; @@ -1473,7 +1485,7 @@ } // query link state - ec_device_poll(master->device); + ec_device_poll(&master->main_device); return; } @@ -1494,7 +1506,7 @@ cycles_t cycles_timeout; // receive datagrams - ec_device_poll(master->device); + ec_device_poll(&master->main_device); cycles_timeout = (cycles_t) EC_IO_TIMEOUT /* us */ * (cpu_khz / 1000); @@ -1502,7 +1514,7 @@ list_for_each_entry_safe(datagram, next, &master->datagram_queue, queue) { if (datagram->state != EC_DATAGRAM_SENT) continue; - if (master->device->cycles_poll - datagram->cycles_sent + if (master->main_device.cycles_poll - datagram->cycles_sent > cycles_timeout) { list_del_init(&datagram->queue); datagram->state = EC_DATAGRAM_TIMED_OUT; diff -r f402b4bd2f4d -r 17c6fd3b076e master/master.h --- a/master/master.h Tue Feb 20 13:42:44 2007 +0000 +++ b/master/master.h Tue Feb 20 17:15:43 2007 +0000 @@ -99,9 +99,9 @@ struct kobject kobj; /**< kobject */ - ec_device_t *device; /**< EtherCAT device */ + ec_device_t main_device; /**< EtherCAT device */ const ec_device_id_t *main_device_id; /**< ID of main device */ - ec_device_t *backup_device; /**< EtherCAT backup device */ + ec_device_t backup_device; /**< EtherCAT backup device */ const ec_device_id_t *backup_device_id; /**< ID of backup device */ struct semaphore device_sem; /**< device semaphore */ diff -r f402b4bd2f4d -r 17c6fd3b076e master/module.c --- a/master/module.c Tue Feb 20 13:42:44 2007 +0000 +++ b/master/module.c Tue Feb 20 17:15:43 2007 +0000 @@ -342,54 +342,35 @@ char str[50]; // FIXME list_for_each_entry(master, &masters, list) { - if (down_interruptible(&master->device_sem)) { - EC_ERR("Interrupted while waiting for device semaphore!\n"); - goto out_return; - } - if (ec_device_id_check(master->main_device_id, net_dev, driver_name, device_index)) { - ec_device_id_print(master->main_device_id, str); EC_INFO("Accepting device %s for master %u.\n", str, master->index); - if (master->device) { - EC_ERR("Master %u already has a device.\n", master->index); - goto out_up; + if (down_interruptible(&master->device_sem)) { + EC_ERR("Interrupted while waiting for device semaphore!\n"); + return -1; + } + + if (master->main_device.dev) { + EC_ERR("Master %u already has a device attached.\n", + master->index); + up(&master->device_sem); + return -1; } - if (!(master->device = (ec_device_t *) - kmalloc(sizeof(ec_device_t), GFP_KERNEL))) { - EC_ERR("Failed to allocate device!\n"); - goto out_up; - } - - if (ec_device_init(master->device, master, - net_dev, poll, module)) { - EC_ERR("Failed to init device!\n"); - goto out_free; - } - + ec_device_attach(&master->main_device, net_dev, poll, module); up(&master->device_sem); + sprintf(net_dev->name, "ec%u", master->index); - *ecdev = master->device; // offer accepted + *ecdev = &master->main_device; // offer accepted return 0; // no error } - - up(&master->device_sem); } *ecdev = NULL; // offer declined return 0; // no error - - out_free: - kfree(master->device); - master->device = NULL; - out_up: - up(&master->device_sem); - out_return: - return 1; } /*****************************************************************************/ @@ -413,11 +394,8 @@ EC_INFO("Master %u releasing main device %s.\n", master->index, str); down(&master->device_sem); - master->device = NULL; + ec_device_detach(device); up(&master->device_sem); - - ec_device_clear(device); - kfree(device); } /*****************************************************************************/ @@ -503,13 +481,13 @@ goto out_release; } - if (!master->device) { + if (master->mode != EC_MASTER_MODE_IDLE) { up(&master->device_sem); - EC_ERR("Master %i has no assigned device!\n", master_index); + EC_ERR("Master %i still waiting for devices!\n", master_index); goto out_release; } - if (!try_module_get(master->device->module)) { + if (!try_module_get(master->main_device.module)) { up(&master->device_sem); EC_ERR("Device module is unloading!\n"); goto out_release; @@ -517,7 +495,7 @@ up(&master->device_sem); - if (!master->device->link_state) { + if (!master->main_device.link_state) { EC_ERR("Link is DOWN.\n"); goto out_module_put; } @@ -531,7 +509,7 @@ return master; out_module_put: - module_put(master->device->module); + module_put(master->main_device.module); out_release: atomic_inc(&master->available); out_return: @@ -556,7 +534,7 @@ ec_master_leave_operation_mode(master); - module_put(master->device->module); + module_put(master->main_device.module); atomic_inc(&master->available); EC_INFO("Released master %i.\n", master->index);