MdeModulePkg/Mtftp4Dxe: Separate the timer ticking to calculate the packet live time.

TPL deadlock issue was enrolled by the commit of 39b0867d. To resolve the issue,
this patch separated the timer ticking for all the MTFTP clients to calculate the
packet live time in TPL_NOTIFY level.

Cc: Wang Fan <fan.wang@intel.com>
Cc: Fu Siyuan <siyuan.fu@intel.com>
Cc: Ye Ting <ting.ye@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Fu Siyuan <siyuan.fu@intel.com>
Signed-off-by: Jiaxin Wu <jiaxin.wu@intel.com>
Reviewed-by: Ye Ting <ting.ye@intel.com>
Reviewed-by: Fu Siyuan <siyuan.fu@intel.com>
This commit is contained in:
Fu Siyuan
2018-03-02 11:33:28 +08:00
committed by Jiaxin Wu
parent 1fa7fdf6ea
commit 0e2a5749d8
5 changed files with 98 additions and 22 deletions

View File

@ -1,7 +1,7 @@
/** @file /** @file
Implementation of Mtftp drivers. Implementation of Mtftp drivers.
Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR> Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at which accompanies this distribution. The full text of the license may be found at
@ -162,11 +162,12 @@ Mtftp4CreateService (
MtftpSb->ChildrenNum = 0; MtftpSb->ChildrenNum = 0;
InitializeListHead (&MtftpSb->Children); InitializeListHead (&MtftpSb->Children);
MtftpSb->Timer = NULL; MtftpSb->Timer = NULL;
MtftpSb->TimerToGetMap = NULL; MtftpSb->TimerNotifyLevel = NULL;
MtftpSb->Controller = Controller; MtftpSb->TimerToGetMap = NULL;
MtftpSb->Image = Image; MtftpSb->Controller = Controller;
MtftpSb->ConnectUdp = NULL; MtftpSb->Image = Image;
MtftpSb->ConnectUdp = NULL;
// //
// Create the timer and a udp to be notified when UDP is uninstalled // Create the timer and a udp to be notified when UDP is uninstalled
@ -178,12 +179,24 @@ Mtftp4CreateService (
MtftpSb, MtftpSb,
&MtftpSb->Timer &MtftpSb->Timer
); );
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
FreePool (MtftpSb); FreePool (MtftpSb);
return Status; return Status;
} }
Status = gBS->CreateEvent (
EVT_NOTIFY_SIGNAL | EVT_TIMER,
TPL_NOTIFY,
Mtftp4OnTimerTickNotifyLevel,
MtftpSb,
&MtftpSb->TimerNotifyLevel
);
if (EFI_ERROR (Status)) {
gBS->CloseEvent (MtftpSb->Timer);
FreePool (MtftpSb);
return Status;
}
// //
// Create the timer used to time out the procedure which is used to // Create the timer used to time out the procedure which is used to
// get the default IP address. // get the default IP address.
@ -196,6 +209,7 @@ Mtftp4CreateService (
&MtftpSb->TimerToGetMap &MtftpSb->TimerToGetMap
); );
if (EFI_ERROR (Status)) { if (EFI_ERROR (Status)) {
gBS->CloseEvent (MtftpSb->TimerNotifyLevel);
gBS->CloseEvent (MtftpSb->Timer); gBS->CloseEvent (MtftpSb->Timer);
FreePool (MtftpSb); FreePool (MtftpSb);
return Status; return Status;
@ -211,6 +225,7 @@ Mtftp4CreateService (
if (MtftpSb->ConnectUdp == NULL) { if (MtftpSb->ConnectUdp == NULL) {
gBS->CloseEvent (MtftpSb->TimerToGetMap); gBS->CloseEvent (MtftpSb->TimerToGetMap);
gBS->CloseEvent (MtftpSb->TimerNotifyLevel);
gBS->CloseEvent (MtftpSb->Timer); gBS->CloseEvent (MtftpSb->Timer);
FreePool (MtftpSb); FreePool (MtftpSb);
return EFI_DEVICE_ERROR; return EFI_DEVICE_ERROR;
@ -234,6 +249,7 @@ Mtftp4CleanService (
{ {
UdpIoFreeIo (MtftpSb->ConnectUdp); UdpIoFreeIo (MtftpSb->ConnectUdp);
gBS->CloseEvent (MtftpSb->TimerToGetMap); gBS->CloseEvent (MtftpSb->TimerToGetMap);
gBS->CloseEvent (MtftpSb->TimerNotifyLevel);
gBS->CloseEvent (MtftpSb->Timer); gBS->CloseEvent (MtftpSb->Timer);
} }
@ -294,6 +310,12 @@ Mtftp4DriverBindingStart (
goto ON_ERROR; goto ON_ERROR;
} }
Status = gBS->SetTimer (MtftpSb->TimerNotifyLevel, TimerPeriodic, TICKS_PER_SECOND);
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
// //
// Install the Mtftp4ServiceBinding Protocol onto Controller // Install the Mtftp4ServiceBinding Protocol onto Controller
// //

View File

@ -1082,6 +1082,7 @@ EfiMtftp4Poll (
{ {
MTFTP4_PROTOCOL *Instance; MTFTP4_PROTOCOL *Instance;
EFI_UDP4_PROTOCOL *Udp; EFI_UDP4_PROTOCOL *Udp;
EFI_STATUS Status;
if (This == NULL) { if (This == NULL) {
return EFI_INVALID_PARAMETER; return EFI_INVALID_PARAMETER;
@ -1096,7 +1097,9 @@ EfiMtftp4Poll (
} }
Udp = Instance->UnicastPort->Protocol.Udp4; Udp = Instance->UnicastPort->Protocol.Udp4;
return Udp->Poll (Udp); Status = Udp->Poll (Udp);
Mtftp4OnTimerTick (NULL, Instance->Service);
return Status;
} }
EFI_MTFTP4_PROTOCOL gMtftp4ProtocolTemplate = { EFI_MTFTP4_PROTOCOL gMtftp4ProtocolTemplate = {

View File

@ -9,7 +9,7 @@
RFC2348 - TFTP Blocksize Option RFC2348 - TFTP Blocksize Option
RFC2349 - TFTP Timeout Interval and Transfer Size Options RFC2349 - TFTP Timeout Interval and Transfer Size Options
Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR> Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at which accompanies this distribution. The full text of the license may be found at
@ -72,7 +72,8 @@ struct _MTFTP4_SERVICE {
UINT16 ChildrenNum; UINT16 ChildrenNum;
LIST_ENTRY Children; LIST_ENTRY Children;
EFI_EVENT Timer; ///< Ticking timer for all the MTFTP clients EFI_EVENT Timer; ///< Ticking timer for all the MTFTP clients to handle the packet timeout case.
EFI_EVENT TimerNotifyLevel; ///< Ticking timer for all the MTFTP clients to calculate the packet live time.
EFI_EVENT TimerToGetMap; EFI_EVENT TimerToGetMap;
EFI_HANDLE Controller; EFI_HANDLE Controller;
@ -135,6 +136,7 @@ struct _MTFTP4_PROTOCOL {
// //
NET_BUF *LastPacket; NET_BUF *LastPacket;
UINT32 PacketToLive; UINT32 PacketToLive;
BOOLEAN HasTimeout;
UINT32 CurRetry; UINT32 CurRetry;
UINT32 MaxRetry; UINT32 MaxRetry;
UINT32 Timeout; UINT32 Timeout;

View File

@ -1,7 +1,7 @@
/** @file /** @file
Support routines for Mtftp. Support routines for Mtftp.
Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR> Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at which accompanies this distribution. The full text of the license may be found at
@ -568,6 +568,42 @@ Mtftp4Retransmit (
} }
/**
The timer ticking function in TPL_NOTIFY level for the Mtftp service instance.
@param Event The ticking event
@param Context The Mtftp service instance
**/
VOID
EFIAPI
Mtftp4OnTimerTickNotifyLevel (
IN EFI_EVENT Event,
IN VOID *Context
)
{
MTFTP4_SERVICE *MtftpSb;
LIST_ENTRY *Entry;
LIST_ENTRY *Next;
MTFTP4_PROTOCOL *Instance;
MtftpSb = (MTFTP4_SERVICE *) Context;
//
// Iterate through all the children of the Mtftp service instance. Time
// out the current packet transmit.
//
NET_LIST_FOR_EACH_SAFE (Entry, Next, &MtftpSb->Children) {
Instance = NET_LIST_USER_STRUCT (Entry, MTFTP4_PROTOCOL, Link);
if ((Instance->PacketToLive == 0) || (--Instance->PacketToLive > 0)) {
Instance->HasTimeout = FALSE;
} else {
Instance->HasTimeout = TRUE;
}
}
}
/** /**
The timer ticking function for the Mtftp service instance. The timer ticking function for the Mtftp service instance.
@ -591,29 +627,28 @@ Mtftp4OnTimerTick (
MtftpSb = (MTFTP4_SERVICE *) Context; MtftpSb = (MTFTP4_SERVICE *) Context;
// //
// Iterate through all the children of the Mtftp service instance. Time // Iterate through all the children of the Mtftp service instance.
// out the packet. If maximum retries reached, clean the session up.
// //
NET_LIST_FOR_EACH_SAFE (Entry, Next, &MtftpSb->Children) { NET_LIST_FOR_EACH_SAFE (Entry, Next, &MtftpSb->Children) {
Instance = NET_LIST_USER_STRUCT (Entry, MTFTP4_PROTOCOL, Link); Instance = NET_LIST_USER_STRUCT (Entry, MTFTP4_PROTOCOL, Link);
if (!Instance->HasTimeout) {
if ((Instance->PacketToLive == 0) || (--Instance->PacketToLive > 0)) {
continue; continue;
} }
Instance->HasTimeout = FALSE;
// //
// Call the user's time out handler // Call the user's time out handler
// //
Token = Instance->Token; Token = Instance->Token;
if ((Token->TimeoutCallback != NULL) && if (Token != NULL && Token->TimeoutCallback != NULL &&
EFI_ERROR (Token->TimeoutCallback (&Instance->Mtftp4, Token))) { EFI_ERROR (Token->TimeoutCallback (&Instance->Mtftp4, Token))) {
Mtftp4SendError ( Mtftp4SendError (
Instance, Instance,
EFI_MTFTP4_ERRORCODE_REQUEST_DENIED, EFI_MTFTP4_ERRORCODE_REQUEST_DENIED,
(UINT8 *) "User aborted the transfer in time out" (UINT8 *) "User aborted the transfer in time out"
); );
Mtftp4CleanOperation (Instance, EFI_ABORTED); Mtftp4CleanOperation (Instance, EFI_ABORTED);
continue; continue;

View File

@ -1,7 +1,7 @@
/** @file /** @file
Support routines for MTFTP. Support routines for MTFTP.
Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR> Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at which accompanies this distribution. The full text of the license may be found at
@ -187,6 +187,20 @@ Mtftp4Retransmit (
IN MTFTP4_PROTOCOL *Instance IN MTFTP4_PROTOCOL *Instance
); );
/**
The timer ticking function in TPL_NOTIFY level for the Mtftp service instance.
@param Event The ticking event
@param Context The Mtftp service instance
**/
VOID
EFIAPI
Mtftp4OnTimerTickNotifyLevel (
IN EFI_EVENT Event,
IN VOID *Context
);
/** /**
The timer ticking function for the Mtftp service instance. The timer ticking function for the Mtftp service instance.