On 01/05/16 04:37, Fu Siyuan wrote: > This patch updates the MNP driver to recycle TX buffer asynchronously, instead > of using a while loop wait after each transmit command. > This patch also fixes a bug in SNP.GetStatus() interface to support the MNP > update. The UNDI driver may return multiple transmitted buffers in a single > GetStatus command, while SNP.GetStatus could only return one pointer each > time, > the rest of them are lost. This patch fixes this issue by store these recycled > pointer in a temporary buffer in SNP driver.
(1) Would it be possible to separate these two changes? For example, would the following work? - The first patch updates only SnpDxe. Since the SnpDxe changes should only affect SnpDxe internals -- the buffering of recycled UNDI TX buffers is internal to SNP, and not visible to MNP --, patching only SnpDxe in the first step should not break MNP. - The second patch updates only MnpDxe; implementing the asynchronous recycling. This would be supported by SnpDxe with the first patch applied. (2) Is there a good way to test the asynchronism? Like an easily available UEFI application, or a UEFI shell command? I think this MNP change is good idea. Is it also observable for an interactive user (e.g., better transfer speed with the TFTP command, or something similar)? Thanks! Laszlo > > Contributed-under: TianoCore Contribution Agreement 1.0 > Signed-off-by: Fu Siyuan <[email protected]> > --- > MdeModulePkg/Universal/Network/MnpDxe/MnpConfig.c | 266 > ++++++++++++++++++--- > MdeModulePkg/Universal/Network/MnpDxe/MnpDriver.h | 7 +- > MdeModulePkg/Universal/Network/MnpDxe/MnpImpl.h | 45 +++- > MdeModulePkg/Universal/Network/MnpDxe/MnpIo.c | 118 ++++----- > MdeModulePkg/Universal/Network/MnpDxe/MnpMain.c | 7 +- > MdeModulePkg/Universal/Network/SnpDxe/Get_status.c | 73 ++++-- > MdeModulePkg/Universal/Network/SnpDxe/Snp.c | 16 +- > MdeModulePkg/Universal/Network/SnpDxe/Snp.h | 18 +- > 8 files changed, 421 insertions(+), 129 deletions(-) > > diff --git a/MdeModulePkg/Universal/Network/MnpDxe/MnpConfig.c > b/MdeModulePkg/Universal/Network/MnpDxe/MnpConfig.c > index 046d4df..d1a4cb5 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 35a9b71..126d968 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 f94e208..dd9ad32 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. > @@ -343,7 +354,7 @@ MnpIsValidTxToken ( > length. > > **/ > -VOID > +EFI_STATUS > MnpBuildTxPacket ( > IN MNP_SERVICE_DATA *MnpServiceData, > IN EFI_MANAGED_NETWORK_TRANSMIT_DATA *TxData, > @@ -449,6 +460,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 7f03b84..45ba1b9 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. > > @@ -114,7 +113,7 @@ MnpIsValidTxToken ( > length. > > **/ > -VOID > +EFI_STATUS > MnpBuildTxPacket ( > IN MNP_SERVICE_DATA *MnpServiceData, > IN EFI_MANAGED_NETWORK_TRANSMIT_DATA *TxData, > @@ -125,14 +124,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 +157,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,6 +186,8 @@ MnpBuildTxPacket ( > // > *PktLen += TxData->DataLength + TxData->HeaderLength; > } > + > + return EFI_SUCCESS; > } > > > @@ -205,14 +216,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 +234,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 +248,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 +275,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 4c0f3dd..31c2e3e 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. > diff --git a/MdeModulePkg/Universal/Network/SnpDxe/Get_status.c > b/MdeModulePkg/Universal/Network/SnpDxe/Get_status.c > index 0532976..8f2ab9b 100644 > --- a/MdeModulePkg/Universal/Network/SnpDxe/Get_status.c > +++ b/MdeModulePkg/Universal/Network/SnpDxe/Get_status.c > @@ -2,7 +2,7 @@ > Implementation of reading the current interrupt status and recycled > transmit > buffer status from a network interface. > > -Copyright (c) 2004 - 2010, Intel Corporation. All rights reserved.<BR> > +Copyright (c) 2004 - 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 text of the license may be found at > @@ -16,15 +16,15 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER > EXPRESS OR IMPLIED. > #include "Snp.h" > > /** > - Call undi to get the status of the interrupts, get the list of transmit > - buffers that completed transmitting. > + Call undi to get the status of the interrupts, get the list of recycled > transmit > + buffers that completed transmitting. The recycled transmit buffer address > will > + be saved into Snp->RecycledTxBuf. > > @param Snp Pointer to snp driver structure. > @param InterruptStatusPtr A non null pointer to contain the interrupt > status. > - @param TransmitBufferListPtrs A non null pointer to contain the list of > - pointers of previous transmitted buffers > whose > - transmission was completed asynchrnously. > + @param GetTransmittedBuf Set to TRUE to retrieve the recycled > transmit > + buffer address. > > @retval EFI_SUCCESS The status of the network interface was > retrieved. > @retval EFI_DEVICE_ERROR The command could not be sent to the network > @@ -35,19 +35,23 @@ EFI_STATUS > PxeGetStatus ( > SNP_DRIVER *Snp, > UINT32 *InterruptStatusPtr, > - VOID **TransmitBufferListPtr > + BOOLEAN GetTransmittedBuf > ) > { > PXE_DB_GET_STATUS *Db; > UINT16 InterruptFlags; > + UINT32 Index; > + UINT64 *Tmp; > > + Tmp = NULL; > Db = Snp->Db; > Snp->Cdb.OpCode = PXE_OPCODE_GET_STATUS; > > Snp->Cdb.OpFlags = 0; > > - if (TransmitBufferListPtr != NULL) { > + if (GetTransmittedBuf) { > Snp->Cdb.OpFlags |= PXE_OPFLAGS_GET_TRANSMITTED_BUFFERS; > + ZeroMem (Db->TxBuffer, sizeof (Db->TxBuffer)); > } > > if (InterruptStatusPtr != NULL) { > @@ -116,13 +120,34 @@ PxeGetStatus ( > > } > > - if (TransmitBufferListPtr != NULL) { > - *TransmitBufferListPtr = > - ( > - ((Snp->Cdb.StatFlags & PXE_STATFLAGS_GET_STATUS_NO_TXBUFS_WRITTEN) > != 0) || > - ((Snp->Cdb.StatFlags & PXE_STATFLAGS_GET_STATUS_TXBUF_QUEUE_EMPTY) > != 0) > - ) ? 0 : (VOID *) (UINTN) Db->TxBuffer[0]; > - > + if (GetTransmittedBuf) { > + if ((Snp->Cdb.StatFlags & PXE_STATFLAGS_GET_STATUS_NO_TXBUFS_WRITTEN) == > 0) { > + // > + // UNDI has written some transmitted buffer addresses into the DB. > Store them into Snp->RecycledTxBuf. > + // > + for (Index = 0; Index < MAX_XMIT_BUFFERS; Index++) { > + if (Db->TxBuffer[Index] != 0) { > + if (Snp->RecycledTxBufCount == Snp->MaxRecycledTxBuf) { > + // > + // Snp->RecycledTxBuf is full, reallocate a new one. > + // > + if ((Snp->MaxRecycledTxBuf + SNP_TX_BUFFER_INCREASEMENT) >= > SNP_MAX_TX_BUFFER_NUM) { > + return EFI_DEVICE_ERROR; > + } > + Tmp = AllocatePool (sizeof (UINT64) * (Snp->MaxRecycledTxBuf + > SNP_TX_BUFFER_INCREASEMENT)); > + if (Tmp == NULL) { > + return EFI_DEVICE_ERROR; > + } > + CopyMem (Tmp, Snp->RecycledTxBuf, sizeof (UINT64) * > Snp->RecycledTxBufCount); > + FreePool (Snp->RecycledTxBuf); > + Snp->RecycledTxBuf = Tmp; > + Snp->MaxRecycledTxBuf += SNP_TX_BUFFER_INCREASEMENT; > + } > + Snp->RecycledTxBuf[Snp->RecycledTxBufCount] = Db->TxBuffer[Index]; > + Snp->RecycledTxBufCount++; > + } > + } > + } > } > > // > @@ -216,7 +241,23 @@ SnpUndi32GetStatus ( > goto ON_EXIT; > } > > - Status = PxeGetStatus (Snp, InterruptStatus, TxBuf); > + if (Snp->RecycledTxBufCount == 0 && TxBuf != NULL) { > + Status = PxeGetStatus (Snp, InterruptStatus, TRUE); > + } else { > + Status = PxeGetStatus (Snp, InterruptStatus, FALSE); > + } > + > + if (TxBuf != NULL) { > + // > + // Get a recycled buf from Snp->RecycledTxBuf > + // > + if (Snp->RecycledTxBufCount == 0) { > + *TxBuf = NULL; > + } else { > + Snp->RecycledTxBufCount--; > + *TxBuf = (VOID *) (UINTN) Snp->RecycledTxBuf[Snp->RecycledTxBufCount]; > + } > + } > > ON_EXIT: > gBS->RestoreTPL (OldTpl); > diff --git a/MdeModulePkg/Universal/Network/SnpDxe/Snp.c > b/MdeModulePkg/Universal/Network/SnpDxe/Snp.c > index db5b626..5ff294f 100644 > --- a/MdeModulePkg/Universal/Network/SnpDxe/Snp.c > +++ b/MdeModulePkg/Universal/Network/SnpDxe/Snp.c > @@ -1,7 +1,7 @@ > /** @file > Implementation of driver entry point and driver binding protocol. > > -Copyright (c) 2004 - 2015, Intel Corporation. All rights reserved.<BR> > +Copyright (c) 2004 - 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 text of the license may be found at > @@ -403,6 +403,14 @@ SimpleNetworkDriverStart ( > > Snp->TxRxBufferSize = 0; > Snp->TxRxBuffer = NULL; > + > + Snp->RecycledTxBuf = AllocatePool (sizeof (UINT64) * > SNP_TX_BUFFER_INCREASEMENT); > + if (Snp->RecycledTxBuf == NULL) { > + Status = EFI_OUT_OF_RESOURCES; > + goto Error_DeleteSNP; > + } > + Snp->MaxRecycledTxBuf = SNP_TX_BUFFER_INCREASEMENT; > + Snp->RecycledTxBufCount = 0; > > if (Nii->Revision >= EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_REVISION) { > Snp->IfNum = Nii->IfNum; > @@ -678,6 +686,10 @@ SimpleNetworkDriverStart ( > > Error_DeleteSNP: > > + if (Snp->RecycledTxBuf != NULL) { > + FreePool (Snp->RecycledTxBuf); > + } > + > PciIo->FreeBuffer ( > PciIo, > SNP_MEM_PAGES (sizeof (SNP_DRIVER)), > @@ -790,6 +802,8 @@ SimpleNetworkDriverStop ( > PxeShutdown (Snp); > PxeStop (Snp); > > + FreePool (Snp->RecycledTxBuf); > + > PciIo = Snp->PciIo; > PciIo->FreeBuffer ( > PciIo, > diff --git a/MdeModulePkg/Universal/Network/SnpDxe/Snp.h > b/MdeModulePkg/Universal/Network/SnpDxe/Snp.h > index f1d0ab3..67f65ff 100644 > --- a/MdeModulePkg/Universal/Network/SnpDxe/Snp.h > +++ b/MdeModulePkg/Universal/Network/SnpDxe/Snp.h > @@ -1,7 +1,7 @@ > /** @file > Declaration of strctures and functions for SnpDxe driver. > > -Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.<BR> > +Copyright (c) 2004 - 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 text of the license may be found at > @@ -49,6 +49,9 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER > EXPRESS OR IMPLIED. > #define PCI_BAR_MEM_MODE 0x00000000 > #define PCI_BAR_MEM_64BIT 0x00000004 > > +#define SNP_TX_BUFFER_INCREASEMENT MAX_XMIT_BUFFERS > +#define SNP_MAX_TX_BUFFER_NUM 65536 > + > typedef > EFI_STATUS > (EFIAPI *ISSUE_UNDI32_COMMAND) ( > @@ -130,6 +133,19 @@ typedef struct { > // i.e. PXE_STATFLAGS_GET_STATUS_NO_MEDIA_SUPPORTED > // > BOOLEAN MediaStatusSupported; > + > + // > + // Array of the recycled transmit buffer address from UNDI. > + // > + UINT64 *RecycledTxBuf; > + // > + // The maximum number of recycled buffer pointers in RecycledTxBuf. > + // > + UINT32 MaxRecycledTxBuf; > + // > + // Current number of recycled buffer pointers in RecycledTxBuf. > + // > + UINT32 RecycledTxBufCount; > } SNP_DRIVER; > > #define EFI_SIMPLE_NETWORK_DEV_FROM_THIS(a) CR (a, SNP_DRIVER, Snp, > SNP_DRIVER_SIGNATURE) > _______________________________________________ edk2-devel mailing list [email protected] https://lists.01.org/mailman/listinfo/edk2-devel

