lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-Id: <20241106101717.981850-1-jiawenwu@trustnetic.com>
Date: Wed,  6 Nov 2024 18:17:17 +0800
From: Jiawen Wu <jiawenwu@...stnetic.com>
To: andrew+netdev@...n.ch,
	davem@...emloft.net,
	edumazet@...gle.com,
	kuba@...nel.org,
	pabeni@...hat.com,
	linux@...linux.org.uk,
	horms@...nel.org,
	netdev@...r.kernel.org
Cc: mengyuanlou@...-swift.com,
	duanqiangwen@...-swift.com,
	Jiawen Wu <jiawenwu@...stnetic.com>
Subject: [PATCH net] net: txgbe: fix lost GPIO interrupt

Sometimes when clearing interrupts for workaround in txgbe_up_complete(),
the GPIO interrupt is lost once due to the interrupt polarity is
consistent with the GPIO state. It causes the SFP state cannot be updated
immediately. That is, SFP driver can only get into the correct state if
the GPIO state changes again.

So mannually trigger the GPIO interrupt while clearing it in
txgbe_reinit_gpio_intr(), causing SFP driver to update to the correct
state. And also clear GPIO interrupts in txgbe_down() to ensure that the
interrupt polarity is consistent with the GPIO state.

Fixes: b4a2496c17ed ("net: txgbe: fix GPIO interrupt blocking")
Signed-off-by: Jiawen Wu <jiawenwu@...stnetic.com>
---
 drivers/net/ethernet/wangxun/libwx/wx_type.h    |  1 +
 drivers/net/ethernet/wangxun/txgbe/txgbe_main.c |  5 ++++-
 drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c  | 15 ++++++++++-----
 3 files changed, 15 insertions(+), 6 deletions(-)

diff --git a/drivers/net/ethernet/wangxun/libwx/wx_type.h b/drivers/net/ethernet/wangxun/libwx/wx_type.h
index b54bffda027b..bf4285db605e 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_type.h
+++ b/drivers/net/ethernet/wangxun/libwx/wx_type.h
@@ -1078,6 +1078,7 @@ struct wx {
 	bool wol_hw_supported;
 	bool ncsi_enabled;
 	bool gpio_ctrl;
+	bool gpio_trigger;
 	raw_spinlock_t gpio_lock;
 
 	/* Tx fast path data */
diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c
index 93180225a6f1..0e6129dcff8f 100644
--- a/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c
+++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c
@@ -82,7 +82,6 @@ static void txgbe_up_complete(struct wx *wx)
 {
 	struct net_device *netdev = wx->netdev;
 
-	txgbe_reinit_gpio_intr(wx);
 	wx_control_hw(wx, true);
 	wx_configure_vectors(wx);
 
@@ -97,6 +96,9 @@ static void txgbe_up_complete(struct wx *wx)
 	rd32(wx, WX_PX_IC(1));
 	rd32(wx, WX_PX_MISC_IC);
 	txgbe_irq_enable(wx, true);
+	wx->gpio_trigger = true;
+	txgbe_reinit_gpio_intr(wx);
+	wx->gpio_trigger = false;
 
 	/* enable transmits */
 	netif_tx_start_all_queues(netdev);
@@ -169,6 +171,7 @@ void txgbe_down(struct wx *wx)
 	txgbe_disable_device(wx);
 	txgbe_reset(wx);
 	phylink_stop(wx->phylink);
+	txgbe_reinit_gpio_intr(wx);
 
 	wx_clean_all_tx_rings(wx);
 	wx_clean_all_rx_rings(wx);
diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c
index 67b61afdde96..361dcb362d42 100644
--- a/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c
+++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c
@@ -401,17 +401,21 @@ static void txgbe_gpio_irq_unmask(struct irq_data *d)
 static void txgbe_toggle_trigger(struct gpio_chip *gc, unsigned int offset)
 {
 	struct wx *wx = gpiochip_get_data(gc);
-	u32 pol, val;
+	u32 pol_r, pol_w, val;
 
-	pol = rd32(wx, WX_GPIO_POLARITY);
+	pol_r = rd32(wx, WX_GPIO_POLARITY);
 	val = rd32(wx, WX_GPIO_EXT);
 
 	if (val & BIT(offset))
-		pol &= ~BIT(offset);
+		pol_w = pol_r & ~BIT(offset);
 	else
-		pol |= BIT(offset);
+		pol_w = pol_r | BIT(offset);
 
-	wr32(wx, WX_GPIO_POLARITY, pol);
+	wr32(wx, WX_GPIO_POLARITY, pol_w);
+
+	/* manually trigger the lost inpterrupt */
+	if (wx->gpio_trigger)
+		wr32(wx, WX_GPIO_POLARITY, pol_r);
 }
 
 static int txgbe_gpio_set_type(struct irq_data *d, unsigned int type)
@@ -560,6 +564,7 @@ static int txgbe_gpio_init(struct txgbe *txgbe)
 		return ret;
 
 	txgbe->gpio = gc;
+	wx->gpio_trigger = false;
 
 	return 0;
 }
-- 
2.27.0


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ