summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaolo Abeni <pabeni@redhat.com>2026-05-28 12:51:54 +0300
committerPaolo Abeni <pabeni@redhat.com>2026-05-28 12:51:54 +0300
commit0cf905cb9a12dbfb5d14896729b74508f83f73df (patch)
treefbaa8c827c778300568ba4b1394e32f247ba842e
parentfabcf8cad67b4e2aa51b4c3f79f26fd215b50c8c (diff)
parentf67aead16e85f7bae5b4c2546f8972e867cd0873 (diff)
downloadlinux-0cf905cb9a12dbfb5d14896729b74508f83f73df.tar.xz
Merge branch 'wangxun-improve-service-task-synchronization'
Jiawen Wu says: ==================== wangxun: improve service task synchronization This series improves synchronization between asynchronous service work, device teardown, and module event handling in the Wangxun drivers. ==================== Link: https://patch.msgid.link/20260525100543.27140-1-jiawenwu@trustnetic.com Signed-off-by: Paolo Abeni <pabeni@redhat.com>
-rw-r--r--drivers/net/ethernet/wangxun/libwx/wx_hw.c3
-rw-r--r--drivers/net/ethernet/wangxun/libwx/wx_lib.c9
-rw-r--r--drivers/net/ethernet/wangxun/libwx/wx_sriov.c2
-rw-r--r--drivers/net/ethernet/wangxun/libwx/wx_type.h1
-rw-r--r--drivers/net/ethernet/wangxun/libwx/wx_vf_common.c8
-rw-r--r--drivers/net/ethernet/wangxun/ngbe/ngbe_main.c14
-rw-r--r--drivers/net/ethernet/wangxun/txgbe/txgbe_aml.c10
-rw-r--r--drivers/net/ethernet/wangxun/txgbe/txgbe_aml.h2
-rw-r--r--drivers/net/ethernet/wangxun/txgbe/txgbe_irq.c2
-rw-r--r--drivers/net/ethernet/wangxun/txgbe/txgbe_main.c25
10 files changed, 39 insertions, 37 deletions
diff --git a/drivers/net/ethernet/wangxun/libwx/wx_hw.c b/drivers/net/ethernet/wangxun/libwx/wx_hw.c
index 2451f6b20b11..260e14d5d541 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_hw.c
+++ b/drivers/net/ethernet/wangxun/libwx/wx_hw.c
@@ -2520,6 +2520,7 @@ int wx_sw_init(struct wx *wx)
mutex_init(&wx->reset_lock);
bitmap_zero(wx->state, WX_STATE_NBITS);
bitmap_zero(wx->flags, WX_PF_FLAGS_NBITS);
+ set_bit(WX_STATE_DOWN, wx->state);
wx->misc_irq_domain = false;
return 0;
@@ -2875,7 +2876,7 @@ void wx_update_stats(struct wx *wx)
u64 restart_queue = 0, tx_busy = 0;
u32 i;
- if (!netif_running(wx->netdev) ||
+ if (test_bit(WX_STATE_DOWN, wx->state) ||
test_bit(WX_STATE_RESETTING, wx->state))
return;
diff --git a/drivers/net/ethernet/wangxun/libwx/wx_lib.c b/drivers/net/ethernet/wangxun/libwx/wx_lib.c
index 746623fa59b4..d042567b8128 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_lib.c
+++ b/drivers/net/ethernet/wangxun/libwx/wx_lib.c
@@ -876,7 +876,7 @@ static bool wx_clean_tx_irq(struct wx_q_vector *q_vector,
if (__netif_subqueue_stopped(tx_ring->netdev,
tx_ring->queue_index) &&
- netif_running(tx_ring->netdev)) {
+ !test_bit(WX_STATE_DOWN, wx->state)) {
netif_wake_subqueue(tx_ring->netdev,
tx_ring->queue_index);
++tx_ring->tx_stats.restart_queue;
@@ -964,7 +964,7 @@ static int wx_poll(struct napi_struct *napi, int budget)
if (likely(napi_complete_done(napi, work_done))) {
if (wx->adaptive_itr)
wx_update_dim_sample(q_vector);
- if (netif_running(wx->netdev))
+ if (!test_bit(WX_STATE_DOWN, wx->state))
wx_intr_enable(wx, WX_INTR_Q(q_vector->v_idx));
}
@@ -2341,6 +2341,8 @@ int wx_init_interrupt_scheme(struct wx *wx)
wx_cache_ring_rss(wx);
+ set_bit(WX_STATE_DOWN, wx->state);
+
return 0;
}
EXPORT_SYMBOL(wx_init_interrupt_scheme);
@@ -3314,7 +3316,8 @@ EXPORT_SYMBOL(wx_set_ring);
void wx_service_event_schedule(struct wx *wx)
{
- if (!test_and_set_bit(WX_STATE_SERVICE_SCHED, wx->state))
+ if (!test_bit(WX_STATE_DOWN, wx->state) &&
+ !test_and_set_bit(WX_STATE_SERVICE_SCHED, wx->state))
queue_work(system_power_efficient_wq, &wx->service_task);
}
EXPORT_SYMBOL(wx_service_event_schedule);
diff --git a/drivers/net/ethernet/wangxun/libwx/wx_sriov.c b/drivers/net/ethernet/wangxun/libwx/wx_sriov.c
index a360b06a086a..0152004a2dd3 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_sriov.c
+++ b/drivers/net/ethernet/wangxun/libwx/wx_sriov.c
@@ -898,7 +898,7 @@ static void wx_set_vf_link_state(struct wx *wx, int vf, int state)
wx->vfinfo[vf].link_state = state;
switch (state) {
case IFLA_VF_LINK_STATE_AUTO:
- if (netif_running(wx->netdev))
+ if (!test_bit(WX_STATE_DOWN, wx->state))
wx->vfinfo[vf].link_enable = true;
else
wx->vfinfo[vf].link_enable = false;
diff --git a/drivers/net/ethernet/wangxun/libwx/wx_type.h b/drivers/net/ethernet/wangxun/libwx/wx_type.h
index 0da5565ee4ff..c7befe4cdfe9 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_type.h
+++ b/drivers/net/ethernet/wangxun/libwx/wx_type.h
@@ -1202,6 +1202,7 @@ struct wx_last_stats {
};
enum wx_state {
+ WX_STATE_DOWN,
WX_STATE_RESETTING,
WX_STATE_SWFW_BUSY,
WX_STATE_PTP_RUNNING,
diff --git a/drivers/net/ethernet/wangxun/libwx/wx_vf_common.c b/drivers/net/ethernet/wangxun/libwx/wx_vf_common.c
index 94ff8f5f0b4c..0d2db8d38cd5 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_vf_common.c
+++ b/drivers/net/ethernet/wangxun/libwx/wx_vf_common.c
@@ -68,7 +68,7 @@ static irqreturn_t wx_msix_misc_vf(int __always_unused irq, void *data)
set_bit(WX_FLAG_NEED_UPDATE_LINK, wx->flags);
/* Clear the interrupt */
- if (netif_running(wx->netdev))
+ if (!test_bit(WX_STATE_DOWN, wx->state))
wr32(wx, WX_VXIMC, wx->eims_other);
return IRQ_HANDLED;
@@ -278,6 +278,7 @@ static void wxvf_up_complete(struct wx *wx)
wx_configure_msix_vf(wx);
smp_mb__before_atomic();
+ clear_bit(WX_STATE_DOWN, wx->state);
wx_napi_enable_all(wx);
/* clear any pending interrupts, may auto mask */
@@ -327,6 +328,9 @@ static void wxvf_down(struct wx *wx)
{
struct net_device *netdev = wx->netdev;
+ if (test_and_set_bit(WX_STATE_DOWN, wx->state))
+ return;
+
timer_delete_sync(&wx->service_timer);
netif_tx_stop_all_queues(netdev);
netif_tx_disable(netdev);
@@ -360,7 +364,7 @@ static void wxvf_reset_subtask(struct wx *wx)
rtnl_lock();
if (test_bit(WX_STATE_RESETTING, wx->state) ||
- !(netif_running(wx->netdev))) {
+ test_bit(WX_STATE_DOWN, wx->state)) {
rtnl_unlock();
return;
}
diff --git a/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c b/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c
index d51d8db95a76..8678c49b892a 100644
--- a/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c
+++ b/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c
@@ -204,7 +204,7 @@ static irqreturn_t ngbe_intr(int __always_unused irq, void *data)
/* shared interrupt alert!
* the interrupt that we masked before the EICR read.
*/
- if (netif_running(wx->netdev))
+ if (!test_bit(WX_STATE_DOWN, wx->state))
ngbe_irq_enable(wx, true);
return IRQ_NONE; /* Not our interrupt */
}
@@ -220,7 +220,7 @@ static irqreturn_t ngbe_intr(int __always_unused irq, void *data)
/* would disable interrupts here but it is auto disabled */
napi_schedule_irqoff(&q_vector->napi);
- if (netif_running(wx->netdev))
+ if (!test_bit(WX_STATE_DOWN, wx->state))
ngbe_irq_enable(wx, false);
return IRQ_HANDLED;
@@ -235,7 +235,7 @@ static irqreturn_t __ngbe_msix_misc(struct wx *wx, u32 eicr)
wx_ptp_check_pps_event(wx);
/* re-enable the original interrupt state, no lsc, no queues */
- if (netif_running(wx->netdev))
+ if (!test_bit(WX_STATE_DOWN, wx->state))
ngbe_irq_enable(wx, false);
return IRQ_HANDLED;
@@ -262,7 +262,7 @@ static irqreturn_t ngbe_misc_and_queue(int __always_unused irq, void *data)
/* queue */
q_vector = wx->q_vector[0];
napi_schedule_irqoff(&q_vector->napi);
- if (netif_running(wx->netdev))
+ if (!test_bit(WX_STATE_DOWN, wx->state))
ngbe_irq_enable(wx, true);
return IRQ_HANDLED;
}
@@ -363,6 +363,9 @@ static void ngbe_disable_device(struct wx *wx)
struct net_device *netdev = wx->netdev;
u32 i;
+ if (test_and_set_bit(WX_STATE_DOWN, wx->state))
+ return;
+
if (wx->num_vfs) {
/* Clear EITR Select mapping */
wr32(wx, WX_PX_ITRSEL, 0);
@@ -401,8 +404,6 @@ static void ngbe_disable_device(struct wx *wx)
wr32(wx, WX_PX_TR_CFG(reg_idx), WX_PX_TR_CFG_SWFLSH);
}
-
- wx_update_stats(wx);
}
static void ngbe_reset(struct wx *wx)
@@ -428,6 +429,7 @@ void ngbe_up(struct wx *wx)
/* make sure to complete pre-operations */
smp_mb__before_atomic();
+ clear_bit(WX_STATE_DOWN, wx->state);
wx_napi_enable_all(wx);
/* enable transmits */
netif_tx_start_all_queues(wx->netdev);
diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_aml.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_aml.c
index f0514251d4f3..da1d3976ed33 100644
--- a/drivers/net/ethernet/wangxun/txgbe/txgbe_aml.c
+++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_aml.c
@@ -186,19 +186,15 @@ static void txgbe_get_mac_link(struct wx *wx, int *speed)
*speed = SPEED_UNKNOWN;
}
-int txgbe_set_phy_link(struct wx *wx)
+void txgbe_set_phy_link(struct wx *wx)
{
int speed, autoneg, duplex, err;
txgbe_get_link_capabilities(wx, &speed, &autoneg, &duplex);
err = txgbe_set_phy_link_hostif(wx, speed, autoneg, duplex);
- if (err) {
+ if (err)
wx_err(wx, "Failed to setup link\n");
- return err;
- }
-
- return 0;
}
static int txgbe_sfp_to_linkmodes(struct wx *wx, struct txgbe_sff_id *id)
@@ -362,7 +358,7 @@ int txgbe_identify_module(struct wx *wx)
id->identifier != TXGBE_SFF_IDENTIFIER_QSFP_PLUS &&
id->identifier != TXGBE_SFF_IDENTIFIER_QSFP28) {
wx_err(wx, "Invalid module\n");
- return -ENODEV;
+ return -EINVAL;
}
if (id->transceiver_type == 0xFF)
diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_aml.h b/drivers/net/ethernet/wangxun/txgbe/txgbe_aml.h
index 4f6df0ee860b..379c74ad19c6 100644
--- a/drivers/net/ethernet/wangxun/txgbe/txgbe_aml.h
+++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_aml.h
@@ -10,7 +10,7 @@ int txgbe_test_hostif(struct wx *wx);
int txgbe_read_eeprom_hostif(struct wx *wx,
struct txgbe_hic_i2c_read *buffer,
u32 length, u8 *data);
-int txgbe_set_phy_link(struct wx *wx);
+void txgbe_set_phy_link(struct wx *wx);
int txgbe_identify_module(struct wx *wx);
void txgbe_setup_link(struct wx *wx);
int txgbe_phylink_init_aml(struct txgbe *txgbe);
diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_irq.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_irq.c
index aa14958d439a..8746318ad3bc 100644
--- a/drivers/net/ethernet/wangxun/txgbe/txgbe_irq.c
+++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_irq.c
@@ -141,7 +141,7 @@ static irqreturn_t txgbe_misc_irq_handle(int irq, void *data)
/* shared interrupt alert!
* the interrupt that we masked before the ICR read.
*/
- if (netif_running(wx->netdev))
+ if (!test_bit(WX_STATE_DOWN, wx->state))
txgbe_irq_enable(wx, true);
return IRQ_NONE; /* Not our interrupt */
}
diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c
index 4c549c2644ab..ce82e13aa8ae 100644
--- a/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c
+++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c
@@ -93,31 +93,23 @@ static void txgbe_module_detection_subtask(struct wx *wx)
{
int err;
- if (!test_bit(WX_FLAG_NEED_MODULE_RESET, wx->flags))
+ if (!test_and_clear_bit(WX_FLAG_NEED_MODULE_RESET, wx->flags))
return;
/* wait for SFF module ready */
msleep(200);
err = txgbe_identify_module(wx);
- if (err)
- return;
-
- clear_bit(WX_FLAG_NEED_MODULE_RESET, wx->flags);
+ if (err == -ENODEV)
+ set_bit(WX_FLAG_NEED_MODULE_RESET, wx->flags);
}
static void txgbe_link_config_subtask(struct wx *wx)
{
- int err;
-
- if (!test_bit(WX_FLAG_NEED_LINK_CONFIG, wx->flags))
+ if (!test_and_clear_bit(WX_FLAG_NEED_LINK_CONFIG, wx->flags))
return;
- err = txgbe_set_phy_link(wx);
- if (err)
- return;
-
- clear_bit(WX_FLAG_NEED_LINK_CONFIG, wx->flags);
+ txgbe_set_phy_link(wx);
}
/**
@@ -151,6 +143,7 @@ static void txgbe_up_complete(struct wx *wx)
/* make sure to complete pre-operations */
smp_mb__before_atomic();
+ clear_bit(WX_STATE_DOWN, wx->state);
wx_napi_enable_all(wx);
switch (wx->mac.type) {
@@ -213,6 +206,9 @@ static void txgbe_disable_device(struct wx *wx)
struct net_device *netdev = wx->netdev;
u32 i;
+ if (test_and_set_bit(WX_STATE_DOWN, wx->state))
+ return;
+
wx_disable_pcie_master(wx);
/* disable receives */
wx_disable_rx(wx);
@@ -229,6 +225,7 @@ static void txgbe_disable_device(struct wx *wx)
wx_napi_disable_all(wx);
timer_delete_sync(&wx->service_timer);
+ cancel_work_sync(&wx->service_task);
if (wx->bus.func < 2)
wr32m(wx, TXGBE_MIS_PRB_CTL, TXGBE_MIS_PRB_CTL_LAN_UP(wx->bus.func), 0);
@@ -261,8 +258,6 @@ static void txgbe_disable_device(struct wx *wx)
/* Disable the Tx DMA engine */
wr32m(wx, WX_TDM_CTL, WX_TDM_CTL_TE, 0);
-
- wx_update_stats(wx);
}
void txgbe_down(struct wx *wx)