IgH EtherCAT Master  1.6.12
device.c
Go to the documentation of this file.
1/*****************************************************************************
2 *
3 * Copyright (C) 2006-2026 Florian Pose, Ingenieurgemeinschaft IgH
4 *
5 * This file is part of the IgH EtherCAT Master.
6 *
7 * The IgH EtherCAT Master is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License version 2, as
9 * published by the Free Software Foundation.
10 *
11 * The IgH EtherCAT Master is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
14 * Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with the IgH EtherCAT Master; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 *
20 ****************************************************************************/
21
26
27/****************************************************************************/
28
29#include <linux/module.h>
30#include <linux/skbuff.h>
31#include <linux/if_ether.h>
32#include <linux/netdevice.h>
33
34#include "device.h"
35#include "master.h"
36
37#ifdef EC_DEBUG_RING
38#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 6, 0)
39#define timersub(a, b, result) \
40 do { \
41 (result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \
42 (result)->tv_usec = (a)->tv_usec - (b)->tv_usec; \
43 if ((result)->tv_usec < 0) { \
44 --(result)->tv_sec; \
45 (result)->tv_usec += 1000000; \
46 } \
47 } while (0)
48#endif
49#endif
50
51/****************************************************************************/
52
53enum {
54 /* genet driver needs extra headroom in skb for status block */
55 EXTRA_HEADROOM = 64,
56};
57
63 ec_device_t *device,
64 ec_master_t *master
65 )
66{
67 int ret;
68 unsigned int i;
69 struct ethhdr *eth;
70#ifdef EC_DEBUG_IF
71 char ifname[10];
72 char mb = 'x';
73#endif
74
75 device->master = master;
76 device->dev = NULL;
77 device->poll = NULL;
78 device->module = NULL;
79 device->open = 0;
80 device->link_state = 0;
81 for (i = 0; i < EC_TX_RING_SIZE; i++) {
82 device->tx_skb[i] = NULL;
83 }
84 device->tx_ring_index = 0;
85#ifdef EC_HAVE_CYCLES
86 device->cycles_poll = 0;
87#endif
88#ifdef EC_DEBUG_RING
89 device->timeval_poll.tv_sec = 0;
90#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0)
91 device->timeval_poll.tv_nsec = 0;
92#else
93 device->timeval_poll.tv_usec = 0;
94#endif
95#endif
96 device->jiffies_poll = 0;
97
99
100#ifdef EC_DEBUG_RING
101 for (i = 0; i < EC_DEBUG_RING_SIZE; i++) {
102 ec_debug_frame_t *df = &device->debug_frames[i];
103 df->dir = TX;
104 df->t.tv_sec = 0;
105#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0)
106 df->t.tv_nsec = 0;
107#else
108 df->t.tv_usec = 0;
109#endif
110 memset(df->data, 0, EC_MAX_DATA_SIZE);
111 df->data_size = 0;
112 }
113#endif
114#ifdef EC_DEBUG_RING
115 device->debug_frame_index = 0;
116 device->debug_frame_count = 0;
117#endif
118
119#ifdef EC_DEBUG_IF
120 if (device == &master->devices[EC_DEVICE_MAIN]) {
121 mb = 'm';
122 }
123 else {
124 mb = 'b';
125 }
126
127 sprintf(ifname, "ecdbg%c%u", mb, master->index);
128
129 ret = ec_debug_init(&device->dbg, device, ifname);
130 if (ret < 0) {
131 EC_MASTER_ERR(master, "Failed to init debug device!\n");
132 goto out_return;
133 }
134#endif
135
136 for (i = 0; i < EC_TX_RING_SIZE; i++) {
137 if (!(device->tx_skb[i] =
138 dev_alloc_skb(ETH_FRAME_LEN + EXTRA_HEADROOM))) {
139 EC_MASTER_ERR(master,
140 "Error allocating device socket buffer!\n");
141 ret = -ENOMEM;
142 goto out_tx_ring;
143 }
144
145 // add Ethernet-II-header
146 skb_reserve(device->tx_skb[i], ETH_HLEN + EXTRA_HEADROOM);
147 eth = (struct ethhdr *) skb_push(device->tx_skb[i], ETH_HLEN);
148 eth->h_proto = htons(0x88A4);
149 memset(eth->h_dest, 0xFF, ETH_ALEN);
150 }
151
152 return 0;
153
154out_tx_ring:
155 for (i = 0; i < EC_TX_RING_SIZE; i++) {
156 if (device->tx_skb[i]) {
157 dev_kfree_skb(device->tx_skb[i]);
158 }
159 }
160#ifdef EC_DEBUG_IF
161 ec_debug_clear(&device->dbg);
162out_return:
163#endif
164 return ret;
165}
166
167/****************************************************************************/
168
172 ec_device_t *device
173 )
174{
175 unsigned int i;
176
177 if (device->open) {
178 ec_device_close(device);
179 }
180
181 for (i = 0; i < EC_TX_RING_SIZE; i++) {
182 dev_kfree_skb(device->tx_skb[i]);
183 }
184
185#ifdef EC_DEBUG_IF
186 ec_debug_clear(&device->dbg);
187#endif
188}
189
190/****************************************************************************/
191
195 ec_device_t *device,
196 struct net_device *net_dev,
197 ec_pollfunc_t poll,
198 struct module *module
199 )
200{
201 unsigned int i;
202 struct ethhdr *eth;
203
204 ec_device_detach(device); // resets fields
205
206 device->dev = net_dev;
207 device->poll = poll;
208 device->module = module;
209
210 for (i = 0; i < EC_TX_RING_SIZE; i++) {
211 device->tx_skb[i]->dev = net_dev;
212 eth = (struct ethhdr *) (device->tx_skb[i]->data);
213 memcpy(eth->h_source, net_dev->dev_addr, ETH_ALEN);
214 }
215
216#ifdef EC_DEBUG_IF
217 ec_debug_register(&device->dbg, net_dev);
218#endif
219} // NOLINT(whitespace/indent) false positive
220
221/****************************************************************************/
222
226 ec_device_t *device
227 )
228{
229 unsigned int i;
230
231#ifdef EC_DEBUG_IF
232 ec_debug_unregister(&device->dbg);
233#endif
234
235 device->dev = NULL;
236 device->poll = NULL;
237 device->module = NULL;
238 device->open = 0;
239 device->link_state = 0; // down
240
241 ec_device_clear_stats(device);
242
243 for (i = 0; i < EC_TX_RING_SIZE; i++) {
244 device->tx_skb[i]->dev = NULL;
245 }
246}
247
248/****************************************************************************/
249
255 ec_device_t *device
256 )
257{
258 int ret;
259
260 if (!device->dev) {
261 EC_MASTER_ERR(device->master, "No net_device to open!\n");
262 return -ENODEV;
263 }
264
265 if (device->open) {
266 EC_MASTER_WARN(device->master, "Device already opened!\n");
267 return 0;
268 }
269
270 device->link_state = 0;
271
272 ec_device_clear_stats(device);
273
274 ret = device->dev->netdev_ops->ndo_open(device->dev);
275 if (!ret)
276 device->open = 1;
277
278 return ret;
279}
280
281/****************************************************************************/
282
288 ec_device_t *device
289 )
290{
291 int ret;
292
293 if (!device->dev) {
294 EC_MASTER_ERR(device->master, "No device to close!\n");
295 return -ENODEV;
296 }
297
298 if (!device->open) {
299 EC_MASTER_WARN(device->master, "Device already closed!\n");
300 return 0;
301 }
302
303 ret = device->dev->netdev_ops->ndo_stop(device->dev);
304 if (!ret)
305 device->open = 0;
306
307 return ret;
308}
309
310/****************************************************************************/
311
317 ec_device_t *device
318 )
319{
320 /* cycle through socket buffers, because otherwise there is a race
321 * condition, if multiple frames are sent and the DMA is not scheduled in
322 * between. */
323 device->tx_ring_index++;
325 return device->tx_skb[device->tx_ring_index]->data + ETH_HLEN;
326}
327
328/****************************************************************************/
329
336 ec_device_t *device,
337 size_t size
338 )
339{
340 struct sk_buff *skb = device->tx_skb[device->tx_ring_index];
341
342 // set the right length for the data
343 skb->len = ETH_HLEN + size;
344
345 if (unlikely(device->master->debug_level > 1)) {
346 EC_MASTER_DBG(device->master, 2, "Sending frame:\n");
347 ec_print_data(skb->data, ETH_HLEN + size);
348 }
349
350 // start sending
351 if (device->dev->netdev_ops->ndo_start_xmit(skb, device->dev) ==
352 NETDEV_TX_OK)
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#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0)
416 ktime_get_real_ts64(&df->t);
417#else
418 do_gettimeofday(&df->t);
419#endif
420 }
421 else {
422 df->t = device->timeval_poll;
423 }
424 memcpy(df->data, data, size);
425 df->data_size = size;
426
427 device->debug_frame_index++;
428 device->debug_frame_index %= EC_DEBUG_RING_SIZE;
429 if (unlikely(device->debug_frame_count < EC_DEBUG_RING_SIZE))
430 device->debug_frame_count++;
431}
432
433/****************************************************************************/
434
437void ec_device_debug_ring_print(
438 const ec_device_t *device
439 )
440{
441 int i;
442 unsigned int ring_index;
443 const ec_debug_frame_t *df;
444#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0)
445 struct timespec64 t0, diff;
446#else
447 struct timeval t0, diff;
448#endif
449
450 // calculate index of the newest frame in the ring to get its time
451 ring_index = (device->debug_frame_index + EC_DEBUG_RING_SIZE - 1)
452 % EC_DEBUG_RING_SIZE;
453 t0 = device->debug_frames[ring_index].t;
454
455 EC_MASTER_DBG(device->master, 1, "Debug ring %u:\n", ring_index);
456
457 // calculate index of the oldest frame in the ring
458 ring_index = (device->debug_frame_index + EC_DEBUG_RING_SIZE
459 - device->debug_frame_count) % EC_DEBUG_RING_SIZE;
460
461 for (i = 0; i < device->debug_frame_count; i++) {
462 df = &device->debug_frames[ring_index];
463#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0)
464 diff = timespec64_sub(t0, df->t);
465#else
466 timersub(&t0, &df->t, &diff);
467#endif
468
469#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0)
470 EC_MASTER_DBG(device->master, 1, "Frame %u, dt=%u.%06u s, %s:\n",
471 i + 1 - device->debug_frame_count,
472 (unsigned int) diff.tv_sec,
473 (unsigned int) (diff.tv_nsec / 1000),
474 (df->dir == TX) ? "TX" : "RX");
475#else
476 EC_MASTER_DBG(device->master, 1, "Frame %u, dt=%u.%06u s, %s:\n",
477 i + 1 - device->debug_frame_count,
478 (unsigned int) diff.tv_sec,
479 (unsigned int) diff.tv_usec,
480 (df->dir == TX) ? "TX" : "RX");
481#endif
482 ec_print_data(df->data, df->data_size);
483
484 ring_index++;
485 ring_index %= EC_DEBUG_RING_SIZE;
486 }
487}
488#endif
489
490/****************************************************************************/
491
499 ec_device_t *device
500 )
501{
502#ifdef EC_HAVE_CYCLES
503 device->cycles_poll = get_cycles();
504#endif
505 device->jiffies_poll = jiffies;
506#ifdef EC_DEBUG_RING
507#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0)
508 ktime_get_real_ts64(&device->timeval_poll);
509#else
510 do_gettimeofday(&device->timeval_poll);
511#endif
512#endif
513 device->poll(device->dev);
514}
515
516/****************************************************************************/
517
521 ec_device_t *device
522 )
523{
524 unsigned int i;
525
526 s32 tx_frame_rate = (device->tx_count - device->last_tx_count) * 1000;
527 s32 rx_frame_rate = (device->rx_count - device->last_rx_count) * 1000;
528 s32 tx_byte_rate = (device->tx_bytes - device->last_tx_bytes);
529 s32 rx_byte_rate = (device->rx_bytes - device->last_rx_bytes);
530
531 /* Low-pass filter:
532 * Y_n = y_(n - 1) + T / tau * (x - y_(n - 1)) | T = 1
533 * -> Y_n += (x - y_(n - 1)) / tau
534 */
535 for (i = 0; i < EC_RATE_COUNT; i++) {
536 s32 n = rate_intervals[i];
537 device->tx_frame_rates[i] +=
538 (tx_frame_rate - device->tx_frame_rates[i]) / n;
539 device->rx_frame_rates[i] +=
540 (rx_frame_rate - device->rx_frame_rates[i]) / n;
541 device->tx_byte_rates[i] +=
542 (tx_byte_rate - device->tx_byte_rates[i]) / n;
543 device->rx_byte_rates[i] +=
544 (rx_byte_rate - device->rx_byte_rates[i]) / n;
545 }
546
547 device->last_tx_count = device->tx_count;
548 device->last_rx_count = device->rx_count;
549 device->last_tx_bytes = device->tx_bytes;
550 device->last_rx_bytes = device->rx_bytes;
551}
552
553/*****************************************************************************
554 * Device interface
555 ****************************************************************************/
556
568{
569 ec_master_t *master = device->master;
570 char dev_str[20], mac_str[20];
571
572 ec_mac_print(device->dev->dev_addr, mac_str);
573
574 if (device == &master->devices[EC_DEVICE_MAIN]) {
575 sprintf(dev_str, "main");
576 } else if (device == &master->devices[EC_DEVICE_BACKUP]) {
577 sprintf(dev_str, "backup");
578 } else {
579 EC_MASTER_WARN(master, "%s() called with unknown device %s!\n",
580 __func__, mac_str);
581 sprintf(dev_str, "UNKNOWN");
582 }
583
584 EC_MASTER_INFO(master, "Releasing %s device %s.\n", dev_str, mac_str);
585
586 down(&master->device_sem);
587 ec_device_detach(device);
588 up(&master->device_sem);
589}
590
591/****************************************************************************/
592
599{
600 int ret;
601 ec_master_t *master = device->master;
602 unsigned int all_open = 1, dev_idx;
603
604 ret = ec_device_open(device);
605 if (ret) {
606 EC_MASTER_ERR(master, "Failed to open device: error %d!\n", ret);
607 return ret;
608 }
609
610 for (dev_idx = EC_DEVICE_MAIN;
611 dev_idx < ec_master_num_devices(device->master); dev_idx++) {
612 if (!master->devices[dev_idx].open) {
613 all_open = 0;
614 break;
615 }
616 }
617
618 if (all_open) {
619 ret = ec_master_enter_idle_phase(device->master);
620 if (ret) {
621 EC_MASTER_ERR(device->master, "Failed to enter IDLE phase!\n");
622 return ret;
623 }
624 }
625
626 return 0;
627}
628
629/****************************************************************************/
630
637{
638 ec_master_t *master = device->master;
639
640 if (master->phase == EC_IDLE) {
642 }
643
644 if (ec_device_close(device)) {
645 EC_MASTER_WARN(master, "Failed to close device!\n");
646 }
647}
648
649/****************************************************************************/
650
661 ec_device_t *device,
662 const void *data,
663 size_t size
664 )
665{
666 const void *ec_data = data + ETH_HLEN;
667 size_t ec_size = size - ETH_HLEN;
668
669 if (unlikely(!data)) {
670 EC_MASTER_WARN(device->master, "%s() called with NULL data.\n",
671 __func__);
672 return;
673 }
674
675 device->rx_count++;
676 device->master->device_stats.rx_count++;
677 device->rx_bytes += size;
678 device->master->device_stats.rx_bytes += size;
679
680 if (unlikely(device->master->debug_level > 1)) {
681 EC_MASTER_DBG(device->master, 2, "Received frame:\n");
682 ec_print_data(data, size);
683 }
684
685#ifdef EC_DEBUG_IF
686 ec_debug_send(&device->dbg, data, size);
687#endif
688#ifdef EC_DEBUG_RING
689 ec_device_debug_ring_append(device, RX, ec_data, ec_size);
690#endif
691
692 ec_master_receive_datagrams(device->master, device, ec_data, ec_size);
693}
694
695/****************************************************************************/
696
705 ec_device_t *device,
706 uint8_t state
707 )
708{
709 if (unlikely(!device)) {
710 EC_WARN("ecdev_set_link() called with null device!\n");
711 return;
712 }
713
714 if (likely(state != device->link_state)) {
715 device->link_state = state;
716 EC_MASTER_INFO(device->master,
717 "Link state of %s changed to %s.\n",
718 device->dev->name, (state ? "UP" : "DOWN"));
719 }
720}
721
722/****************************************************************************/
723
731 const ec_device_t *device
732 )
733{
734 if (unlikely(!device)) {
735 EC_WARN("ecdev_get_link() called with null device!\n");
736 return 0;
737 }
738
739 return device->link_state;
740}
741
742/****************************************************************************/
743
745
746EXPORT_SYMBOL(ecdev_withdraw);
747EXPORT_SYMBOL(ecdev_open);
748EXPORT_SYMBOL(ecdev_close);
749EXPORT_SYMBOL(ecdev_receive);
750EXPORT_SYMBOL(ecdev_get_link);
751EXPORT_SYMBOL(ecdev_set_link);
752
754
755/****************************************************************************/
void ec_debug_clear(ec_debug_t *dbg)
Debug interface destructor.
Definition debug.c:103
void ec_debug_unregister(ec_debug_t *dbg)
Unregister debug interface.
Definition debug.c:144
void ec_debug_register(ec_debug_t *dbg, const struct net_device *net_dev)
Register debug interface.
Definition debug.c:115
int ec_debug_init(ec_debug_t *dbg, ec_device_t *device, const char *name)
Debug interface constructor.
Definition debug.c:64
void ec_debug_send(ec_debug_t *dbg, const uint8_t *data, size_t size)
Sends frame data to the interface.
Definition debug.c:159
void ec_device_detach(ec_device_t *device)
Disconnect from net_device.
Definition device.c:225
void ec_device_update_stats(ec_device_t *device)
Update device statistics.
Definition device.c:520
int ec_device_close(ec_device_t *device)
Stops the EtherCAT device.
Definition device.c:287
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:194
int ec_device_init(ec_device_t *device, ec_master_t *master)
Constructor.
Definition device.c:62
uint8_t * ec_device_tx_data(ec_device_t *device)
Returns a pointer to the device's transmit memory.
Definition device.c:316
void ec_device_poll(ec_device_t *device)
Calls the poll function of the assigned net_device.
Definition device.c:498
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:171
void ec_device_send(ec_device_t *device, size_t size)
Sends the content of the transmit socket buffer.
Definition device.c:335
int ec_device_open(ec_device_t *device)
Opens the EtherCAT device.
Definition device.c:254
EtherCAT device structure.
#define EC_TX_RING_SIZE
Size of the transmit ring.
Definition device.h:43
void(* ec_pollfunc_t)(struct net_device *)
Device poll function type.
Definition ecdev.h:49
struct ec_device ec_device_t
Definition ecdev.h:45
#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:233
ssize_t ec_mac_print(const uint8_t *, char *)
Print a MAC address to a buffer.
Definition module.c:245
@ EC_DEVICE_MAIN
Main device.
Definition globals.h:198
@ EC_DEVICE_BACKUP
Backup device.
Definition globals.h:199
void ec_print_data(const uint8_t *, size_t)
Outputs frame contents for debugging purposes.
Definition module.c:344
struct ec_master ec_master_t
Definition ecrt.h:300
void ecdev_close(ec_device_t *device)
Makes the master leave IDLE phase and closes the network device.
Definition device.c:636
int ecdev_open(ec_device_t *device)
Opens the network device and makes the master enter IDLE phase.
Definition device.c:598
void ecdev_withdraw(ec_device_t *device)
Withdraws an EtherCAT device from the master.
Definition device.c:567
uint8_t ecdev_get_link(const ec_device_t *device)
Reads the link state.
Definition device.c:730
void ecdev_set_link(ec_device_t *device, uint8_t state)
Sets a new link state.
Definition device.c:704
void ecdev_receive(ec_device_t *device, const void *data, size_t size)
Accepts a received frame.
Definition device.c:660
void ec_master_leave_idle_phase(ec_master_t *master)
Transition function from IDLE to ORPHANED phase.
Definition master.c:681
const unsigned int rate_intervals[]
List of intervals for statistics [s].
Definition master.c:105
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:1133
int ec_master_enter_idle_phase(ec_master_t *master)
Transition function from ORPHANED to IDLE phase.
Definition master.c:648
EtherCAT master structure.
#define ec_master_num_devices(MASTER)
Number of Ethernet devices.
Definition master.h:323
#define EC_MASTER_INFO(master, fmt, args...)
Convenience macro for printing master-specific information to syslog.
Definition master.h:62
#define EC_MASTER_DBG(master, level, fmt, args...)
Convenience macro for printing master-specific debug messages to syslog.
Definition master.h:100
@ EC_IDLE
Idle phase.
Definition master.h:126
#define EC_MASTER_ERR(master, fmt, args...)
Convenience macro for printing master-specific errors to syslog.
Definition master.h:74
#define EC_MASTER_WARN(master, fmt, args...)
Convenience macro for printing master-specific warnings to syslog.
Definition master.h:86
u64 tx_count
Number of frames sent.
Definition master.h:149
u64 rx_bytes
Number of bytes received.
Definition master.h:156
u64 tx_bytes
Number of bytes sent.
Definition master.h:154
u64 rx_count
Number of frames received.
Definition master.h:151
u64 tx_errors
Number of transmit errors.
Definition device.h:111
uint8_t open
true, if the net_device has been opened
Definition device.h:84
u64 tx_count
Number of frames sent.
Definition device.h:101
s32 tx_frame_rates[EC_RATE_COUNT]
Transmit rates in frames/s for different statistics cycle periods.
Definition device.h:112
ec_master_t * master
EtherCAT master.
Definition device.h:80
u64 last_rx_bytes
Number of bytes received of last statistics cycle.
Definition device.h:109
s32 rx_byte_rates[EC_RATE_COUNT]
Receive rates in byte/s for different statistics cycle periods.
Definition device.h:120
u64 last_rx_count
Number of frames received of last statistics cycle.
Definition device.h:104
s32 tx_byte_rates[EC_RATE_COUNT]
Transmit rates in byte/s for different statistics cycle periods.
Definition device.h:118
struct sk_buff * tx_skb[EC_TX_RING_SIZE]
transmit skb ring
Definition device.h:86
struct module * module
pointer to the device's owning module
Definition device.h:83
s32 rx_frame_rates[EC_RATE_COUNT]
Receive rates in frames/s for different statistics cycle periods.
Definition device.h:115
struct net_device * dev
pointer to the assigned net_device
Definition device.h:81
u64 tx_bytes
Number of bytes sent.
Definition device.h:106
ec_pollfunc_t poll
pointer to the device's poll function
Definition device.h:82
u64 rx_count
Number of frames received.
Definition device.h:103
uint8_t link_state
device link state
Definition device.h:85
u64 last_tx_bytes
Number of bytes sent of last statistics cycle.
Definition device.h:107
unsigned int tx_ring_index
last ring entry used to transmit
Definition device.h:87
unsigned long jiffies_poll
jiffies of last poll
Definition device.h:98
u64 last_tx_count
Number of frames sent of last statistics cycle.
Definition device.h:102
u64 rx_bytes
Number of bytes received.
Definition device.h:108
unsigned int index
Index.
Definition master.h:188
ec_device_stats_t device_stats
Device statistics.
Definition master.h:208
unsigned int debug_level
Master debug level.
Definition master.h:275
struct semaphore device_sem
Device semaphore.
Definition master.h:207
ec_master_phase_t phase
Master phase.
Definition master.h:212
ec_device_t devices[EC_MAX_NUM_DEVICES]
EtherCAT devices.
Definition master.h:200