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

Reply via email to