[8/8] net/txgbe: add SFP hot-plug identification support

Message ID 20230118060039.3074016-9-jiawenwu@trustnetic.com (mailing list archive)
State Superseded, archived
Delegated to: Ferruh Yigit
Headers
Series Wangxun fixes and new supports |

Checks

Context Check Description
ci/checkpatch success coding style OK
ci/loongarch-compilation success Compilation OK
ci/loongarch-unit-testing success Unit Testing PASS
ci/iol-broadcom-Performance success Performance Testing PASS
ci/iol-mellanox-Performance success Performance Testing PASS
ci/iol-aarch64-unit-testing success Testing PASS
ci/Intel-compilation success Compilation OK
ci/iol-intel-Functional success Functional Testing PASS
ci/iol-intel-Performance success Performance Testing PASS
ci/intel-Testing success Testing PASS
ci/iol-x86_64-compile-testing success Testing PASS
ci/github-robot: build success github build: passed
ci/iol-aarch64-compile-testing success Testing PASS
ci/iol-testing success Testing PASS
ci/iol-x86_64-unit-testing success Testing PASS
ci/iol-abi-testing success Testing PASS

Commit Message

Jiawen Wu Jan. 18, 2023, 6 a.m. UTC
  Support to identify the new SFP/SFP+ module when the device is started.

Signed-off-by: Jiawen Wu <jiawenwu@trustnetic.com>
---
 doc/guides/rel_notes/release_23_03.rst |  1 +
 drivers/net/txgbe/base/txgbe_regs.h    |  1 +
 drivers/net/txgbe/txgbe_ethdev.c       | 70 +++++++++++++++++++++++---
 3 files changed, 65 insertions(+), 7 deletions(-)
  

Comments

Ferruh Yigit Jan. 27, 2023, 3:38 p.m. UTC | #1
On 1/18/2023 6:00 AM, Jiawen Wu wrote:
> Support to identify the new SFP/SFP+ module when the device is started.
> 
> Signed-off-by: Jiawen Wu <jiawenwu@trustnetic.com>

<...>

> @@ -2972,9 +3029,6 @@ txgbe_dev_interrupt_get_status(struct rte_eth_dev *dev,
>  		rte_intr_type_get(intr_handle) != RTE_INTR_HANDLE_VFIO_MSIX)
>  		wr32(hw, TXGBE_PX_INTA, 1);
>  
> -	/* clear all cause mask */
> -	txgbe_disable_intr(hw);
> -

This change looks like a major one, is it related to the "SFP/SFP+ module"?

I assume this is replace by below line [1], if this is unrelated please
separate it to its own patch, and if it related can you please explain
why it is related in the commit log.

>  	/* read-on-clear nic registers here */
>  	eicr = ((u32 *)hw->isb_mem)[TXGBE_ISB_MISC];
>  	PMD_DRV_LOG(DEBUG, "eicr %x", eicr);
> @@ -3000,6 +3054,8 @@ txgbe_dev_interrupt_get_status(struct rte_eth_dev *dev,
>  	if (eicr & TXGBE_ICRMISC_HEAT)
>  		intr->flags |= TXGBE_FLAG_OVERHEAT;
> 

[1]

> +	((u32 *)hw->isb_mem)[TXGBE_ISB_MISC] = 0;
> +
  

Patch

diff --git a/doc/guides/rel_notes/release_23_03.rst b/doc/guides/rel_notes/release_23_03.rst
index e64cb2d974..3c43b75ac0 100644
--- a/doc/guides/rel_notes/release_23_03.rst
+++ b/doc/guides/rel_notes/release_23_03.rst
@@ -62,6 +62,7 @@  New Features
 * **Updated Wangxun txgbe driver.**
 
   * Added chip overheat detection support.
+  * Added SFP hot-plug identification support.
 
 
 Removed Items
diff --git a/drivers/net/txgbe/base/txgbe_regs.h b/drivers/net/txgbe/base/txgbe_regs.h
index 911bb6e04e..bc2854b01a 100644
--- a/drivers/net/txgbe/base/txgbe_regs.h
+++ b/drivers/net/txgbe/base/txgbe_regs.h
@@ -1579,6 +1579,7 @@  enum txgbe_5tuple_protocol {
 #define TXGBE_GPIOINTMASK               0x014834
 #define TXGBE_GPIOINTTYPE               0x014838
 #define TXGBE_GPIOINTSTAT               0x014840
+#define TXGBE_GPIORAWINTSTAT            0x014844
 #define TXGBE_GPIOEOI                   0x01484C
 
 
diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c
index ce7cf2506d..a502618bc5 100644
--- a/drivers/net/txgbe/txgbe_ethdev.c
+++ b/drivers/net/txgbe/txgbe_ethdev.c
@@ -114,6 +114,7 @@  static int txgbe_dev_interrupt_get_status(struct rte_eth_dev *dev,
 static int txgbe_dev_interrupt_action(struct rte_eth_dev *dev,
 				      struct rte_intr_handle *handle);
 static void txgbe_dev_interrupt_handler(void *param);
+static void txgbe_dev_detect_sfp(void *param);
 static void txgbe_dev_interrupt_delayed_handler(void *param);
 static void txgbe_configure_msix(struct rte_eth_dev *dev);
 
@@ -1535,11 +1536,20 @@  txgbe_dev_phy_intr_setup(struct rte_eth_dev *dev)
 {
 	struct txgbe_hw *hw = TXGBE_DEV_HW(dev);
 	struct txgbe_interrupt *intr = TXGBE_DEV_INTR(dev);
+	u8 device_type = hw->subsystem_device_id & 0xF0;
 	uint32_t gpie;
 
-	gpie = rd32(hw, TXGBE_GPIOINTEN);
-	gpie |= TXGBE_GPIOBIT_6;
-	wr32(hw, TXGBE_GPIOINTEN, gpie);
+	if (device_type != TXGBE_DEV_ID_MAC_XAUI &&
+			device_type != TXGBE_DEV_ID_MAC_SGMII) {
+		gpie = rd32(hw, TXGBE_GPIOINTEN);
+		gpie |= TXGBE_GPIOBIT_2 | TXGBE_GPIOBIT_3 | TXGBE_GPIOBIT_6;
+		wr32(hw, TXGBE_GPIOINTEN, gpie);
+
+		gpie = rd32(hw, TXGBE_GPIOINTTYPE);
+		gpie |= TXGBE_GPIOBIT_2 | TXGBE_GPIOBIT_3 | TXGBE_GPIOBIT_6;
+		wr32(hw, TXGBE_GPIOINTTYPE, gpie);
+	}
+
 	intr->mask_misc |= TXGBE_ICRMISC_GPIO;
 	intr->mask_misc |= TXGBE_ICRMISC_ANDONE;
 	intr->mask_misc |= TXGBE_ICRMISC_HEAT;
@@ -1648,6 +1658,7 @@  txgbe_dev_start(struct rte_eth_dev *dev)
 	PMD_INIT_FUNC_TRACE();
 
 	/* Stop the link setup handler before resetting the HW. */
+	rte_eal_alarm_cancel(txgbe_dev_detect_sfp, dev);
 	rte_eal_alarm_cancel(txgbe_dev_setup_link_alarm_handler, dev);
 
 	/* disable uio/vfio intr/eventfd mapping */
@@ -1880,6 +1891,7 @@  txgbe_dev_stop(struct rte_eth_dev *dev)
 
 	PMD_INIT_FUNC_TRACE();
 
+	rte_eal_alarm_cancel(txgbe_dev_detect_sfp, dev);
 	rte_eal_alarm_cancel(txgbe_dev_setup_link_alarm_handler, dev);
 
 	/* disable interrupts */
@@ -2673,6 +2685,51 @@  txgbe_dev_supported_ptypes_get(struct rte_eth_dev *dev)
 	return NULL;
 }
 
+static void
+txgbe_dev_detect_sfp(void *param)
+{
+	struct rte_eth_dev *dev = (struct rte_eth_dev *)param;
+	struct txgbe_hw *hw = TXGBE_DEV_HW(dev);
+	s32 err;
+
+	err = hw->phy.identify_sfp(hw);
+	if (err == TXGBE_ERR_SFP_NOT_SUPPORTED) {
+		PMD_DRV_LOG(ERR, "Unsupported SFP+ module type was detected.");
+	} else if (err == TXGBE_ERR_SFP_NOT_PRESENT) {
+		PMD_DRV_LOG(INFO, "SFP not present.");
+	} else if (err == 0) {
+		hw->mac.setup_sfp(hw);
+		PMD_DRV_LOG(INFO, "detected SFP+: %d\n", hw->phy.sfp_type);
+		txgbe_dev_setup_link_alarm_handler(dev);
+		txgbe_dev_link_update(dev, 0);
+	}
+}
+
+static void
+txgbe_dev_sfp_event(struct rte_eth_dev *dev)
+{
+	struct txgbe_interrupt *intr = TXGBE_DEV_INTR(dev);
+	struct txgbe_hw *hw = TXGBE_DEV_HW(dev);
+	u32 reg;
+
+	wr32(hw, TXGBE_GPIOINTMASK, 0xFF);
+	reg = rd32(hw, TXGBE_GPIORAWINTSTAT);
+	if (reg & TXGBE_GPIOBIT_2) {
+		wr32(hw, TXGBE_GPIOEOI, TXGBE_GPIOBIT_2);
+		rte_eal_alarm_set(1000 * 100, txgbe_dev_detect_sfp, dev);
+	}
+	if (reg & TXGBE_GPIOBIT_3) {
+		wr32(hw, TXGBE_GPIOEOI, TXGBE_GPIOBIT_3);
+		intr->flags |= TXGBE_FLAG_NEED_LINK_UPDATE;
+	}
+	if (reg & TXGBE_GPIOBIT_6) {
+		wr32(hw, TXGBE_GPIOEOI, TXGBE_GPIOBIT_6);
+		intr->flags |= TXGBE_FLAG_NEED_LINK_UPDATE;
+	}
+
+	wr32(hw, TXGBE_GPIOINTMASK, 0);
+}
+
 static void
 txgbe_dev_overheat(struct rte_eth_dev *dev)
 {
@@ -2972,9 +3029,6 @@  txgbe_dev_interrupt_get_status(struct rte_eth_dev *dev,
 		rte_intr_type_get(intr_handle) != RTE_INTR_HANDLE_VFIO_MSIX)
 		wr32(hw, TXGBE_PX_INTA, 1);
 
-	/* clear all cause mask */
-	txgbe_disable_intr(hw);
-
 	/* read-on-clear nic registers here */
 	eicr = ((u32 *)hw->isb_mem)[TXGBE_ISB_MISC];
 	PMD_DRV_LOG(DEBUG, "eicr %x", eicr);
@@ -3000,6 +3054,8 @@  txgbe_dev_interrupt_get_status(struct rte_eth_dev *dev,
 	if (eicr & TXGBE_ICRMISC_HEAT)
 		intr->flags |= TXGBE_FLAG_OVERHEAT;
 
+	((u32 *)hw->isb_mem)[TXGBE_ISB_MISC] = 0;
+
 	return 0;
 }
 
@@ -3064,7 +3120,7 @@  txgbe_dev_interrupt_action(struct rte_eth_dev *dev,
 	}
 
 	if (intr->flags & TXGBE_FLAG_PHY_INTERRUPT) {
-		hw->phy.handle_lasi(hw);
+		txgbe_dev_sfp_event(dev);
 		intr->flags &= ~TXGBE_FLAG_PHY_INTERRUPT;
 	}