On 01/07/16 11:32, Gary Lin wrote:
> 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.

Stashing this for later, many thanks.

Laszlo

> 
> 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:ler...@redhat.com] 
>>> Sent: Tuesday, January 5, 2016 7:26 PM
>>> To: Fu, Siyuan <siyuan...@intel.com>
>>> Cc: edk2-de...@ml01.01.org; Ye, Ting <ting...@intel.com>; Wu, Jiaxin 
>>> <jiaxin...@intel.com>
>>> 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 <siyuan...@intel.com>
>>>> ---
>>>>  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
>> edk2-devel@lists.01.org
>> https://lists.01.org/mailman/listinfo/edk2-devel
>>
> _______________________________________________
> edk2-devel mailing list
> edk2-devel@lists.01.org
> https://lists.01.org/mailman/listinfo/edk2-devel
> 

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel

Reply via email to