IgH EtherCAT Master  1.5.2
device.c
Go to the documentation of this file.
1/******************************************************************************
2 *
3 * $Id$
4 *
5 * Copyright (C) 2006-2008 Florian Pose, Ingenieurgemeinschaft IgH
6 *
7 * This file is part of the IgH EtherCAT Master.
8 *
9 * The IgH EtherCAT Master is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License version 2, as
11 * published by the Free Software Foundation.
12 *
13 * The IgH EtherCAT Master is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
16 * Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with the IgH EtherCAT Master; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21 *
22 * ---
23 *
24 * The license mentioned above concerns the source code only. Using the
25 * EtherCAT technology and brand is only permitted in compliance with the
26 * industrial property and similar rights of Beckhoff Automation GmbH.
27 *
28 *****************************************************************************/
29
35/*****************************************************************************/
36
37#include <linux/module.h>
38#include <linux/skbuff.h>
39#include <linux/if_ether.h>
40#include <linux/netdevice.h>
41
42#include "device.h"
43#include "master.h"
44
45#ifdef EC_DEBUG_RING
46#define timersub(a, b, result) \
47 do { \
48 (result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \
49 (result)->tv_usec = (a)->tv_usec - (b)->tv_usec; \
50 if ((result)->tv_usec < 0) { \
51 --(result)->tv_sec; \
52 (result)->tv_usec += 1000000; \
53 } \
54 } while (0)
55#endif
56
57/*****************************************************************************/
58
64 ec_device_t *device,
65 ec_master_t *master
66 )
67{
68 int ret;
69 unsigned int i;
70 struct ethhdr *eth;
71#ifdef EC_DEBUG_IF
72 char ifname[10];
73 char mb = 'x';
74#endif
75
76 device->master = master;
77 device->dev = NULL;
78 device->poll = NULL;
79 device->module = NULL;
80 device->open = 0;
81 device->link_state = 0;
82 for (i = 0; i < EC_TX_RING_SIZE; i++) {
83 device->tx_skb[i] = NULL;
84 }
85 device->tx_ring_index = 0;
86#ifdef EC_HAVE_CYCLES
87 device->cycles_poll = 0;
88#endif
89#ifdef EC_DEBUG_RING
90 device->timeval_poll.tv_sec = 0;
91 device->timeval_poll.tv_usec = 0;
92#endif
93 device->jiffies_poll = 0;
94
96
97#ifdef EC_DEBUG_RING
98 for (i = 0; i < EC_DEBUG_RING_SIZE; i++) {
99 ec_debug_frame_t *df = &device->debug_frames[i];
100 df->dir = TX;
101 df->t.tv_sec = 0;
102 df->t.tv_usec = 0;
103 memset(df->data, 0, EC_MAX_DATA_SIZE);
104 df->data_size = 0;
105 }
106#endif
107#ifdef EC_DEBUG_RING
108 device->debug_frame_index = 0;
109 device->debug_frame_count = 0;
110#endif
111
112#ifdef EC_DEBUG_IF
113 if (device == &master->devices[EC_DEVICE_MAIN]) {
114 mb = 'm';
115 }
116 else {
117 mb = 'b';
118 }
119
120 sprintf(ifname, "ecdbg%c%u", mb, master->index);
121
122 ret = ec_debug_init(&device->dbg, device, ifname);
123 if (ret < 0) {
124 EC_MASTER_ERR(master, "Failed to init debug device!\n");
125 goto out_return;
126 }
127#endif
128
129 for (i = 0; i < EC_TX_RING_SIZE; i++) {
130 if (!(device->tx_skb[i] = dev_alloc_skb(ETH_FRAME_LEN))) {
131 EC_MASTER_ERR(master, "Error allocating device socket buffer!\n");
132 ret = -ENOMEM;
133 goto out_tx_ring;
134 }
135
136 // add Ethernet-II-header
137 skb_reserve(device->tx_skb[i], ETH_HLEN);
138 eth = (struct ethhdr *) skb_push(device->tx_skb[i], ETH_HLEN);
139 eth->h_proto = htons(0x88A4);
140 memset(eth->h_dest, 0xFF, ETH_ALEN);
141 }
142
143 return 0;
144
145out_tx_ring:
146 for (i = 0; i < EC_TX_RING_SIZE; i++) {
147 if (device->tx_skb[i]) {
148 dev_kfree_skb(device->tx_skb[i]);
149 }
150 }
151#ifdef EC_DEBUG_IF
152 ec_debug_clear(&device->dbg);
153out_return:
154#endif
155 return ret;
156}
157
158/*****************************************************************************/
159
163 ec_device_t *device
164 )
165{
166 unsigned int i;
167
168 if (device->open) {
169 ec_device_close(device);
170 }
171 for (i = 0; i < EC_TX_RING_SIZE; i++)
172 dev_kfree_skb(device->tx_skb[i]);
173#ifdef EC_DEBUG_IF
174 ec_debug_clear(&device->dbg);
175#endif
176}
177
178/*****************************************************************************/
179
183 ec_device_t *device,
184 struct net_device *net_dev,
185 ec_pollfunc_t poll,
186 struct module *module
187 )
188{
189 unsigned int i;
190 struct ethhdr *eth;
191
192 ec_device_detach(device); // resets fields
193
194 device->dev = net_dev;
195 device->poll = poll;
196 device->module = module;
197
198 for (i = 0; i < EC_TX_RING_SIZE; i++) {
199 device->tx_skb[i]->dev = net_dev;
200 eth = (struct ethhdr *) (device->tx_skb[i]->data);
201 memcpy(eth->h_source, net_dev->dev_addr, ETH_ALEN);
202 }
203
204#ifdef EC_DEBUG_IF
205 ec_debug_register(&device->dbg, net_dev);
206#endif
207}
208
209/*****************************************************************************/
210
214 ec_device_t *device
215 )
216{
217 unsigned int i;
218
219#ifdef EC_DEBUG_IF
220 ec_debug_unregister(&device->dbg);
221#endif
222
223 device->dev = NULL;
224 device->poll = NULL;
225 device->module = NULL;
226 device->open = 0;
227 device->link_state = 0; // down
228
229 ec_device_clear_stats(device);
230
231 for (i = 0; i < EC_TX_RING_SIZE; i++) {
232 device->tx_skb[i]->dev = NULL;
233 }
234}
235
236/*****************************************************************************/
237
243 ec_device_t *device
244 )
245{
246 int ret;
247
248 if (!device->dev) {
249 EC_MASTER_ERR(device->master, "No net_device to open!\n");
250 return -ENODEV;
251 }
252
253 if (device->open) {
254 EC_MASTER_WARN(device->master, "Device already opened!\n");
255 return 0;
256 }
257
258 device->link_state = 0;
259
260 ec_device_clear_stats(device);
261
262#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29)
263 ret = device->dev->netdev_ops->ndo_open(device->dev);
264#else
265 ret = device->dev->open(device->dev);
266#endif
267 if (!ret)
268 device->open = 1;
269
270 return ret;
271}
272
273/*****************************************************************************/
274
280 ec_device_t *device
281 )
282{
283 int ret;
284
285 if (!device->dev) {
286 EC_MASTER_ERR(device->master, "No device to close!\n");
287 return -ENODEV;
288 }
289
290 if (!device->open) {
291 EC_MASTER_WARN(device->master, "Device already closed!\n");
292 return 0;
293 }
294
295#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29)
296 ret = device->dev->netdev_ops->ndo_stop(device->dev);
297#else
298 ret = device->dev->stop(device->dev);
299#endif
300 if (!ret)
301 device->open = 0;
302
303 return ret;
304}
305
306/*****************************************************************************/
307
313 ec_device_t *device
314 )
315{
316 /* cycle through socket buffers, because otherwise there is a race
317 * condition, if multiple frames are sent and the DMA is not scheduled in
318 * between. */
319 device->tx_ring_index++;
321 return device->tx_skb[device->tx_ring_index]->data + ETH_HLEN;
322}
323
324/*****************************************************************************/
325
332 ec_device_t *device,
333 size_t size
334 )
335{
336 struct sk_buff *skb = device->tx_skb[device->tx_ring_index];
337
338 // set the right length for the data
339 skb->len = ETH_HLEN + size;
340
341 if (unlikely(device->master->debug_level > 1)) {
342 EC_MASTER_DBG(device->master, 2, "Sending frame:\n");
343 ec_print_data(skb->data, ETH_HLEN + size);
344 }
345
346 // start sending
347#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29)
348 if (device->dev->netdev_ops->ndo_start_xmit(skb, device->dev) ==
349 NETDEV_TX_OK)
350#else
351 if (device->dev->hard_start_xmit(skb, device->dev) == NETDEV_TX_OK)
352#endif
353 {
354 device->tx_count++;
355 device->master->device_stats.tx_count++;
356 device->tx_bytes += ETH_HLEN + size;
357 device->master->device_stats.tx_bytes += ETH_HLEN + size;
358#ifdef EC_DEBUG_IF
359 ec_debug_send(&device->dbg, skb->data, ETH_HLEN + size);
360#endif
361#ifdef EC_DEBUG_RING
362 ec_device_debug_ring_append(
363 device, TX, skb->data + ETH_HLEN, size);
364#endif
365 } else {
366 device->tx_errors++;
367 }
368}
369
370/*****************************************************************************/
371
375 ec_device_t *device
376 )
377{
378 unsigned int i;
379
380 // zero frame statistics
381 device->tx_count = 0;
382 device->last_tx_count = 0;
383 device->rx_count = 0;
384 device->last_rx_count = 0;
385 device->tx_bytes = 0;
386 device->last_tx_bytes = 0;
387 device->rx_bytes = 0;
388 device->last_rx_bytes = 0;
389 device->tx_errors = 0;
390
391 for (i = 0; i < EC_RATE_COUNT; i++) {
392 device->tx_frame_rates[i] = 0;
393 device->rx_frame_rates[i] = 0;
394 device->tx_byte_rates[i] = 0;
395 device->rx_byte_rates[i] = 0;
396 }
397}
398
399/*****************************************************************************/
400
401#ifdef EC_DEBUG_RING
404void ec_device_debug_ring_append(
405 ec_device_t *device,
406 ec_debug_frame_dir_t dir,
407 const void *data,
408 size_t size
409 )
410{
411 ec_debug_frame_t *df = &device->debug_frames[device->debug_frame_index];
412
413 df->dir = dir;
414 if (dir == TX) {
415 do_gettimeofday(&df->t);
416 }
417 else {
418 df->t = device->timeval_poll;
419 }
420 memcpy(df->data, data, size);
421 df->data_size = size;
422
423 device->debug_frame_index++;
424 device->debug_frame_index %= EC_DEBUG_RING_SIZE;
425 if (unlikely(device->debug_frame_count < EC_DEBUG_RING_SIZE))
426 device->debug_frame_count++;
427}
428
429/*****************************************************************************/
430
433void ec_device_debug_ring_print(
434 const ec_device_t *device
435 )
436{
437 int i;
438 unsigned int ring_index;
439 const ec_debug_frame_t *df;
440 struct timeval t0, diff;
441
442 // calculate index of the newest frame in the ring to get its time
443 ring_index = (device->debug_frame_index + EC_DEBUG_RING_SIZE - 1)
444 % EC_DEBUG_RING_SIZE;
445 t0 = device->debug_frames[ring_index].t;
446
447 EC_MASTER_DBG(device->master, 1, "Debug ring %u:\n", ring_index);
448
449 // calculate index of the oldest frame in the ring
450 ring_index = (device->debug_frame_index + EC_DEBUG_RING_SIZE
451 - device->debug_frame_count) % EC_DEBUG_RING_SIZE;
452
453 for (i = 0; i < device->debug_frame_count; i++) {
454 df = &device->debug_frames[ring_index];
455 timersub(&t0, &df->t, &diff);
456
457 EC_MASTER_DBG(device->master, 1, "Frame %u, dt=%u.%06u s, %s:\n",
458 i + 1 - device->debug_frame_count,
459 (unsigned int) diff.tv_sec,
460 (unsigned int) diff.tv_usec,
461 (df->dir == TX) ? "TX" : "RX");
462 ec_print_data(df->data, df->data_size);
463
464 ring_index++;
465 ring_index %= EC_DEBUG_RING_SIZE;
466 }
467}
468#endif
469
470/*****************************************************************************/
471
479 ec_device_t *device
480 )
481{
482#ifdef EC_HAVE_CYCLES
483 device->cycles_poll = get_cycles();
484#endif
485 device->jiffies_poll = jiffies;
486#ifdef EC_DEBUG_RING
487 do_gettimeofday(&device->timeval_poll);
488#endif
489 device->poll(device->dev);
490}
491
492/*****************************************************************************/
493
497 ec_device_t *device
498 )
499{
500 unsigned int i;
501
502 s32 tx_frame_rate = (device->tx_count - device->last_tx_count) * 1000;
503 s32 rx_frame_rate = (device->rx_count - device->last_rx_count) * 1000;
504 s32 tx_byte_rate = (device->tx_bytes - device->last_tx_bytes);
505 s32 rx_byte_rate = (device->rx_bytes - device->last_rx_bytes);
506
507 /* Low-pass filter:
508 * Y_n = y_(n - 1) + T / tau * (x - y_(n - 1)) | T = 1
509 * -> Y_n += (x - y_(n - 1)) / tau
510 */
511 for (i = 0; i < EC_RATE_COUNT; i++) {
512 s32 n = rate_intervals[i];
513 device->tx_frame_rates[i] +=
514 (tx_frame_rate - device->tx_frame_rates[i]) / n;
515 device->rx_frame_rates[i] +=
516 (rx_frame_rate - device->rx_frame_rates[i]) / n;
517 device->tx_byte_rates[i] +=
518 (tx_byte_rate - device->tx_byte_rates[i]) / n;
519 device->rx_byte_rates[i] +=
520 (rx_byte_rate - device->rx_byte_rates[i]) / n;
521 }
522
523 device->last_tx_count = device->tx_count;
524 device->last_rx_count = device->rx_count;
525 device->last_tx_bytes = device->tx_bytes;
526 device->last_rx_bytes = device->rx_bytes;
527}
528
529/******************************************************************************
530 * Device interface
531 *****************************************************************************/
532
544{
545 ec_master_t *master = device->master;
546 char dev_str[20], mac_str[20];
547
548 ec_mac_print(device->dev->dev_addr, mac_str);
549
550 if (device == &master->devices[EC_DEVICE_MAIN]) {
551 sprintf(dev_str, "main");
552 } else if (device == &master->devices[EC_DEVICE_BACKUP]) {
553 sprintf(dev_str, "backup");
554 } else {
555 EC_MASTER_WARN(master, "%s() called with unknown device %s!\n",
556 __func__, mac_str);
557 sprintf(dev_str, "UNKNOWN");
558 }
559
560 EC_MASTER_INFO(master, "Releasing %s device %s.\n", dev_str, mac_str);
561
562 down(&master->device_sem);
563 ec_device_detach(device);
564 up(&master->device_sem);
565}
566
567/*****************************************************************************/
568
575{
576 int ret;
577 ec_master_t *master = device->master;
578 unsigned int all_open = 1, dev_idx;
579
580 ret = ec_device_open(device);
581 if (ret) {
582 EC_MASTER_ERR(master, "Failed to open device!\n");
583 return ret;
584 }
585
586 for (dev_idx = EC_DEVICE_MAIN;
587 dev_idx < ec_master_num_devices(device->master); dev_idx++) {
588 if (!master->devices[dev_idx].open) {
589 all_open = 0;
590 break;
591 }
592 }
593
594 if (all_open) {
595 ret = ec_master_enter_idle_phase(device->master);
596 if (ret) {
597 EC_MASTER_ERR(device->master, "Failed to enter IDLE phase!\n");
598 return ret;
599 }
600 }
601
602 return 0;
603}
604
605/*****************************************************************************/
606
613{
614 ec_master_t *master = device->master;
615
616 if (master->phase == EC_IDLE) {
618 }
619
620 if (ec_device_close(device)) {
621 EC_MASTER_WARN(master, "Failed to close device!\n");
622 }
623}
624
625/*****************************************************************************/
626
637 ec_device_t *device,
638 const void *data,
639 size_t size
640 )
641{
642 const void *ec_data = data + ETH_HLEN;
643 size_t ec_size = size - ETH_HLEN;
644
645 if (unlikely(!data)) {
646 EC_MASTER_WARN(device->master, "%s() called with NULL data.\n",
647 __func__);
648 return;
649 }
650
651 device->rx_count++;
652 device->master->device_stats.rx_count++;
653 device->rx_bytes += size;
654 device->master->device_stats.rx_bytes += size;
655
656 if (unlikely(device->master->debug_level > 1)) {
657 EC_MASTER_DBG(device->master, 2, "Received frame:\n");
658 ec_print_data(data, size);
659 }
660
661#ifdef EC_DEBUG_IF
662 ec_debug_send(&device->dbg, data, size);
663#endif
664#ifdef EC_DEBUG_RING
665 ec_device_debug_ring_append(device, RX, ec_data, ec_size);
666#endif
667
668 ec_master_receive_datagrams(device->master, device, ec_data, ec_size);
669}
670
671/*****************************************************************************/
672
681 ec_device_t *device,
682 uint8_t state
683 )
684{
685 if (unlikely(!device)) {
686 EC_WARN("ecdev_set_link() called with null device!\n");
687 return;
688 }
689
690 if (likely(state != device->link_state)) {
691 device->link_state = state;
692 EC_MASTER_INFO(device->master,
693 "Link state of %s changed to %s.\n",
694 device->dev->name, (state ? "UP" : "DOWN"));
695 }
696}
697
698/*****************************************************************************/
699
707 const ec_device_t *device
708 )
709{
710 if (unlikely(!device)) {
711 EC_WARN("ecdev_get_link() called with null device!\n");
712 return 0;
713 }
714
715 return device->link_state;
716}
717
718/*****************************************************************************/
719
722EXPORT_SYMBOL(ecdev_withdraw);
723EXPORT_SYMBOL(ecdev_open);
724EXPORT_SYMBOL(ecdev_close);
725EXPORT_SYMBOL(ecdev_receive);
726EXPORT_SYMBOL(ecdev_get_link);
727EXPORT_SYMBOL(ecdev_set_link);
728
731/*****************************************************************************/
void ec_debug_clear(ec_debug_t *dbg)
Debug interface destructor.
Definition: debug.c:120
void ec_debug_unregister(ec_debug_t *dbg)
Unregister debug interface.
Definition: debug.c:161
void ec_debug_register(ec_debug_t *dbg, const struct net_device *net_dev)
Register debug interface.
Definition: debug.c:132
int ec_debug_init(ec_debug_t *dbg, ec_device_t *device, const char *name)
Debug interface constructor.
Definition: debug.c:74
void ec_debug_send(ec_debug_t *dbg, const uint8_t *data, size_t size)
Sends frame data to the interface.
Definition: debug.c:176
void ec_device_detach(ec_device_t *device)
Disconnect from net_device.
Definition: device.c:213
void ec_device_update_stats(ec_device_t *device)
Update device statistics.
Definition: device.c:496
int ec_device_close(ec_device_t *device)
Stops the EtherCAT device.
Definition: device.c:279
void ec_device_attach(ec_device_t *device, struct net_device *net_dev, ec_pollfunc_t poll, struct module *module)
Associate with net_device.
Definition: device.c:182
int ec_device_init(ec_device_t *device, ec_master_t *master)
Constructor.
Definition: device.c:63
uint8_t * ec_device_tx_data(ec_device_t *device)
Returns a pointer to the device's transmit memory.
Definition: device.c:312
void ec_device_poll(ec_device_t *device)
Calls the poll function of the assigned net_device.
Definition: device.c:478
void ec_device_clear_stats(ec_device_t *device)
Clears the frame statistics.
Definition: device.c:374
void ec_device_clear(ec_device_t *device)
Destructor.
Definition: device.c:162
void ec_device_send(ec_device_t *device, size_t size)
Sends the content of the transmit socket buffer.
Definition: device.c:331
int ec_device_open(ec_device_t *device)
Opens the EtherCAT device.
Definition: device.c:242
EtherCAT device structure.
#define EC_TX_RING_SIZE
Size of the transmit ring.
Definition: device.h:51
void(* ec_pollfunc_t)(struct net_device *)
Device poll function type.
Definition: ecdev.h:57
#define EC_RATE_COUNT
Number of statistic rate intervals to maintain.
Definition: globals.h:60
#define EC_MAX_DATA_SIZE
Resulting maximum data size of a single datagram in a frame.
Definition: globals.h:79
#define EC_WARN(fmt, args...)
Convenience macro for printing EtherCAT-specific warnings to syslog.
Definition: globals.h:225
ssize_t ec_mac_print(const uint8_t *, char *)
Print a MAC address to a buffer.
Definition: module.c:249
@ EC_DEVICE_MAIN
Main device.
Definition: globals.h:190
@ EC_DEVICE_BACKUP
Backup device.
Definition: globals.h:191
void ec_print_data(const uint8_t *, size_t)
Outputs frame contents for debugging purposes.
Definition: module.c:348
void ecdev_close(ec_device_t *device)
Makes the master leave IDLE phase and closes the network device.
Definition: device.c:612
int ecdev_open(ec_device_t *device)
Opens the network device and makes the master enter IDLE phase.
Definition: device.c:574
void ecdev_withdraw(ec_device_t *device)
Withdraws an EtherCAT device from the master.
Definition: device.c:543
uint8_t ecdev_get_link(const ec_device_t *device)
Reads the link state.
Definition: device.c:706
void ecdev_set_link(ec_device_t *device, uint8_t state)
Sets a new link state.
Definition: device.c:680
void ecdev_receive(ec_device_t *device, const void *data, size_t size)
Accepts a received frame.
Definition: device.c:636
void ec_master_leave_idle_phase(ec_master_t *master)
Transition function from IDLE to ORPHANED phase.
Definition: master.c:674
const unsigned int rate_intervals[]
List of intervals for statistics [s].
Definition: master.c:100
void ec_master_receive_datagrams(ec_master_t *master, ec_device_t *device, const uint8_t *frame_data, size_t size)
Processes a received frame.
Definition: master.c:1137
int ec_master_enter_idle_phase(ec_master_t *master)
Transition function from ORPHANED to IDLE phase.
Definition: master.c:641
EtherCAT master structure.
#define ec_master_num_devices(MASTER)
Number of Ethernet devices.
Definition: master.h:330
#define EC_MASTER_INFO(master, fmt, args...)
Convenience macro for printing master-specific information to syslog.
Definition: master.h:73
#define EC_MASTER_DBG(master, level, fmt, args...)
Convenience macro for printing master-specific debug messages to syslog.
Definition: master.h:111
@ EC_IDLE
Idle phase.
Definition: master.h:133
#define EC_MASTER_ERR(master, fmt, args...)
Convenience macro for printing master-specific errors to syslog.
Definition: master.h:85
#define EC_MASTER_WARN(master, fmt, args...)
Convenience macro for printing master-specific warnings to syslog.
Definition: master.h:97
u64 tx_count
Number of frames sent.
Definition: master.h:156
u64 rx_bytes
Number of bytes received.
Definition: master.h:163
u64 tx_bytes
Number of bytes sent.
Definition: master.h:161
u64 rx_count
Number of frames received.
Definition: master.h:158
EtherCAT device.
Definition: device.h:82
u64 tx_errors
Number of transmit errors.
Definition: device.h:110
uint8_t open
true, if the net_device has been opened
Definition: device.h:87
u64 tx_count
Number of frames sent.
Definition: device.h:100
s32 tx_frame_rates[EC_RATE_COUNT]
Transmit rates in frames/s for different statistics cycle periods.
Definition: device.h:111
ec_master_t * master
EtherCAT master.
Definition: device.h:83
u64 last_rx_bytes
Number of bytes received of last statistics cycle.
Definition: device.h:108
s32 rx_byte_rates[EC_RATE_COUNT]
Receive rates in byte/s for different statistics cycle periods.
Definition: device.h:119
u64 last_rx_count
Number of frames received of last statistics cycle.
Definition: device.h:103
s32 tx_byte_rates[EC_RATE_COUNT]
Transmit rates in byte/s for different statistics cycle periods.
Definition: device.h:117
struct sk_buff * tx_skb[EC_TX_RING_SIZE]
transmit skb ring
Definition: device.h:89
struct module * module
pointer to the device's owning module
Definition: device.h:86
s32 rx_frame_rates[EC_RATE_COUNT]
Receive rates in frames/s for different statistics cycle periods.
Definition: device.h:114
struct net_device * dev
pointer to the assigned net_device
Definition: device.h:84
u64 tx_bytes
Number of bytes sent.
Definition: device.h:105
ec_pollfunc_t poll
pointer to the device's poll function
Definition: device.h:85
u64 rx_count
Number of frames received.
Definition: device.h:102
uint8_t link_state
device link state
Definition: device.h:88
u64 last_tx_bytes
Number of bytes sent of last statistics cycle.
Definition: device.h:106
unsigned int tx_ring_index
last ring entry used to transmit
Definition: device.h:90
unsigned long jiffies_poll
jiffies of last poll
Definition: device.h:97
u64 last_tx_count
Number of frames sent of last statistics cycle.
Definition: device.h:101
u64 rx_bytes
Number of bytes received.
Definition: device.h:107
EtherCAT master.
Definition: master.h:194
unsigned int index
Index.
Definition: master.h:195
ec_device_stats_t device_stats
Device statistics.
Definition: master.h:219
unsigned int debug_level
Master debug level.
Definition: master.h:285
struct semaphore device_sem
Device semaphore.
Definition: master.h:218
ec_master_phase_t phase
Master phase.
Definition: master.h:223
ec_device_t devices[EC_MAX_NUM_DEVICES]
EtherCAT devices.
Definition: master.h:211