From 34c56eae7d935e723502c041dbe0c8ca50cf3326 Mon Sep 17 00:00:00 2001 From: Bjarne von Horn Date: Fri, 2 Feb 2024 13:24:20 +0100 Subject: [PATCH] Fix igc link detection with xenomai --- devices/igc/igc-6.4-ethercat.h | 2 ++ devices/igc/igc-6.6-ethercat.h | 2 ++ devices/igc/igc_main-6.4-ethercat.c | 25 +++++++++++++++++++------ devices/igc/igc_main-6.6-ethercat.c | 25 +++++++++++++++++++------ 4 files changed, 42 insertions(+), 12 deletions(-) diff --git a/devices/igc/igc-6.4-ethercat.h b/devices/igc/igc-6.4-ethercat.h index 52ad0a95..5f01efdf 100644 --- a/devices/igc/igc-6.4-ethercat.h +++ b/devices/igc/igc-6.4-ethercat.h @@ -5,6 +5,7 @@ #define _IGC_H_ #include "../ecdev.h" +#include #include #include #include @@ -268,6 +269,7 @@ struct igc_adapter { /* EtherCAT device variables */ ec_device_t *ecdev; unsigned long ec_watchdog_jiffies; + struct irq_work ec_watchdog_kicker; }; void igc_up(struct igc_adapter *adapter); diff --git a/devices/igc/igc-6.6-ethercat.h b/devices/igc/igc-6.6-ethercat.h index 18efb14e..dc1b5813 100644 --- a/devices/igc/igc-6.6-ethercat.h +++ b/devices/igc/igc-6.6-ethercat.h @@ -5,6 +5,7 @@ #define _IGC_H_ #include "../ecdev.h" +#include #include #include #include @@ -283,6 +284,7 @@ struct igc_adapter { /* EtherCAT device variables */ ec_device_t *ecdev; unsigned long ec_watchdog_jiffies; + struct irq_work ec_watchdog_kicker; }; void igc_up(struct igc_adapter *adapter); diff --git a/devices/igc/igc_main-6.4-ethercat.c b/devices/igc/igc_main-6.4-ethercat.c index 7c6b5dc8..ef1e34fe 100644 --- a/devices/igc/igc_main-6.4-ethercat.c +++ b/devices/igc/igc_main-6.4-ethercat.c @@ -5576,8 +5576,16 @@ static void igc_watchdog_task(struct work_struct *work) u32 link; int i; + if (adapter->ecdev) + hw->mac.get_link_status = true; + link = igc_has_link(adapter); + if (adapter->ecdev) { + ecdev_set_link(adapter->ecdev, link); + 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; @@ -6537,6 +6545,14 @@ static const struct net_device_ops igc_netdev_ops = { .ndo_xsk_wakeup = igc_xsk_wakeup, }; +static void ec_kick_watchdog(struct irq_work *work) +{ + struct igc_adapter *adapter = + container_of(work, struct igc_adapter, ec_watchdog_kicker); + + schedule_work(&adapter->watchdog_task); +} + /** * ec_poll - EtherCAT poll routine * @netdev: net device structure @@ -6551,13 +6567,8 @@ void ec_poll(struct net_device *netdev) int budget = 64; if (jiffies - adapter->ec_watchdog_jiffies >= 2 * HZ) { - struct igc_hw *hw = &adapter->hw; - - bool link; - hw->mac.get_link_status = true; - link = igc_has_link(adapter); - ecdev_set_link(adapter->ecdev, link); adapter->ec_watchdog_jiffies = jiffies; + irq_work_queue(&adapter->ec_watchdog_kicker); } for (i = 0; i < adapter->num_q_vectors; i++) { @@ -6910,6 +6921,7 @@ static int igc_probe(struct pci_dev *pdev, adapter->ecdev = ecdev_offer(netdev, ec_poll, THIS_MODULE); if (adapter->ecdev) { + init_irq_work(&adapter->ec_watchdog_kicker, ec_kick_watchdog); err = ecdev_open(adapter->ecdev); if (err) { ecdev_withdraw(adapter->ecdev); @@ -6976,6 +6988,7 @@ static void igc_remove(struct pci_dev *pdev) if (adapter->ecdev) { ecdev_close(adapter->ecdev); + irq_work_sync(&adapter->irq_work); ecdev_withdraw(adapter->ecdev); } diff --git a/devices/igc/igc_main-6.6-ethercat.c b/devices/igc/igc_main-6.6-ethercat.c index 7faa0df1..81e911ad 100644 --- a/devices/igc/igc_main-6.6-ethercat.c +++ b/devices/igc/igc_main-6.6-ethercat.c @@ -5641,8 +5641,16 @@ static void igc_watchdog_task(struct work_struct *work) u32 link; int i; + if (adapter->ecdev) + hw->mac.get_link_status = true; + link = igc_has_link(adapter); + if (adapter->ecdev) { + ecdev_set_link(adapter->ecdev, link); + 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; @@ -6657,6 +6665,14 @@ static const struct net_device_ops igc_netdev_ops = { .ndo_xsk_wakeup = igc_xsk_wakeup, }; +static void ec_kick_watchdog(struct irq_work *work) +{ + struct igc_adapter *adapter = + container_of(work, struct igc_adapter, ec_watchdog_kicker); + + schedule_work(&adapter->watchdog_task); +} + /** * ec_poll - EtherCAT poll routine * @netdev: net device structure @@ -6671,13 +6687,8 @@ void ec_poll(struct net_device *netdev) int budget = 64; if (jiffies - adapter->ec_watchdog_jiffies >= 2 * HZ) { - struct igc_hw *hw = &adapter->hw; - - bool link; - hw->mac.get_link_status = true; - link = igc_has_link(adapter); - ecdev_set_link(adapter->ecdev, link); adapter->ec_watchdog_jiffies = jiffies; + irq_work_queue(&adapter->ec_watchdog_kicker); } for (i = 0; i < adapter->num_q_vectors; i++) { @@ -7050,6 +7061,7 @@ static int igc_probe(struct pci_dev *pdev, adapter->ecdev = ecdev_offer(netdev, ec_poll, THIS_MODULE); if (adapter->ecdev) { + init_irq_work(&adapter->ec_watchdog_kicker, ec_kick_watchdog); err = ecdev_open(adapter->ecdev); if (err) { ecdev_withdraw(adapter->ecdev); @@ -7116,6 +7128,7 @@ static void igc_remove(struct pci_dev *pdev) if (adapter->ecdev) { ecdev_close(adapter->ecdev); + irq_work_sync(&adapter->irq_work); ecdev_withdraw(adapter->ecdev); }