MdeModulePkg: update SNP.GetStatus to handle multiple recycled TX buffer.

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
This commit is contained in:
Fu Siyuan 2016-01-08 02:21:25 +00:00 committed by sfu5
parent c2967d35d8
commit 7b4b93a247
3 changed files with 89 additions and 18 deletions

View File

@ -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);

View File

@ -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
@ -404,6 +404,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,

View File

@ -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)