summaryrefslogtreecommitdiff
path: root/MdeModulePkg
diff options
context:
space:
mode:
authorFu Siyuan <siyuan.fu@intel.com>2016-01-08 02:38:34 +0000
committerHao Wu <hao.a.wu@intel.com>2016-02-22 15:43:31 +0800
commit9b0c2eceebbe81300bcc9a0df142ad7c2da1e2f4 (patch)
tree6c3f153310e94b3f3f573cf86b3350aaddb35377 /MdeModulePkg
parentf24b415887c88e342aa5386e0a3e7db1e8ac340a (diff)
downloadedk2-platforms-9b0c2eceebbe81300bcc9a0df142ad7c2da1e2f4.tar.xz
MdeModulePkg: Update MNP driver to recycle TX buffer asynchronously.
This patch updates the MNP driver to recycle TX buffer asynchronously, instead of using a while loop wait after each transmit command. (Sync patch r19624 from main trunk.) Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Fu Siyuan <siyuan.fu@intel.com> Reviewed-by: Jiaxin Wu <jiaxin.wu@intel.com> Reviewed-by: Ye Ting <ting.ye@intel.com>
Diffstat (limited to 'MdeModulePkg')
-rw-r--r--MdeModulePkg/Universal/Network/MnpDxe/MnpConfig.c266
-rw-r--r--MdeModulePkg/Universal/Network/MnpDxe/MnpDriver.h7
-rw-r--r--MdeModulePkg/Universal/Network/MnpDxe/MnpImpl.h54
-rw-r--r--MdeModulePkg/Universal/Network/MnpDxe/MnpIo.c127
-rw-r--r--MdeModulePkg/Universal/Network/MnpDxe/MnpMain.c7
5 files changed, 348 insertions, 113 deletions
diff --git a/MdeModulePkg/Universal/Network/MnpDxe/MnpConfig.c b/MdeModulePkg/Universal/Network/MnpDxe/MnpConfig.c
index 046d4dfddc..d1a4cb5dd2 100644
--- a/MdeModulePkg/Universal/Network/MnpDxe/MnpConfig.c
+++ b/MdeModulePkg/Universal/Network/MnpDxe/MnpConfig.c
@@ -1,7 +1,7 @@
/** @file
Implementation of Managed Network Protocol private services.
-Copyright (c) 2005 - 2012, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2005 - 2016, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions
of the BSD License which accompanies this distribution. The full
@@ -209,6 +209,208 @@ MnpFreeNbuf (
gBS->RestoreTPL (OldTpl);
}
+/**
+ Add Count of TX buffers to MnpDeviceData->AllTxBufList and MnpDeviceData->FreeTxBufList.
+ The length of the buffer is specified by MnpDeviceData->BufferLength.
+
+ @param[in, out] MnpDeviceData Pointer to the MNP_DEVICE_DATA.
+ @param[in] Count Number of TX buffers to add.
+
+ @retval EFI_SUCCESS The specified amount of TX buffers are allocated.
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate a TX buffer.
+
+**/
+EFI_STATUS
+MnpAddFreeTxBuf (
+ IN OUT MNP_DEVICE_DATA *MnpDeviceData,
+ IN UINTN Count
+ )
+{
+ EFI_STATUS Status;
+ UINT32 Index;
+ MNP_TX_BUF_WRAP *TxBufWrap;
+
+ NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);
+ ASSERT ((Count > 0) && (MnpDeviceData->BufferLength > 0));
+
+ Status = EFI_SUCCESS;
+ for (Index = 0; Index < Count; Index++) {
+ TxBufWrap = (MNP_TX_BUF_WRAP*) AllocatePool (sizeof (MNP_TX_BUF_WRAP) + MnpDeviceData->BufferLength - 1);
+ if (TxBufWrap == NULL) {
+ DEBUG ((EFI_D_ERROR, "MnpAddFreeTxBuf: TxBuf Alloc failed.\n"));
+
+ Status = EFI_OUT_OF_RESOURCES;
+ break;
+ }
+ DEBUG ((EFI_D_INFO, "MnpAddFreeTxBuf: Add TxBufWrap %p, TxBuf %p\n", TxBufWrap, TxBufWrap->TxBuf));
+ TxBufWrap->Signature = MNP_TX_BUF_WRAP_SIGNATURE;
+ TxBufWrap->InUse = FALSE;
+ InsertTailList (&MnpDeviceData->FreeTxBufList, &TxBufWrap->WrapEntry);
+ InsertTailList (&MnpDeviceData->AllTxBufList, &TxBufWrap->AllEntry);
+ }
+
+ MnpDeviceData->TxBufCount += Index;
+ return Status;
+}
+
+/**
+ Allocate a free TX buffer from MnpDeviceData->FreeTxBufList. If there is none
+ in the queue, first try to recycle some from SNP, then try to allocate some and add
+ them into the queue, then fetch the NET_BUF from the updated FreeTxBufList.
+
+ @param[in, out] MnpDeviceData Pointer to the MNP_DEVICE_DATA.
+
+ @return Pointer to the allocated free NET_BUF structure, if NULL the
+ operation is failed.
+
+**/
+UINT8 *
+MnpAllocTxBuf (
+ IN OUT MNP_DEVICE_DATA *MnpDeviceData
+ )
+{
+ EFI_TPL OldTpl;
+ UINT8 *TxBuf;
+ EFI_STATUS Status;
+ LIST_ENTRY *Entry;
+ MNP_TX_BUF_WRAP *TxBufWrap;
+
+ NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);
+
+ OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
+
+ if (IsListEmpty (&MnpDeviceData->FreeTxBufList)) {
+ //
+ // First try to recycle some TX buffer from SNP
+ //
+ Status = MnpRecycleTxBuf (MnpDeviceData);
+ if (EFI_ERROR (Status)) {
+ TxBuf = NULL;
+ goto ON_EXIT;
+ }
+
+ //
+ // If still no free TX buffer, allocate more.
+ //
+ if (IsListEmpty (&MnpDeviceData->FreeTxBufList)) {
+ if ((MnpDeviceData->TxBufCount + MNP_TX_BUFFER_INCREASEMENT) > MNP_MAX_TX_BUFFER_NUM) {
+ DEBUG (
+ (EFI_D_ERROR,
+ "MnpAllocTxBuf: The maximum TxBuf size is reached for MNP driver instance %p.\n",
+ MnpDeviceData)
+ );
+
+ TxBuf = NULL;
+ goto ON_EXIT;
+ }
+
+ Status = MnpAddFreeTxBuf (MnpDeviceData, MNP_TX_BUFFER_INCREASEMENT);
+ if (IsListEmpty (&MnpDeviceData->FreeTxBufList)) {
+ DEBUG (
+ (EFI_D_ERROR,
+ "MnpAllocNbuf: Failed to add TxBuf into the FreeTxBufList, %r.\n",
+ Status)
+ );
+
+ TxBuf = NULL;
+ goto ON_EXIT;
+ }
+ }
+ }
+
+ ASSERT (!IsListEmpty (&MnpDeviceData->FreeTxBufList));
+ Entry = MnpDeviceData->FreeTxBufList.ForwardLink;
+ RemoveEntryList (MnpDeviceData->FreeTxBufList.ForwardLink);
+ TxBufWrap = NET_LIST_USER_STRUCT_S (Entry, MNP_TX_BUF_WRAP, WrapEntry, MNP_TX_BUF_WRAP_SIGNATURE);
+ TxBufWrap->InUse = TRUE;
+ TxBuf = TxBufWrap->TxBuf;
+
+ON_EXIT:
+ gBS->RestoreTPL (OldTpl);
+
+ return TxBuf;
+}
+
+/**
+ Try to reclaim the TX buffer into the buffer pool.
+
+ @param[in, out] MnpDeviceData Pointer to the mnp device context data.
+ @param[in, out] TxBuf Pointer to the TX buffer to free.
+
+**/
+VOID
+MnpFreeTxBuf (
+ IN OUT MNP_DEVICE_DATA *MnpDeviceData,
+ IN OUT UINT8 *TxBuf
+ )
+{
+ MNP_TX_BUF_WRAP *TxBufWrap;
+ EFI_TPL OldTpl;
+
+ NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);
+
+ if (TxBuf == NULL) {
+ return;
+ }
+
+ TxBufWrap = NET_LIST_USER_STRUCT (TxBuf, MNP_TX_BUF_WRAP, TxBuf);
+ if (TxBufWrap->Signature != MNP_TX_BUF_WRAP_SIGNATURE) {
+ DEBUG (
+ (EFI_D_ERROR,
+ "MnpFreeTxBuf: Signature check failed in MnpFreeTxBuf.\n")
+ );
+ return;
+ }
+
+ if (!TxBufWrap->InUse) {
+ DEBUG (
+ (EFI_D_WARN,
+ "MnpFreeTxBuf: Duplicated recycle report from SNP.\n")
+ );
+ return;
+ }
+
+ OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
+ InsertTailList (&MnpDeviceData->FreeTxBufList, &TxBufWrap->WrapEntry);
+ TxBufWrap->InUse = FALSE;
+ gBS->RestoreTPL (OldTpl);
+}
+
+/**
+ Try to recycle all the transmitted buffer address from SNP.
+
+ @param[in, out] MnpDeviceData Pointer to the mnp device context data.
+
+ @retval EFI_SUCCESS Successed to recyclethe transmitted buffer address.
+ @retval Others Failed to recyclethe transmitted buffer address.
+
+**/
+EFI_STATUS
+MnpRecycleTxBuf (
+ IN OUT MNP_DEVICE_DATA *MnpDeviceData
+ )
+{
+ UINT8 *TxBuf;
+ EFI_SIMPLE_NETWORK_PROTOCOL *Snp;
+ EFI_STATUS Status;
+
+ Snp = MnpDeviceData->Snp;
+ ASSERT (Snp != NULL);
+
+ do {
+ TxBuf = NULL;
+ Status = Snp->GetStatus (Snp, NULL, (VOID **) &TxBuf);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (TxBuf != NULL) {
+ MnpFreeTxBuf (MnpDeviceData, TxBuf);
+ }
+ } while (TxBuf != NULL);
+
+ return EFI_SUCCESS;
+}
/**
Initialize the mnp device context data.
@@ -314,13 +516,9 @@ MnpInitializeDeviceData (
//
// Allocate buffer pool for tx.
//
- MnpDeviceData->TxBuf = AllocatePool (MnpDeviceData->BufferLength);
- if (MnpDeviceData->TxBuf == NULL) {
- DEBUG ((EFI_D_ERROR, "MnpInitializeDeviceData: AllocatePool failed.\n"));
-
- Status = EFI_OUT_OF_RESOURCES;
- goto ERROR;
- }
+ InitializeListHead (&MnpDeviceData->FreeTxBufList);
+ InitializeListHead (&MnpDeviceData->AllTxBufList);
+ MnpDeviceData->TxBufCount = 0;
//
// Create the system poll timer.
@@ -370,20 +568,6 @@ MnpInitializeDeviceData (
goto ERROR;
}
- //
- // Create the timer for tx timeout check.
- //
- Status = gBS->CreateEvent (
- EVT_TIMER,
- TPL_CALLBACK,
- NULL,
- NULL,
- &MnpDeviceData->TxTimeoutEvent
- );
- if (EFI_ERROR (Status)) {
- DEBUG ((EFI_D_ERROR, "MnpInitializeDeviceData: CreateEvent for tx timeout event failed.\n"));
- }
-
ERROR:
if (EFI_ERROR (Status)) {
//
@@ -405,10 +589,6 @@ ERROR:
gBS->CloseEvent (MnpDeviceData->PollTimer);
}
- if (MnpDeviceData->TxBuf != NULL) {
- FreePool (MnpDeviceData->TxBuf);
- }
-
if (MnpDeviceData->RxNbufCache != NULL) {
MnpFreeNbuf (MnpDeviceData, MnpDeviceData->RxNbufCache);
}
@@ -445,6 +625,10 @@ MnpDestroyDeviceData (
IN EFI_HANDLE ImageHandle
)
{
+ LIST_ENTRY *Entry;
+ LIST_ENTRY *NextEntry;
+ MNP_TX_BUF_WRAP *TxBufWrap;
+
NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);
//
@@ -462,15 +646,21 @@ MnpDestroyDeviceData (
//
// Close the event.
//
- gBS->CloseEvent (MnpDeviceData->TxTimeoutEvent);
gBS->CloseEvent (MnpDeviceData->TimeoutCheckTimer);
gBS->CloseEvent (MnpDeviceData->MediaDetectTimer);
gBS->CloseEvent (MnpDeviceData->PollTimer);
//
- // Free the tx buffer.
+ // Free the Tx buffer pool.
//
- FreePool (MnpDeviceData->TxBuf);
+ NET_LIST_FOR_EACH_SAFE(Entry, NextEntry, &MnpDeviceData->AllTxBufList) {
+ TxBufWrap = NET_LIST_USER_STRUCT (Entry, MNP_TX_BUF_WRAP, AllEntry);
+ RemoveEntryList (Entry);
+ FreePool (TxBufWrap);
+ MnpDeviceData->TxBufCount--;
+ }
+ ASSERT (IsListEmpty (&MnpDeviceData->AllTxBufList));
+ ASSERT (MnpDeviceData->TxBufCount == 0);
//
// Free the RxNbufCache.
@@ -957,7 +1147,7 @@ MnpStartSnp (
/**
Stop the simple network.
- @param[in] Snp Pointer to the simple network protocol.
+ @param[in] MnpDeviceData Pointer to the MNP_DEVICE_DATA.
@retval EFI_SUCCESS The simple network is stopped.
@retval Others Other errors as indicated.
@@ -965,14 +1155,24 @@ MnpStartSnp (
**/
EFI_STATUS
MnpStopSnp (
- IN EFI_SIMPLE_NETWORK_PROTOCOL *Snp
+ IN MNP_DEVICE_DATA *MnpDeviceData
)
{
EFI_STATUS Status;
-
+ EFI_SIMPLE_NETWORK_PROTOCOL *Snp;
+
+ Snp = MnpDeviceData->Snp;
ASSERT (Snp != NULL);
//
+ // Recycle all the transmit buffer from SNP.
+ //
+ Status = MnpRecycleTxBuf (MnpDeviceData);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
// Shut down the simple network.
//
Status = Snp->Shutdown (Snp);
@@ -1162,7 +1362,7 @@ MnpStop (
//
// Stop the simple network.
//
- Status = MnpStopSnp (MnpDeviceData->Snp);
+ Status = MnpStopSnp (MnpDeviceData);
return Status;
}
diff --git a/MdeModulePkg/Universal/Network/MnpDxe/MnpDriver.h b/MdeModulePkg/Universal/Network/MnpDxe/MnpDriver.h
index 35a9b710db..126d968200 100644
--- a/MdeModulePkg/Universal/Network/MnpDxe/MnpDriver.h
+++ b/MdeModulePkg/Universal/Network/MnpDxe/MnpDriver.h
@@ -1,7 +1,7 @@
/** @file
Declaration of strctures and functions for MnpDxe driver.
-Copyright (c) 2005 - 2012, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2005 - 2016, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions
of the BSD License which accompanies this distribution. The full
@@ -67,7 +67,9 @@ typedef struct {
LIST_ENTRY GroupAddressList;
UINT32 GroupAddressCount;
- EFI_EVENT TxTimeoutEvent;
+ LIST_ENTRY FreeTxBufList;
+ LIST_ENTRY AllTxBufList;
+ UINT32 TxBufCount;
NET_BUF_QUEUE FreeNbufQue;
INTN NbufCnt;
@@ -90,7 +92,6 @@ typedef struct {
UINT32 BufferLength;
UINT32 PaddingSize;
NET_BUF *RxNbufCache;
- UINT8 *TxBuf;
} MNP_DEVICE_DATA;
#define MNP_DEVICE_DATA_FROM_THIS(a) \
diff --git a/MdeModulePkg/Universal/Network/MnpDxe/MnpImpl.h b/MdeModulePkg/Universal/Network/MnpDxe/MnpImpl.h
index f94e208306..c66be6487b 100644
--- a/MdeModulePkg/Universal/Network/MnpDxe/MnpImpl.h
+++ b/MdeModulePkg/Universal/Network/MnpDxe/MnpImpl.h
@@ -1,7 +1,7 @@
/** @file
Declaration of structures and functions of MnpDxe driver.
-Copyright (c) 2005 - 2010, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2005 - 2016, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions
of the BSD License which accompanies this distribution. The full
@@ -27,6 +27,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#define MNP_INIT_NET_BUFFER_NUM 512
#define MNP_NET_BUFFER_INCREASEMENT 64
#define MNP_MAX_NET_BUFFER_NUM 65536
+#define MNP_TX_BUFFER_INCREASEMENT 64
+#define MNP_MAX_TX_BUFFER_NUM 65536
#define MNP_MAX_RCVD_PACKET_QUE_SIZE 256
@@ -92,6 +94,15 @@ typedef struct {
UINT64 TimeoutTick;
} MNP_RXDATA_WRAP;
+#define MNP_TX_BUF_WRAP_SIGNATURE SIGNATURE_32 ('M', 'T', 'B', 'W')
+
+typedef struct {
+ UINT32 Signature;
+ LIST_ENTRY WrapEntry; // Link to FreeTxBufList
+ LIST_ENTRY AllEntry; // Link to AllTxBufList
+ BOOLEAN InUse;
+ UINT8 TxBuf[1];
+} MNP_TX_BUF_WRAP;
/**
Initialize the mnp device context data.
@@ -342,8 +353,11 @@ MnpIsValidTxToken (
@param[out] PktLen Pointer to a UINT32 variable used to record the packet's
length.
+ @retval EFI_SUCCESS TxPackage is built.
+ @retval EFI_OUT_OF_RESOURCES The deliver fails due to lack of memory resource.
+
**/
-VOID
+EFI_STATUS
MnpBuildTxPacket (
IN MNP_SERVICE_DATA *MnpServiceData,
IN EFI_MANAGED_NETWORK_TRANSMIT_DATA *TxData,
@@ -352,7 +366,11 @@ MnpBuildTxPacket (
);
/**
- Synchronously send out the packet.
+ Synchronously send out the packet.
+
+ This functon places the packet buffer to SNP driver's tansmit queue. The packet
+ can be considered successfully sent out once SNP acccetp the packet, while the
+ packet buffer recycle is deferred for better performance.
@param[in] MnpServiceData Pointer to the mnp service context data.
@param[in] Packet Pointer to the pakcet buffer.
@@ -449,6 +467,36 @@ MnpFreeNbuf (
);
/**
+ Allocate a free TX buffer from MnpDeviceData->FreeTxBufList. If there is none
+ in the queue, first try to recycle some from SNP, then try to allocate some and add
+ them into the queue, then fetch the NET_BUF from the updated FreeTxBufList.
+
+ @param[in, out] MnpDeviceData Pointer to the MNP_DEVICE_DATA.
+
+ @return Pointer to the allocated free NET_BUF structure, if NULL the
+ operation is failed.
+
+**/
+UINT8 *
+MnpAllocTxBuf (
+ IN OUT MNP_DEVICE_DATA *MnpDeviceData
+ );
+
+/**
+ Try to recycle all the transmitted buffer address from SNP.
+
+ @param[in, out] MnpDeviceData Pointer to the mnp device context data.
+
+ @retval EFI_SUCCESS Successed to recyclethe transmitted buffer address.
+ @retval Others Failed to recyclethe transmitted buffer address.
+
+**/
+EFI_STATUS
+MnpRecycleTxBuf (
+ IN OUT MNP_DEVICE_DATA *MnpDeviceData
+ );
+
+/**
Remove the received packets if timeout occurs.
@param[in] Event The event this notify function registered to.
diff --git a/MdeModulePkg/Universal/Network/MnpDxe/MnpIo.c b/MdeModulePkg/Universal/Network/MnpDxe/MnpIo.c
index 7f03b848ef..1cbfc30e5c 100644
--- a/MdeModulePkg/Universal/Network/MnpDxe/MnpIo.c
+++ b/MdeModulePkg/Universal/Network/MnpDxe/MnpIo.c
@@ -1,7 +1,7 @@
/** @file
Implementation of Managed Network Protocol I/O functions.
-Copyright (c) 2005 - 2014, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2005 - 2016, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions
of the BSD License which accompanies this distribution. The full
@@ -102,7 +102,6 @@ MnpIsValidTxToken (
return TRUE;
}
-
/**
Build the packet to transmit from the TxData passed in.
@@ -113,8 +112,11 @@ MnpIsValidTxToken (
@param[out] PktLen Pointer to a UINT32 variable used to record the packet's
length.
+ @retval EFI_SUCCESS TxPackage is built.
+ @retval EFI_OUT_OF_RESOURCES The deliver fails due to lack of memory resource.
+
**/
-VOID
+EFI_STATUS
MnpBuildTxPacket (
IN MNP_SERVICE_DATA *MnpServiceData,
IN EFI_MANAGED_NETWORK_TRANSMIT_DATA *TxData,
@@ -125,14 +127,24 @@ MnpBuildTxPacket (
EFI_SIMPLE_NETWORK_MODE *SnpMode;
UINT8 *DstPos;
UINT16 Index;
- MNP_DEVICE_DATA *MnpDerviceData;
-
- MnpDerviceData = MnpServiceData->MnpDeviceData;
-
+ MNP_DEVICE_DATA *MnpDeviceData;
+ UINT8 *TxBuf;
+
+ MnpDeviceData = MnpServiceData->MnpDeviceData;
+
+ TxBuf = MnpAllocTxBuf (MnpDeviceData);
+ if (TxBuf == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
//
- // Reserve space for vlan tag.
+ // Reserve space for vlan tag if needed.
//
- *PktBuf = MnpDerviceData->TxBuf + NET_VLAN_TAG_LEN;
+ if (MnpServiceData->VlanId != 0) {
+ *PktBuf = TxBuf + NET_VLAN_TAG_LEN;
+ } else {
+ *PktBuf = TxBuf;
+ }
if ((TxData->DestinationAddress == NULL) && (TxData->FragmentCount == 1)) {
CopyMem (
@@ -148,7 +160,7 @@ MnpBuildTxPacket (
// one fragment, copy the data into the packet buffer. Reserve the
// media header space if necessary.
//
- SnpMode = MnpDerviceData->Snp->Mode;
+ SnpMode = MnpDeviceData->Snp->Mode;
DstPos = *PktBuf;
*PktLen = 0;
if (TxData->DestinationAddress != NULL) {
@@ -177,11 +189,17 @@ MnpBuildTxPacket (
//
*PktLen += TxData->DataLength + TxData->HeaderLength;
}
+
+ return EFI_SUCCESS;
}
/**
- Synchronously send out the packet.
+ Synchronously send out the packet.
+
+ This functon places the packet buffer to SNP driver's tansmit queue. The packet
+ can be considered successfully sent out once SNP acccetp the packet, while the
+ packet buffer recycle is deferred for better performance.
@param[in] MnpServiceData Pointer to the mnp service context data.
@param[in] Packet Pointer to the pakcet buffer.
@@ -205,14 +223,13 @@ MnpSyncSendPacket (
EFI_SIMPLE_NETWORK_PROTOCOL *Snp;
EFI_MANAGED_NETWORK_TRANSMIT_DATA *TxData;
UINT32 HeaderSize;
- UINT8 *TxBuf;
MNP_DEVICE_DATA *MnpDeviceData;
UINT16 ProtocolType;
MnpDeviceData = MnpServiceData->MnpDeviceData;
Snp = MnpDeviceData->Snp;
TxData = Token->Packet.TxData;
-
+ Token->Status = EFI_SUCCESS;
HeaderSize = Snp->Mode->MediaHeaderSize - TxData->HeaderLength;
//
@@ -224,19 +241,7 @@ MnpSyncSendPacket (
// Media not present, skip packet transmit and report EFI_NO_MEDIA
//
DEBUG ((EFI_D_WARN, "MnpSyncSendPacket: No network cable detected.\n"));
- Status = EFI_NO_MEDIA;
- goto SIGNAL_TOKEN;
- }
-
- //
- // Start the timeout event.
- //
- Status = gBS->SetTimer (
- MnpDeviceData->TxTimeoutEvent,
- TimerRelative,
- MNP_TX_TIMEOUT_TIME
- );
- if (EFI_ERROR (Status)) {
+ Token->Status = EFI_NO_MEDIA;
goto SIGNAL_TOKEN;
}
@@ -250,10 +255,25 @@ MnpSyncSendPacket (
ProtocolType = TxData->ProtocolType;
}
- for (;;) {
- //
- // Transmit the packet through SNP.
- //
+ //
+ // Transmit the packet through SNP.
+ //
+ Status = Snp->Transmit (
+ Snp,
+ HeaderSize,
+ Length,
+ Packet,
+ TxData->SourceAddress,
+ TxData->DestinationAddress,
+ &ProtocolType
+ );
+ if (Status == EFI_NOT_READY) {
+ Status = MnpRecycleTxBuf (MnpDeviceData);
+ if (EFI_ERROR (Status)) {
+ Token->Status = EFI_DEVICE_ERROR;
+ goto SIGNAL_TOKEN;
+ }
+
Status = Snp->Transmit (
Snp,
HeaderSize,
@@ -262,52 +282,15 @@ MnpSyncSendPacket (
TxData->SourceAddress,
TxData->DestinationAddress,
&ProtocolType
- );
- if ((Status != EFI_SUCCESS) && (Status != EFI_NOT_READY)) {
- Status = EFI_DEVICE_ERROR;
- break;
- }
-
- //
- // If Status is EFI_SUCCESS, the packet is put in the transmit queue.
- // if Status is EFI_NOT_READY, the transmit engine of the network interface is busy.
- // Both need to sync SNP.
- //
- TxBuf = NULL;
- do {
- //
- // Get the recycled transmit buffer status.
- //
- Snp->GetStatus (Snp, NULL, (VOID **) &TxBuf);
-
- if (!EFI_ERROR (gBS->CheckEvent (MnpDeviceData->TxTimeoutEvent))) {
- Status = EFI_TIMEOUT;
- break;
- }
- } while (TxBuf == NULL);
-
- if ((Status == EFI_SUCCESS) || (Status == EFI_TIMEOUT)) {
- break;
- } else {
- //
- // Status is EFI_NOT_READY. Restart the timer event and call Snp->Transmit again.
- //
- gBS->SetTimer (
- MnpDeviceData->TxTimeoutEvent,
- TimerRelative,
- MNP_TX_TIMEOUT_TIME
- );
- }
+ );
+ }
+
+ if (EFI_ERROR (Status)) {
+ Token->Status = EFI_DEVICE_ERROR;
}
-
- //
- // Cancel the timer event.
- //
- gBS->SetTimer (MnpDeviceData->TxTimeoutEvent, TimerCancel, 0);
SIGNAL_TOKEN:
- Token->Status = Status;
gBS->SignalEvent (Token->Event);
//
diff --git a/MdeModulePkg/Universal/Network/MnpDxe/MnpMain.c b/MdeModulePkg/Universal/Network/MnpDxe/MnpMain.c
index 4c0f3ddd9a..31c2e3e5b8 100644
--- a/MdeModulePkg/Universal/Network/MnpDxe/MnpMain.c
+++ b/MdeModulePkg/Universal/Network/MnpDxe/MnpMain.c
@@ -1,7 +1,7 @@
/** @file
Implementation of Managed Network Protocol public services.
-Copyright (c) 2005 - 2010, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2005 - 2016, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions
of the BSD License which accompanies this distribution. The full
@@ -552,7 +552,10 @@ MnpTransmit (
//
// Build the tx packet
//
- MnpBuildTxPacket (MnpServiceData, Token->Packet.TxData, &PktBuf, &PktLen);
+ Status = MnpBuildTxPacket (MnpServiceData, Token->Packet.TxData, &PktBuf, &PktLen);
+ if (EFI_ERROR (Status)) {
+ goto ON_EXIT;
+ }
//
// OK, send the packet synchronously.