MdeModulePkg: update SNP.GetStatus to handle multiple recycled TX buffer.
authorFu Siyuan <siyuan.fu@intel.com>
Fri, 8 Jan 2016 02:21:25 +0000 (02:21 +0000)
committersfu5 <sfu5@Edk2>
Fri, 8 Jan 2016 02:21:25 +0000 (02:21 +0000)
This patch fixes a bug in SNP.GetStatus() interface. 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.

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@19623 6f19259b-4bc3-4df7-8a09-765794883524

MdeModulePkg/Universal/Network/SnpDxe/Get_status.c
MdeModulePkg/Universal/Network/SnpDxe/Snp.c
MdeModulePkg/Universal/Network/SnpDxe/Snp.h

index 053297605b78c7b3e31624ed8fd795490ea68dbe..8f2ab9b24ab5b150acdbfb1eddd92d4164133311 100644 (file)
@@ -2,7 +2,7 @@
   Implementation of reading the current interrupt status and recycled transmit\r
   buffer status from a network interface.\r
 \r
-Copyright (c) 2004 - 2010, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2004 - 2016, Intel Corporation. All rights reserved.<BR>\r
 This program and the accompanying materials are licensed\r
 and made available under the terms and conditions of the BSD License which\r
 accompanies this distribution. The full text of the license may be found at\r
@@ -16,15 +16,15 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #include "Snp.h"\r
 \r
 /**\r
-  Call undi to get the status of the interrupts, get the list of transmit\r
-  buffers that completed transmitting.\r
+  Call undi to get the status of the interrupts, get the list of recycled transmit\r
+  buffers that completed transmitting. The recycled transmit buffer address will\r
+  be saved into Snp->RecycledTxBuf.\r
 \r
   @param  Snp                     Pointer to snp driver structure.\r
   @param  InterruptStatusPtr      A non null pointer to contain the interrupt\r
                                   status.\r
-  @param  TransmitBufferListPtrs  A non null pointer to contain the list of\r
-                                  pointers of previous transmitted buffers whose\r
-                                  transmission was completed asynchrnously.\r
+  @param  GetTransmittedBuf       Set to TRUE to retrieve the recycled transmit\r
+                                  buffer address.\r
 \r
   @retval EFI_SUCCESS         The status of the network interface was retrieved.\r
   @retval EFI_DEVICE_ERROR    The command could not be sent to the network\r
@@ -35,19 +35,23 @@ EFI_STATUS
 PxeGetStatus (\r
   SNP_DRIVER *Snp,\r
   UINT32     *InterruptStatusPtr,\r
-  VOID       **TransmitBufferListPtr\r
+  BOOLEAN    GetTransmittedBuf\r
   )\r
 {\r
   PXE_DB_GET_STATUS *Db;\r
   UINT16            InterruptFlags;\r
+  UINT32            Index;\r
+  UINT64            *Tmp;\r
 \r
+  Tmp               = NULL;\r
   Db                = Snp->Db;\r
   Snp->Cdb.OpCode   = PXE_OPCODE_GET_STATUS;\r
 \r
   Snp->Cdb.OpFlags  = 0;\r
 \r
-  if (TransmitBufferListPtr != NULL) {\r
+  if (GetTransmittedBuf) {\r
     Snp->Cdb.OpFlags |= PXE_OPFLAGS_GET_TRANSMITTED_BUFFERS;\r
+    ZeroMem (Db->TxBuffer, sizeof (Db->TxBuffer));\r
   }\r
 \r
   if (InterruptStatusPtr != NULL) {\r
@@ -116,13 +120,34 @@ PxeGetStatus (
 \r
   }\r
 \r
-  if (TransmitBufferListPtr != NULL) {\r
-    *TransmitBufferListPtr =\r
-      (\r
-        ((Snp->Cdb.StatFlags & PXE_STATFLAGS_GET_STATUS_NO_TXBUFS_WRITTEN) != 0) ||\r
-        ((Snp->Cdb.StatFlags & PXE_STATFLAGS_GET_STATUS_TXBUF_QUEUE_EMPTY) != 0)\r
-      ) ? 0 : (VOID *) (UINTN) Db->TxBuffer[0];\r
-\r
+  if (GetTransmittedBuf) {\r
+    if ((Snp->Cdb.StatFlags & PXE_STATFLAGS_GET_STATUS_NO_TXBUFS_WRITTEN) == 0) {\r
+      //\r
+      // UNDI has written some transmitted buffer addresses into the DB. Store them into Snp->RecycledTxBuf.\r
+      //\r
+      for (Index = 0; Index < MAX_XMIT_BUFFERS; Index++) {\r
+        if (Db->TxBuffer[Index] != 0) {\r
+          if (Snp->RecycledTxBufCount == Snp->MaxRecycledTxBuf) {\r
+            //\r
+            // Snp->RecycledTxBuf is full, reallocate a new one.\r
+            //\r
+            if ((Snp->MaxRecycledTxBuf + SNP_TX_BUFFER_INCREASEMENT) >= SNP_MAX_TX_BUFFER_NUM) {\r
+              return EFI_DEVICE_ERROR;\r
+            }\r
+            Tmp = AllocatePool (sizeof (UINT64) * (Snp->MaxRecycledTxBuf + SNP_TX_BUFFER_INCREASEMENT));\r
+            if (Tmp == NULL) {\r
+              return EFI_DEVICE_ERROR;\r
+            }\r
+            CopyMem (Tmp, Snp->RecycledTxBuf, sizeof (UINT64) * Snp->RecycledTxBufCount);\r
+            FreePool (Snp->RecycledTxBuf);\r
+            Snp->RecycledTxBuf    =  Tmp;\r
+            Snp->MaxRecycledTxBuf += SNP_TX_BUFFER_INCREASEMENT;\r
+          }\r
+          Snp->RecycledTxBuf[Snp->RecycledTxBufCount] = Db->TxBuffer[Index];\r
+          Snp->RecycledTxBufCount++;\r
+        }\r
+      }\r
+    }\r
   }\r
 \r
   //\r
@@ -216,7 +241,23 @@ SnpUndi32GetStatus (
     goto ON_EXIT;\r
   }\r
 \r
-  Status = PxeGetStatus (Snp, InterruptStatus, TxBuf);\r
+  if (Snp->RecycledTxBufCount == 0 && TxBuf != NULL) {\r
+    Status = PxeGetStatus (Snp, InterruptStatus, TRUE);\r
+  } else {\r
+    Status = PxeGetStatus (Snp, InterruptStatus, FALSE);\r
+  }\r
+\r
+  if (TxBuf != NULL) {\r
+    //\r
+    // Get a recycled buf from Snp->RecycledTxBuf\r
+    //\r
+    if (Snp->RecycledTxBufCount == 0) {\r
+      *TxBuf = NULL;\r
+    } else {\r
+      Snp->RecycledTxBufCount--;\r
+      *TxBuf = (VOID *) (UINTN) Snp->RecycledTxBuf[Snp->RecycledTxBufCount];\r
+    }\r
+  }\r
 \r
 ON_EXIT:\r
   gBS->RestoreTPL (OldTpl);\r
index db5b6267a613111bae3407cfc95c20a1e20b7699..5ff294f8b59b47d503edbc49e3f819c6c605eeb2 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   Implementation of driver entry point and driver binding protocol.\r
 \r
-Copyright (c) 2004 - 2015, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2004 - 2016, Intel Corporation. All rights reserved.<BR>\r
 This program and the accompanying materials are licensed\r
 and made available under the terms and conditions of the BSD License which\r
 accompanies this distribution. The full text of the license may be found at\r
@@ -403,6 +403,14 @@ SimpleNetworkDriverStart (
 \r
   Snp->TxRxBufferSize     = 0;\r
   Snp->TxRxBuffer         = NULL;\r
+\r
+  Snp->RecycledTxBuf = AllocatePool (sizeof (UINT64) * SNP_TX_BUFFER_INCREASEMENT);\r
+  if (Snp->RecycledTxBuf == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto Error_DeleteSNP;\r
+  }\r
+  Snp->MaxRecycledTxBuf    = SNP_TX_BUFFER_INCREASEMENT;\r
+  Snp->RecycledTxBufCount  = 0;\r
  \r
   if (Nii->Revision >= EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_REVISION) {\r
     Snp->IfNum = Nii->IfNum;\r
@@ -678,6 +686,10 @@ SimpleNetworkDriverStart (
 \r
 Error_DeleteSNP:\r
 \r
+  if (Snp->RecycledTxBuf != NULL) {\r
+    FreePool (Snp->RecycledTxBuf);\r
+  }\r
+\r
   PciIo->FreeBuffer (\r
            PciIo,\r
            SNP_MEM_PAGES (sizeof (SNP_DRIVER)),\r
@@ -790,6 +802,8 @@ SimpleNetworkDriverStop (
   PxeShutdown (Snp);\r
   PxeStop (Snp);\r
 \r
+  FreePool (Snp->RecycledTxBuf);\r
+\r
   PciIo = Snp->PciIo;\r
   PciIo->FreeBuffer (\r
            PciIo,\r
index f1d0ab36dbcfa79c73a997e3f1dcafe3a29550a3..67f65ffc422f0997dfc69d1d05304b2fdc909e27 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
     Declaration of strctures and functions for SnpDxe driver.\r
 \r
-Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2004 - 2016, Intel Corporation. All rights reserved.<BR>\r
 This program and the accompanying materials are licensed\r
 and made available under the terms and conditions of the BSD License which\r
 accompanies this distribution. The full text of the license may be found at\r
@@ -49,6 +49,9 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #define PCI_BAR_MEM_MODE      0x00000000\r
 #define PCI_BAR_MEM_64BIT     0x00000004\r
 \r
+#define SNP_TX_BUFFER_INCREASEMENT    MAX_XMIT_BUFFERS\r
+#define SNP_MAX_TX_BUFFER_NUM         65536\r
+\r
 typedef\r
 EFI_STATUS\r
 (EFIAPI *ISSUE_UNDI32_COMMAND) (\r
@@ -130,6 +133,19 @@ typedef struct {
   // i.e. PXE_STATFLAGS_GET_STATUS_NO_MEDIA_SUPPORTED\r
   //\r
   BOOLEAN                MediaStatusSupported;\r
+\r
+  //\r
+  // Array of the recycled transmit buffer address from UNDI.\r
+  //\r
+  UINT64                 *RecycledTxBuf;\r
+  //\r
+  // The maximum number of recycled buffer pointers in RecycledTxBuf.\r
+  //\r
+  UINT32                 MaxRecycledTxBuf;\r
+  //\r
+  // Current number of recycled buffer pointers in RecycledTxBuf.\r
+  //\r
+  UINT32                 RecycledTxBufCount;\r
 } SNP_DRIVER;\r
 \r
 #define EFI_SIMPLE_NETWORK_DEV_FROM_THIS(a) CR (a, SNP_DRIVER, Snp, SNP_DRIVER_SIGNATURE)\r