From 10edf82dcb23c1fb919652d9f7d94d0a4dcd9d6f Mon Sep 17 00:00:00 2001 From: Masahisa KOJIMA Date: Thu, 19 Apr 2018 10:23:57 +0900 Subject: Silicon/SynQuacer/NetsecDxe: Add polling function to reinitialize GMAC GMAC is a Gigabit Ethernet MAC implemented in NETSEC. When the physical link is changed from DOWN to UP, GMAC should be reinitialized properly. We add polling function to check the physical link status and reinitializa GMAC. When the GMAC is running and physical link is down, stop GMAC. When the GMAC is stopped and physical link is up, start GMAC Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Masahisa KOJIMA Reviewed-by: Ard Biesheuvel --- .../SynQuacer/Drivers/Net/NetsecDxe/NetsecDxe.c | 113 +++++++++++++++++++++ .../SynQuacer/Drivers/Net/NetsecDxe/NetsecDxe.h | 4 + 2 files changed, 117 insertions(+) diff --git a/Silicon/Socionext/SynQuacer/Drivers/Net/NetsecDxe/NetsecDxe.c b/Silicon/Socionext/SynQuacer/Drivers/Net/NetsecDxe/NetsecDxe.c index 764c44bb..a30ebd93 100644 --- a/Silicon/Socionext/SynQuacer/Drivers/Net/NetsecDxe/NetsecDxe.c +++ b/Silicon/Socionext/SynQuacer/Drivers/Net/NetsecDxe/NetsecDxe.c @@ -161,6 +161,10 @@ SnpStop ( gBS->CloseEvent (LanDriver->ExitBootEvent); + gBS->SetTimer (LanDriver->PhyStatusEvent, TimerCancel, 0); + gBS->CloseEvent (LanDriver->PhyStatusEvent); + LanDriver->PhyStatusEvent = NULL; + // Change the state Snp->Mode->State = EfiSimpleNetworkStopped; Status = EFI_SUCCESS; @@ -406,6 +410,104 @@ NotifyExitBoot ( gBS->CloseEvent (Event); } +/** + Polling function to check the physical link status with GMAC + + @param Timer[in] Event + @param *Context[in] Pointer to the Snp structure + + @return none + +**/ +STATIC +VOID +EFIAPI +NetsecPollPhyStatus ( + IN EFI_EVENT Timer, + IN VOID *Context + ) +{ + EFI_SIMPLE_NETWORK_PROTOCOL *Snp; + NETSEC_DRIVER *LanDriver; + ogma_phy_link_status_t phy_link_status; + ogma_gmac_mode_t ogma_gmac_mode; + ogma_err_t ogma_err; + BOOLEAN ValidFlag; + ogma_gmac_mode_t GmacMode; + BOOLEAN RxRunningFlag; + BOOLEAN TxRunningFlag; + + Snp = (EFI_SIMPLE_NETWORK_PROTOCOL *) Context; + if (Snp == NULL) { + DEBUG((DEBUG_ERROR, "NETSEC: PollPhyStatus() invalid Snp\n")); + return; + } + LanDriver = INSTANCE_FROM_SNP_THIS (Snp); + + // Update the media status + ogma_err = ogma_get_phy_link_status (LanDriver->Handle, LanDriver->PhyAddress, + &phy_link_status); + if (ogma_err != OGMA_ERR_OK) { + DEBUG ((DEBUG_ERROR, + "NETSEC: ogma_get_phy_link_status failed with error code: %d\n", + (INT32)ogma_err)); + goto Exit; + } + + // Update the GMAC status + ogma_err = ogma_get_gmac_status (LanDriver->Handle, &ValidFlag, &GmacMode, + &RxRunningFlag, &TxRunningFlag); + if (ogma_err != OGMA_ERR_OK) { + DEBUG ((DEBUG_ERROR, + "NETSEC: ogma_get_gmac_status failed with error code: %d\n", + (INT32)ogma_err)); + goto Exit; + } + + // Stop GMAC when GMAC is running and physical link is down + if ( (RxRunningFlag) && (TxRunningFlag) && (!phy_link_status.up_flag) ) { + ogma_err = ogma_stop_gmac (LanDriver->Handle, OGMA_TRUE, OGMA_TRUE); + if (ogma_err != OGMA_ERR_OK) { + DEBUG ((DEBUG_ERROR, + "NETSEC: ogma_stop_gmac() failed with error status %d\n", + ogma_err)); + goto Exit; + } + } + + // Start GMAC when GMAC is stopped and physical link is up + if ( (!RxRunningFlag) && (!TxRunningFlag) && (phy_link_status.up_flag) ) { + SetMem (&ogma_gmac_mode, sizeof (ogma_gmac_mode_t), 0); + ogma_gmac_mode.link_speed = phy_link_status.link_speed; + ogma_gmac_mode.half_duplex_flag = (ogma_bool)phy_link_status.half_duplex_flag; + if ((!phy_link_status.half_duplex_flag) && FixedPcdGet8 (PcdFlowCtrl)) { + ogma_gmac_mode.flow_ctrl_enable_flag = FixedPcdGet8 (PcdFlowCtrl); + ogma_gmac_mode.flow_ctrl_start_threshold = FixedPcdGet16 (PcdFlowCtrlStartThreshold); + ogma_gmac_mode.flow_ctrl_stop_threshold = FixedPcdGet16 (PcdFlowCtrlStopThreshold); + ogma_gmac_mode.pause_time = FixedPcdGet16 (PcdPauseTime); + } + + ogma_err = ogma_set_gmac_mode (LanDriver->Handle, &ogma_gmac_mode); + if (ogma_err != OGMA_ERR_OK) { + DEBUG ((DEBUG_ERROR, + "NETSEC: ogma_set_gmac() failed with error status %d\n", + (INT32)ogma_err)); + goto Exit; + } + + ogma_err = ogma_start_gmac (LanDriver->Handle, OGMA_TRUE, OGMA_TRUE); + if (ogma_err != OGMA_ERR_OK) { + DEBUG ((DEBUG_ERROR, + "NETSEC: ogma_start_gmac() failed with error status %d\n", + (INT32)ogma_err)); + goto Exit; + } + } + +Exit: + return; +} + /* * UEFI Start() function */ @@ -450,6 +552,17 @@ SnpStart ( NotifyExitBoot, Snp, &LanDriver->ExitBootEvent); ASSERT_EFI_ERROR (Status); + Status = gBS->CreateEvent (EVT_TIMER | EVT_NOTIFY_SIGNAL, TPL_CALLBACK, + NetsecPollPhyStatus, Snp, &LanDriver->PhyStatusEvent); + ASSERT_EFI_ERROR (Status); + + Status = gBS->SetTimer ( + LanDriver->PhyStatusEvent, + TimerPeriodic, + NETSEC_PHY_STATUS_POLL_INTERVAL + ); + ASSERT_EFI_ERROR (Status); + // Change state Mode->State = EfiSimpleNetworkStarted; Status = EFI_SUCCESS; diff --git a/Silicon/Socionext/SynQuacer/Drivers/Net/NetsecDxe/NetsecDxe.h b/Silicon/Socionext/SynQuacer/Drivers/Net/NetsecDxe/NetsecDxe.h index 6aa7f1a1..f09fb609 100644 --- a/Silicon/Socionext/SynQuacer/Drivers/Net/NetsecDxe/NetsecDxe.h +++ b/Silicon/Socionext/SynQuacer/Drivers/Net/NetsecDxe/NetsecDxe.h @@ -71,6 +71,8 @@ typedef struct { EFI_EVENT ExitBootEvent; + EFI_EVENT PhyStatusEvent; + NON_DISCOVERABLE_DEVICE *Dev; NETSEC_DEVICE_PATH DevicePath; @@ -115,4 +117,6 @@ NetsecRelease ( #define RXINT_TMR_CNT_US 0 #define RXINT_PKTCNT 1 +#define NETSEC_PHY_STATUS_POLL_INTERVAL (EFI_TIMER_PERIOD_MILLISECONDS (1000)) + #endif -- cgit v1.2.3