From 0c3f54bc4213493a9eee30979ecce30a33c95738 Mon Sep 17 00:00:00 2001 From: Robert Burger Date: Wed, 27 Nov 2024 07:39:48 +0100 Subject: [PATCH] driver: patched igc for opensuse 15.5 --- .../opensuse/15.5/5.14.21/intel/Makefile | 1 + .../15.5/5.14.21/intel/igb/igb_main.c | 2 - .../opensuse/15.5/5.14.21/intel/igc/Makefile | 7 +- .../opensuse/15.5/5.14.21/intel/igc/igc.h | 6 + .../15.5/5.14.21/intel/igc/igc_main.c | 550 +++++++-- .../intel_igb_opensuse_15.5_5.14.21.patch | 153 ++- .../intel_igc_opensuse_15.5_5.14.21.patch | 1030 +++++++++++++++++ .../15.5/realtek_opensuse_15.5_5.14.21.patch | 132 ++- 8 files changed, 1644 insertions(+), 237 deletions(-) create mode 100644 linux/drivers/opensuse/15.5/intel_igc_opensuse_15.5_5.14.21.patch diff --git a/linux/drivers/opensuse/15.5/5.14.21/intel/Makefile b/linux/drivers/opensuse/15.5/5.14.21/intel/Makefile index 4d3fc05..e2b7431 100644 --- a/linux/drivers/opensuse/15.5/5.14.21/intel/Makefile +++ b/linux/drivers/opensuse/15.5/5.14.21/intel/Makefile @@ -1 +1,2 @@ obj-m += igb/ +obj-m += igc/ diff --git a/linux/drivers/opensuse/15.5/5.14.21/intel/igb/igb_main.c b/linux/drivers/opensuse/15.5/5.14.21/intel/igb/igb_main.c index d198af1..ec9f680 100644 --- a/linux/drivers/opensuse/15.5/5.14.21/intel/igb/igb_main.c +++ b/linux/drivers/opensuse/15.5/5.14.21/intel/igb/igb_main.c @@ -212,8 +212,6 @@ module_param_array(ethercat_mac_addr, charp, ðercat_mac_addr_count, 0660); MODULE_PARM_DESC(ethercat_mac_addr, "List of MAC addresses to use as EtherCAT device"); static unsigned int ethercat_polling; -module_param(ethercat_polling, uint, 0); -MODULE_PARM_DESC(ethercat_polling, "Set interface to polling mode (no interrupt) for EtherCAT case"); static pci_ers_result_t igb_io_error_detected(struct pci_dev *, pci_channel_state_t); diff --git a/linux/drivers/opensuse/15.5/5.14.21/intel/igc/Makefile b/linux/drivers/opensuse/15.5/5.14.21/intel/igc/Makefile index 95d1e8c..3bce083 100644 --- a/linux/drivers/opensuse/15.5/5.14.21/intel/igc/Makefile +++ b/linux/drivers/opensuse/15.5/5.14.21/intel/igc/Makefile @@ -5,7 +5,10 @@ # Intel(R) I225-LM/I225-V 2.5G Ethernet Controller # -obj-$(CONFIG_IGC) += igc.o +obj-m += igc-ethercat.o -igc-objs := igc_main.o igc_mac.o igc_i225.o igc_base.o igc_nvm.o igc_phy.o \ +igc-ethercat-objs := igc_main.o igc_mac.o igc_i225.o igc_base.o igc_nvm.o igc_phy.o \ igc_diag.o igc_ethtool.o igc_ptp.o igc_dump.o igc_tsn.o igc_xdp.o + +EXTRA_CFLAGS=-I$(src)/../../../../../../ +KBUILD_EXTRA_SYMBOLS=$(src)/../../../../../../Module.symvers diff --git a/linux/drivers/opensuse/15.5/5.14.21/intel/igc/igc.h b/linux/drivers/opensuse/15.5/5.14.21/intel/igc/igc.h index ae67ada..5da7b58 100644 --- a/linux/drivers/opensuse/15.5/5.14.21/intel/igc/igc.h +++ b/linux/drivers/opensuse/15.5/5.14.21/intel/igc/igc.h @@ -17,6 +17,9 @@ #include "igc_hw.h" +#include "ethercat_device.h" +#include "ethercat_device_ioctl.h" + void igc_ethtool_set_ops(struct net_device *); /* Transmit and receive queues */ @@ -255,6 +258,9 @@ struct igc_adapter { struct timespec64 start; struct timespec64 period; } perout[IGC_N_PEROUT]; + + bool is_ecat; + struct ethercat_device *ecat_dev; }; void igc_up(struct igc_adapter *adapter); diff --git a/linux/drivers/opensuse/15.5/5.14.21/intel/igc/igc_main.c b/linux/drivers/opensuse/15.5/5.14.21/intel/igc/igc_main.c index 2207cda..82277d7 100644 --- a/linux/drivers/opensuse/15.5/5.14.21/intel/igc/igc_main.c +++ b/linux/drivers/opensuse/15.5/5.14.21/intel/igc/igc_main.c @@ -21,7 +21,7 @@ #include "igc_tsn.h" #include "igc_xdp.h" -#define DRV_SUMMARY "Intel(R) 2.5G Ethernet Linux Driver" +#define DRV_SUMMARY "Intel(R) 2.5G Ethernet Linux Driver (EtherCAT enabled)" #define DEFAULT_MSG_ENABLE (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_LINK) @@ -35,10 +35,19 @@ static int debug = -1; MODULE_AUTHOR("Intel Corporation, "); MODULE_DESCRIPTION(DRV_SUMMARY); MODULE_LICENSE("GPL v2"); +MODULE_SOFTDEP("pre: ethercat_chrdev"); module_param(debug, int, 0); MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)"); -char igc_driver_name[] = "igc"; +#define ETHERCAT_MAC_ADDR_SIZE 10 +static char * ethercat_mac_addr[ETHERCAT_MAC_ADDR_SIZE]; +static int ethercat_mac_addr_count; +module_param_array(ethercat_mac_addr, charp, ðercat_mac_addr_count, 0660); +MODULE_PARM_DESC(ethercat_mac_addr, "List of MAC addresses to use as EtherCAT device"); + +static unsigned int ethercat_polling = 0; + +char igc_driver_name[] = "igc-ethercat"; static const char igc_driver_string[] = DRV_SUMMARY; static const char igc_copyright[] = "Copyright(c) 2018 Intel Corporation."; @@ -111,8 +120,10 @@ void igc_reset(struct igc_adapter *adapter) /* Re-establish EEE setting */ igc_set_eee_i225(hw, true, true, true); - if (!netif_running(adapter->netdev)) - igc_power_down_phy_copper_base(&adapter->hw); + if (!adapter->is_ecat) { + if (!netif_running(adapter->netdev)) + igc_power_down_phy_copper_base(&adapter->hw); + } /* Enable HW to recognize an 802.1Q VLAN Ethernet packet */ wr32(IGC_VET, ETH_P_8021Q); @@ -197,6 +208,7 @@ static void igc_clean_tx_ring(struct igc_ring *tx_ring) u16 i = tx_ring->next_to_clean; struct igc_tx_buffer *tx_buffer = &tx_ring->tx_buffer_info[i]; u32 xsk_frames = 0; + struct igc_adapter *adapter = netdev_priv(tx_ring->netdev); while (i != tx_ring->next_to_use) { union igc_adv_tx_desc *eop_desc, *tx_desc; @@ -206,11 +218,17 @@ static void igc_clean_tx_ring(struct igc_ring *tx_ring) xsk_frames++; break; case IGC_TX_BUFFER_TYPE_XDP: - xdp_return_frame(tx_buffer->xdpf); + if (unlikely(!adapter->is_ecat)) { + /* buffer is reused in EtherCAT TX operation */ + xdp_return_frame(tx_buffer->xdpf); + } igc_unmap_tx_buffer(tx_ring->dev, tx_buffer); break; case IGC_TX_BUFFER_TYPE_SKB: - dev_kfree_skb_any(tx_buffer->skb); + if (unlikely(!adapter->is_ecat)) { + /* skb is reused in EtherCAT TX operation */ + dev_kfree_skb_any(tx_buffer->skb); + } igc_unmap_tx_buffer(tx_ring->dev, tx_buffer); break; default: @@ -1223,8 +1241,11 @@ static void igc_tx_csum(struct igc_ring *tx_ring, struct igc_tx_buffer *first, static int __igc_maybe_stop_tx(struct igc_ring *tx_ring, const u16 size) { struct net_device *netdev = tx_ring->netdev; + struct igc_adapter *adapter = netdev_priv(netdev); - netif_stop_subqueue(netdev, tx_ring->queue_index); + if (!adapter->is_ecat) { + netif_stop_subqueue(netdev, tx_ring->queue_index); + } /* memory barriier comment */ smp_mb(); @@ -1236,7 +1257,9 @@ static int __igc_maybe_stop_tx(struct igc_ring *tx_ring, const u16 size) return -EBUSY; /* A reprieve! */ - netif_wake_subqueue(netdev, tx_ring->queue_index); + if (!adapter->is_ecat) { + netif_wake_subqueue(netdev, tx_ring->queue_index); + } u64_stats_update_begin(&tx_ring->tx_syncp2); tx_ring->tx_stats.restart_queue2++; @@ -1314,6 +1337,7 @@ static int igc_tx_map(struct igc_ring *tx_ring, unsigned int data_len, size; dma_addr_t dma; u32 cmd_type; + struct igc_adapter *adapter = netdev_priv(tx_ring->netdev); cmd_type = igc_tx_cmd_type(skb, tx_flags); tx_desc = IGC_TX_DESC(tx_ring, i); @@ -1381,7 +1405,9 @@ static int igc_tx_map(struct igc_ring *tx_ring, cmd_type |= size | IGC_TXD_DCMD; tx_desc->read.cmd_type_len = cpu_to_le32(cmd_type); - netdev_tx_sent_queue(txring_txq(tx_ring), first->bytecount); + if (unlikely(!adapter->is_ecat)) { + netdev_tx_sent_queue(txring_txq(tx_ring), first->bytecount); + } /* set the timestamp */ first->time_stamp = jiffies; @@ -1409,8 +1435,13 @@ static int igc_tx_map(struct igc_ring *tx_ring, /* Make sure there is space in the ring for the next send. */ igc_maybe_stop_tx(tx_ring, DESC_NEEDED); - if (netif_xmit_stopped(txring_txq(tx_ring)) || !netdev_xmit_more()) { + if (likely(adapter->is_ecat)) { writel(i, tx_ring->tail); + wmb(); + } else { + if (netif_xmit_stopped(txring_txq(tx_ring)) || !netdev_xmit_more()) { + writel(i, tx_ring->tail); + } } return 0; @@ -1431,8 +1462,10 @@ static int igc_tx_map(struct igc_ring *tx_ring, if (dma_unmap_len(tx_buffer, len)) igc_unmap_tx_buffer(tx_ring->dev, tx_buffer); - dev_kfree_skb_any(tx_buffer->skb); - tx_buffer->skb = NULL; + if (!adapter->is_ecat) { + dev_kfree_skb_any(tx_buffer->skb); + tx_buffer->skb = NULL; + } tx_ring->next_to_use = i; @@ -1547,6 +1580,7 @@ static netdev_tx_t igc_xmit_frame_ring(struct sk_buff *skb, ktime_t txtime; u8 hdr_len = 0; int tso = 0; + struct igc_adapter *adapter = netdev_priv(tx_ring->netdev); /* need: 1 descriptor per page * PAGE_SIZE/IGC_MAX_DATA_PER_TXD, * + 1 desc for skb_headlen/IGC_MAX_DATA_PER_TXD, @@ -1563,7 +1597,7 @@ static netdev_tx_t igc_xmit_frame_ring(struct sk_buff *skb, return NETDEV_TX_BUSY; } - if (!tx_ring->launchtime_enable) + if (likely(adapter->is_ecat) || !tx_ring->launchtime_enable) goto done; txtime = skb->tstamp; @@ -1599,52 +1633,55 @@ static netdev_tx_t igc_xmit_frame_ring(struct sk_buff *skb, first->bytecount = skb->len; first->gso_segs = 1; - if (unlikely(test_bit(IGC_RING_FLAG_TX_HWTSTAMP, &tx_ring->flags) && - skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) { - struct igc_adapter *adapter = netdev_priv(tx_ring->netdev); + if (unlikely(!adapter->is_ecat)) { + if (unlikely(test_bit(IGC_RING_FLAG_TX_HWTSTAMP, &tx_ring->flags) && + skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) { - /* FIXME: add support for retrieving timestamps from - * the other timer registers before skipping the - * timestamping request. - */ - unsigned long flags; + /* FIXME: add support for retrieving timestamps from + * the other timer registers before skipping the + * timestamping request. + */ + unsigned long flags; - spin_lock_irqsave(&adapter->ptp_tx_lock, flags); - if (!adapter->ptp_tx_skb) { - skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; - tx_flags |= IGC_TX_FLAGS_TSTAMP; + spin_lock_irqsave(&adapter->ptp_tx_lock, flags); + if (!adapter->ptp_tx_skb) { + skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; + tx_flags |= IGC_TX_FLAGS_TSTAMP; - adapter->ptp_tx_skb = skb_get(skb); - adapter->ptp_tx_start = jiffies; - } else { - adapter->tx_hwtstamp_skipped++; - } + adapter->ptp_tx_skb = skb_get(skb); + adapter->ptp_tx_start = jiffies; + } else { + adapter->tx_hwtstamp_skipped++; + } - spin_unlock_irqrestore(&adapter->ptp_tx_lock, flags); - } + spin_unlock_irqrestore(&adapter->ptp_tx_lock, flags); + } - if (skb_vlan_tag_present(skb)) { - tx_flags |= IGC_TX_FLAGS_VLAN; - tx_flags |= (skb_vlan_tag_get(skb) << IGC_TX_FLAGS_VLAN_SHIFT); - } + if (skb_vlan_tag_present(skb)) { + tx_flags |= IGC_TX_FLAGS_VLAN; + tx_flags |= (skb_vlan_tag_get(skb) << IGC_TX_FLAGS_VLAN_SHIFT); + } - /* record initial flags and protocol */ - first->tx_flags = tx_flags; - first->protocol = protocol; + /* record initial flags and protocol */ + first->tx_flags = tx_flags; + first->protocol = protocol; - tso = igc_tso(tx_ring, first, launch_time, first_flag, &hdr_len); - if (tso < 0) - goto out_drop; - else if (!tso) - igc_tx_csum(tx_ring, first, launch_time, first_flag); + tso = igc_tso(tx_ring, first, launch_time, first_flag, &hdr_len); + if (tso < 0) + goto out_drop; + else if (!tso) + igc_tx_csum(tx_ring, first, launch_time, first_flag); + } igc_tx_map(tx_ring, first, hdr_len); return NETDEV_TX_OK; out_drop: - dev_kfree_skb_any(first->skb); - first->skb = NULL; + if (unlikely(!adapter->is_ecat)) { + dev_kfree_skb_any(first->skb); + first->skb = NULL; + } return NETDEV_TX_OK; } @@ -1942,8 +1979,11 @@ static struct sk_buff *igc_construct_skb(struct igc_ring *rx_ring, net_prefetch(xdp->data_meta); /* allocate a skb to store the frags */ - skb = napi_alloc_skb(&rx_ring->q_vector->napi, - IGC_RX_HDR_LEN + metasize); + if (likely(rx_ring->q_vector->adapter->is_ecat)) { + skb = dev_alloc_skb(IGC_RX_HDR_LEN + metasize); + } else { + skb = napi_alloc_skb(&rx_ring->q_vector->napi, IGC_RX_HDR_LEN + metasize); + } if (unlikely(!skb)) return NULL; @@ -2581,54 +2621,68 @@ static int igc_clean_rx_irq(struct igc_q_vector *q_vector, const int budget) size -= IGC_TS_HDR_LEN; } - if (!skb) { - xdp_init_buff(&xdp, truesize, &rx_ring->xdp_rxq); - xdp_prepare_buff(&xdp, pktbuf - igc_rx_offset(rx_ring), - igc_rx_offset(rx_ring) + pkt_offset, - size, true); - xdp_buff_clear_frags_flag(&xdp); + if (likely(adapter->is_ecat)) { + if (size > 0) { + prefetch(pktbuf); + ethercat_device_receive(adapter->ecat_dev, pktbuf, size); + } + igc_reuse_rx_page(rx_ring, rx_buffer); + } else { + if (!skb) { + xdp_init_buff(&xdp, truesize, &rx_ring->xdp_rxq); + xdp_prepare_buff(&xdp, pktbuf - igc_rx_offset(rx_ring), + igc_rx_offset(rx_ring) + pkt_offset, + size, true); + xdp_buff_clear_frags_flag(&xdp); + + skb = igc_xdp_run_prog(adapter, &xdp); + } - skb = igc_xdp_run_prog(adapter, &xdp); - } + if (IS_ERR(skb)) { + unsigned int xdp_res = -PTR_ERR(skb); + + switch (xdp_res) { + case IGC_XDP_CONSUMED: + rx_buffer->pagecnt_bias++; + break; + case IGC_XDP_TX: + case IGC_XDP_REDIRECT: + igc_rx_buffer_flip(rx_buffer, truesize); + xdp_status |= xdp_res; + break; + } - if (IS_ERR(skb)) { - unsigned int xdp_res = -PTR_ERR(skb); + total_packets++; + total_bytes += size; + } else if (skb) + igc_add_rx_frag(rx_ring, rx_buffer, skb, size); + else if (ring_uses_build_skb(rx_ring)) + skb = igc_build_skb(rx_ring, rx_buffer, &xdp); + else + skb = igc_construct_skb(rx_ring, rx_buffer, &xdp, + timestamp); - switch (xdp_res) { - case IGC_XDP_CONSUMED: + /* exit if we failed to retrieve a buffer */ + if (!skb) { + rx_ring->rx_stats.alloc_failed++; rx_buffer->pagecnt_bias++; break; - case IGC_XDP_TX: - case IGC_XDP_REDIRECT: - igc_rx_buffer_flip(rx_buffer, truesize); - xdp_status |= xdp_res; - break; } - total_packets++; - total_bytes += size; - } else if (skb) - igc_add_rx_frag(rx_ring, rx_buffer, skb, size); - else if (ring_uses_build_skb(rx_ring)) - skb = igc_build_skb(rx_ring, rx_buffer, &xdp); - else - skb = igc_construct_skb(rx_ring, rx_buffer, &xdp, - timestamp); - - /* exit if we failed to retrieve a buffer */ - if (!skb) { - rx_ring->rx_stats.alloc_failed++; - rx_buffer->pagecnt_bias++; - break; + igc_put_rx_buffer(rx_ring, rx_buffer, rx_buffer_pgcnt); } - - igc_put_rx_buffer(rx_ring, rx_buffer, rx_buffer_pgcnt); cleaned_count++; /* fetch next buffer in frame if non-eop */ if (igc_is_non_eop(rx_ring, rx_desc)) continue; + if (likely(adapter->is_ecat)) { + total_bytes += size; + total_packets++; + continue; + } + /* verify the packet layout is correct */ if (igc_cleanup_headers(rx_ring, rx_desc, skb)) { skb = NULL; @@ -2933,11 +2987,15 @@ static bool igc_clean_tx_irq(struct igc_q_vector *q_vector, int napi_budget) xsk_frames++; break; case IGC_TX_BUFFER_TYPE_XDP: - xdp_return_frame(tx_buffer->xdpf); + if (unlikely(!adapter->is_ecat)) { + xdp_return_frame(tx_buffer->xdpf); + } igc_unmap_tx_buffer(tx_ring->dev, tx_buffer); break; case IGC_TX_BUFFER_TYPE_SKB: - napi_consume_skb(tx_buffer->skb, napi_budget); + if (unlikely(!adapter->is_ecat)) { + napi_consume_skb(tx_buffer->skb, napi_budget); + } igc_unmap_tx_buffer(tx_ring->dev, tx_buffer); break; default: @@ -2994,7 +3052,8 @@ static bool igc_clean_tx_irq(struct igc_q_vector *q_vector, int napi_budget) igc_xdp_xmit_zc(tx_ring); } - if (test_bit(IGC_RING_FLAG_TX_DETECT_HANG, &tx_ring->flags)) { + if (unlikely(!adapter->is_ecat) && + test_bit(IGC_RING_FLAG_TX_DETECT_HANG, &tx_ring->flags)) { struct igc_hw *hw = &adapter->hw; /* Detect a transmit hang in hardware, this serializes the @@ -3038,7 +3097,7 @@ static bool igc_clean_tx_irq(struct igc_q_vector *q_vector, int napi_budget) } #define TX_WAKE_THRESHOLD (DESC_NEEDED * 2) - if (unlikely(total_packets && + if (unlikely(!adapter->is_ecat && total_packets && netif_carrier_ok(tx_ring->netdev) && igc_desc_unused(tx_ring) >= TX_WAKE_THRESHOLD)) { /* Make sure that anybody stopping the queue after this @@ -4110,7 +4169,9 @@ static void igc_reset_q_vector(struct igc_adapter *adapter, int v_idx) if (q_vector->rx.ring) adapter->rx_ring[q_vector->rx.ring->queue_index] = NULL; - netif_napi_del(&q_vector->napi); + if (unlikely(!adapter->is_ecat)) { + netif_napi_del(&q_vector->napi); + } } /** @@ -4399,7 +4460,10 @@ static void igc_update_ring_itr(struct igc_q_vector *q_vector) switch (adapter->link_speed) { case SPEED_10: case SPEED_100: - new_val = IGC_4K_ITR; + if (adapter->is_ecat) + new_val = IGC_20K_ITR; + else + new_val = IGC_4K_ITR; goto set_itr_val; default: break; @@ -4532,7 +4596,7 @@ static int igc_poll(struct napi_struct *napi, int budget) /* Exit the polling mode, but don't re-enable interrupts if stack might * poll us due to busy-polling */ - if (likely(napi_complete_done(napi, work_done))) + if (likely(q_vector->adapter->is_ecat) || likely(napi_complete_done(napi, work_done))) igc_ring_irq_enable(q_vector); return min(work_done, budget - 1); @@ -4575,9 +4639,11 @@ static int igc_alloc_q_vector(struct igc_adapter *adapter, if (!q_vector) return -ENOMEM; - /* initialize NAPI */ - netif_napi_add(adapter->netdev, &q_vector->napi, - igc_poll, 64); + if (unlikely(!adapter->is_ecat)) { + /* initialize NAPI */ + netif_napi_add(adapter->netdev, &q_vector->napi, + igc_poll, 64); + } /* tie q_vector and adapter together */ adapter->q_vector[v_idx] = q_vector; @@ -4806,8 +4872,10 @@ void igc_up(struct igc_adapter *adapter) clear_bit(__IGC_DOWN, &adapter->state); - for (i = 0; i < adapter->num_q_vectors; i++) - napi_enable(&adapter->q_vector[i]->napi); + if (unlikely(!adapter->is_ecat)) { + for (i = 0; i < adapter->num_q_vectors; i++) + napi_enable(&adapter->q_vector[i]->napi); + } if (adapter->msix_entries) igc_configure_msix(adapter); @@ -4818,7 +4886,9 @@ void igc_up(struct igc_adapter *adapter) rd32(IGC_ICR); igc_irq_enable(adapter); - netif_tx_start_all_queues(adapter->netdev); + if (unlikely(!adapter->is_ecat)) { + netif_tx_start_all_queues(adapter->netdev); + } /* start the watchdog. */ hw->mac.get_link_status = true; @@ -5015,8 +5085,10 @@ void igc_down(struct igc_adapter *adapter) /* set trans_start so we don't get spurious watchdogs during reset */ netif_trans_update(netdev); - netif_carrier_off(netdev); - netif_tx_stop_all_queues(netdev); + if (unlikely(!adapter->is_ecat)) { + netif_carrier_off(netdev); + netif_tx_stop_all_queues(netdev); + } if (pci_device_is_present(adapter->pdev)) { /* disable transmits in the hardware */ @@ -5032,10 +5104,12 @@ void igc_down(struct igc_adapter *adapter) adapter->flags &= ~IGC_FLAG_NEED_LINK_UPDATE; - for (i = 0; i < adapter->num_q_vectors; i++) { - if (adapter->q_vector[i]) { - napi_synchronize(&adapter->q_vector[i]->napi); - napi_disable(&adapter->q_vector[i]->napi); + if (unlikely(!adapter->is_ecat)) { + for (i = 0; i < adapter->num_q_vectors; i++) { + if (adapter->q_vector[i]) { + napi_synchronize(&adapter->q_vector[i]->napi); + napi_disable(&adapter->q_vector[i]->napi); + } } } @@ -5372,11 +5446,16 @@ static void igc_write_itr(struct igc_q_vector *q_vector) static irqreturn_t igc_msix_ring(int irq, void *data) { struct igc_q_vector *q_vector = data; + struct igc_adapter *adapter = q_vector->adapter; /* Write the ITR value calculated from the previous interrupt. */ igc_write_itr(q_vector); - napi_schedule(&q_vector->napi); + if (likely(adapter->is_ecat)) { + igc_poll(&q_vector->napi, 64); + } else { + napi_schedule(&q_vector->napi); + } return IRQ_HANDLED; } @@ -5393,9 +5472,13 @@ static int igc_request_msix(struct igc_adapter *adapter) unsigned int num_q_vectors = adapter->num_q_vectors; int i = 0, err = 0, vector = 0, free_vector = 0; struct net_device *netdev = adapter->netdev; + unsigned long irq_flags = 0; + if (adapter->is_ecat) { + irq_flags = IRQF_NO_THREAD; + } err = request_irq(adapter->msix_entries[vector].vector, - &igc_msix_other, 0, netdev->name, adapter); + &igc_msix_other, irq_flags, netdev->name, adapter); if (err) goto err_out; @@ -5425,7 +5508,7 @@ static int igc_request_msix(struct igc_adapter *adapter) sprintf(q_vector->name, "%s-unused", netdev->name); err = request_irq(adapter->msix_entries[vector].vector, - igc_msix_ring, 0, q_vector->name, + igc_msix_ring, irq_flags, q_vector->name, q_vector); if (err) goto err_free; @@ -5526,6 +5609,24 @@ static void igc_watchdog_task(struct work_struct *work) link = igc_has_link(adapter); + if (likely(adapter->is_ecat)) { + if (adapter->ecat_dev) { + ethercat_device_set_link(adapter->ecat_dev, link); + } + + if (!test_bit(__IGC_DOWN, &adapter->state)) { + mod_timer(&adapter->watchdog_timer, round_jiffies(jiffies + HZ)); + } + + adapter->link_speed = SPEED_100; + + spin_lock(&adapter->stats64_lock); + igc_update_stats(adapter); + spin_unlock(&adapter->stats64_lock); + + return; + } + if (adapter->flags & IGC_FLAG_NEED_LINK_UPDATE) { if (time_after(jiffies, (adapter->link_check_timeout + HZ))) adapter->flags &= ~IGC_FLAG_NEED_LINK_UPDATE; @@ -5726,7 +5827,11 @@ static irqreturn_t igc_intr_msi(int irq, void *data) if (icr & IGC_ICR_TS) igc_tsync_interrupt(adapter); - napi_schedule(&q_vector->napi); + if (likely(adapter->is_ecat)) { + igc_poll(&q_vector->napi, 64); + } else { + napi_schedule(&q_vector->napi); + } return IRQ_HANDLED; } @@ -5772,13 +5877,21 @@ static irqreturn_t igc_intr(int irq, void *data) if (icr & IGC_ICR_TS) igc_tsync_interrupt(adapter); - napi_schedule(&q_vector->napi); + if (likely(adapter->is_ecat)) { + igc_poll(&q_vector->napi, 64); + } else { + napi_schedule(&q_vector->napi); + } return IRQ_HANDLED; } static void igc_free_irq(struct igc_adapter *adapter) { + if ((adapter->is_ecat) && (ethercat_polling != 0)) { + return; + } + if (adapter->msix_entries) { int vector = 0, i; @@ -5804,8 +5917,16 @@ static int igc_request_irq(struct igc_adapter *adapter) struct net_device *netdev = adapter->netdev; struct pci_dev *pdev = adapter->pdev; int err = 0; + unsigned long irq_flags = 0; + if (adapter->is_ecat) { + irq_flags = IRQF_NO_THREAD; + } if (adapter->flags & IGC_FLAG_HAS_MSIX) { + if ((adapter->is_ecat) && (ethercat_polling != 0)) { + goto request_done; + } + err = igc_request_msix(adapter); if (!err) goto request_done; @@ -5824,8 +5945,12 @@ static int igc_request_irq(struct igc_adapter *adapter) igc_assign_vector(adapter->q_vector[0], 0); + if ((adapter->is_ecat) && (ethercat_polling != 0)) { + goto request_done; + } + if (adapter->flags & IGC_FLAG_HAS_MSI) { - err = request_irq(pdev->irq, &igc_intr_msi, 0, + err = request_irq(pdev->irq, &igc_intr_msi, irq_flags, netdev->name, adapter); if (!err) goto request_done; @@ -5834,8 +5959,12 @@ static int igc_request_irq(struct igc_adapter *adapter) igc_reset_interrupt_capability(adapter); adapter->flags &= ~IGC_FLAG_HAS_MSI; } + + if (!adapter->is_ecat) { + irq_flags = IRQF_SHARED; + } - err = request_irq(pdev->irq, &igc_intr, IRQF_SHARED, + err = request_irq(pdev->irq, &igc_intr, irq_flags, netdev->name, adapter); if (err) @@ -5876,7 +6005,9 @@ static int __igc_open(struct net_device *netdev, bool resuming) if (!resuming) pm_runtime_get_sync(&pdev->dev); - netif_carrier_off(netdev); + if (!adapter->is_ecat) { + netif_carrier_off(netdev); + } /* allocate transmit descriptors */ err = igc_setup_all_tx_resources(adapter); @@ -5896,19 +6027,23 @@ static int __igc_open(struct net_device *netdev, bool resuming) if (err) goto err_req_irq; - /* Notify the stack of the actual queue counts. */ - err = netif_set_real_num_tx_queues(netdev, adapter->num_tx_queues); - if (err) - goto err_set_queues; + if (!adapter->is_ecat) { + /* Notify the stack of the actual queue counts. */ + err = netif_set_real_num_tx_queues(netdev, adapter->num_tx_queues); + if (err) + goto err_set_queues; - err = netif_set_real_num_rx_queues(netdev, adapter->num_rx_queues); - if (err) - goto err_set_queues; + err = netif_set_real_num_rx_queues(netdev, adapter->num_rx_queues); + if (err) + goto err_set_queues; + } clear_bit(__IGC_DOWN, &adapter->state); - for (i = 0; i < adapter->num_q_vectors; i++) - napi_enable(&adapter->q_vector[i]->napi); + if (unlikely(!adapter->is_ecat)) { + for (i = 0; i < adapter->num_q_vectors; i++) + napi_enable(&adapter->q_vector[i]->napi); + } /* Clear any pending interrupts. */ rd32(IGC_ICR); @@ -5917,7 +6052,9 @@ static int __igc_open(struct net_device *netdev, bool resuming) if (!resuming) pm_runtime_put(&pdev->dev); - netif_tx_start_all_queues(netdev); + if (!adapter->is_ecat) { + netif_tx_start_all_queues(netdev); + } /* start the watchdog. */ hw->mac.get_link_status = true; @@ -5977,6 +6114,9 @@ static int __igc_close(struct net_device *netdev, bool suspending) igc_free_all_tx_resources(adapter); igc_free_all_rx_resources(adapter); + if (adapter->is_ecat) + igc_reset(adapter); + if (!suspending) pm_runtime_put_sync(&pdev->dev); @@ -5985,7 +6125,9 @@ static int __igc_close(struct net_device *netdev, bool suspending) int igc_close(struct net_device *netdev) { - if (netif_device_present(netdev) || netdev->dismantle) + struct igc_adapter *adapter = netdev_priv(netdev); + + if (adapter->is_ecat || netif_device_present(netdev) || netdev->dismantle) return __igc_close(netdev, false); return 0; } @@ -6003,6 +6145,79 @@ static int igc_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) return igc_ptp_get_ts_config(netdev, ifr); case SIOCSHWTSTAMP: return igc_ptp_set_ts_config(netdev, ifr); + case ETHERCAT_DEVICE_NET_DEVICE_DO_POLL: { + struct igc_adapter *adapter = netdev_priv(netdev); + struct igc_q_vector *q_vector = adapter->q_vector[0]; + int budget = 64; + bool clean_complete = true; + + if (!adapter->is_ecat) { + return -EOPNOTSUPP; + } + + if (q_vector->tx.ring) { + clean_complete = igc_clean_tx_irq(q_vector, budget); + } + + if (q_vector->rx.ring) { + int cleaned = igc_clean_rx_irq(q_vector, budget); + + if (cleaned >= budget) + clean_complete = false; + } + if (!clean_complete) + return 1; + + return 0; + } + case ETHERCAT_DEVICE_NET_DEVICE_SET_POLLING: { + int do_reopen = ethercat_polling != 1; + struct igc_adapter *adapter = netdev_priv(netdev); + if (!adapter->is_ecat) { + return -EOPNOTSUPP; + } + + if (do_reopen) { + igc_close(netdev); + } + + ethercat_polling = 1; + + if (do_reopen) { + igc_open(netdev); + } + return 1; + } + case ETHERCAT_DEVICE_NET_DEVICE_RESET_POLLING: { + int do_reopen = ethercat_polling != 0; + struct igc_adapter *adapter = netdev_priv(netdev); + if (!adapter->is_ecat) { + return -EOPNOTSUPP; + } + + if (do_reopen) { + igc_close(netdev); + } + + ethercat_polling = 0; + + if (do_reopen) { + igc_open(netdev); + } + return 1; + } + case ETHERCAT_DEVICE_NET_DEVICE_GET_POLLING: { + struct igc_adapter *adapter = netdev_priv(netdev); + if (!adapter->is_ecat) { + return -EOPNOTSUPP; + } + + if (ethercat_polling == 0) { + return 0; + } + + return 1; + } default: return -EOPNOTSUPP; } @@ -6472,6 +6687,35 @@ u32 igc_rd32(struct igc_hw *hw, u32 reg) return value; } +static int parse_macaddr(const char *macstr, char *dev_addr) +{ + int i, h, l; + + for (i = 0; i < 6; i++) { + h = hex_to_bin(*macstr); + if (h == -1) + goto err; + macstr++; + + l = hex_to_bin(*macstr); + if (l == -1) + goto err; + macstr++; + + if (i != 5) { + if (*macstr != ':') + goto err; + macstr++; + } + dev_addr[i] = (h << 4) + l; + } + if (is_valid_ether_addr(dev_addr)) + return 0; + +err: + return -EINVAL; +} + /** * igc_probe - Device Initialization Routine * @pdev: PCI device information struct @@ -6491,6 +6735,7 @@ static int igc_probe(struct pci_dev *pdev, struct igc_hw *hw; const struct igc_info *ei = igc_info_tbl[ent->driver_data]; int err; + int cnt = 0; err = pci_enable_device_mem(pdev); if (err) @@ -6528,6 +6773,8 @@ static int igc_probe(struct pci_dev *pdev, adapter = netdev_priv(netdev); adapter->netdev = netdev; adapter->pdev = pdev; + adapter->is_ecat = false; + adapter->ecat_dev = NULL; hw = &adapter->hw; hw->back = adapter; adapter->port_num = hw->bus.func; @@ -6678,13 +6925,53 @@ static int igc_probe(struct pci_dev *pdev, */ igc_get_hw_control(adapter); - strncpy(netdev->name, "eth%d", IFNAMSIZ); - err = register_netdev(netdev); - if (err) - goto err_register; + /* check if we should use this one as EtherCAT device + */ + if (ethercat_mac_addr_count > 0) { + for (cnt = 0; cnt < ethercat_mac_addr_count; ++cnt) { + char ethercat_dev_addr[6]; + parse_macaddr(ethercat_mac_addr[cnt], ethercat_dev_addr); + + if (ether_addr_equal(netdev->dev_addr, ethercat_dev_addr)) { + int i = 0; + + dev_info(&pdev->dev, "attaching as EtherCAT interface\n"); + adapter->is_ecat = true; + adapter->ecat_dev = ethercat_device_create(netdev); + + /* set low ITR values */ + adapter->rx_itr_setting = 0; + adapter->tx_itr_setting = 0; + + /* If ITR is disabled, disable DMAC */ + if (adapter->flags & IGC_FLAG_DMAC) + adapter->flags &= ~IGC_FLAG_DMAC; + + for (i = 0; i < adapter->num_q_vectors; i++) { + struct igc_q_vector *q_vector = adapter->q_vector[i]; + q_vector->tx.work_limit = adapter->tx_work_limit; + if (q_vector->rx.ring) + q_vector->itr_val = adapter->rx_itr_setting; + else + q_vector->itr_val = adapter->tx_itr_setting; + + /* configure q_vector to set itr on next interrupt */ + q_vector->set_itr = 1; + } + break; + } + } + } - /* carrier off reporting is important to ethtool even BEFORE open */ - netif_carrier_off(netdev); + if (!adapter->is_ecat) { + strncpy(netdev->name, "eth%d", IFNAMSIZ); + err = register_netdev(netdev); + if (err) + goto err_register; + + /* carrier off reporting is important to ethtool even BEFORE open */ + netif_carrier_off(netdev); + } /* Check if Media Autosense is enabled */ adapter->ei = *ei; @@ -6736,6 +7023,10 @@ static void igc_remove(struct pci_dev *pdev) struct net_device *netdev = pci_get_drvdata(pdev); struct igc_adapter *adapter = netdev_priv(netdev); + if (adapter->ecat_dev) { + ethercat_device_destroy(adapter->ecat_dev); + } + pm_runtime_get_noresume(&pdev->dev); igc_flush_nfc_rules(adapter); @@ -6757,7 +7048,10 @@ static void igc_remove(struct pci_dev *pdev) * would have already happened in close and is redundant. */ igc_release_hw_control(adapter); - unregister_netdev(netdev); + + if (!adapter->is_ecat) { + unregister_netdev(netdev); + } igc_clear_interrupt_scheme(adapter); pci_iounmap(pdev, adapter->io_addr); @@ -6783,7 +7077,7 @@ static int __igc_shutdown(struct pci_dev *pdev, bool *enable_wake, rtnl_lock(); netif_device_detach(netdev); - if (netif_running(netdev)) + if (adapter->is_ecat || netif_running(netdev)) __igc_close(netdev, true); igc_ptp_suspend(adapter); diff --git a/linux/drivers/opensuse/15.5/intel_igb_opensuse_15.5_5.14.21.patch b/linux/drivers/opensuse/15.5/intel_igb_opensuse_15.5_5.14.21.patch index 9184ee0..9c2a5ce 100644 --- a/linux/drivers/opensuse/15.5/intel_igb_opensuse_15.5_5.14.21.patch +++ b/linux/drivers/opensuse/15.5/intel_igb_opensuse_15.5_5.14.21.patch @@ -1,4 +1,27 @@ -diff -ru /usr/src/linux-rt/drivers/net/ethernet/intel/igb/igb.h 5.14.21/intel/igb/igb.h +Only in 5.14.21/intel/igb/: e1000_82575.o +Only in 5.14.21/intel/igb/: .e1000_82575.o.cmd +Only in 5.14.21/intel/igb/: e1000_i210.o +Only in 5.14.21/intel/igb/: .e1000_i210.o.cmd +Only in 5.14.21/intel/igb/: e1000_mac.o +Only in 5.14.21/intel/igb/: .e1000_mac.o.cmd +Only in 5.14.21/intel/igb/: e1000_mbx.o +Only in 5.14.21/intel/igb/: .e1000_mbx.o.cmd +Only in 5.14.21/intel/igb/: e1000_nvm.o +Only in 5.14.21/intel/igb/: .e1000_nvm.o.cmd +Only in 5.14.21/intel/igb/: e1000_phy.o +Only in 5.14.21/intel/igb/: .e1000_phy.o.cmd +Only in 5.14.21/intel/igb/: igb-ethercat.ko +Only in 5.14.21/intel/igb/: .igb-ethercat.ko.cmd +Only in 5.14.21/intel/igb/: igb-ethercat.mod +Only in 5.14.21/intel/igb/: igb-ethercat.mod.c +Only in 5.14.21/intel/igb/: .igb-ethercat.mod.cmd +Only in 5.14.21/intel/igb/: igb-ethercat.mod.o +Only in 5.14.21/intel/igb/: .igb-ethercat.mod.o.cmd +Only in 5.14.21/intel/igb/: igb-ethercat.o +Only in 5.14.21/intel/igb/: .igb-ethercat.o.cmd +Only in 5.14.21/intel/igb/: igb_ethtool.o +Only in 5.14.21/intel/igb/: .igb_ethtool.o.cmd +diff -rup /usr/src/linux-rt/drivers/net/ethernet/intel/igb/igb.h 5.14.21/intel/igb/igb.h --- /usr/src/linux-rt/drivers/net/ethernet/intel/igb/igb.h 2024-11-06 14:07:03.000000000 +0100 +++ 5.14.21/intel/igb/igb.h 2024-11-25 09:14:55.132245825 +0100 @@ -21,6 +21,9 @@ @@ -11,7 +34,7 @@ diff -ru /usr/src/linux-rt/drivers/net/ethernet/intel/igb/igb.h 5.14.21/intel/ig struct igb_adapter; #define E1000_PCS_CFG_IGN_SD 1 -@@ -666,6 +669,9 @@ +@@ -666,6 +669,9 @@ struct igb_adapter { struct vf_mac_filter *vf_mac_list; /* lock for VF resources */ spinlock_t vfs_lock; @@ -21,10 +44,12 @@ diff -ru /usr/src/linux-rt/drivers/net/ethernet/intel/igb/igb.h 5.14.21/intel/ig }; /* flags controlling PTP/1588 function */ -diff -ru /usr/src/linux-rt/drivers/net/ethernet/intel/igb/igb_main.c 5.14.21/intel/igb/igb_main.c +Only in 5.14.21/intel/igb/: igb_hwmon.o +Only in 5.14.21/intel/igb/: .igb_hwmon.o.cmd +diff -rup /usr/src/linux-rt/drivers/net/ethernet/intel/igb/igb_main.c 5.14.21/intel/igb/igb_main.c --- /usr/src/linux-rt/drivers/net/ethernet/intel/igb/igb_main.c 2024-11-06 14:07:03.000000000 +0100 -+++ 5.14.21/intel/igb/igb_main.c 2024-11-27 06:31:48.793104659 +0100 -@@ -50,9 +50,9 @@ ++++ 5.14.21/intel/igb/igb_main.c 2024-11-27 07:02:40.405767534 +0100 +@@ -50,9 +50,9 @@ enum tx_queue_prio { TX_QUEUE_PRIO_LOW, }; @@ -36,7 +61,7 @@ diff -ru /usr/src/linux-rt/drivers/net/ethernet/intel/igb/igb_main.c 5.14.21/int static const char igb_copyright[] = "Copyright (c) 2007-2014 Intel Corporation."; -@@ -205,6 +205,14 @@ +@@ -205,6 +205,14 @@ module_param(max_vfs, uint, 0); MODULE_PARM_DESC(max_vfs, "Maximum number of virtual functions to allocate per physical function"); #endif /* CONFIG_PCI_IOV */ @@ -51,7 +76,7 @@ diff -ru /usr/src/linux-rt/drivers/net/ethernet/intel/igb/igb_main.c 5.14.21/int static pci_ers_result_t igb_io_error_detected(struct pci_dev *, pci_channel_state_t); static pci_ers_result_t igb_io_slot_reset(struct pci_dev *); -@@ -234,6 +242,7 @@ +@@ -234,6 +242,7 @@ static struct pci_driver igb_driver = { MODULE_AUTHOR("Intel Corporation, "); MODULE_DESCRIPTION("Intel(R) Gigabit Ethernet Network Driver"); MODULE_LICENSE("GPL v2"); @@ -59,7 +84,7 @@ diff -ru /usr/src/linux-rt/drivers/net/ethernet/intel/igb/igb_main.c 5.14.21/int #define DEFAULT_MSG_ENABLE (NETIF_MSG_DRV|NETIF_MSG_PROBE|NETIF_MSG_LINK) static int debug = -1; -@@ -361,7 +370,7 @@ +@@ -361,7 +370,7 @@ static void igb_dump(struct igb_adapter u32 staterr; u16 i, n; @@ -68,7 +93,7 @@ diff -ru /usr/src/linux-rt/drivers/net/ethernet/intel/igb/igb_main.c 5.14.21/int return; /* Print netdevice Info */ -@@ -381,7 +390,7 @@ +@@ -381,7 +390,7 @@ static void igb_dump(struct igb_adapter } /* Print TX Ring Summary */ @@ -77,7 +102,7 @@ diff -ru /usr/src/linux-rt/drivers/net/ethernet/intel/igb/igb_main.c 5.14.21/int goto exit; dev_info(&adapter->pdev->dev, "TX Rings Summary\n"); -@@ -399,7 +408,7 @@ +@@ -399,7 +408,7 @@ static void igb_dump(struct igb_adapter } /* Print TX Rings */ @@ -86,7 +111,7 @@ diff -ru /usr/src/linux-rt/drivers/net/ethernet/intel/igb/igb_main.c 5.14.21/int goto rx_ring_summary; dev_info(&adapter->pdev->dev, "TX Rings Dump\n"); -@@ -931,9 +940,13 @@ +@@ -931,9 +940,13 @@ static int igb_request_msix(struct igb_a unsigned int num_q_vectors = adapter->num_q_vectors; struct net_device *netdev = adapter->netdev; int i, err = 0, vector = 0, free_vector = 0; @@ -101,7 +126,7 @@ diff -ru /usr/src/linux-rt/drivers/net/ethernet/intel/igb/igb_main.c 5.14.21/int if (err) goto err_out; -@@ -963,7 +976,7 @@ +@@ -963,7 +976,7 @@ static int igb_request_msix(struct igb_a sprintf(q_vector->name, "%s-unused", netdev->name); err = request_irq(adapter->msix_entries[vector].vector, @@ -110,7 +135,7 @@ diff -ru /usr/src/linux-rt/drivers/net/ethernet/intel/igb/igb_main.c 5.14.21/int q_vector); if (err) goto err_free; -@@ -1029,8 +1042,9 @@ +@@ -1029,8 +1042,9 @@ static void igb_reset_q_vector(struct ig if (q_vector->rx.ring) adapter->rx_ring[q_vector->rx.ring->queue_index] = NULL; @@ -122,7 +147,7 @@ diff -ru /usr/src/linux-rt/drivers/net/ethernet/intel/igb/igb_main.c 5.14.21/int } static void igb_reset_interrupt_capability(struct igb_adapter *adapter) -@@ -1209,9 +1223,11 @@ +@@ -1209,9 +1223,11 @@ static int igb_alloc_q_vector(struct igb if (!q_vector) return -ENOMEM; @@ -137,7 +162,7 @@ diff -ru /usr/src/linux-rt/drivers/net/ethernet/intel/igb/igb_main.c 5.14.21/int /* tie q_vector and adapter together */ adapter->q_vector[v_idx] = q_vector; -@@ -1408,8 +1424,16 @@ +@@ -1408,8 +1424,16 @@ static int igb_request_irq(struct igb_ad struct net_device *netdev = adapter->netdev; struct pci_dev *pdev = adapter->pdev; int err = 0; @@ -154,7 +179,7 @@ diff -ru /usr/src/linux-rt/drivers/net/ethernet/intel/igb/igb_main.c 5.14.21/int err = igb_request_msix(adapter); if (!err) goto request_done; -@@ -1429,8 +1453,12 @@ +@@ -1429,8 +1453,12 @@ static int igb_request_irq(struct igb_ad igb_assign_vector(adapter->q_vector[0], 0); @@ -168,7 +193,7 @@ diff -ru /usr/src/linux-rt/drivers/net/ethernet/intel/igb/igb_main.c 5.14.21/int netdev->name, adapter); if (!err) goto request_done; -@@ -1440,7 +1468,11 @@ +@@ -1440,7 +1468,11 @@ static int igb_request_irq(struct igb_ad adapter->flags &= ~IGB_FLAG_HAS_MSI; } @@ -181,7 +206,7 @@ diff -ru /usr/src/linux-rt/drivers/net/ethernet/intel/igb/igb_main.c 5.14.21/int netdev->name, adapter); if (err) -@@ -1453,6 +1485,10 @@ +@@ -1453,6 +1485,10 @@ request_done: static void igb_free_irq(struct igb_adapter *adapter) { @@ -192,7 +217,7 @@ diff -ru /usr/src/linux-rt/drivers/net/ethernet/intel/igb/igb_main.c 5.14.21/int if (adapter->flags & IGB_FLAG_HAS_MSIX) { int vector = 0, i; -@@ -1696,7 +1732,7 @@ +@@ -1696,7 +1732,7 @@ static void igb_config_tx_modes(struct i * with HIGH PRIO. If none is, then configure them with LOW PRIO and * as SP. */ @@ -201,7 +226,7 @@ diff -ru /usr/src/linux-rt/drivers/net/ethernet/intel/igb/igb_main.c 5.14.21/int set_tx_desc_fetch_prio(hw, queue, TX_QUEUE_PRIO_HIGH); set_queue_mode(hw, queue, QUEUE_MODE_STREAM_RESERVATION); } else { -@@ -1705,7 +1741,7 @@ +@@ -1705,7 +1741,7 @@ static void igb_config_tx_modes(struct i } /* If CBS is enabled, set DataTranARB and config its parameters. */ @@ -210,7 +235,7 @@ diff -ru /usr/src/linux-rt/drivers/net/ethernet/intel/igb/igb_main.c 5.14.21/int /* i210 does not allow the queue 0 to be in the Strict * Priority mode while the Qav mode is enabled, so, * instead of disabling strict priority mode, we give -@@ -2123,8 +2159,10 @@ +@@ -2123,8 +2159,10 @@ int igb_up(struct igb_adapter *adapter) clear_bit(__IGB_DOWN, &adapter->state); @@ -223,7 +248,7 @@ diff -ru /usr/src/linux-rt/drivers/net/ethernet/intel/igb/igb_main.c 5.14.21/int if (adapter->flags & IGB_FLAG_HAS_MSIX) igb_configure_msix(adapter); -@@ -2144,7 +2182,9 @@ +@@ -2144,7 +2182,9 @@ int igb_up(struct igb_adapter *adapter) wr32(E1000_CTRL_EXT, reg_data); } @@ -234,7 +259,7 @@ diff -ru /usr/src/linux-rt/drivers/net/ethernet/intel/igb/igb_main.c 5.14.21/int /* start the watchdog. */ hw->mac.get_link_status = 1; -@@ -2176,8 +2216,10 @@ +@@ -2176,8 +2216,10 @@ void igb_down(struct igb_adapter *adapte igb_nfc_filter_exit(adapter); @@ -247,7 +272,7 @@ diff -ru /usr/src/linux-rt/drivers/net/ethernet/intel/igb/igb_main.c 5.14.21/int /* disable transmits in the hardware */ tctl = rd32(E1000_TCTL); -@@ -2191,10 +2233,12 @@ +@@ -2191,10 +2233,12 @@ void igb_down(struct igb_adapter *adapte adapter->flags &= ~IGB_FLAG_NEED_LINK_UPDATE; @@ -264,7 +289,7 @@ diff -ru /usr/src/linux-rt/drivers/net/ethernet/intel/igb/igb_main.c 5.14.21/int } } -@@ -2440,8 +2484,11 @@ +@@ -2440,8 +2484,11 @@ void igb_reset(struct igb_adapter *adapt break; } } @@ -278,7 +303,7 @@ diff -ru /usr/src/linux-rt/drivers/net/ethernet/intel/igb/igb_main.c 5.14.21/int igb_update_mng_vlan(adapter); -@@ -3159,6 +3206,35 @@ +@@ -3159,6 +3206,35 @@ static s32 igb_init_i2c(struct igb_adapt return status; } @@ -314,7 +339,7 @@ diff -ru /usr/src/linux-rt/drivers/net/ethernet/intel/igb/igb_main.c 5.14.21/int /** * igb_probe - Device Initialization Routine * @pdev: PCI device information struct -@@ -3181,6 +3257,7 @@ +@@ -3181,6 +3257,7 @@ static int igb_probe(struct pci_dev *pde const struct e1000_info *ei = igb_info_tbl[ent->driver_data]; u8 part_str[E1000_PBANUM_LENGTH]; int err; @@ -322,7 +347,7 @@ diff -ru /usr/src/linux-rt/drivers/net/ethernet/intel/igb/igb_main.c 5.14.21/int /* Catch broken hardware that put the wrong VF device ID in * the PCIe SR-IOV capability. -@@ -3223,6 +3300,8 @@ +@@ -3223,6 +3300,8 @@ static int igb_probe(struct pci_dev *pde adapter = netdev_priv(netdev); adapter->netdev = netdev; adapter->pdev = pdev; @@ -331,7 +356,7 @@ diff -ru /usr/src/linux-rt/drivers/net/ethernet/intel/igb/igb_main.c 5.14.21/int hw = &adapter->hw; hw->back = adapter; adapter->msg_enable = netif_msg_init(debug, DEFAULT_MSG_ENABLE); -@@ -3504,13 +3583,53 @@ +@@ -3504,13 +3583,53 @@ static int igb_probe(struct pci_dev *pde */ igb_get_hw_control(adapter); @@ -391,7 +416,7 @@ diff -ru /usr/src/linux-rt/drivers/net/ethernet/intel/igb/igb_main.c 5.14.21/int #ifdef CONFIG_IGB_DCA if (dca_add_requester(&pdev->dev) == 0) { -@@ -3845,6 +3964,10 @@ +@@ -3845,6 +3964,10 @@ static void igb_remove(struct pci_dev *p struct igb_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; @@ -402,7 +427,7 @@ diff -ru /usr/src/linux-rt/drivers/net/ethernet/intel/igb/igb_main.c 5.14.21/int pm_runtime_get_noresume(&pdev->dev); #ifdef CONFIG_IGB_HWMON igb_sysfs_exit(adapter); -@@ -3879,7 +4002,9 @@ +@@ -3879,7 +4002,9 @@ static void igb_remove(struct pci_dev *p igb_disable_sriov(pdev, false); #endif @@ -413,7 +438,7 @@ diff -ru /usr/src/linux-rt/drivers/net/ethernet/intel/igb/igb_main.c 5.14.21/int igb_clear_interrupt_scheme(adapter); -@@ -4124,7 +4249,9 @@ +@@ -4124,7 +4249,9 @@ static int __igb_open(struct net_device if (!resuming) pm_runtime_get_sync(&pdev->dev); @@ -424,7 +449,7 @@ diff -ru /usr/src/linux-rt/drivers/net/ethernet/intel/igb/igb_main.c 5.14.21/int /* allocate transmit descriptors */ err = igb_setup_all_tx_resources(adapter); -@@ -4149,22 +4276,26 @@ +@@ -4149,22 +4276,26 @@ static int __igb_open(struct net_device if (err) goto err_req_irq; @@ -462,7 +487,7 @@ diff -ru /usr/src/linux-rt/drivers/net/ethernet/intel/igb/igb_main.c 5.14.21/int /* Clear any pending interrupts. */ rd32(E1000_TSICR); -@@ -4180,7 +4311,9 @@ +@@ -4180,7 +4311,9 @@ static int __igb_open(struct net_device wr32(E1000_CTRL_EXT, reg_data); } @@ -473,7 +498,7 @@ diff -ru /usr/src/linux-rt/drivers/net/ethernet/intel/igb/igb_main.c 5.14.21/int if (!resuming) pm_runtime_put(&pdev->dev); -@@ -4240,6 +4373,9 @@ +@@ -4240,6 +4373,9 @@ static int __igb_close(struct net_device igb_free_all_tx_resources(adapter); igb_free_all_rx_resources(adapter); @@ -483,7 +508,7 @@ diff -ru /usr/src/linux-rt/drivers/net/ethernet/intel/igb/igb_main.c 5.14.21/int if (!suspending) pm_runtime_put_sync(&pdev->dev); return 0; -@@ -4247,7 +4383,9 @@ +@@ -4247,7 +4383,9 @@ static int __igb_close(struct net_device int igb_close(struct net_device *netdev) { @@ -494,7 +519,7 @@ diff -ru /usr/src/linux-rt/drivers/net/ethernet/intel/igb/igb_main.c 5.14.21/int return __igb_close(netdev, false); return 0; } -@@ -4888,11 +5026,16 @@ +@@ -4888,11 +5026,16 @@ static void igb_clean_tx_ring(struct igb while (i != tx_ring->next_to_use) { union e1000_adv_tx_desc *eop_desc, *tx_desc; @@ -516,7 +541,7 @@ diff -ru /usr/src/linux-rt/drivers/net/ethernet/intel/igb/igb_main.c 5.14.21/int /* unmap skb header data */ dma_unmap_single(tx_ring->dev, -@@ -5502,6 +5645,24 @@ +@@ -5502,6 +5645,24 @@ static void igb_watchdog_task(struct wor link = igb_has_link(adapter); @@ -541,7 +566,7 @@ diff -ru /usr/src/linux-rt/drivers/net/ethernet/intel/igb/igb_main.c 5.14.21/int if (adapter->flags & IGB_FLAG_NEED_LINK_UPDATE) { if (time_after(jiffies, (adapter->link_check_timeout + HZ))) adapter->flags &= ~IGB_FLAG_NEED_LINK_UPDATE; -@@ -5742,7 +5903,11 @@ +@@ -5742,7 +5903,11 @@ static void igb_update_ring_itr(struct i * ints/sec - ITR timer value of 120 ticks. */ if (adapter->link_speed != SPEED_1000) { @@ -554,7 +579,7 @@ diff -ru /usr/src/linux-rt/drivers/net/ethernet/intel/igb/igb_main.c 5.14.21/int goto set_itr_val; } -@@ -6148,8 +6313,11 @@ +@@ -6148,8 +6313,11 @@ static void igb_tx_olinfo_status(struct static int __igb_maybe_stop_tx(struct igb_ring *tx_ring, const u16 size) { struct net_device *netdev = tx_ring->netdev; @@ -567,7 +592,7 @@ diff -ru /usr/src/linux-rt/drivers/net/ethernet/intel/igb/igb_main.c 5.14.21/int /* Herbert's original patch had: * smp_mb__after_netif_stop_queue(); -@@ -6164,7 +6332,9 @@ +@@ -6164,7 +6332,9 @@ static int __igb_maybe_stop_tx(struct ig return -EBUSY; /* A reprieve! */ @@ -578,7 +603,7 @@ diff -ru /usr/src/linux-rt/drivers/net/ethernet/intel/igb/igb_main.c 5.14.21/int u64_stats_update_begin(&tx_ring->tx_syncp2); tx_ring->tx_stats.restart_queue2++; -@@ -6193,6 +6363,7 @@ +@@ -6193,6 +6363,7 @@ static int igb_tx_map(struct igb_ring *t u32 tx_flags = first->tx_flags; u32 cmd_type = igb_tx_cmd_type(skb, tx_flags); u16 i = tx_ring->next_to_use; @@ -586,7 +611,7 @@ diff -ru /usr/src/linux-rt/drivers/net/ethernet/intel/igb/igb_main.c 5.14.21/int tx_desc = IGB_TX_DESC(tx_ring, i); -@@ -6259,7 +6430,9 @@ +@@ -6259,7 +6430,9 @@ static int igb_tx_map(struct igb_ring *t cmd_type |= size | IGB_TXD_DCMD; tx_desc->read.cmd_type_len = cpu_to_le32(cmd_type); @@ -597,7 +622,7 @@ diff -ru /usr/src/linux-rt/drivers/net/ethernet/intel/igb/igb_main.c 5.14.21/int /* set the timestamp */ first->time_stamp = jiffies; -@@ -6287,8 +6460,13 @@ +@@ -6287,8 +6460,13 @@ static int igb_tx_map(struct igb_ring *t /* Make sure there is space in the ring for the next send. */ igb_maybe_stop_tx(tx_ring, DESC_NEEDED); @@ -612,7 +637,7 @@ diff -ru /usr/src/linux-rt/drivers/net/ethernet/intel/igb/igb_main.c 5.14.21/int } return 0; -@@ -6317,8 +6495,10 @@ +@@ -6317,8 +6495,10 @@ dma_error: DMA_TO_DEVICE); dma_unmap_len_set(tx_buffer, len, 0); @@ -625,7 +650,7 @@ diff -ru /usr/src/linux-rt/drivers/net/ethernet/intel/igb/igb_main.c 5.14.21/int tx_ring->next_to_use = i; -@@ -6443,6 +6623,7 @@ +@@ -6443,6 +6623,7 @@ netdev_tx_t igb_xmit_frame_ring(struct s u16 count = TXD_USE_COUNT(skb_headlen(skb)); __be16 protocol = vlan_get_protocol(skb); u8 hdr_len = 0; @@ -633,7 +658,7 @@ diff -ru /usr/src/linux-rt/drivers/net/ethernet/intel/igb/igb_main.c 5.14.21/int /* need: 1 descriptor per page * PAGE_SIZE/IGB_MAX_DATA_PER_TXD, * + 1 desc for skb_headlen/IGB_MAX_DATA_PER_TXD, -@@ -6466,38 +6647,39 @@ +@@ -6466,38 +6647,39 @@ netdev_tx_t igb_xmit_frame_ring(struct s first->bytecount = skb->len; first->gso_segs = 1; @@ -701,7 +726,7 @@ diff -ru /usr/src/linux-rt/drivers/net/ethernet/intel/igb/igb_main.c 5.14.21/int if (igb_tx_map(tx_ring, first, hdr_len)) goto cleanup_tx_tstamp; -@@ -6505,12 +6687,12 @@ +@@ -6505,12 +6687,12 @@ netdev_tx_t igb_xmit_frame_ring(struct s return NETDEV_TX_OK; out_drop: @@ -719,7 +744,7 @@ diff -ru /usr/src/linux-rt/drivers/net/ethernet/intel/igb/igb_main.c 5.14.21/int dev_kfree_skb_any(adapter->ptp_tx_skb); adapter->ptp_tx_skb = NULL; if (adapter->hw.mac.type == e1000_82576) -@@ -7063,11 +7245,16 @@ +@@ -7063,11 +7245,16 @@ static void igb_write_itr(struct igb_q_v static irqreturn_t igb_msix_ring(int irq, void *data) { struct igb_q_vector *q_vector = data; @@ -737,7 +762,7 @@ diff -ru /usr/src/linux-rt/drivers/net/ethernet/intel/igb/igb_main.c 5.14.21/int return IRQ_HANDLED; } -@@ -8108,7 +8295,11 @@ +@@ -8108,7 +8295,11 @@ static irqreturn_t igb_intr_msi(int irq, if (icr & E1000_ICR_TS) igb_tsync_interrupt(adapter); @@ -750,7 +775,7 @@ diff -ru /usr/src/linux-rt/drivers/net/ethernet/intel/igb/igb_main.c 5.14.21/int return IRQ_HANDLED; } -@@ -8154,7 +8345,11 @@ +@@ -8154,7 +8345,11 @@ static irqreturn_t igb_intr(int irq, voi if (icr & E1000_ICR_TS) igb_tsync_interrupt(adapter); @@ -763,7 +788,7 @@ diff -ru /usr/src/linux-rt/drivers/net/ethernet/intel/igb/igb_main.c 5.14.21/int return IRQ_HANDLED; } -@@ -8215,7 +8410,7 @@ +@@ -8215,7 +8410,7 @@ static int igb_poll(struct napi_struct * /* Exit the polling mode, but don't re-enable interrupts if stack might * poll us due to busy-polling */ @@ -772,7 +797,7 @@ diff -ru /usr/src/linux-rt/drivers/net/ethernet/intel/igb/igb_main.c 5.14.21/int igb_ring_irq_enable(q_vector); return work_done; -@@ -8266,11 +8461,13 @@ +@@ -8266,11 +8461,13 @@ static bool igb_clean_tx_irq(struct igb_ total_bytes += tx_buffer->bytecount; total_packets += tx_buffer->gso_segs; @@ -791,7 +816,7 @@ diff -ru /usr/src/linux-rt/drivers/net/ethernet/intel/igb/igb_main.c 5.14.21/int /* unmap skb header data */ dma_unmap_single(tx_ring->dev, -@@ -8319,8 +8516,10 @@ +@@ -8319,8 +8516,10 @@ static bool igb_clean_tx_irq(struct igb_ budget--; } while (likely(budget)); @@ -804,7 +829,7 @@ diff -ru /usr/src/linux-rt/drivers/net/ethernet/intel/igb/igb_main.c 5.14.21/int i += tx_ring->count; tx_ring->next_to_clean = i; u64_stats_update_begin(&tx_ring->tx_syncp); -@@ -8330,7 +8529,8 @@ +@@ -8330,7 +8529,8 @@ static bool igb_clean_tx_irq(struct igb_ q_vector->tx.total_bytes += total_bytes; q_vector->tx.total_packets += total_packets; @@ -814,7 +839,7 @@ diff -ru /usr/src/linux-rt/drivers/net/ethernet/intel/igb/igb_main.c 5.14.21/int struct e1000_hw *hw = &adapter->hw; /* Detect a transmit hang in hardware, this serializes the -@@ -8373,7 +8573,7 @@ +@@ -8373,7 +8573,7 @@ static bool igb_clean_tx_irq(struct igb_ } #define TX_WAKE_THRESHOLD (DESC_NEEDED * 2) @@ -823,7 +848,7 @@ diff -ru /usr/src/linux-rt/drivers/net/ethernet/intel/igb/igb_main.c 5.14.21/int netif_carrier_ok(tx_ring->netdev) && igb_desc_unused(tx_ring) >= TX_WAKE_THRESHOLD)) { /* Make sure that anybody stopping the queue after this -@@ -8507,7 +8707,11 @@ +@@ -8507,7 +8707,11 @@ static struct sk_buff *igb_construct_skb net_prefetch(xdp->data); /* allocate a skb to store the frags */ @@ -836,7 +861,7 @@ diff -ru /usr/src/linux-rt/drivers/net/ethernet/intel/igb/igb_main.c 5.14.21/int if (unlikely(!skb)) return NULL; -@@ -8922,54 +9126,69 @@ +@@ -8922,54 +9126,69 @@ static int igb_clean_rx_irq(struct igb_q size -= ts_hdr_len; } @@ -941,7 +966,7 @@ diff -ru /usr/src/linux-rt/drivers/net/ethernet/intel/igb/igb_main.c 5.14.21/int /* verify the packet layout is correct */ if (igb_cleanup_headers(rx_ring, rx_desc, skb)) { skb = NULL; -@@ -9175,6 +9394,79 @@ +@@ -9175,6 +9394,79 @@ static int igb_ioctl(struct net_device * return igb_ptp_get_ts_config(netdev, ifr); case SIOCSHWTSTAMP: return igb_ptp_set_ts_config(netdev, ifr); @@ -1021,7 +1046,7 @@ diff -ru /usr/src/linux-rt/drivers/net/ethernet/intel/igb/igb_main.c 5.14.21/int default: return -EOPNOTSUPP; } -@@ -9356,7 +9648,7 @@ +@@ -9356,7 +9648,7 @@ static int __igb_shutdown(struct pci_dev rtnl_lock(); netif_device_detach(netdev); @@ -1030,7 +1055,11 @@ diff -ru /usr/src/linux-rt/drivers/net/ethernet/intel/igb/igb_main.c 5.14.21/int __igb_close(netdev, true); igb_ptp_suspend(adapter); -diff -ru /usr/src/linux-rt/drivers/net/ethernet/intel/igb/Makefile 5.14.21/intel/igb/Makefile +Only in 5.14.21/intel/igb/: igb_main.o +Only in 5.14.21/intel/igb/: .igb_main.o.cmd +Only in 5.14.21/intel/igb/: igb_ptp.o +Only in 5.14.21/intel/igb/: .igb_ptp.o.cmd +diff -rup /usr/src/linux-rt/drivers/net/ethernet/intel/igb/Makefile 5.14.21/intel/igb/Makefile --- /usr/src/linux-rt/drivers/net/ethernet/intel/igb/Makefile 2024-11-06 14:07:03.000000000 +0100 +++ 5.14.21/intel/igb/Makefile 2024-11-25 09:14:55.106245831 +0100 @@ -4,8 +4,11 @@ @@ -1047,3 +1076,5 @@ diff -ru /usr/src/linux-rt/drivers/net/ethernet/intel/igb/Makefile 5.14.21/intel + +EXTRA_CFLAGS=-I$(src)/../../../../../../ +KBUILD_EXTRA_SYMBOLS=$(src)/../../../../../../Module.symvers +Only in 5.14.21/intel/igb/: modules.order +Only in 5.14.21/intel/igb/: .modules.order.cmd diff --git a/linux/drivers/opensuse/15.5/intel_igc_opensuse_15.5_5.14.21.patch b/linux/drivers/opensuse/15.5/intel_igc_opensuse_15.5_5.14.21.patch new file mode 100644 index 0000000..28d139e --- /dev/null +++ b/linux/drivers/opensuse/15.5/intel_igc_opensuse_15.5_5.14.21.patch @@ -0,0 +1,1030 @@ +Only in 5.14.21/intel/igc/: igc_base.o +Only in 5.14.21/intel/igc/: .igc_base.o.cmd +Only in 5.14.21/intel/igc/: igc_diag.o +Only in 5.14.21/intel/igc/: .igc_diag.o.cmd +Only in 5.14.21/intel/igc/: igc_dump.o +Only in 5.14.21/intel/igc/: .igc_dump.o.cmd +Only in 5.14.21/intel/igc/: igc-ethercat.ko +Only in 5.14.21/intel/igc/: .igc-ethercat.ko.cmd +Only in 5.14.21/intel/igc/: igc-ethercat.mod +Only in 5.14.21/intel/igc/: igc-ethercat.mod.c +Only in 5.14.21/intel/igc/: .igc-ethercat.mod.cmd +Only in 5.14.21/intel/igc/: igc-ethercat.mod.o +Only in 5.14.21/intel/igc/: .igc-ethercat.mod.o.cmd +Only in 5.14.21/intel/igc/: igc-ethercat.o +Only in 5.14.21/intel/igc/: .igc-ethercat.o.cmd +Only in 5.14.21/intel/igc/: igc_ethtool.o +Only in 5.14.21/intel/igc/: .igc_ethtool.o.cmd +diff -rup /usr/src/linux-rt/drivers/net/ethernet/intel/igc/igc.h 5.14.21/intel/igc/igc.h +--- /usr/src/linux-rt/drivers/net/ethernet/intel/igc/igc.h 2024-11-06 14:07:03.000000000 +0100 ++++ 5.14.21/intel/igc/igc.h 2024-11-26 15:40:47.919748856 +0100 +@@ -17,6 +17,9 @@ + + #include "igc_hw.h" + ++#include "ethercat_device.h" ++#include "ethercat_device_ioctl.h" ++ + void igc_ethtool_set_ops(struct net_device *); + + /* Transmit and receive queues */ +@@ -255,6 +258,9 @@ struct igc_adapter { + struct timespec64 start; + struct timespec64 period; + } perout[IGC_N_PEROUT]; ++ ++ bool is_ecat; ++ struct ethercat_device *ecat_dev; + }; + + void igc_up(struct igc_adapter *adapter); +Only in 5.14.21/intel/igc/: igc_i225.o +Only in 5.14.21/intel/igc/: .igc_i225.o.cmd +Only in 5.14.21/intel/igc/: igc_mac.o +Only in 5.14.21/intel/igc/: .igc_mac.o.cmd +diff -rup /usr/src/linux-rt/drivers/net/ethernet/intel/igc/igc_main.c 5.14.21/intel/igc/igc_main.c +--- /usr/src/linux-rt/drivers/net/ethernet/intel/igc/igc_main.c 2024-11-06 14:07:03.000000000 +0100 ++++ 5.14.21/intel/igc/igc_main.c 2024-11-27 07:38:27.400321115 +0100 +@@ -21,7 +21,7 @@ + #include "igc_tsn.h" + #include "igc_xdp.h" + +-#define DRV_SUMMARY "Intel(R) 2.5G Ethernet Linux Driver" ++#define DRV_SUMMARY "Intel(R) 2.5G Ethernet Linux Driver (EtherCAT enabled)" + + #define DEFAULT_MSG_ENABLE (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_LINK) + +@@ -35,10 +35,19 @@ static int debug = -1; + MODULE_AUTHOR("Intel Corporation, "); + MODULE_DESCRIPTION(DRV_SUMMARY); + MODULE_LICENSE("GPL v2"); ++MODULE_SOFTDEP("pre: ethercat_chrdev"); + module_param(debug, int, 0); + MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)"); + +-char igc_driver_name[] = "igc"; ++#define ETHERCAT_MAC_ADDR_SIZE 10 ++static char * ethercat_mac_addr[ETHERCAT_MAC_ADDR_SIZE]; ++static int ethercat_mac_addr_count; ++module_param_array(ethercat_mac_addr, charp, ðercat_mac_addr_count, 0660); ++MODULE_PARM_DESC(ethercat_mac_addr, "List of MAC addresses to use as EtherCAT device"); ++ ++static unsigned int ethercat_polling = 0; ++ ++char igc_driver_name[] = "igc-ethercat"; + static const char igc_driver_string[] = DRV_SUMMARY; + static const char igc_copyright[] = + "Copyright(c) 2018 Intel Corporation."; +@@ -111,8 +120,10 @@ void igc_reset(struct igc_adapter *adapt + /* Re-establish EEE setting */ + igc_set_eee_i225(hw, true, true, true); + +- if (!netif_running(adapter->netdev)) +- igc_power_down_phy_copper_base(&adapter->hw); ++ if (!adapter->is_ecat) { ++ if (!netif_running(adapter->netdev)) ++ igc_power_down_phy_copper_base(&adapter->hw); ++ } + + /* Enable HW to recognize an 802.1Q VLAN Ethernet packet */ + wr32(IGC_VET, ETH_P_8021Q); +@@ -197,6 +208,7 @@ static void igc_clean_tx_ring(struct igc + u16 i = tx_ring->next_to_clean; + struct igc_tx_buffer *tx_buffer = &tx_ring->tx_buffer_info[i]; + u32 xsk_frames = 0; ++ struct igc_adapter *adapter = netdev_priv(tx_ring->netdev); + + while (i != tx_ring->next_to_use) { + union igc_adv_tx_desc *eop_desc, *tx_desc; +@@ -206,11 +218,17 @@ static void igc_clean_tx_ring(struct igc + xsk_frames++; + break; + case IGC_TX_BUFFER_TYPE_XDP: +- xdp_return_frame(tx_buffer->xdpf); ++ if (unlikely(!adapter->is_ecat)) { ++ /* buffer is reused in EtherCAT TX operation */ ++ xdp_return_frame(tx_buffer->xdpf); ++ } + igc_unmap_tx_buffer(tx_ring->dev, tx_buffer); + break; + case IGC_TX_BUFFER_TYPE_SKB: +- dev_kfree_skb_any(tx_buffer->skb); ++ if (unlikely(!adapter->is_ecat)) { ++ /* skb is reused in EtherCAT TX operation */ ++ dev_kfree_skb_any(tx_buffer->skb); ++ } + igc_unmap_tx_buffer(tx_ring->dev, tx_buffer); + break; + default: +@@ -1223,8 +1241,11 @@ no_csum: + static int __igc_maybe_stop_tx(struct igc_ring *tx_ring, const u16 size) + { + struct net_device *netdev = tx_ring->netdev; ++ struct igc_adapter *adapter = netdev_priv(netdev); + +- netif_stop_subqueue(netdev, tx_ring->queue_index); ++ if (!adapter->is_ecat) { ++ netif_stop_subqueue(netdev, tx_ring->queue_index); ++ } + + /* memory barriier comment */ + smp_mb(); +@@ -1236,7 +1257,9 @@ static int __igc_maybe_stop_tx(struct ig + return -EBUSY; + + /* A reprieve! */ +- netif_wake_subqueue(netdev, tx_ring->queue_index); ++ if (!adapter->is_ecat) { ++ netif_wake_subqueue(netdev, tx_ring->queue_index); ++ } + + u64_stats_update_begin(&tx_ring->tx_syncp2); + tx_ring->tx_stats.restart_queue2++; +@@ -1314,6 +1337,7 @@ static int igc_tx_map(struct igc_ring *t + unsigned int data_len, size; + dma_addr_t dma; + u32 cmd_type; ++ struct igc_adapter *adapter = netdev_priv(tx_ring->netdev); + + cmd_type = igc_tx_cmd_type(skb, tx_flags); + tx_desc = IGC_TX_DESC(tx_ring, i); +@@ -1381,7 +1405,9 @@ static int igc_tx_map(struct igc_ring *t + cmd_type |= size | IGC_TXD_DCMD; + tx_desc->read.cmd_type_len = cpu_to_le32(cmd_type); + +- netdev_tx_sent_queue(txring_txq(tx_ring), first->bytecount); ++ if (unlikely(!adapter->is_ecat)) { ++ netdev_tx_sent_queue(txring_txq(tx_ring), first->bytecount); ++ } + + /* set the timestamp */ + first->time_stamp = jiffies; +@@ -1409,8 +1435,13 @@ static int igc_tx_map(struct igc_ring *t + /* Make sure there is space in the ring for the next send. */ + igc_maybe_stop_tx(tx_ring, DESC_NEEDED); + +- if (netif_xmit_stopped(txring_txq(tx_ring)) || !netdev_xmit_more()) { ++ if (likely(adapter->is_ecat)) { + writel(i, tx_ring->tail); ++ wmb(); ++ } else { ++ if (netif_xmit_stopped(txring_txq(tx_ring)) || !netdev_xmit_more()) { ++ writel(i, tx_ring->tail); ++ } + } + + return 0; +@@ -1431,8 +1462,10 @@ dma_error: + if (dma_unmap_len(tx_buffer, len)) + igc_unmap_tx_buffer(tx_ring->dev, tx_buffer); + +- dev_kfree_skb_any(tx_buffer->skb); +- tx_buffer->skb = NULL; ++ if (!adapter->is_ecat) { ++ dev_kfree_skb_any(tx_buffer->skb); ++ tx_buffer->skb = NULL; ++ } + + tx_ring->next_to_use = i; + +@@ -1547,6 +1580,7 @@ static netdev_tx_t igc_xmit_frame_ring(s + ktime_t txtime; + u8 hdr_len = 0; + int tso = 0; ++ struct igc_adapter *adapter = netdev_priv(tx_ring->netdev); + + /* need: 1 descriptor per page * PAGE_SIZE/IGC_MAX_DATA_PER_TXD, + * + 1 desc for skb_headlen/IGC_MAX_DATA_PER_TXD, +@@ -1563,7 +1597,7 @@ static netdev_tx_t igc_xmit_frame_ring(s + return NETDEV_TX_BUSY; + } + +- if (!tx_ring->launchtime_enable) ++ if (likely(adapter->is_ecat) || !tx_ring->launchtime_enable) + goto done; + + txtime = skb->tstamp; +@@ -1599,52 +1633,55 @@ done: + first->bytecount = skb->len; + first->gso_segs = 1; + +- if (unlikely(test_bit(IGC_RING_FLAG_TX_HWTSTAMP, &tx_ring->flags) && +- skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) { +- struct igc_adapter *adapter = netdev_priv(tx_ring->netdev); +- +- /* FIXME: add support for retrieving timestamps from +- * the other timer registers before skipping the +- * timestamping request. +- */ +- unsigned long flags; ++ if (unlikely(!adapter->is_ecat)) { ++ if (unlikely(test_bit(IGC_RING_FLAG_TX_HWTSTAMP, &tx_ring->flags) && ++ skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) { ++ ++ /* FIXME: add support for retrieving timestamps from ++ * the other timer registers before skipping the ++ * timestamping request. ++ */ ++ unsigned long flags; + +- spin_lock_irqsave(&adapter->ptp_tx_lock, flags); +- if (!adapter->ptp_tx_skb) { +- skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; +- tx_flags |= IGC_TX_FLAGS_TSTAMP; ++ spin_lock_irqsave(&adapter->ptp_tx_lock, flags); ++ if (!adapter->ptp_tx_skb) { ++ skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; ++ tx_flags |= IGC_TX_FLAGS_TSTAMP; + +- adapter->ptp_tx_skb = skb_get(skb); +- adapter->ptp_tx_start = jiffies; +- } else { +- adapter->tx_hwtstamp_skipped++; +- } ++ adapter->ptp_tx_skb = skb_get(skb); ++ adapter->ptp_tx_start = jiffies; ++ } else { ++ adapter->tx_hwtstamp_skipped++; ++ } + +- spin_unlock_irqrestore(&adapter->ptp_tx_lock, flags); +- } ++ spin_unlock_irqrestore(&adapter->ptp_tx_lock, flags); ++ } + +- if (skb_vlan_tag_present(skb)) { +- tx_flags |= IGC_TX_FLAGS_VLAN; +- tx_flags |= (skb_vlan_tag_get(skb) << IGC_TX_FLAGS_VLAN_SHIFT); +- } ++ if (skb_vlan_tag_present(skb)) { ++ tx_flags |= IGC_TX_FLAGS_VLAN; ++ tx_flags |= (skb_vlan_tag_get(skb) << IGC_TX_FLAGS_VLAN_SHIFT); ++ } + +- /* record initial flags and protocol */ +- first->tx_flags = tx_flags; +- first->protocol = protocol; ++ /* record initial flags and protocol */ ++ first->tx_flags = tx_flags; ++ first->protocol = protocol; + +- tso = igc_tso(tx_ring, first, launch_time, first_flag, &hdr_len); +- if (tso < 0) +- goto out_drop; +- else if (!tso) +- igc_tx_csum(tx_ring, first, launch_time, first_flag); ++ tso = igc_tso(tx_ring, first, launch_time, first_flag, &hdr_len); ++ if (tso < 0) ++ goto out_drop; ++ else if (!tso) ++ igc_tx_csum(tx_ring, first, launch_time, first_flag); ++ } + + igc_tx_map(tx_ring, first, hdr_len); + + return NETDEV_TX_OK; + + out_drop: +- dev_kfree_skb_any(first->skb); +- first->skb = NULL; ++ if (unlikely(!adapter->is_ecat)) { ++ dev_kfree_skb_any(first->skb); ++ first->skb = NULL; ++ } + + return NETDEV_TX_OK; + } +@@ -1942,8 +1979,11 @@ static struct sk_buff *igc_construct_skb + net_prefetch(xdp->data_meta); + + /* allocate a skb to store the frags */ +- skb = napi_alloc_skb(&rx_ring->q_vector->napi, +- IGC_RX_HDR_LEN + metasize); ++ if (likely(rx_ring->q_vector->adapter->is_ecat)) { ++ skb = dev_alloc_skb(IGC_RX_HDR_LEN + metasize); ++ } else { ++ skb = napi_alloc_skb(&rx_ring->q_vector->napi, IGC_RX_HDR_LEN + metasize); ++ } + if (unlikely(!skb)) + return NULL; + +@@ -2581,54 +2621,68 @@ static int igc_clean_rx_irq(struct igc_q + size -= IGC_TS_HDR_LEN; + } + +- if (!skb) { +- xdp_init_buff(&xdp, truesize, &rx_ring->xdp_rxq); +- xdp_prepare_buff(&xdp, pktbuf - igc_rx_offset(rx_ring), +- igc_rx_offset(rx_ring) + pkt_offset, +- size, true); +- xdp_buff_clear_frags_flag(&xdp); ++ if (likely(adapter->is_ecat)) { ++ if (size > 0) { ++ prefetch(pktbuf); ++ ethercat_device_receive(adapter->ecat_dev, pktbuf, size); ++ } ++ igc_reuse_rx_page(rx_ring, rx_buffer); ++ } else { ++ if (!skb) { ++ xdp_init_buff(&xdp, truesize, &rx_ring->xdp_rxq); ++ xdp_prepare_buff(&xdp, pktbuf - igc_rx_offset(rx_ring), ++ igc_rx_offset(rx_ring) + pkt_offset, ++ size, true); ++ xdp_buff_clear_frags_flag(&xdp); + +- skb = igc_xdp_run_prog(adapter, &xdp); +- } ++ skb = igc_xdp_run_prog(adapter, &xdp); ++ } + +- if (IS_ERR(skb)) { +- unsigned int xdp_res = -PTR_ERR(skb); ++ if (IS_ERR(skb)) { ++ unsigned int xdp_res = -PTR_ERR(skb); + +- switch (xdp_res) { +- case IGC_XDP_CONSUMED: ++ switch (xdp_res) { ++ case IGC_XDP_CONSUMED: ++ rx_buffer->pagecnt_bias++; ++ break; ++ case IGC_XDP_TX: ++ case IGC_XDP_REDIRECT: ++ igc_rx_buffer_flip(rx_buffer, truesize); ++ xdp_status |= xdp_res; ++ break; ++ } ++ ++ total_packets++; ++ total_bytes += size; ++ } else if (skb) ++ igc_add_rx_frag(rx_ring, rx_buffer, skb, size); ++ else if (ring_uses_build_skb(rx_ring)) ++ skb = igc_build_skb(rx_ring, rx_buffer, &xdp); ++ else ++ skb = igc_construct_skb(rx_ring, rx_buffer, &xdp, ++ timestamp); ++ ++ /* exit if we failed to retrieve a buffer */ ++ if (!skb) { ++ rx_ring->rx_stats.alloc_failed++; + rx_buffer->pagecnt_bias++; + break; +- case IGC_XDP_TX: +- case IGC_XDP_REDIRECT: +- igc_rx_buffer_flip(rx_buffer, truesize); +- xdp_status |= xdp_res; +- break; + } + +- total_packets++; +- total_bytes += size; +- } else if (skb) +- igc_add_rx_frag(rx_ring, rx_buffer, skb, size); +- else if (ring_uses_build_skb(rx_ring)) +- skb = igc_build_skb(rx_ring, rx_buffer, &xdp); +- else +- skb = igc_construct_skb(rx_ring, rx_buffer, &xdp, +- timestamp); +- +- /* exit if we failed to retrieve a buffer */ +- if (!skb) { +- rx_ring->rx_stats.alloc_failed++; +- rx_buffer->pagecnt_bias++; +- break; ++ igc_put_rx_buffer(rx_ring, rx_buffer, rx_buffer_pgcnt); + } +- +- igc_put_rx_buffer(rx_ring, rx_buffer, rx_buffer_pgcnt); + cleaned_count++; + + /* fetch next buffer in frame if non-eop */ + if (igc_is_non_eop(rx_ring, rx_desc)) + continue; + ++ if (likely(adapter->is_ecat)) { ++ total_bytes += size; ++ total_packets++; ++ continue; ++ } ++ + /* verify the packet layout is correct */ + if (igc_cleanup_headers(rx_ring, rx_desc, skb)) { + skb = NULL; +@@ -2933,11 +2987,15 @@ static bool igc_clean_tx_irq(struct igc_ + xsk_frames++; + break; + case IGC_TX_BUFFER_TYPE_XDP: +- xdp_return_frame(tx_buffer->xdpf); ++ if (unlikely(!adapter->is_ecat)) { ++ xdp_return_frame(tx_buffer->xdpf); ++ } + igc_unmap_tx_buffer(tx_ring->dev, tx_buffer); + break; + case IGC_TX_BUFFER_TYPE_SKB: +- napi_consume_skb(tx_buffer->skb, napi_budget); ++ if (unlikely(!adapter->is_ecat)) { ++ napi_consume_skb(tx_buffer->skb, napi_budget); ++ } + igc_unmap_tx_buffer(tx_ring->dev, tx_buffer); + break; + default: +@@ -2994,7 +3052,8 @@ static bool igc_clean_tx_irq(struct igc_ + igc_xdp_xmit_zc(tx_ring); + } + +- if (test_bit(IGC_RING_FLAG_TX_DETECT_HANG, &tx_ring->flags)) { ++ if (unlikely(!adapter->is_ecat) && ++ test_bit(IGC_RING_FLAG_TX_DETECT_HANG, &tx_ring->flags)) { + struct igc_hw *hw = &adapter->hw; + + /* Detect a transmit hang in hardware, this serializes the +@@ -3038,7 +3097,7 @@ static bool igc_clean_tx_irq(struct igc_ + } + + #define TX_WAKE_THRESHOLD (DESC_NEEDED * 2) +- if (unlikely(total_packets && ++ if (unlikely(!adapter->is_ecat && total_packets && + netif_carrier_ok(tx_ring->netdev) && + igc_desc_unused(tx_ring) >= TX_WAKE_THRESHOLD)) { + /* Make sure that anybody stopping the queue after this +@@ -4110,7 +4169,9 @@ static void igc_reset_q_vector(struct ig + if (q_vector->rx.ring) + adapter->rx_ring[q_vector->rx.ring->queue_index] = NULL; + +- netif_napi_del(&q_vector->napi); ++ if (unlikely(!adapter->is_ecat)) { ++ netif_napi_del(&q_vector->napi); ++ } + } + + /** +@@ -4399,7 +4460,10 @@ static void igc_update_ring_itr(struct i + switch (adapter->link_speed) { + case SPEED_10: + case SPEED_100: +- new_val = IGC_4K_ITR; ++ if (adapter->is_ecat) ++ new_val = IGC_20K_ITR; ++ else ++ new_val = IGC_4K_ITR; + goto set_itr_val; + default: + break; +@@ -4532,7 +4596,7 @@ static int igc_poll(struct napi_struct * + /* Exit the polling mode, but don't re-enable interrupts if stack might + * poll us due to busy-polling + */ +- if (likely(napi_complete_done(napi, work_done))) ++ if (likely(q_vector->adapter->is_ecat) || likely(napi_complete_done(napi, work_done))) + igc_ring_irq_enable(q_vector); + + return min(work_done, budget - 1); +@@ -4575,9 +4639,11 @@ static int igc_alloc_q_vector(struct igc + if (!q_vector) + return -ENOMEM; + +- /* initialize NAPI */ +- netif_napi_add(adapter->netdev, &q_vector->napi, +- igc_poll, 64); ++ if (unlikely(!adapter->is_ecat)) { ++ /* initialize NAPI */ ++ netif_napi_add(adapter->netdev, &q_vector->napi, ++ igc_poll, 64); ++ } + + /* tie q_vector and adapter together */ + adapter->q_vector[v_idx] = q_vector; +@@ -4806,8 +4872,10 @@ void igc_up(struct igc_adapter *adapter) + + clear_bit(__IGC_DOWN, &adapter->state); + +- for (i = 0; i < adapter->num_q_vectors; i++) +- napi_enable(&adapter->q_vector[i]->napi); ++ if (unlikely(!adapter->is_ecat)) { ++ for (i = 0; i < adapter->num_q_vectors; i++) ++ napi_enable(&adapter->q_vector[i]->napi); ++ } + + if (adapter->msix_entries) + igc_configure_msix(adapter); +@@ -4818,7 +4886,9 @@ void igc_up(struct igc_adapter *adapter) + rd32(IGC_ICR); + igc_irq_enable(adapter); + +- netif_tx_start_all_queues(adapter->netdev); ++ if (unlikely(!adapter->is_ecat)) { ++ netif_tx_start_all_queues(adapter->netdev); ++ } + + /* start the watchdog. */ + hw->mac.get_link_status = true; +@@ -5015,8 +5085,10 @@ void igc_down(struct igc_adapter *adapte + /* set trans_start so we don't get spurious watchdogs during reset */ + netif_trans_update(netdev); + +- netif_carrier_off(netdev); +- netif_tx_stop_all_queues(netdev); ++ if (unlikely(!adapter->is_ecat)) { ++ netif_carrier_off(netdev); ++ netif_tx_stop_all_queues(netdev); ++ } + + if (pci_device_is_present(adapter->pdev)) { + /* disable transmits in the hardware */ +@@ -5032,10 +5104,12 @@ void igc_down(struct igc_adapter *adapte + + adapter->flags &= ~IGC_FLAG_NEED_LINK_UPDATE; + +- for (i = 0; i < adapter->num_q_vectors; i++) { +- if (adapter->q_vector[i]) { +- napi_synchronize(&adapter->q_vector[i]->napi); +- napi_disable(&adapter->q_vector[i]->napi); ++ if (unlikely(!adapter->is_ecat)) { ++ for (i = 0; i < adapter->num_q_vectors; i++) { ++ if (adapter->q_vector[i]) { ++ napi_synchronize(&adapter->q_vector[i]->napi); ++ napi_disable(&adapter->q_vector[i]->napi); ++ } + } + } + +@@ -5372,11 +5446,16 @@ static void igc_write_itr(struct igc_q_v + static irqreturn_t igc_msix_ring(int irq, void *data) + { + struct igc_q_vector *q_vector = data; ++ struct igc_adapter *adapter = q_vector->adapter; + + /* Write the ITR value calculated from the previous interrupt. */ + igc_write_itr(q_vector); + +- napi_schedule(&q_vector->napi); ++ if (likely(adapter->is_ecat)) { ++ igc_poll(&q_vector->napi, 64); ++ } else { ++ napi_schedule(&q_vector->napi); ++ } + + return IRQ_HANDLED; + } +@@ -5393,9 +5472,13 @@ static int igc_request_msix(struct igc_a + unsigned int num_q_vectors = adapter->num_q_vectors; + int i = 0, err = 0, vector = 0, free_vector = 0; + struct net_device *netdev = adapter->netdev; ++ unsigned long irq_flags = 0; ++ if (adapter->is_ecat) { ++ irq_flags = IRQF_NO_THREAD; ++ } + + err = request_irq(adapter->msix_entries[vector].vector, +- &igc_msix_other, 0, netdev->name, adapter); ++ &igc_msix_other, irq_flags, netdev->name, adapter); + if (err) + goto err_out; + +@@ -5425,7 +5508,7 @@ static int igc_request_msix(struct igc_a + sprintf(q_vector->name, "%s-unused", netdev->name); + + err = request_irq(adapter->msix_entries[vector].vector, +- igc_msix_ring, 0, q_vector->name, ++ igc_msix_ring, irq_flags, q_vector->name, + q_vector); + if (err) + goto err_free; +@@ -5526,6 +5609,24 @@ static void igc_watchdog_task(struct wor + + link = igc_has_link(adapter); + ++ if (likely(adapter->is_ecat)) { ++ if (adapter->ecat_dev) { ++ ethercat_device_set_link(adapter->ecat_dev, link); ++ } ++ ++ if (!test_bit(__IGC_DOWN, &adapter->state)) { ++ mod_timer(&adapter->watchdog_timer, round_jiffies(jiffies + HZ)); ++ } ++ ++ adapter->link_speed = SPEED_100; ++ ++ spin_lock(&adapter->stats64_lock); ++ igc_update_stats(adapter); ++ spin_unlock(&adapter->stats64_lock); ++ ++ return; ++ } ++ + if (adapter->flags & IGC_FLAG_NEED_LINK_UPDATE) { + if (time_after(jiffies, (adapter->link_check_timeout + HZ))) + adapter->flags &= ~IGC_FLAG_NEED_LINK_UPDATE; +@@ -5726,7 +5827,11 @@ static irqreturn_t igc_intr_msi(int irq, + if (icr & IGC_ICR_TS) + igc_tsync_interrupt(adapter); + +- napi_schedule(&q_vector->napi); ++ if (likely(adapter->is_ecat)) { ++ igc_poll(&q_vector->napi, 64); ++ } else { ++ napi_schedule(&q_vector->napi); ++ } + + return IRQ_HANDLED; + } +@@ -5772,13 +5877,21 @@ static irqreturn_t igc_intr(int irq, voi + if (icr & IGC_ICR_TS) + igc_tsync_interrupt(adapter); + +- napi_schedule(&q_vector->napi); ++ if (likely(adapter->is_ecat)) { ++ igc_poll(&q_vector->napi, 64); ++ } else { ++ napi_schedule(&q_vector->napi); ++ } + + return IRQ_HANDLED; + } + + static void igc_free_irq(struct igc_adapter *adapter) + { ++ if ((adapter->is_ecat) && (ethercat_polling != 0)) { ++ return; ++ } ++ + if (adapter->msix_entries) { + int vector = 0, i; + +@@ -5804,8 +5917,16 @@ static int igc_request_irq(struct igc_ad + struct net_device *netdev = adapter->netdev; + struct pci_dev *pdev = adapter->pdev; + int err = 0; ++ unsigned long irq_flags = 0; ++ if (adapter->is_ecat) { ++ irq_flags = IRQF_NO_THREAD; ++ } + + if (adapter->flags & IGC_FLAG_HAS_MSIX) { ++ if ((adapter->is_ecat) && (ethercat_polling != 0)) { ++ goto request_done; ++ } ++ + err = igc_request_msix(adapter); + if (!err) + goto request_done; +@@ -5824,8 +5945,12 @@ static int igc_request_irq(struct igc_ad + + igc_assign_vector(adapter->q_vector[0], 0); + ++ if ((adapter->is_ecat) && (ethercat_polling != 0)) { ++ goto request_done; ++ } ++ + if (adapter->flags & IGC_FLAG_HAS_MSI) { +- err = request_irq(pdev->irq, &igc_intr_msi, 0, ++ err = request_irq(pdev->irq, &igc_intr_msi, irq_flags, + netdev->name, adapter); + if (!err) + goto request_done; +@@ -5834,8 +5959,12 @@ static int igc_request_irq(struct igc_ad + igc_reset_interrupt_capability(adapter); + adapter->flags &= ~IGC_FLAG_HAS_MSI; + } ++ ++ if (!adapter->is_ecat) { ++ irq_flags = IRQF_SHARED; ++ } + +- err = request_irq(pdev->irq, &igc_intr, IRQF_SHARED, ++ err = request_irq(pdev->irq, &igc_intr, irq_flags, + netdev->name, adapter); + + if (err) +@@ -5876,7 +6005,9 @@ static int __igc_open(struct net_device + if (!resuming) + pm_runtime_get_sync(&pdev->dev); + +- netif_carrier_off(netdev); ++ if (!adapter->is_ecat) { ++ netif_carrier_off(netdev); ++ } + + /* allocate transmit descriptors */ + err = igc_setup_all_tx_resources(adapter); +@@ -5896,19 +6027,23 @@ static int __igc_open(struct net_device + if (err) + goto err_req_irq; + +- /* Notify the stack of the actual queue counts. */ +- err = netif_set_real_num_tx_queues(netdev, adapter->num_tx_queues); +- if (err) +- goto err_set_queues; ++ if (!adapter->is_ecat) { ++ /* Notify the stack of the actual queue counts. */ ++ err = netif_set_real_num_tx_queues(netdev, adapter->num_tx_queues); ++ if (err) ++ goto err_set_queues; + +- err = netif_set_real_num_rx_queues(netdev, adapter->num_rx_queues); +- if (err) +- goto err_set_queues; ++ err = netif_set_real_num_rx_queues(netdev, adapter->num_rx_queues); ++ if (err) ++ goto err_set_queues; ++ } + + clear_bit(__IGC_DOWN, &adapter->state); + +- for (i = 0; i < adapter->num_q_vectors; i++) +- napi_enable(&adapter->q_vector[i]->napi); ++ if (unlikely(!adapter->is_ecat)) { ++ for (i = 0; i < adapter->num_q_vectors; i++) ++ napi_enable(&adapter->q_vector[i]->napi); ++ } + + /* Clear any pending interrupts. */ + rd32(IGC_ICR); +@@ -5917,7 +6052,9 @@ static int __igc_open(struct net_device + if (!resuming) + pm_runtime_put(&pdev->dev); + +- netif_tx_start_all_queues(netdev); ++ if (!adapter->is_ecat) { ++ netif_tx_start_all_queues(netdev); ++ } + + /* start the watchdog. */ + hw->mac.get_link_status = true; +@@ -5977,6 +6114,9 @@ static int __igc_close(struct net_device + igc_free_all_tx_resources(adapter); + igc_free_all_rx_resources(adapter); + ++ if (adapter->is_ecat) ++ igc_reset(adapter); ++ + if (!suspending) + pm_runtime_put_sync(&pdev->dev); + +@@ -5985,7 +6125,9 @@ static int __igc_close(struct net_device + + int igc_close(struct net_device *netdev) + { +- if (netif_device_present(netdev) || netdev->dismantle) ++ struct igc_adapter *adapter = netdev_priv(netdev); ++ ++ if (adapter->is_ecat || netif_device_present(netdev) || netdev->dismantle) + return __igc_close(netdev, false); + return 0; + } +@@ -6003,6 +6145,79 @@ static int igc_ioctl(struct net_device * + return igc_ptp_get_ts_config(netdev, ifr); + case SIOCSHWTSTAMP: + return igc_ptp_set_ts_config(netdev, ifr); ++ case ETHERCAT_DEVICE_NET_DEVICE_DO_POLL: { ++ struct igc_adapter *adapter = netdev_priv(netdev); ++ struct igc_q_vector *q_vector = adapter->q_vector[0]; ++ int budget = 64; ++ bool clean_complete = true; ++ ++ if (!adapter->is_ecat) { ++ return -EOPNOTSUPP; ++ } ++ ++ if (q_vector->tx.ring) { ++ clean_complete = igc_clean_tx_irq(q_vector, budget); ++ } ++ ++ if (q_vector->rx.ring) { ++ int cleaned = igc_clean_rx_irq(q_vector, budget); ++ ++ if (cleaned >= budget) ++ clean_complete = false; ++ } ++ if (!clean_complete) ++ return 1; ++ ++ return 0; ++ } ++ case ETHERCAT_DEVICE_NET_DEVICE_SET_POLLING: { ++ int do_reopen = ethercat_polling != 1; ++ struct igc_adapter *adapter = netdev_priv(netdev); ++ if (!adapter->is_ecat) { ++ return -EOPNOTSUPP; ++ } ++ ++ if (do_reopen) { ++ igc_close(netdev); ++ } ++ ++ ethercat_polling = 1; ++ ++ if (do_reopen) { ++ igc_open(netdev); ++ } ++ return 1; ++ } ++ case ETHERCAT_DEVICE_NET_DEVICE_RESET_POLLING: { ++ int do_reopen = ethercat_polling != 0; ++ struct igc_adapter *adapter = netdev_priv(netdev); ++ if (!adapter->is_ecat) { ++ return -EOPNOTSUPP; ++ } ++ ++ if (do_reopen) { ++ igc_close(netdev); ++ } ++ ++ ethercat_polling = 0; ++ ++ if (do_reopen) { ++ igc_open(netdev); ++ } ++ return 1; ++ } ++ case ETHERCAT_DEVICE_NET_DEVICE_GET_POLLING: { ++ struct igc_adapter *adapter = netdev_priv(netdev); ++ if (!adapter->is_ecat) { ++ return -EOPNOTSUPP; ++ } ++ ++ if (ethercat_polling == 0) { ++ return 0; ++ } ++ ++ return 1; ++ } + default: + return -EOPNOTSUPP; + } +@@ -6472,6 +6687,35 @@ u32 igc_rd32(struct igc_hw *hw, u32 reg) + return value; + } + ++static int parse_macaddr(const char *macstr, char *dev_addr) ++{ ++ int i, h, l; ++ ++ for (i = 0; i < 6; i++) { ++ h = hex_to_bin(*macstr); ++ if (h == -1) ++ goto err; ++ macstr++; ++ ++ l = hex_to_bin(*macstr); ++ if (l == -1) ++ goto err; ++ macstr++; ++ ++ if (i != 5) { ++ if (*macstr != ':') ++ goto err; ++ macstr++; ++ } ++ dev_addr[i] = (h << 4) + l; ++ } ++ if (is_valid_ether_addr(dev_addr)) ++ return 0; ++ ++err: ++ return -EINVAL; ++} ++ + /** + * igc_probe - Device Initialization Routine + * @pdev: PCI device information struct +@@ -6491,6 +6735,7 @@ static int igc_probe(struct pci_dev *pde + struct igc_hw *hw; + const struct igc_info *ei = igc_info_tbl[ent->driver_data]; + int err; ++ int cnt = 0; + + err = pci_enable_device_mem(pdev); + if (err) +@@ -6528,6 +6773,8 @@ static int igc_probe(struct pci_dev *pde + adapter = netdev_priv(netdev); + adapter->netdev = netdev; + adapter->pdev = pdev; ++ adapter->is_ecat = false; ++ adapter->ecat_dev = NULL; + hw = &adapter->hw; + hw->back = adapter; + adapter->port_num = hw->bus.func; +@@ -6678,13 +6925,53 @@ static int igc_probe(struct pci_dev *pde + */ + igc_get_hw_control(adapter); + +- strncpy(netdev->name, "eth%d", IFNAMSIZ); +- err = register_netdev(netdev); +- if (err) +- goto err_register; ++ /* check if we should use this one as EtherCAT device ++ */ ++ if (ethercat_mac_addr_count > 0) { ++ for (cnt = 0; cnt < ethercat_mac_addr_count; ++cnt) { ++ char ethercat_dev_addr[6]; ++ parse_macaddr(ethercat_mac_addr[cnt], ethercat_dev_addr); ++ ++ if (ether_addr_equal(netdev->dev_addr, ethercat_dev_addr)) { ++ int i = 0; ++ ++ dev_info(&pdev->dev, "attaching as EtherCAT interface\n"); ++ adapter->is_ecat = true; ++ adapter->ecat_dev = ethercat_device_create(netdev); ++ ++ /* set low ITR values */ ++ adapter->rx_itr_setting = 0; ++ adapter->tx_itr_setting = 0; ++ ++ /* If ITR is disabled, disable DMAC */ ++ if (adapter->flags & IGC_FLAG_DMAC) ++ adapter->flags &= ~IGC_FLAG_DMAC; ++ ++ for (i = 0; i < adapter->num_q_vectors; i++) { ++ struct igc_q_vector *q_vector = adapter->q_vector[i]; ++ q_vector->tx.work_limit = adapter->tx_work_limit; ++ if (q_vector->rx.ring) ++ q_vector->itr_val = adapter->rx_itr_setting; ++ else ++ q_vector->itr_val = adapter->tx_itr_setting; + +- /* carrier off reporting is important to ethtool even BEFORE open */ +- netif_carrier_off(netdev); ++ /* configure q_vector to set itr on next interrupt */ ++ q_vector->set_itr = 1; ++ } ++ break; ++ } ++ } ++ } ++ ++ if (!adapter->is_ecat) { ++ strncpy(netdev->name, "eth%d", IFNAMSIZ); ++ err = register_netdev(netdev); ++ if (err) ++ goto err_register; ++ ++ /* carrier off reporting is important to ethtool even BEFORE open */ ++ netif_carrier_off(netdev); ++ } + + /* Check if Media Autosense is enabled */ + adapter->ei = *ei; +@@ -6736,6 +7023,10 @@ static void igc_remove(struct pci_dev *p + struct net_device *netdev = pci_get_drvdata(pdev); + struct igc_adapter *adapter = netdev_priv(netdev); + ++ if (adapter->ecat_dev) { ++ ethercat_device_destroy(adapter->ecat_dev); ++ } ++ + pm_runtime_get_noresume(&pdev->dev); + + igc_flush_nfc_rules(adapter); +@@ -6757,7 +7048,10 @@ static void igc_remove(struct pci_dev *p + * would have already happened in close and is redundant. + */ + igc_release_hw_control(adapter); +- unregister_netdev(netdev); ++ ++ if (!adapter->is_ecat) { ++ unregister_netdev(netdev); ++ } + + igc_clear_interrupt_scheme(adapter); + pci_iounmap(pdev, adapter->io_addr); +@@ -6783,7 +7077,7 @@ static int __igc_shutdown(struct pci_dev + rtnl_lock(); + netif_device_detach(netdev); + +- if (netif_running(netdev)) ++ if (adapter->is_ecat || netif_running(netdev)) + __igc_close(netdev, true); + + igc_ptp_suspend(adapter); +Only in 5.14.21/intel/igc/: igc_main.o +Only in 5.14.21/intel/igc/: .igc_main.o.cmd +Only in 5.14.21/intel/igc/: igc_nvm.o +Only in 5.14.21/intel/igc/: .igc_nvm.o.cmd +Only in 5.14.21/intel/igc/: igc_phy.o +Only in 5.14.21/intel/igc/: .igc_phy.o.cmd +Only in 5.14.21/intel/igc/: igc_ptp.o +Only in 5.14.21/intel/igc/: .igc_ptp.o.cmd +Only in 5.14.21/intel/igc/: igc_tsn.o +Only in 5.14.21/intel/igc/: .igc_tsn.o.cmd +Only in 5.14.21/intel/igc/: igc_xdp.o +Only in 5.14.21/intel/igc/: .igc_xdp.o.cmd +diff -rup /usr/src/linux-rt/drivers/net/ethernet/intel/igc/Makefile 5.14.21/intel/igc/Makefile +--- /usr/src/linux-rt/drivers/net/ethernet/intel/igc/Makefile 2024-11-06 14:07:03.000000000 +0100 ++++ 5.14.21/intel/igc/Makefile 2024-11-26 15:38:37.112784532 +0100 +@@ -5,7 +5,10 @@ + # Intel(R) I225-LM/I225-V 2.5G Ethernet Controller + # + +-obj-$(CONFIG_IGC) += igc.o ++obj-m += igc-ethercat.o + +-igc-objs := igc_main.o igc_mac.o igc_i225.o igc_base.o igc_nvm.o igc_phy.o \ ++igc-ethercat-objs := igc_main.o igc_mac.o igc_i225.o igc_base.o igc_nvm.o igc_phy.o \ + igc_diag.o igc_ethtool.o igc_ptp.o igc_dump.o igc_tsn.o igc_xdp.o ++ ++EXTRA_CFLAGS=-I$(src)/../../../../../../ ++KBUILD_EXTRA_SYMBOLS=$(src)/../../../../../../Module.symvers +Only in 5.14.21/intel/igc/: modules.order +Only in 5.14.21/intel/igc/: .modules.order.cmd diff --git a/linux/drivers/opensuse/15.5/realtek_opensuse_15.5_5.14.21.patch b/linux/drivers/opensuse/15.5/realtek_opensuse_15.5_5.14.21.patch index f367aeb..b11d1db 100644 --- a/linux/drivers/opensuse/15.5/realtek_opensuse_15.5_5.14.21.patch +++ b/linux/drivers/opensuse/15.5/realtek_opensuse_15.5_5.14.21.patch @@ -1,4 +1,31 @@ -diff -ru /usr/src/linux-rt/drivers/net/ethernet/realtek/Makefile 5.14.21/realtek/Makefile +Only in 5.14.21/realtek/: 8139cp.ko +Only in 5.14.21/realtek/: .8139cp.ko.cmd +Only in 5.14.21/realtek/: 8139cp.mod +Only in 5.14.21/realtek/: 8139cp.mod.c +Only in 5.14.21/realtek/: .8139cp.mod.cmd +Only in 5.14.21/realtek/: 8139cp.mod.o +Only in 5.14.21/realtek/: .8139cp.mod.o.cmd +Only in 5.14.21/realtek/: 8139cp.o +Only in 5.14.21/realtek/: .8139cp.o.cmd +Only in 5.14.21/realtek/: 8139too.ko +Only in 5.14.21/realtek/: .8139too.ko.cmd +Only in 5.14.21/realtek/: 8139too.mod +Only in 5.14.21/realtek/: 8139too.mod.c +Only in 5.14.21/realtek/: .8139too.mod.cmd +Only in 5.14.21/realtek/: 8139too.mod.o +Only in 5.14.21/realtek/: .8139too.mod.o.cmd +Only in 5.14.21/realtek/: 8139too.o +Only in 5.14.21/realtek/: .8139too.o.cmd +Only in 5.14.21/realtek/: atp.ko +Only in 5.14.21/realtek/: .atp.ko.cmd +Only in 5.14.21/realtek/: atp.mod +Only in 5.14.21/realtek/: atp.mod.c +Only in 5.14.21/realtek/: .atp.mod.cmd +Only in 5.14.21/realtek/: atp.mod.o +Only in 5.14.21/realtek/: .atp.mod.o.cmd +Only in 5.14.21/realtek/: atp.o +Only in 5.14.21/realtek/: .atp.o.cmd +diff -rup /usr/src/linux-rt/drivers/net/ethernet/realtek/Makefile 5.14.21/realtek/Makefile --- /usr/src/linux-rt/drivers/net/ethernet/realtek/Makefile 2024-11-06 14:07:03.000000000 +0100 +++ 5.14.21/realtek/Makefile 2024-11-25 10:06:09.650350735 +0100 @@ -6,5 +6,8 @@ @@ -12,7 +39,11 @@ diff -ru /usr/src/linux-rt/drivers/net/ethernet/realtek/Makefile 5.14.21/realtek + +EXTRA_CFLAGS=-I$(src)/../../../../../ +KBUILD_EXTRA_SYMBOLS=$(src)/../../../../../Module.symvers -diff -ru /usr/src/linux-rt/drivers/net/ethernet/realtek/r8169.h 5.14.21/realtek/r8169.h +Only in 5.14.21/realtek/: modules.order +Only in 5.14.21/realtek/: .modules.order.cmd +Only in 5.14.21/realtek/: r8169_firmware.o +Only in 5.14.21/realtek/: .r8169_firmware.o.cmd +diff -rup /usr/src/linux-rt/drivers/net/ethernet/realtek/r8169.h 5.14.21/realtek/r8169.h --- /usr/src/linux-rt/drivers/net/ethernet/realtek/r8169.h 2024-11-06 14:07:03.000000000 +0100 +++ 5.14.21/realtek/r8169.h 2024-11-25 10:06:09.653350734 +0100 @@ -11,6 +11,8 @@ @@ -24,7 +55,16 @@ diff -ru /usr/src/linux-rt/drivers/net/ethernet/realtek/r8169.h 5.14.21/realtek/ enum mac_version { /* support for ancient RTL_GIGA_MAC_VER_01 has been removed */ RTL_GIGA_MAC_VER_02, -diff -ru /usr/src/linux-rt/drivers/net/ethernet/realtek/r8169_main.c 5.14.21/realtek/r8169_main.c +Only in 5.14.21/realtek/: r8169-libethercat.ko +Only in 5.14.21/realtek/: .r8169-libethercat.ko.cmd +Only in 5.14.21/realtek/: r8169-libethercat.mod +Only in 5.14.21/realtek/: r8169-libethercat.mod.c +Only in 5.14.21/realtek/: .r8169-libethercat.mod.cmd +Only in 5.14.21/realtek/: r8169-libethercat.mod.o +Only in 5.14.21/realtek/: .r8169-libethercat.mod.o.cmd +Only in 5.14.21/realtek/: r8169-libethercat.o +Only in 5.14.21/realtek/: .r8169-libethercat.o.cmd +diff -rup /usr/src/linux-rt/drivers/net/ethernet/realtek/r8169_main.c 5.14.21/realtek/r8169_main.c --- /usr/src/linux-rt/drivers/net/ethernet/realtek/r8169_main.c 2024-11-06 14:07:03.000000000 +0100 +++ 5.14.21/realtek/r8169_main.c 2024-11-25 10:27:14.661967250 +0100 @@ -34,6 +34,8 @@ @@ -36,7 +76,7 @@ diff -ru /usr/src/linux-rt/drivers/net/ethernet/realtek/r8169_main.c 5.14.21/rea #define FIRMWARE_8168D_1 "rtl_nic/rtl8168d-1.fw" #define FIRMWARE_8168D_2 "rtl_nic/rtl8168d-2.fw" #define FIRMWARE_8168E_1 "rtl_nic/rtl8168e-1.fw" -@@ -575,33 +577,6 @@ +@@ -575,33 +577,6 @@ struct rtl8169_counters { __le32 rx_multicast; __le16 tx_aborted; __le16 tx_underun; @@ -70,7 +110,7 @@ diff -ru /usr/src/linux-rt/drivers/net/ethernet/realtek/r8169_main.c 5.14.21/rea }; struct rtl8169_tc_offsets { -@@ -644,6 +619,7 @@ +@@ -644,6 +619,7 @@ struct rtl8169_private { u16 cp_cmd; u32 irq_mask; struct clk *clk; @@ -78,7 +118,7 @@ diff -ru /usr/src/linux-rt/drivers/net/ethernet/realtek/r8169_main.c 5.14.21/rea struct { DECLARE_BITMAP(flags, RTL_FLAG_MAX); -@@ -662,8 +638,21 @@ +@@ -662,8 +638,21 @@ struct rtl8169_private { struct rtl_fw *rtl_fw; u32 ocp_base; @@ -100,7 +140,7 @@ diff -ru /usr/src/linux-rt/drivers/net/ethernet/realtek/r8169_main.c 5.14.21/rea typedef void (*rtl_generic_fct)(struct rtl8169_private *tp); MODULE_AUTHOR("Realtek and the Linux r8169 crew "); -@@ -3963,7 +3952,7 @@ +@@ -3963,7 +3952,7 @@ static void rtl8169_tx_clear_range(struc struct sk_buff *skb = tx_skb->skb; rtl8169_unmap_tx_skb(tp, entry); @@ -109,7 +149,7 @@ diff -ru /usr/src/linux-rt/drivers/net/ethernet/realtek/r8169_main.c 5.14.21/rea dev_consume_skb_any(skb); } } -@@ -3972,12 +3961,15 @@ +@@ -3972,12 +3961,15 @@ static void rtl8169_tx_clear_range(struc static void rtl8169_tx_clear(struct rtl8169_private *tp) { rtl8169_tx_clear_range(tp, tp->dirty_tx, NUM_TX_DESC); @@ -127,7 +167,7 @@ diff -ru /usr/src/linux-rt/drivers/net/ethernet/realtek/r8169_main.c 5.14.21/rea /* Give a racing hard_start_xmit a few cycles to complete. */ synchronize_net(); -@@ -4020,14 +4012,18 @@ +@@ -4020,14 +4012,18 @@ static void rtl_reset_work(struct rtl816 { int i; @@ -148,7 +188,7 @@ diff -ru /usr/src/linux-rt/drivers/net/ethernet/realtek/r8169_main.c 5.14.21/rea rtl_hw_start(tp); } -@@ -4035,7 +4031,9 @@ +@@ -4035,7 +4031,9 @@ static void rtl8169_tx_timeout(struct ne { struct rtl8169_private *tp = netdev_priv(dev); @@ -159,7 +199,7 @@ diff -ru /usr/src/linux-rt/drivers/net/ethernet/realtek/r8169_main.c 5.14.21/rea } static int rtl8169_tx_map(struct rtl8169_private *tp, const u32 *opts, u32 len, -@@ -4278,6 +4276,10 @@ +@@ -4278,6 +4276,10 @@ static netdev_tx_t rtl8169_start_xmit(st bool stop_queue, door_bell; unsigned int frags; u32 opts[2]; @@ -170,7 +210,7 @@ diff -ru /usr/src/linux-rt/drivers/net/ethernet/realtek/r8169_main.c 5.14.21/rea if (unlikely(!rtl_tx_slots_avail(tp))) { if (net_ratelimit()) -@@ -4315,14 +4317,21 @@ +@@ -4315,14 +4317,21 @@ static netdev_tx_t rtl8169_start_xmit(st /* Force memory writes to complete before releasing descriptor */ dma_wmb(); @@ -194,7 +234,7 @@ diff -ru /usr/src/linux-rt/drivers/net/ethernet/realtek/r8169_main.c 5.14.21/rea stop_queue = !rtl_tx_slots_avail(tp); if (unlikely(stop_queue)) { -@@ -4330,7 +4339,9 @@ +@@ -4330,7 +4339,9 @@ static netdev_tx_t rtl8169_start_xmit(st * not miss a ring update when it notices a stopped queue. */ smp_wmb(); @@ -205,7 +245,7 @@ diff -ru /usr/src/linux-rt/drivers/net/ethernet/realtek/r8169_main.c 5.14.21/rea /* Sync with rtl_tx: * - publish queue status and cur_tx ring index (write barrier) * - refresh dirty_tx ring index (read barrier). -@@ -4339,7 +4350,7 @@ +@@ -4339,7 +4350,7 @@ static netdev_tx_t rtl8169_start_xmit(st * can't. */ smp_mb__after_atomic(); @@ -214,7 +254,7 @@ diff -ru /usr/src/linux-rt/drivers/net/ethernet/realtek/r8169_main.c 5.14.21/rea netif_start_queue(dev); door_bell = true; } -@@ -4347,18 +4358,27 @@ +@@ -4347,18 +4358,27 @@ static netdev_tx_t rtl8169_start_xmit(st if (door_bell) rtl8169_doorbell(tp); @@ -244,7 +284,7 @@ diff -ru /usr/src/linux-rt/drivers/net/ethernet/realtek/r8169_main.c 5.14.21/rea return NETDEV_TX_BUSY; } -@@ -4446,6 +4466,33 @@ +@@ -4446,6 +4466,33 @@ static void rtl_tx(struct net_device *de unsigned int dirty_tx, bytes_compl = 0, pkts_compl = 0; struct sk_buff *skb; @@ -278,7 +318,7 @@ diff -ru /usr/src/linux-rt/drivers/net/ethernet/realtek/r8169_main.c 5.14.21/rea dirty_tx = tp->dirty_tx; while (READ_ONCE(tp->cur_tx) != dirty_tx) { -@@ -4462,13 +4509,20 @@ +@@ -4462,13 +4509,20 @@ static void rtl_tx(struct net_device *de if (skb) { pkts_compl++; bytes_compl += skb->len; @@ -301,7 +341,7 @@ diff -ru /usr/src/linux-rt/drivers/net/ethernet/realtek/r8169_main.c 5.14.21/rea dev_sw_netstats_tx_add(dev, pkts_compl, bytes_compl); /* Sync with rtl8169_start_xmit: -@@ -4479,8 +4533,11 @@ +@@ -4479,8 +4533,11 @@ static void rtl_tx(struct net_device *de * ring status. */ smp_store_mb(tp->dirty_tx, dirty_tx); @@ -315,7 +355,7 @@ diff -ru /usr/src/linux-rt/drivers/net/ethernet/realtek/r8169_main.c 5.14.21/rea /* * 8168 hack: TxPoll requests are lost when the Tx packets are * too close. Let's kick an extra TxPoll request when a burst -@@ -4521,6 +4578,9 @@ +@@ -4521,6 +4578,9 @@ static int rtl_rx(struct net_device *dev const void *rx_buf; dma_addr_t addr; u32 status; @@ -325,7 +365,7 @@ diff -ru /usr/src/linux-rt/drivers/net/ethernet/realtek/r8169_main.c 5.14.21/rea status = le32_to_cpu(desc->opts1); if (status & DescOwn) -@@ -4561,10 +4621,13 @@ +@@ -4561,10 +4621,13 @@ static int rtl_rx(struct net_device *dev goto release_descriptor; } @@ -343,7 +383,7 @@ diff -ru /usr/src/linux-rt/drivers/net/ethernet/realtek/r8169_main.c 5.14.21/rea } addr = le64_to_cpu(desc->addr); -@@ -4572,6 +4635,12 @@ +@@ -4572,6 +4635,12 @@ static int rtl_rx(struct net_device *dev dma_sync_single_for_cpu(d, addr, pkt_size, DMA_FROM_DEVICE); prefetch(rx_buf); @@ -356,7 +396,7 @@ diff -ru /usr/src/linux-rt/drivers/net/ethernet/realtek/r8169_main.c 5.14.21/rea skb_copy_to_linear_data(skb, rx_buf, pkt_size); skb->tail += pkt_size; skb->len = pkt_size; -@@ -4595,15 +4664,19 @@ +@@ -4595,15 +4664,19 @@ release_descriptor: return count; } @@ -379,7 +419,7 @@ diff -ru /usr/src/linux-rt/drivers/net/ethernet/realtek/r8169_main.c 5.14.21/rea rtl8169_pcierr_interrupt(tp->dev); goto out; } -@@ -4611,16 +4684,22 @@ +@@ -4611,16 +4684,22 @@ static irqreturn_t rtl8169_interrupt(int if (status & LinkChg) phy_mac_interrupt(tp->phydev); @@ -410,7 +450,7 @@ diff -ru /usr/src/linux-rt/drivers/net/ethernet/realtek/r8169_main.c 5.14.21/rea out: rtl_ack_events(tp, status); -@@ -4634,29 +4713,37 @@ +@@ -4634,29 +4713,37 @@ static void rtl_task(struct work_struct rtnl_lock(); @@ -453,7 +493,7 @@ diff -ru /usr/src/linux-rt/drivers/net/ethernet/realtek/r8169_main.c 5.14.21/rea rtl_irq_enable(tp); return work_done; -@@ -4666,7 +4753,7 @@ +@@ -4666,7 +4753,7 @@ static void r8169_phylink_handler(struct { struct rtl8169_private *tp = netdev_priv(ndev); @@ -462,7 +502,7 @@ diff -ru /usr/src/linux-rt/drivers/net/ethernet/realtek/r8169_main.c 5.14.21/rea rtl_link_chg_patch(tp); pm_request_resume(&tp->pci_dev->dev); } else { -@@ -4691,7 +4778,7 @@ +@@ -4691,7 +4778,7 @@ static int r8169_phy_connect(struct rtl8 if (ret) return ret; @@ -471,7 +511,7 @@ diff -ru /usr/src/linux-rt/drivers/net/ethernet/realtek/r8169_main.c 5.14.21/rea phy_set_max_speed(phydev, SPEED_100); phy_attached_info(phydev); -@@ -4722,7 +4809,9 @@ +@@ -4722,7 +4809,9 @@ static void rtl8169_up(struct rtl8169_pr phy_init_hw(tp->phydev); phy_resume(tp->phydev); rtl8169_init_phy(tp); @@ -482,7 +522,7 @@ diff -ru /usr/src/linux-rt/drivers/net/ethernet/realtek/r8169_main.c 5.14.21/rea set_bit(RTL_FLAG_TASK_ENABLED, tp->wk.flags); rtl_reset_work(tp); -@@ -4736,7 +4825,9 @@ +@@ -4736,7 +4825,9 @@ static int rtl8169_close(struct net_devi pm_runtime_get_sync(&pdev->dev); @@ -493,7 +533,7 @@ diff -ru /usr/src/linux-rt/drivers/net/ethernet/realtek/r8169_main.c 5.14.21/rea rtl8169_down(tp); rtl8169_rx_clear(tp); -@@ -4776,6 +4867,10 @@ +@@ -4776,6 +4867,10 @@ static int rtl_open(struct net_device *d pm_runtime_get_sync(&pdev->dev); @@ -504,7 +544,7 @@ diff -ru /usr/src/linux-rt/drivers/net/ethernet/realtek/r8169_main.c 5.14.21/rea /* * Rx and Tx descriptors needs 256 bytes alignment. * dma_alloc_coherent provides more. -@@ -4796,11 +4891,13 @@ +@@ -4796,11 +4891,13 @@ static int rtl_open(struct net_device *d rtl_request_firmware(tp); @@ -523,7 +563,7 @@ diff -ru /usr/src/linux-rt/drivers/net/ethernet/realtek/r8169_main.c 5.14.21/rea retval = r8169_phy_connect(tp); if (retval) -@@ -4808,7 +4905,10 @@ +@@ -4808,7 +4905,10 @@ static int rtl_open(struct net_device *d rtl8169_up(tp); rtl8169_init_counter_offsets(tp); @@ -535,7 +575,7 @@ diff -ru /usr/src/linux-rt/drivers/net/ethernet/realtek/r8169_main.c 5.14.21/rea out: pm_runtime_put_sync(&pdev->dev); -@@ -4867,10 +4967,14 @@ +@@ -4867,10 +4967,14 @@ rtl8169_get_stats64(struct net_device *d static void rtl8169_net_suspend(struct rtl8169_private *tp) { @@ -553,7 +593,7 @@ diff -ru /usr/src/linux-rt/drivers/net/ethernet/realtek/r8169_main.c 5.14.21/rea } #ifdef CONFIG_PM -@@ -4879,6 +4983,10 @@ +@@ -4879,6 +4983,10 @@ static int rtl8169_runtime_resume(struct { struct rtl8169_private *tp = dev_get_drvdata(dev); @@ -564,7 +604,7 @@ diff -ru /usr/src/linux-rt/drivers/net/ethernet/realtek/r8169_main.c 5.14.21/rea rtl_rar_set(tp, tp->dev->dev_addr); __rtl8169_set_wol(tp, tp->saved_wolopts); -@@ -4893,6 +5001,10 @@ +@@ -4893,6 +5001,10 @@ static int rtl8169_runtime_resume(struct static int __maybe_unused rtl8169_suspend(struct device *device) { struct rtl8169_private *tp = dev_get_drvdata(device); @@ -575,7 +615,7 @@ diff -ru /usr/src/linux-rt/drivers/net/ethernet/realtek/r8169_main.c 5.14.21/rea rtnl_lock(); rtl8169_net_suspend(tp); -@@ -4906,6 +5018,10 @@ +@@ -4906,6 +5018,10 @@ static int __maybe_unused rtl8169_suspen static int __maybe_unused rtl8169_resume(struct device *device) { struct rtl8169_private *tp = dev_get_drvdata(device); @@ -586,7 +626,7 @@ diff -ru /usr/src/linux-rt/drivers/net/ethernet/realtek/r8169_main.c 5.14.21/rea if (!device_may_wakeup(tp_to_dev(tp))) clk_prepare_enable(tp->clk); -@@ -4920,6 +5036,10 @@ +@@ -4920,6 +5036,10 @@ static int __maybe_unused rtl8169_resume static int rtl8169_runtime_suspend(struct device *device) { struct rtl8169_private *tp = dev_get_drvdata(device); @@ -597,7 +637,7 @@ diff -ru /usr/src/linux-rt/drivers/net/ethernet/realtek/r8169_main.c 5.14.21/rea if (!tp->TxDescArray) { netif_device_detach(tp->dev); -@@ -4937,8 +5057,12 @@ +@@ -4937,8 +5057,12 @@ static int rtl8169_runtime_suspend(struc static int rtl8169_runtime_idle(struct device *device) { struct rtl8169_private *tp = dev_get_drvdata(device); @@ -611,7 +651,7 @@ diff -ru /usr/src/linux-rt/drivers/net/ethernet/realtek/r8169_main.c 5.14.21/rea pm_schedule_suspend(device, 10000); return -EBUSY; -@@ -4992,11 +5116,17 @@ +@@ -4992,11 +5116,17 @@ static void rtl_shutdown(struct pci_dev static void rtl_remove_one(struct pci_dev *pdev) { struct rtl8169_private *tp = pci_get_drvdata(pdev); @@ -630,7 +670,7 @@ diff -ru /usr/src/linux-rt/drivers/net/ethernet/realtek/r8169_main.c 5.14.21/rea if (tp->dash_type != RTL_DASH_NONE) rtl8168_driver_stop(tp); -@@ -5007,6 +5137,80 @@ +@@ -5007,6 +5137,80 @@ static void rtl_remove_one(struct pci_de rtl_rar_set(tp, tp->dev->perm_addr); } @@ -711,7 +751,7 @@ diff -ru /usr/src/linux-rt/drivers/net/ethernet/realtek/r8169_main.c 5.14.21/rea static const struct net_device_ops rtl_netdev_ops = { .ndo_open = rtl_open, .ndo_stop = rtl8169_close, -@@ -5020,6 +5224,7 @@ +@@ -5020,6 +5224,7 @@ static const struct net_device_ops rtl_n .ndo_set_features = rtl8169_set_features, .ndo_set_mac_address = rtl_set_mac_address, .ndo_eth_ioctl = phy_do_ioctl_running, @@ -719,7 +759,7 @@ diff -ru /usr/src/linux-rt/drivers/net/ethernet/realtek/r8169_main.c 5.14.21/rea .ndo_set_rx_mode = rtl_set_rx_mode, #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = rtl8169_netpoll, -@@ -5285,6 +5490,35 @@ +@@ -5285,6 +5490,35 @@ done: rtl_rar_set(tp, mac_addr); } @@ -755,7 +795,7 @@ diff -ru /usr/src/linux-rt/drivers/net/ethernet/realtek/r8169_main.c 5.14.21/rea static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { struct rtl8169_private *tp; -@@ -5292,6 +5526,7 @@ +@@ -5292,6 +5526,7 @@ static int rtl_init_one(struct pci_dev * enum mac_version chipset; struct net_device *dev; u16 xid; @@ -763,7 +803,7 @@ diff -ru /usr/src/linux-rt/drivers/net/ethernet/realtek/r8169_main.c 5.14.21/rea dev = devm_alloc_etherdev(&pdev->dev, sizeof (*tp)); if (!dev) -@@ -5393,7 +5628,9 @@ +@@ -5393,7 +5628,9 @@ static int rtl_init_one(struct pci_dev * dev->ethtool_ops = &rtl8169_ethtool_ops; @@ -774,7 +814,7 @@ diff -ru /usr/src/linux-rt/drivers/net/ethernet/realtek/r8169_main.c 5.14.21/rea dev->hw_features = NETIF_F_IP_CSUM | NETIF_F_RXCSUM | NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX; -@@ -5456,9 +5693,43 @@ +@@ -5456,9 +5693,43 @@ static int rtl_init_one(struct pci_dev * if (rc) return rc; @@ -821,3 +861,7 @@ diff -ru /usr/src/linux-rt/drivers/net/ethernet/realtek/r8169_main.c 5.14.21/rea netdev_info(dev, "%s, %pM, XID %03x, IRQ %d\n", rtl_chip_infos[chipset].name, dev->dev_addr, xid, +Only in 5.14.21/realtek/: r8169_main.o +Only in 5.14.21/realtek/: .r8169_main.o.cmd +Only in 5.14.21/realtek/: r8169_phy_config.o +Only in 5.14.21/realtek/: .r8169_phy_config.o.cmd