]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/Network/MnpDxe/MnpIo.c
MdeModulePkg: Update MNP driver to recycle TX buffer asynchronously.
[mirror_edk2.git] / MdeModulePkg / Universal / Network / MnpDxe / MnpIo.c
index b8f61bf696fe1d82e45b9122202e18ee59da1d67..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 - 2013, 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,19 +127,26 @@ 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
+  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
+  // Reserve space for vlan tag if needed.\r
+  //\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
   if ((TxData->DestinationAddress == NULL) && (TxData->FragmentCount == 1)) {\r
-    //\r
-    // Reserve space for vlan tag,if necessary.\r
-    //\r
-    if (MnpServiceData->VlanId != 0) {\r
-      *PktBuf = MnpDerviceData->TxBuf + NET_VLAN_TAG_LEN;\r
-    } else {\r
-      *PktBuf = MnpDerviceData->TxBuf;\r
-    } \r
-    \r
     CopyMem (\r
         *PktBuf,\r
         TxData->FragmentTable[0].FragmentBuffer,\r
     CopyMem (\r
         *PktBuf,\r
         TxData->FragmentTable[0].FragmentBuffer,\r
@@ -151,9 +160,8 @@ 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
-    DstPos  = MnpDerviceData->TxBuf;\r
-\r
+    SnpMode = MnpDeviceData->Snp->Mode; \r
+    DstPos  = *PktBuf;\r
     *PktLen = 0;\r
     if (TxData->DestinationAddress != NULL) {\r
       //\r
     *PktLen = 0;\r
     if (TxData->DestinationAddress != NULL) {\r
       //\r
@@ -177,16 +185,21 @@ MnpBuildTxPacket (
     }\r
 \r
     //\r
     }\r
 \r
     //\r
-    // Set the buffer pointer and the buffer length.\r
+    // Set the buffer length.\r
     //\r
     //\r
-    *PktBuf = MnpDerviceData->TxBuf;\r
     *PktLen += TxData->DataLength + TxData->HeaderLength;\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
@@ -210,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
@@ -229,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
@@ -255,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
@@ -267,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