Adding Josh

On 01/06/16 13:28, 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 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?

I just noticed that the most recent release of BITS provides a
standalone HTTP client!

http://biosbits.org/news/bits-2070/

Josh, a couple of points:

- edk2 doesn't provide EFI_IP4_CONFIG_PROTOCOL any longer; it provides
  EFI_IP4_CONFIG2_PROTOCOL. I haven't tested this new release of BITS
  just yet, but I know this caused problems for a few consumers of edk2.

- OVMF *should* provide EFI_DNS4_SERVICE_BINDING_PROTOCOL: if you
  build it with -D HTTP_BOOT_ENABLE, then "NetworkPkg/DnsDxe/DnsDxe.inf"
  gets included, and that INF file says:

[Protocols]
  gEfiDns4ServiceBindingProtocolGuid              ## BY_START

Are you using Gerd's RPMs?

Gerd, can you please add -D HTTP_BOOT_ENABLE to the OVMF (IA32 / X64)
build commands edk2.git.spec?

Thanks!
Laszlo


> 
> ... 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