29 #include <linux/version.h>    30 #include <linux/netdevice.h>    31 #include <linux/etherdevice.h>    32 #include <linux/lockdep.h>    33 #include <linux/skbuff.h>    41 #if defined(CONFIG_SUSE_KERNEL) && LINUX_VERSION_CODE >= KERNEL_VERSION(5, 14, 0)    42 #include <linux/suse_version.h>    45 #    define SUSE_VERSION 0    47 #  ifndef SUSE_PATCHLEVEL    48 #    define SUSE_PATCHLEVEL 0    61 #define EOE_DEBUG_LEVEL 1    65 #define EC_EOE_TX_QUEUE_SIZE 100    69 #define EC_EOE_TRIES 100   119     u8 mac_addr[ETH_ALEN] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55};
   136     memset(&eoe->
stats, 0, 
sizeof(
struct net_device_stats));
   158 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0)   159     eoe->
dev = alloc_netdev(
sizeof(
ec_eoe_t *), name, NET_NAME_UNKNOWN,
   162     eoe->
dev = alloc_netdev(
sizeof(
ec_eoe_t *), name, ether_setup);
   166                 " for EoE handler!\n", name);
   174 #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0) || (SUSE_VERSION == 15 && SUSE_PATCHLEVEL >= 5)   175     eth_hw_addr_set(eoe->
dev, mac_addr);
   177     memcpy(eoe->
dev->dev_addr, mac_addr, 
sizeof(mac_addr));
   181     priv = netdev_priv(eoe->
dev);
   193     ret = register_netdev(eoe->
dev);
   201     mac_addr[ETH_ALEN - 1] = (uint8_t) eoe->
dev->ifindex;
   202 #
if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0) || (SUSE_VERSION == 15 && SUSE_PATCHLEVEL >= 5)
   203     eth_hw_addr_set(eoe->
dev, mac_addr);
   205     memcpy(eoe->
dev->dev_addr, mac_addr, 
sizeof(mac_addr));
   211     free_netdev(eoe->
dev);
   225     unregister_netdev(eoe->
dev); 
   236         dev_kfree_skb(eoe->
rx_skb);
   238     free_netdev(eoe->
dev);
   250     struct list_head tx_queue;
   252     netif_tx_lock_bh(eoe->
dev);
   254     list_replace_init(&eoe->
tx_queue, &tx_queue);
   257     netif_tx_unlock_bh(eoe->
dev);
   259     list_for_each_entry_safe(frame, next, &tx_queue, queue) {
   260         list_del(&frame->
queue);
   261         dev_kfree_skb(frame->
skb);
   274     size_t remaining_size, current_size, complete_offset;
   275     unsigned int last_fragment;
   277 #if EOE_DEBUG_LEVEL >= 3   283     if (remaining_size <= eoe->slave->configured_tx_mailbox_size - 10) {
   284         current_size = remaining_size;
   296         complete_offset = remaining_size / 32 + 1;
   299 #if EOE_DEBUG_LEVEL >= 2   301             " with %zu octets (%zu). %u frames queued.\n",
   303             last_fragment ? 
"" : 
"+", current_size, complete_offset,
   307 #if EOE_DEBUG_LEVEL >= 3   309     for (i = 0; i < current_size; i++) {
   310         printk(KERN_CONT 
"%02X ",
   312         if ((i + 1) % 16 == 0) {
   313             printk(KERN_CONT 
"\n");
   317     printk(KERN_CONT 
"\n");
   321             EC_MBOX_TYPE_EOE, current_size + 4);
   323         return PTR_ERR(data);
   328                             (complete_offset & 0x3F) << 6 |
   437         eoe->
stats.rx_errors++;
   438 #if EOE_DEBUG_LEVEL >= 1   440                 " check datagram for %s.\n", eoe->
dev->name);
   467     size_t rec_size, data_size;
   468     uint8_t *data, frame_type, last_fragment, time_appended, mbox_prot;
   469     uint8_t fragment_offset, fragment_number;
   470 #if EOE_DEBUG_LEVEL >= 2   471     uint8_t frame_number;
   474 #if EOE_DEBUG_LEVEL >= 3   479         eoe->
stats.rx_errors++;
   480 #if EOE_DEBUG_LEVEL >= 1   482                 " fetch datagram for %s.\n", eoe->
dev->name);
   489             &mbox_prot, &rec_size);
   491         eoe->
stats.rx_errors++;
   492 #if EOE_DEBUG_LEVEL >= 1   500     if (mbox_prot != EC_MBOX_TYPE_EOE) { 
   501         eoe->
stats.rx_errors++;
   502 #if EOE_DEBUG_LEVEL >= 1   512     if (frame_type != EC_EOE_FRAMETYPE_INIT_REQ) { 
   513 #if EOE_DEBUG_LEVEL >= 1   515                 " Dropping.\n", eoe->
dev->name);
   517         eoe->
stats.rx_dropped++;
   527     fragment_offset = (
EC_READ_U16(data + 2) >> 6) & 0x003F;
   528 #if EOE_DEBUG_LEVEL >= 2   529     frame_number = (
EC_READ_U16(data + 2) >> 12) & 0x000F;
   532 #if EOE_DEBUG_LEVEL >= 2   534             " frame %u%s, %zu octets\n", eoe->
dev->name, fragment_number,
   535            last_fragment ? 
"" : 
"+", fragment_offset, frame_number,
   536            time_appended ? 
", + timestamp" : 
"",
   537            time_appended ? rec_size - 8 : rec_size - 4);
   540 #if EOE_DEBUG_LEVEL >= 3   542     for (i = 0; i < rec_size - 4; i++) {
   543         printk(KERN_CONT 
"%02X ", data[i + 4]);
   544         if ((i + 1) % 16 == 0) {
   545             printk(KERN_CONT 
"\n");
   549     printk(KERN_CONT 
"\n");
   552     data_size = time_appended ? rec_size - 8 : rec_size - 4;
   554     if (!fragment_number) {
   557             dev_kfree_skb(eoe->
rx_skb);
   561         if (!(eoe->
rx_skb = dev_alloc_skb(fragment_offset * 32))) {
   562             if (printk_ratelimit())
   564                         " frame dropped.\n");
   565             eoe->
stats.rx_dropped++;
   576             eoe->
stats.rx_dropped++;
   581         offset = fragment_offset * 32;
   585             dev_kfree_skb(eoe->
rx_skb);
   587             eoe->
stats.rx_errors++;
   588 #if EOE_DEBUG_LEVEL >= 1   598     memcpy(skb_put(eoe->
rx_skb, data_size), data + 4, data_size);
   603         eoe->
stats.rx_packets++;
   607 #if EOE_DEBUG_LEVEL >= 2   609                 " with %u octets.\n", eoe->
dev->name, eoe->
rx_skb->len);
   615         eoe->
rx_skb->ip_summed = CHECKSUM_UNNECESSARY;
   616         if (netif_rx(eoe->
rx_skb)) {
   625 #if EOE_DEBUG_LEVEL >= 2   644 #if EOE_DEBUG_LEVEL >= 2   645     unsigned int wakeup = 0;
   655     netif_tx_lock_bh(eoe->
dev);
   658         netif_tx_unlock_bh(eoe->
dev);
   671         netif_wake_queue(eoe->
dev);
   673 #if EOE_DEBUG_LEVEL >= 2   679     netif_tx_unlock_bh(eoe->
dev);
   692         eoe->
stats.tx_errors++;
   694 #if EOE_DEBUG_LEVEL >= 1   700 #if EOE_DEBUG_LEVEL >= 2   724             eoe->
stats.tx_errors++;
   725 #if EOE_DEBUG_LEVEL >= 1   727                     " datagram for %s after %u tries.\n",
   740             eoe->
stats.tx_errors++;
   741 #if EOE_DEBUG_LEVEL >= 1   743                     " for %s after %u tries.\n",
   753         eoe->
stats.tx_packets++;
   766             eoe->
stats.tx_errors++;
   767 #if EOE_DEBUG_LEVEL >= 1   790     netif_start_queue(dev);
   792 #if EOE_DEBUG_LEVEL >= 2   807     netif_stop_queue(dev);
   813 #if EOE_DEBUG_LEVEL >= 2   826                  struct net_device *dev 
   835                 " exceeds MTU. dropping.\n", skb->len);
   837         eoe->
stats.tx_dropped++;
   842     WARN_ON_ONCE(skb_get_queue_mapping(skb) != 0);
   843     lockdep_assert_held(&netdev_get_tx_queue(dev, 0)->_xmit_lock);
   847         if (printk_ratelimit())
   857         netif_stop_queue(dev);
   861 #if EOE_DEBUG_LEVEL >= 2   863             " with %u octets (%u frames queued).\n",
   879         struct net_device *dev 
 void ec_eoe_queue(ec_eoe_t *eoe)
Queues the datagram, if necessary. 
 
int ec_eoedev_tx(struct sk_buff *, struct net_device *)
Transmits data via the virtual network device. 
 
uint8_t * ec_slave_mbox_prepare_send(const ec_slave_t *slave, ec_datagram_t *datagram, uint8_t type, size_t size)
Prepares a mailbox-send datagram. 
 
uint16_t ring_position
Ring position. 
 
#define EC_DATAGRAM_NAME_SIZE
Size of the datagram description string. 
 
uint32_t tx_counter
octets transmitted during last second 
 
#define EC_EOE_TX_QUEUE_SIZE
Size of the EoE tx queue. 
 
uint8_t * ec_slave_mbox_fetch(const ec_slave_t *slave, const ec_datagram_t *datagram, uint8_t *type, size_t *size)
Processes received mailbox data. 
 
static const struct net_device_ops ec_eoedev_ops
Device operations for EoE interfaces. 
 
struct sk_buff * skb
socket buffer 
 
uint16_t configured_tx_mailbox_size
Configured send mailbox size. 
 
void ec_eoe_state_rx_fetch(ec_eoe_t *)
State: RX_FETCH. 
 
struct list_head tx_queue
queue for frames to send 
 
#define EC_SLAVE_DBG(slave, level, fmt, args...)
Convenience macro for printing slave-specific debug messages to syslog. 
 
uint8_t tx_fragment_number
number of the fragment 
 
int ec_eoe_send(ec_eoe_t *)
Sends a frame or the next fragment. 
 
ec_slave_t * slave
pointer to the corresponding slave 
 
void ec_master_queue_datagram_ext(ec_master_t *master, ec_datagram_t *datagram)
Places a datagram in the non-application datagram queue. 
 
unsigned int tx_queue_size
Transmit queue size. 
 
size_t rx_skb_size
size of the allocated socket buffer memory 
 
size_t tx_offset
number of octets sent 
 
EtherCAT slave structure. 
 
int ec_slave_mbox_prepare_fetch(const ec_slave_t *slave, ec_datagram_t *datagram)
Prepares a datagram to fetch mailbox data. 
 
void ec_eoe_state_tx_start(ec_eoe_t *)
State: TX START. 
 
#define EC_SLAVE_WARN(slave, fmt, args...)
Convenience macro for printing slave-specific warnings to syslog. 
 
#define EC_WRITE_U8(DATA, VAL)
Write an 8-bit unsigned value to EtherCAT data. 
 
void ec_eoe_state_rx_check(ec_eoe_t *)
State: RX_CHECK. 
 
unsigned int tx_queue_active
kernel netif queue started 
 
char name[EC_DATAGRAM_NAME_SIZE]
Description of the datagram. 
 
uint16_t working_counter
Working counter. 
 
int ec_eoe_init(ec_eoe_t *eoe, ec_slave_t *slave)
EoE constructor. 
 
uint8_t link_state
device link state 
 
#define EC_EOE_TRIES
Number of tries. 
 
Sent (still in the queue). 
 
void ec_eoe_flush(ec_eoe_t *)
Empties the transmit queue. 
 
uint32_t tx_rate
transmit rate (bps) 
 
void ec_datagram_output_stats(ec_datagram_t *datagram)
Outputs datagram statistics at most every second. 
 
Global definitions and macros. 
 
uint8_t rx_expected_fragment
next expected fragment number 
 
EtherCAT master structure. 
 
void ec_eoe_state_rx_start(ec_eoe_t *)
State: RX_START. 
 
Ethernet over EtherCAT (EoE) 
 
ec_datagram_state_t state
State. 
 
int ec_eoe_is_idle(const ec_eoe_t *eoe)
Returns the idle state. 
 
#define EC_SLAVE_ERR(slave, fmt, args...)
Convenience macro for printing slave-specific errors to syslog. 
 
unsigned long rate_jiffies
time of last rate output 
 
#define EC_WRITE_U16(DATA, VAL)
Write a 16-bit unsigned value to EtherCAT data. 
 
ec_master_t * master
Master owning the slave. 
 
struct list_head queue
list item 
 
void ec_eoe_state_tx_sent(ec_eoe_t *)
State: TX SENT. 
 
unsigned int opened
net_device is opened 
 
off_t rx_skb_offset
current write pointer in the socket buffer 
 
ec_datagram_t datagram
datagram 
 
struct net_device_stats stats
device statistics 
 
uint16_t effective_alias
Effective alias address. 
 
int ec_slave_mbox_prepare_check(const ec_slave_t *slave, ec_datagram_t *datagram)
Prepares a datagram for checking the mailbox state. 
 
unsigned int tx_idle
Idle flag. 
 
#define EC_READ_U16(DATA)
Read a 16-bit unsigned value from EtherCAT data. 
 
uint32_t rx_rate
receive rate (bps) 
 
struct sk_buff * rx_skb
current rx socket buffer 
 
void(* state)(ec_eoe_t *)
state function for the state machine 
 
void ec_datagram_init(ec_datagram_t *datagram)
Constructor. 
 
uint8_t tx_frame_number
number of the transmitted frame 
 
uint32_t rx_counter
octets received during last second 
 
uint16_t configured_rx_mailbox_size
Configured receive mailbox size. 
 
int ec_eoedev_open(struct net_device *)
Opens the virtual network device. 
 
ec_eoe_frame_t * tx_frame
current TX frame 
 
void ec_eoe_run(ec_eoe_t *eoe)
Runs the EoE state machine. 
 
int ec_eoedev_stop(struct net_device *)
Stops the virtual network device. 
 
void ec_eoe_clear(ec_eoe_t *eoe)
EoE destructor. 
 
Ethernet over EtherCAT (EoE) handler. 
 
unsigned int error_flag
Stop processing after an error. 
 
unsigned int rx_idle
Idle flag. 
 
ec_device_t devices[EC_MAX_NUM_DEVICES]
EtherCAT devices. 
 
struct net_device_stats * ec_eoedev_stats(struct net_device *)
Gets statistics about the virtual network device. 
 
int ec_eoe_is_open(const ec_eoe_t *eoe)
Returns the state of the device. 
 
int ec_slave_mbox_check(const ec_datagram_t *datagram)
Processes a mailbox state checking datagram. 
 
struct net_device * dev
net_device for virtual ethernet device 
 
unsigned int queue_datagram
the datagram is ready for queuing 
 
unsigned int tx_queued_frames
number of frames in the queue 
 
void ec_datagram_clear(ec_datagram_t *datagram)
Destructor.