]> git.proxmox.com Git - mirror_edk2.git/commitdiff
MdeModulePkg: Update MNP driver to recycle TX buffer asynchronously.
authorFu Siyuan <siyuan.fu@intel.com>
Fri, 8 Jan 2016 02:38:34 +0000 (02:38 +0000)
committersfu5 <sfu5@Edk2>
Fri, 8 Jan 2016 02:38:34 +0000 (02:38 +0000)
This patch updates the MNP driver to recycle TX buffer asynchronously, instead
of using a while loop wait after each transmit command.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Fu Siyuan <siyuan.fu@intel.com>
Reviewed-by: Jiaxin Wu <jiaxin.wu@intel.com>
Reviewed-by: Ye Ting <ting.ye@intel.com>
git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@19624 6f19259b-4bc3-4df7-8a09-765794883524

MdeModulePkg/Universal/Network/MnpDxe/MnpConfig.c
MdeModulePkg/Universal/Network/MnpDxe/MnpDriver.h
MdeModulePkg/Universal/Network/MnpDxe/MnpImpl.h
MdeModulePkg/Universal/Network/MnpDxe/MnpIo.c
MdeModulePkg/Universal/Network/MnpDxe/MnpMain.c

index 046d4dfddccbc24b0f330389d7c16dec5075cb85..d1a4cb5dd2a3103727e833cad59d05e9a9b17a42 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   Implementation of Managed Network Protocol private services.\r
 \r
 /** @file\r
   Implementation of Managed Network Protocol private services.\r
 \r
-Copyright (c) 2005 - 2012, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2005 - 2016, Intel Corporation. All rights reserved.<BR>\r
 This program and the accompanying materials\r
 are licensed and made available under the terms and conditions\r
 of the BSD License which accompanies this distribution.  The full\r
 This program and the accompanying materials\r
 are licensed and made available under the terms and conditions\r
 of the BSD License which accompanies this distribution.  The full\r
@@ -209,6 +209,208 @@ MnpFreeNbuf (
   gBS->RestoreTPL (OldTpl);\r
 }\r
 \r
   gBS->RestoreTPL (OldTpl);\r
 }\r
 \r
+/**\r
+  Add Count of TX buffers to MnpDeviceData->AllTxBufList and MnpDeviceData->FreeTxBufList.\r
+  The length of the buffer is specified by MnpDeviceData->BufferLength.\r
+\r
+  @param[in, out]  MnpDeviceData         Pointer to the MNP_DEVICE_DATA.\r
+  @param[in]       Count                 Number of TX buffers to add.\r
+\r
+  @retval EFI_SUCCESS           The specified amount of TX buffers are allocated.\r
+  @retval EFI_OUT_OF_RESOURCES  Failed to allocate a TX buffer.\r
+\r
+**/\r
+EFI_STATUS\r
+MnpAddFreeTxBuf (\r
+  IN OUT MNP_DEVICE_DATA   *MnpDeviceData,\r
+  IN     UINTN             Count\r
+  )\r
+{\r
+  EFI_STATUS        Status;\r
+  UINT32            Index;\r
+  MNP_TX_BUF_WRAP   *TxBufWrap;\r
+\r
+  NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);\r
+  ASSERT ((Count > 0) && (MnpDeviceData->BufferLength > 0));\r
+\r
+  Status = EFI_SUCCESS;\r
+  for (Index = 0; Index < Count; Index++) {\r
+    TxBufWrap = (MNP_TX_BUF_WRAP*) AllocatePool (sizeof (MNP_TX_BUF_WRAP) + MnpDeviceData->BufferLength - 1);\r
+    if (TxBufWrap == NULL) {\r
+      DEBUG ((EFI_D_ERROR, "MnpAddFreeTxBuf: TxBuf Alloc failed.\n"));\r
+\r
+      Status = EFI_OUT_OF_RESOURCES;\r
+      break;\r
+    }\r
+    DEBUG ((EFI_D_INFO, "MnpAddFreeTxBuf: Add TxBufWrap %p, TxBuf %p\n", TxBufWrap, TxBufWrap->TxBuf));\r
+    TxBufWrap->Signature = MNP_TX_BUF_WRAP_SIGNATURE;\r
+    TxBufWrap->InUse     = FALSE;\r
+    InsertTailList (&MnpDeviceData->FreeTxBufList, &TxBufWrap->WrapEntry);\r
+    InsertTailList (&MnpDeviceData->AllTxBufList, &TxBufWrap->AllEntry);\r
+  }\r
+\r
+  MnpDeviceData->TxBufCount += Index;\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Allocate a free TX buffer from MnpDeviceData->FreeTxBufList. If there is none\r
+  in the queue, first try to recycle some from SNP, then try to allocate some and add \r
+  them into the queue, then fetch the NET_BUF from the updated FreeTxBufList.\r
+\r
+  @param[in, out]  MnpDeviceData        Pointer to the MNP_DEVICE_DATA.\r
+\r
+  @return     Pointer to the allocated free NET_BUF structure, if NULL the\r
+              operation is failed.\r
+\r
+**/\r
+UINT8 *\r
+MnpAllocTxBuf (\r
+  IN OUT MNP_DEVICE_DATA   *MnpDeviceData\r
+  )\r
+{\r
+  EFI_TPL           OldTpl;\r
+  UINT8             *TxBuf;\r
+  EFI_STATUS        Status;\r
+  LIST_ENTRY        *Entry;\r
+  MNP_TX_BUF_WRAP   *TxBufWrap;\r
+  \r
+  NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);\r
+\r
+  OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
+\r
+  if (IsListEmpty (&MnpDeviceData->FreeTxBufList)) {\r
+    //\r
+    // First try to recycle some TX buffer from SNP\r
+    //\r
+    Status = MnpRecycleTxBuf (MnpDeviceData);\r
+    if (EFI_ERROR (Status)) {\r
+      TxBuf = NULL;\r
+      goto ON_EXIT;\r
+    }\r
+\r
+    //\r
+    // If still no free TX buffer, allocate more.\r
+    //\r
+    if (IsListEmpty (&MnpDeviceData->FreeTxBufList)) {\r
+      if ((MnpDeviceData->TxBufCount + MNP_TX_BUFFER_INCREASEMENT) > MNP_MAX_TX_BUFFER_NUM) {\r
+        DEBUG (\r
+          (EFI_D_ERROR,\r
+          "MnpAllocTxBuf: The maximum TxBuf size is reached for MNP driver instance %p.\n",\r
+          MnpDeviceData)\r
+          );\r
+\r
+        TxBuf = NULL;\r
+        goto ON_EXIT;\r
+      }\r
+\r
+      Status = MnpAddFreeTxBuf (MnpDeviceData, MNP_TX_BUFFER_INCREASEMENT);\r
+      if (IsListEmpty (&MnpDeviceData->FreeTxBufList)) {\r
+        DEBUG (\r
+          (EFI_D_ERROR,\r
+          "MnpAllocNbuf: Failed to add TxBuf into the FreeTxBufList, %r.\n",\r
+          Status)\r
+          );\r
+\r
+        TxBuf = NULL;\r
+        goto ON_EXIT;\r
+      }\r
+    }\r
+  }\r
+\r
+  ASSERT (!IsListEmpty (&MnpDeviceData->FreeTxBufList));\r
+  Entry = MnpDeviceData->FreeTxBufList.ForwardLink;\r
+  RemoveEntryList (MnpDeviceData->FreeTxBufList.ForwardLink);\r
+  TxBufWrap = NET_LIST_USER_STRUCT_S (Entry, MNP_TX_BUF_WRAP, WrapEntry, MNP_TX_BUF_WRAP_SIGNATURE);\r
+  TxBufWrap->InUse = TRUE;\r
+  TxBuf = TxBufWrap->TxBuf;\r
+\r
+ON_EXIT:\r
+  gBS->RestoreTPL (OldTpl);\r
+\r
+  return TxBuf;\r
+}\r
+\r
+/**\r
+  Try to reclaim the TX buffer into the buffer pool.\r
+\r
+  @param[in, out]  MnpDeviceData         Pointer to the mnp device context data.\r
+  @param[in, out]  TxBuf                 Pointer to the TX buffer to free.\r
+\r
+**/\r
+VOID\r
+MnpFreeTxBuf (\r
+  IN OUT MNP_DEVICE_DATA   *MnpDeviceData,\r
+  IN OUT UINT8             *TxBuf\r
+  )\r
+{\r
+  MNP_TX_BUF_WRAP   *TxBufWrap;\r
+  EFI_TPL           OldTpl;\r
+\r
+  NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);\r
+\r
+  if (TxBuf == NULL) {\r
+    return;\r
+  }\r
+\r
+  TxBufWrap = NET_LIST_USER_STRUCT (TxBuf, MNP_TX_BUF_WRAP, TxBuf);\r
+  if (TxBufWrap->Signature != MNP_TX_BUF_WRAP_SIGNATURE) {\r
+    DEBUG (\r
+      (EFI_D_ERROR,\r
+      "MnpFreeTxBuf: Signature check failed in MnpFreeTxBuf.\n")\r
+      );\r
+    return;\r
+  }\r
+\r
+  if (!TxBufWrap->InUse) {\r
+    DEBUG (\r
+      (EFI_D_WARN,\r
+      "MnpFreeTxBuf: Duplicated recycle report from SNP.\n")\r
+      );\r
+    return;\r
+  }\r
+  \r
+  OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
+  InsertTailList (&MnpDeviceData->FreeTxBufList, &TxBufWrap->WrapEntry);\r
+  TxBufWrap->InUse = FALSE;\r
+  gBS->RestoreTPL (OldTpl);\r
+}\r
+\r
+/**\r
+  Try to recycle all the transmitted buffer address from SNP.\r
+\r
+  @param[in, out]  MnpDeviceData     Pointer to the mnp device context data.\r
+\r
+  @retval EFI_SUCCESS             Successed to recyclethe transmitted buffer address.\r
+  @retval Others                  Failed to recyclethe transmitted buffer address.\r
+\r
+**/\r
+EFI_STATUS\r
+MnpRecycleTxBuf (\r
+  IN OUT MNP_DEVICE_DATA   *MnpDeviceData\r
+  )\r
+{\r
+  UINT8                         *TxBuf;\r
+  EFI_SIMPLE_NETWORK_PROTOCOL   *Snp;\r
+  EFI_STATUS                    Status;\r
+\r
+  Snp = MnpDeviceData->Snp;\r
+  ASSERT (Snp != NULL);\r
+\r
+  do {\r
+    TxBuf = NULL;\r
+    Status = Snp->GetStatus (Snp, NULL, (VOID **) &TxBuf);\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+\r
+    if (TxBuf != NULL) {\r
+      MnpFreeTxBuf (MnpDeviceData, TxBuf);\r
+    }\r
+  } while (TxBuf != NULL);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
 \r
 /**\r
   Initialize the mnp device context data.\r
 \r
 /**\r
   Initialize the mnp device context data.\r
@@ -314,13 +516,9 @@ MnpInitializeDeviceData (
   //\r
   // Allocate buffer pool for tx.\r
   //\r
   //\r
   // Allocate buffer pool for tx.\r
   //\r
-  MnpDeviceData->TxBuf = AllocatePool (MnpDeviceData->BufferLength);\r
-  if (MnpDeviceData->TxBuf == NULL) {\r
-    DEBUG ((EFI_D_ERROR, "MnpInitializeDeviceData: AllocatePool failed.\n"));\r
-\r
-    Status = EFI_OUT_OF_RESOURCES;\r
-    goto ERROR;\r
-  }\r
+  InitializeListHead (&MnpDeviceData->FreeTxBufList);\r
+  InitializeListHead (&MnpDeviceData->AllTxBufList);\r
+  MnpDeviceData->TxBufCount = 0;\r
 \r
   //\r
   // Create the system poll timer.\r
 \r
   //\r
   // Create the system poll timer.\r
@@ -370,20 +568,6 @@ MnpInitializeDeviceData (
     goto ERROR;\r
   }\r
 \r
     goto ERROR;\r
   }\r
 \r
-  //\r
-  // Create the timer for tx timeout check.\r
-  //\r
-  Status = gBS->CreateEvent (\r
-                  EVT_TIMER,\r
-                  TPL_CALLBACK,\r
-                  NULL,\r
-                  NULL,\r
-                  &MnpDeviceData->TxTimeoutEvent\r
-                  );\r
-  if (EFI_ERROR (Status)) {\r
-    DEBUG ((EFI_D_ERROR, "MnpInitializeDeviceData: CreateEvent for tx timeout event failed.\n"));\r
-  }\r
-\r
 ERROR:\r
   if (EFI_ERROR (Status)) {\r
     //\r
 ERROR:\r
   if (EFI_ERROR (Status)) {\r
     //\r
@@ -405,10 +589,6 @@ ERROR:
       gBS->CloseEvent (MnpDeviceData->PollTimer);\r
     }\r
 \r
       gBS->CloseEvent (MnpDeviceData->PollTimer);\r
     }\r
 \r
-    if (MnpDeviceData->TxBuf != NULL) {\r
-      FreePool (MnpDeviceData->TxBuf);\r
-    }\r
-\r
     if (MnpDeviceData->RxNbufCache != NULL) {\r
       MnpFreeNbuf (MnpDeviceData, MnpDeviceData->RxNbufCache);\r
     }\r
     if (MnpDeviceData->RxNbufCache != NULL) {\r
       MnpFreeNbuf (MnpDeviceData, MnpDeviceData->RxNbufCache);\r
     }\r
@@ -445,6 +625,10 @@ MnpDestroyDeviceData (
   IN     EFI_HANDLE        ImageHandle\r
   )\r
 {\r
   IN     EFI_HANDLE        ImageHandle\r
   )\r
 {\r
+  LIST_ENTRY         *Entry;\r
+  LIST_ENTRY         *NextEntry;\r
+  MNP_TX_BUF_WRAP    *TxBufWrap;\r
+\r
   NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);\r
 \r
   //\r
   NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);\r
 \r
   //\r
@@ -462,15 +646,21 @@ MnpDestroyDeviceData (
   //\r
   // Close the event.\r
   //\r
   //\r
   // Close the event.\r
   //\r
-  gBS->CloseEvent (MnpDeviceData->TxTimeoutEvent);\r
   gBS->CloseEvent (MnpDeviceData->TimeoutCheckTimer);\r
   gBS->CloseEvent (MnpDeviceData->MediaDetectTimer);\r
   gBS->CloseEvent (MnpDeviceData->PollTimer);\r
 \r
   //\r
   gBS->CloseEvent (MnpDeviceData->TimeoutCheckTimer);\r
   gBS->CloseEvent (MnpDeviceData->MediaDetectTimer);\r
   gBS->CloseEvent (MnpDeviceData->PollTimer);\r
 \r
   //\r
-  // Free the tx buffer.\r
+  // Free the Tx buffer pool.\r
   //\r
   //\r
-  FreePool (MnpDeviceData->TxBuf);\r
+  NET_LIST_FOR_EACH_SAFE(Entry, NextEntry, &MnpDeviceData->AllTxBufList) {\r
+    TxBufWrap = NET_LIST_USER_STRUCT (Entry, MNP_TX_BUF_WRAP, AllEntry);\r
+    RemoveEntryList (Entry);\r
+    FreePool (TxBufWrap);\r
+    MnpDeviceData->TxBufCount--;\r
+  }\r
+  ASSERT (IsListEmpty (&MnpDeviceData->AllTxBufList));\r
+  ASSERT (MnpDeviceData->TxBufCount == 0);\r
 \r
   //\r
   // Free the RxNbufCache.\r
 \r
   //\r
   // Free the RxNbufCache.\r
@@ -957,7 +1147,7 @@ MnpStartSnp (
 /**\r
   Stop the simple network.\r
 \r
 /**\r
   Stop the simple network.\r
 \r
-  @param[in]  Snp               Pointer to the simple network protocol.\r
+  @param[in]  MnpDeviceData     Pointer to the MNP_DEVICE_DATA.\r
 \r
   @retval EFI_SUCCESS           The simple network is stopped.\r
   @retval Others                Other errors as indicated.\r
 \r
   @retval EFI_SUCCESS           The simple network is stopped.\r
   @retval Others                Other errors as indicated.\r
@@ -965,13 +1155,23 @@ MnpStartSnp (
 **/\r
 EFI_STATUS\r
 MnpStopSnp (\r
 **/\r
 EFI_STATUS\r
 MnpStopSnp (\r
-  IN EFI_SIMPLE_NETWORK_PROTOCOL     *Snp\r
+  IN  MNP_DEVICE_DATA   *MnpDeviceData\r
   )\r
 {\r
   EFI_STATUS  Status;\r
   )\r
 {\r
   EFI_STATUS  Status;\r
-\r
+  EFI_SIMPLE_NETWORK_PROTOCOL     *Snp;\r
+  \r
+  Snp = MnpDeviceData->Snp;\r
   ASSERT (Snp != NULL);\r
 \r
   ASSERT (Snp != NULL);\r
 \r
+  //\r
+  // Recycle all the transmit buffer from SNP.\r
+  //\r
+  Status = MnpRecycleTxBuf (MnpDeviceData);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
   //\r
   // Shut down the simple network.\r
   //\r
   //\r
   // Shut down the simple network.\r
   //\r
@@ -1162,7 +1362,7 @@ MnpStop (
   //\r
   // Stop the simple network.\r
   //\r
   //\r
   // Stop the simple network.\r
   //\r
-  Status = MnpStopSnp (MnpDeviceData->Snp);\r
+  Status = MnpStopSnp (MnpDeviceData);\r
   return Status;\r
 }\r
 \r
   return Status;\r
 }\r
 \r
index 35a9b710dbfa33b8eeb71288297fdd5bd4bf5d4b..126d9682001cc585a58d9982b5de591c6347bc5e 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   Declaration of strctures and functions for MnpDxe driver.\r
 \r
 /** @file\r
   Declaration of strctures and functions for MnpDxe driver.\r
 \r
-Copyright (c) 2005 - 2012, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2005 - 2016, Intel Corporation. All rights reserved.<BR>\r
 This program and the accompanying materials\r
 are licensed and made available under the terms and conditions\r
 of the BSD License which accompanies this distribution.  The full\r
 This program and the accompanying materials\r
 are licensed and made available under the terms and conditions\r
 of the BSD License which accompanies this distribution.  The full\r
@@ -67,7 +67,9 @@ typedef struct {
   LIST_ENTRY                    GroupAddressList;\r
   UINT32                        GroupAddressCount;\r
 \r
   LIST_ENTRY                    GroupAddressList;\r
   UINT32                        GroupAddressCount;\r
 \r
-  EFI_EVENT                     TxTimeoutEvent;\r
+  LIST_ENTRY                    FreeTxBufList;\r
+  LIST_ENTRY                    AllTxBufList;\r
+  UINT32                        TxBufCount;\r
 \r
   NET_BUF_QUEUE                 FreeNbufQue;\r
   INTN                          NbufCnt;\r
 \r
   NET_BUF_QUEUE                 FreeNbufQue;\r
   INTN                          NbufCnt;\r
@@ -90,7 +92,6 @@ typedef struct {
   UINT32                        BufferLength;\r
   UINT32                        PaddingSize;\r
   NET_BUF                       *RxNbufCache;\r
   UINT32                        BufferLength;\r
   UINT32                        PaddingSize;\r
   NET_BUF                       *RxNbufCache;\r
-  UINT8                         *TxBuf;\r
 } MNP_DEVICE_DATA;\r
 \r
 #define MNP_DEVICE_DATA_FROM_THIS(a) \\r
 } MNP_DEVICE_DATA;\r
 \r
 #define MNP_DEVICE_DATA_FROM_THIS(a) \\r
index f94e2083065aa5b4ce3d131906d8dd4d604fab50..c66be6487b82900179bb98f0d1ede00e09230ee2 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   Declaration of structures and functions of MnpDxe driver.\r
 \r
 /** @file\r
   Declaration of structures and functions of MnpDxe driver.\r
 \r
-Copyright (c) 2005 - 2010, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2005 - 2016, Intel Corporation. All rights reserved.<BR>\r
 This program and the accompanying materials\r
 are licensed and made available under the terms and conditions\r
 of the BSD License which accompanies this distribution.  The full\r
 This program and the accompanying materials\r
 are licensed and made available under the terms and conditions\r
 of the BSD License which accompanies this distribution.  The full\r
@@ -27,6 +27,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #define MNP_INIT_NET_BUFFER_NUM       512\r
 #define MNP_NET_BUFFER_INCREASEMENT   64\r
 #define MNP_MAX_NET_BUFFER_NUM        65536\r
 #define MNP_INIT_NET_BUFFER_NUM       512\r
 #define MNP_NET_BUFFER_INCREASEMENT   64\r
 #define MNP_MAX_NET_BUFFER_NUM        65536\r
+#define MNP_TX_BUFFER_INCREASEMENT    64\r
+#define MNP_MAX_TX_BUFFER_NUM         65536\r
 \r
 #define MNP_MAX_RCVD_PACKET_QUE_SIZE  256\r
 \r
 \r
 #define MNP_MAX_RCVD_PACKET_QUE_SIZE  256\r
 \r
@@ -92,6 +94,15 @@ typedef struct {
   UINT64                            TimeoutTick;\r
 } MNP_RXDATA_WRAP;\r
 \r
   UINT64                            TimeoutTick;\r
 } MNP_RXDATA_WRAP;\r
 \r
+#define MNP_TX_BUF_WRAP_SIGNATURE   SIGNATURE_32 ('M', 'T', 'B', 'W')\r
+\r
+typedef struct {\r
+  UINT32                  Signature;\r
+  LIST_ENTRY              WrapEntry;  // Link to FreeTxBufList\r
+  LIST_ENTRY              AllEntry;   // Link to AllTxBufList\r
+  BOOLEAN                 InUse;\r
+  UINT8                   TxBuf[1];\r
+} MNP_TX_BUF_WRAP;\r
 \r
 /**\r
   Initialize the mnp device context data.\r
 \r
 /**\r
   Initialize the mnp device context data.\r
@@ -342,8 +353,11 @@ MnpIsValidTxToken (
   @param[out]  PktLen              Pointer to a UINT32 variable used to record the packet's\r
                                    length.\r
 \r
   @param[out]  PktLen              Pointer to a UINT32 variable used to record the packet's\r
                                    length.\r
 \r
+  @retval EFI_SUCCESS           TxPackage is built.\r
+  @retval EFI_OUT_OF_RESOURCES  The deliver fails due to lack of memory resource.\r
+\r
 **/\r
 **/\r
-VOID\r
+EFI_STATUS\r
 MnpBuildTxPacket (\r
   IN     MNP_SERVICE_DATA                    *MnpServiceData,\r
   IN     EFI_MANAGED_NETWORK_TRANSMIT_DATA   *TxData,\r
 MnpBuildTxPacket (\r
   IN     MNP_SERVICE_DATA                    *MnpServiceData,\r
   IN     EFI_MANAGED_NETWORK_TRANSMIT_DATA   *TxData,\r
@@ -352,7 +366,11 @@ MnpBuildTxPacket (
   );\r
 \r
 /**\r
   );\r
 \r
 /**\r
-  Synchronously send out the packet.\r
+  Synchronously send out the packet. \r
+\r
+  This functon places the packet buffer to SNP driver's tansmit queue. The packet\r
+  can be considered successfully sent out once SNP acccetp the packet, while the\r
+  packet buffer recycle is deferred for better performance.\r
 \r
   @param[in]       MnpServiceData      Pointer to the mnp service context data.\r
   @param[in]       Packet              Pointer to the pakcet buffer.\r
 \r
   @param[in]       MnpServiceData      Pointer to the mnp service context data.\r
   @param[in]       Packet              Pointer to the pakcet buffer.\r
@@ -448,6 +466,36 @@ MnpFreeNbuf (
   IN OUT NET_BUF           *Nbuf\r
   );\r
 \r
   IN OUT NET_BUF           *Nbuf\r
   );\r
 \r
+/**\r
+  Allocate a free TX buffer from MnpDeviceData->FreeTxBufList. If there is none\r
+  in the queue, first try to recycle some from SNP, then try to allocate some and add \r
+  them into the queue, then fetch the NET_BUF from the updated FreeTxBufList.\r
+\r
+  @param[in, out]  MnpDeviceData        Pointer to the MNP_DEVICE_DATA.\r
+\r
+  @return     Pointer to the allocated free NET_BUF structure, if NULL the\r
+              operation is failed.\r
+\r
+**/\r
+UINT8 *\r
+MnpAllocTxBuf (\r
+  IN OUT MNP_DEVICE_DATA   *MnpDeviceData\r
+  );\r
+\r
+/**\r
+  Try to recycle all the transmitted buffer address from SNP.\r
+\r
+  @param[in, out]  MnpDeviceData     Pointer to the mnp device context data.\r
+\r
+  @retval EFI_SUCCESS             Successed to recyclethe transmitted buffer address.\r
+  @retval Others                  Failed to recyclethe transmitted buffer address.\r
+\r
+**/\r
+EFI_STATUS\r
+MnpRecycleTxBuf (\r
+  IN OUT MNP_DEVICE_DATA   *MnpDeviceData\r
+  );\r
+\r
 /**\r
   Remove the received packets if timeout occurs.\r
 \r
 /**\r
   Remove the received packets if timeout occurs.\r
 \r
index 7f03b848ef396fda0f75b0cbe8149340f669092d..1cbfc30e5c21128e8c44fb382fe866ce5c44d5aa 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   Implementation of Managed Network Protocol I/O functions.\r
 \r
 /** @file\r
   Implementation of Managed Network Protocol I/O functions.\r
 \r
-Copyright (c) 2005 - 2014, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2005 - 2016, Intel Corporation. All rights reserved.<BR>\r
 This program and the accompanying materials\r
 are licensed and made available under the terms and conditions\r
 of the BSD License which accompanies this distribution.  The full\r
 This program and the accompanying materials\r
 are licensed and made available under the terms and conditions\r
 of the BSD License which accompanies this distribution.  The full\r
@@ -102,7 +102,6 @@ MnpIsValidTxToken (
   return TRUE;\r
 }\r
 \r
   return TRUE;\r
 }\r
 \r
-\r
 /**\r
   Build the packet to transmit from the TxData passed in.\r
 \r
 /**\r
   Build the packet to transmit from the TxData passed in.\r
 \r
@@ -113,8 +112,11 @@ MnpIsValidTxToken (
   @param[out]  PktLen              Pointer to a UINT32 variable used to record the packet's\r
                                    length.\r
 \r
   @param[out]  PktLen              Pointer to a UINT32 variable used to record the packet's\r
                                    length.\r
 \r
+  @retval EFI_SUCCESS           TxPackage is built.\r
+  @retval EFI_OUT_OF_RESOURCES  The deliver fails due to lack of memory resource.\r
+\r
 **/\r
 **/\r
-VOID\r
+EFI_STATUS\r
 MnpBuildTxPacket (\r
   IN     MNP_SERVICE_DATA                    *MnpServiceData,\r
   IN     EFI_MANAGED_NETWORK_TRANSMIT_DATA   *TxData,\r
 MnpBuildTxPacket (\r
   IN     MNP_SERVICE_DATA                    *MnpServiceData,\r
   IN     EFI_MANAGED_NETWORK_TRANSMIT_DATA   *TxData,\r
@@ -125,14 +127,24 @@ MnpBuildTxPacket (
   EFI_SIMPLE_NETWORK_MODE *SnpMode;\r
   UINT8                   *DstPos;\r
   UINT16                  Index;\r
   EFI_SIMPLE_NETWORK_MODE *SnpMode;\r
   UINT8                   *DstPos;\r
   UINT16                  Index;\r
-  MNP_DEVICE_DATA         *MnpDerviceData;\r
-\r
-  MnpDerviceData = MnpServiceData->MnpDeviceData;\r
-\r
+  MNP_DEVICE_DATA         *MnpDeviceData;\r
+  UINT8                   *TxBuf;\r
+  \r
+  MnpDeviceData = MnpServiceData->MnpDeviceData;\r
+  \r
+  TxBuf = MnpAllocTxBuf (MnpDeviceData);\r
+  if (TxBuf == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+  \r
   //\r
   //\r
-  // Reserve space for vlan tag.\r
+  // Reserve space for vlan tag if needed.\r
   //\r
   //\r
-  *PktBuf = MnpDerviceData->TxBuf + NET_VLAN_TAG_LEN;\r
+  if (MnpServiceData->VlanId != 0) {\r
+    *PktBuf = TxBuf + NET_VLAN_TAG_LEN;\r
+  } else {\r
+    *PktBuf = TxBuf;\r
+  }\r
   \r
   if ((TxData->DestinationAddress == NULL) && (TxData->FragmentCount == 1)) {\r
     CopyMem (\r
   \r
   if ((TxData->DestinationAddress == NULL) && (TxData->FragmentCount == 1)) {\r
     CopyMem (\r
@@ -148,7 +160,7 @@ MnpBuildTxPacket (
     // one fragment, copy the data into the packet buffer. Reserve the\r
     // media header space if necessary.\r
     //\r
     // one fragment, copy the data into the packet buffer. Reserve the\r
     // media header space if necessary.\r
     //\r
-    SnpMode = MnpDerviceData->Snp->Mode; \r
+    SnpMode = MnpDeviceData->Snp->Mode; \r
     DstPos  = *PktBuf;\r
     *PktLen = 0;\r
     if (TxData->DestinationAddress != NULL) {\r
     DstPos  = *PktBuf;\r
     *PktLen = 0;\r
     if (TxData->DestinationAddress != NULL) {\r
@@ -177,11 +189,17 @@ MnpBuildTxPacket (
     //\r
     *PktLen += TxData->DataLength + TxData->HeaderLength;\r
   }\r
     //\r
     *PktLen += TxData->DataLength + TxData->HeaderLength;\r
   }\r
+\r
+  return EFI_SUCCESS;\r
 }\r
 \r
 \r
 /**\r
 }\r
 \r
 \r
 /**\r
-  Synchronously send out the packet.\r
+  Synchronously send out the packet. \r
+\r
+  This functon places the packet buffer to SNP driver's tansmit queue. The packet\r
+  can be considered successfully sent out once SNP acccetp the packet, while the\r
+  packet buffer recycle is deferred for better performance.\r
 \r
   @param[in]       MnpServiceData      Pointer to the mnp service context data.\r
   @param[in]       Packet              Pointer to the pakcet buffer.\r
 \r
   @param[in]       MnpServiceData      Pointer to the mnp service context data.\r
   @param[in]       Packet              Pointer to the pakcet buffer.\r
@@ -205,14 +223,13 @@ MnpSyncSendPacket (
   EFI_SIMPLE_NETWORK_PROTOCOL       *Snp;\r
   EFI_MANAGED_NETWORK_TRANSMIT_DATA *TxData;\r
   UINT32                            HeaderSize;\r
   EFI_SIMPLE_NETWORK_PROTOCOL       *Snp;\r
   EFI_MANAGED_NETWORK_TRANSMIT_DATA *TxData;\r
   UINT32                            HeaderSize;\r
-  UINT8                             *TxBuf;\r
   MNP_DEVICE_DATA                   *MnpDeviceData;\r
   UINT16                            ProtocolType;\r
 \r
   MnpDeviceData = MnpServiceData->MnpDeviceData;\r
   Snp           = MnpDeviceData->Snp;\r
   TxData        = Token->Packet.TxData;\r
   MNP_DEVICE_DATA                   *MnpDeviceData;\r
   UINT16                            ProtocolType;\r
 \r
   MnpDeviceData = MnpServiceData->MnpDeviceData;\r
   Snp           = MnpDeviceData->Snp;\r
   TxData        = Token->Packet.TxData;\r
-\r
+  Token->Status = EFI_SUCCESS;\r
   HeaderSize    = Snp->Mode->MediaHeaderSize - TxData->HeaderLength;\r
 \r
   //\r
   HeaderSize    = Snp->Mode->MediaHeaderSize - TxData->HeaderLength;\r
 \r
   //\r
@@ -224,19 +241,7 @@ MnpSyncSendPacket (
     // Media not present, skip packet transmit and report EFI_NO_MEDIA\r
     //\r
     DEBUG ((EFI_D_WARN, "MnpSyncSendPacket: No network cable detected.\n"));\r
     // Media not present, skip packet transmit and report EFI_NO_MEDIA\r
     //\r
     DEBUG ((EFI_D_WARN, "MnpSyncSendPacket: No network cable detected.\n"));\r
-    Status = EFI_NO_MEDIA;\r
-    goto SIGNAL_TOKEN;\r
-  }\r
-\r
-  //\r
-  // Start the timeout event.\r
-  //\r
-  Status = gBS->SetTimer (\r
-                  MnpDeviceData->TxTimeoutEvent,\r
-                  TimerRelative,\r
-                  MNP_TX_TIMEOUT_TIME\r
-                  );\r
-  if (EFI_ERROR (Status)) {\r
+    Token->Status = EFI_NO_MEDIA;\r
     goto SIGNAL_TOKEN;\r
   }\r
 \r
     goto SIGNAL_TOKEN;\r
   }\r
 \r
@@ -250,10 +255,25 @@ MnpSyncSendPacket (
     ProtocolType = TxData->ProtocolType;\r
   }\r
 \r
     ProtocolType = TxData->ProtocolType;\r
   }\r
 \r
-  for (;;) {\r
-    //\r
-    // Transmit the packet through SNP.\r
-    //\r
+  //\r
+  // Transmit the packet through SNP.\r
+  //\r
+  Status = Snp->Transmit (\r
+                  Snp,\r
+                  HeaderSize,\r
+                  Length,\r
+                  Packet,\r
+                  TxData->SourceAddress,\r
+                  TxData->DestinationAddress,\r
+                  &ProtocolType\r
+                  );\r
+  if (Status == EFI_NOT_READY) {\r
+    Status = MnpRecycleTxBuf (MnpDeviceData);\r
+    if (EFI_ERROR (Status)) {\r
+      Token->Status = EFI_DEVICE_ERROR;\r
+      goto SIGNAL_TOKEN;\r
+    }\r
+\r
     Status = Snp->Transmit (\r
                     Snp,\r
                     HeaderSize,\r
     Status = Snp->Transmit (\r
                     Snp,\r
                     HeaderSize,\r
@@ -262,52 +282,15 @@ MnpSyncSendPacket (
                     TxData->SourceAddress,\r
                     TxData->DestinationAddress,\r
                     &ProtocolType\r
                     TxData->SourceAddress,\r
                     TxData->DestinationAddress,\r
                     &ProtocolType\r
-                    );\r
-    if ((Status != EFI_SUCCESS) && (Status != EFI_NOT_READY)) {\r
-      Status = EFI_DEVICE_ERROR;\r
-      break;\r
-    }\r
-\r
-    //\r
-    // If Status is EFI_SUCCESS, the packet is put in the transmit queue.\r
-    // if Status is EFI_NOT_READY, the transmit engine of the network interface is busy.\r
-    // Both need to sync SNP.\r
-    //\r
-    TxBuf = NULL;\r
-    do {\r
-      //\r
-      // Get the recycled transmit buffer status.\r
-      //\r
-      Snp->GetStatus (Snp, NULL, (VOID **) &TxBuf);\r
-\r
-      if (!EFI_ERROR (gBS->CheckEvent (MnpDeviceData->TxTimeoutEvent))) {\r
-        Status = EFI_TIMEOUT;\r
-        break;\r
-      }\r
-    } while (TxBuf == NULL);\r
-\r
-    if ((Status == EFI_SUCCESS) || (Status == EFI_TIMEOUT)) {\r
-      break;\r
-    } else {\r
-      //\r
-      // Status is EFI_NOT_READY. Restart the timer event and call Snp->Transmit again.\r
-      //\r
-      gBS->SetTimer (\r
-            MnpDeviceData->TxTimeoutEvent,\r
-            TimerRelative,\r
-            MNP_TX_TIMEOUT_TIME\r
-            );\r
-    }\r
+                    ); \r
+  }\r
+  \r
+  if (EFI_ERROR (Status)) {\r
+    Token->Status = EFI_DEVICE_ERROR;\r
   }\r
   }\r
-\r
-  //\r
-  // Cancel the timer event.\r
-  //\r
-  gBS->SetTimer (MnpDeviceData->TxTimeoutEvent, TimerCancel, 0);\r
 \r
 SIGNAL_TOKEN:\r
 \r
 \r
 SIGNAL_TOKEN:\r
 \r
-  Token->Status = Status;\r
   gBS->SignalEvent (Token->Event);\r
 \r
   //\r
   gBS->SignalEvent (Token->Event);\r
 \r
   //\r
index 4c0f3ddd9a9904daee2f6749e81bcff7ffc5cd82..31c2e3e5b849ed8cd24794c3e7cee7c54d52654d 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   Implementation of Managed Network Protocol public services.\r
 \r
 /** @file\r
   Implementation of Managed Network Protocol public services.\r
 \r
-Copyright (c) 2005 - 2010, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2005 - 2016, Intel Corporation. All rights reserved.<BR>\r
 This program and the accompanying materials\r
 are licensed and made available under the terms and conditions\r
 of the BSD License which accompanies this distribution.  The full\r
 This program and the accompanying materials\r
 are licensed and made available under the terms and conditions\r
 of the BSD License which accompanies this distribution.  The full\r
@@ -552,7 +552,10 @@ MnpTransmit (
   //\r
   // Build the tx packet\r
   //\r
   //\r
   // Build the tx packet\r
   //\r
-  MnpBuildTxPacket (MnpServiceData, Token->Packet.TxData, &PktBuf, &PktLen);\r
+  Status = MnpBuildTxPacket (MnpServiceData, Token->Packet.TxData, &PktBuf, &PktLen);\r
+  if (EFI_ERROR (Status)) {\r
+    goto ON_EXIT;\r
+  }\r
 \r
   //\r
   //  OK, send the packet synchronously.\r
 \r
   //\r
   //  OK, send the packet synchronously.\r