On Wed, Jan 06, 2016 at 01:28:40PM +0100, Laszlo Ersek wrote: > On 01/06/16 01:55, Fu, Siyuan wrote: > > Hi, Laszlo > > > > You suggestion make sense, I will separate the patch into 2 commits > > when check in it. > > Thanks. > > > For the second question, this patch only make the TX buffer recycle > > asynchronously and it's handled internal the MNP driver itself. For > > the MNP's consumer point of view the function behaves exactly same as > > before. > > Right. > > > But this patch also depends on a correctly implementation of > > the UNDI GetStatus command, which should return the recycled TX > > buffer address in it, and we are planning to update the SCT test case > > to cover this point. > > In your environment, you probably have a > > [UNDI] -> [SnpDxe] -> [MnpDxe] -> [...] > > driver / protocol chain. The one that I have in mind however is > > [NIC specific SNP driver] -> [MnpDxe] -> [...] > > This is what I could test (without any UNDI dependency), if I only knew > what to use for the "[...]" part. > > > In our test environment, this patch could improve about 20% download > > speed of the HTTP boot. This result could be different on other > > platform and NIC, but I think the user should be able to see the > > better download performance. > > That's great, thanks! > > I've never tried HTTP boot before. I found some hints at > <http://ipxe.org/appnote/uefihttp>, but I don't use "ISC dhcpd" -- in my > (virtual) environment, DHCP is provided by "dnsmasq", and that is in > turn configured by libvirtd. > > Based on the docs <http://libvirt.org/formatnetwork.html>, I don't think > it is currently possible to set up HTTP netboot with libvirtd. > I used dnsmasq to setup a DHCP server for HTTP boot before. Just 2 more options in my config:
dhcp-option=60,"HTTPClient" dhcp-boot="http://192.168.111.1/default.efi" Hope this helps. Cheers, Gary Lin > I guess I could set up an independent DHCP server or config, but maybe > there's a simpler way. In the UEFI shell, the TFTP command enables the > user to download a file with TFTP. This seems to be implemented in > ShellPkg/Library/UefiShellTftpCommandLib. > > Is there a similar shell command for HTTP perhaps? > > ... Anyway I better read "23.7 HTTP Boot" now. > > Thanks! > Laszlo > > > > > Best Regards > > Siyuan > > > > -----Original Message----- > > From: Laszlo Ersek [mailto:[email protected]] > > Sent: Tuesday, January 5, 2016 7:26 PM > > To: Fu, Siyuan <[email protected]> > > Cc: [email protected]; Ye, Ting <[email protected]>; Wu, Jiaxin > > <[email protected]> > > Subject: Re: [edk2] [PATCH v2] MdeModulePkg: Update MNP driver to recycle > > TX buffer asynchronously. > > > > 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 > _______________________________________________ edk2-devel mailing list [email protected] https://lists.01.org/mailman/listinfo/edk2-devel

