summaryrefslogtreecommitdiffstats
path: root/NetworkPkg/DpcDxe/Dpc.c
diff options
context:
space:
mode:
authorLiming Gao <liming.gao@intel.com>2019-05-15 20:02:18 +0800
committerLiming Gao <liming.gao@intel.com>2019-05-27 09:25:18 +0800
commit4542f8b8135f1f1ee5654e25139be9769e139ddd (patch)
tree6e05d7c624d89b3df27d0d3437815a2587f0640f /NetworkPkg/DpcDxe/Dpc.c
parentc0fd7f734e2d33e22215899b40a47b843129541d (diff)
downloadedk2-4542f8b8135f1f1ee5654e25139be9769e139ddd.tar.gz
edk2-4542f8b8135f1f1ee5654e25139be9769e139ddd.tar.bz2
edk2-4542f8b8135f1f1ee5654e25139be9769e139ddd.zip
NetworkPkg: Move Network library and drivers from MdeModulePkg to NetworkPkg
Signed-off-by: Liming Gao <liming.gao@intel.com> Cc: Siyuan Fu <siyuan.fu@intel.com> Cc: Jiaxin Wu <jiaxin.wu@intel.com> Reviewed-by: Jiaxin Wu <jiaxin.wu@intel.com> Reviewed-by: Siyuan Fu <siyuan.fu@intel.com>
Diffstat (limited to 'NetworkPkg/DpcDxe/Dpc.c')
-rw-r--r--NetworkPkg/DpcDxe/Dpc.c341
1 files changed, 341 insertions, 0 deletions
diff --git a/NetworkPkg/DpcDxe/Dpc.c b/NetworkPkg/DpcDxe/Dpc.c
new file mode 100644
index 0000000000..8a490949dc
--- /dev/null
+++ b/NetworkPkg/DpcDxe/Dpc.c
@@ -0,0 +1,341 @@
+/** @file
+
+Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+Module Name:
+
+ Dpc.c
+
+Abstract:
+
+
+**/
+
+#include "Dpc.h"
+
+//
+// Handle for the EFI_DPC_PROTOCOL instance
+//
+EFI_HANDLE mDpcHandle = NULL;
+
+//
+// The EFI_DPC_PROTOCOL instances that is installed onto mDpcHandle
+//
+EFI_DPC_PROTOCOL mDpc = {
+ DpcQueueDpc,
+ DpcDispatchDpc
+};
+
+//
+// Global variables used to meaasure the DPC Queue Depths
+//
+UINTN mDpcQueueDepth = 0;
+UINTN mMaxDpcQueueDepth = 0;
+
+//
+// Free list of DPC entries. As DPCs are queued, entries are removed from this
+// free list. As DPC entries are dispatched, DPC entries are added to the free list.
+// If the free list is empty and a DPC is queued, the free list is grown by allocating
+// an additional set of DPC entries.
+//
+LIST_ENTRY mDpcEntryFreeList = INITIALIZE_LIST_HEAD_VARIABLE(mDpcEntryFreeList);
+
+//
+// An array of DPC queues. A DPC queue is allocated for every leval EFI_TPL value.
+// As DPCs are queued, they are added to the end of the linked list.
+// As DPCs are dispatched, they are removed from the beginning of the linked list.
+//
+LIST_ENTRY mDpcQueue[TPL_HIGH_LEVEL + 1];
+
+/**
+ Add a Deferred Procedure Call to the end of the DPC queue.
+
+ @param This Protocol instance pointer.
+ @param DpcTpl The EFI_TPL that the DPC should be invoked.
+ @param DpcProcedure Pointer to the DPC's function.
+ @param DpcContext Pointer to the DPC's context. Passed to DpcProcedure
+ when DpcProcedure is invoked.
+
+ @retval EFI_SUCCESS The DPC was queued.
+ @retval EFI_INVALID_PARAMETER DpcTpl is not a valid EFI_TPL.
+ @retval EFI_INVALID_PARAMETER DpcProcedure is NULL.
+ @retval EFI_OUT_OF_RESOURCES There are not enough resources available to
+ add the DPC to the queue.
+
+**/
+EFI_STATUS
+EFIAPI
+DpcQueueDpc (
+ IN EFI_DPC_PROTOCOL *This,
+ IN EFI_TPL DpcTpl,
+ IN EFI_DPC_PROCEDURE DpcProcedure,
+ IN VOID *DpcContext OPTIONAL
+ )
+{
+ EFI_STATUS ReturnStatus;
+ EFI_TPL OriginalTpl;
+ DPC_ENTRY *DpcEntry;
+ UINTN Index;
+
+ //
+ // Make sure DpcTpl is valid
+ //
+ if (DpcTpl < TPL_APPLICATION || DpcTpl > TPL_HIGH_LEVEL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Make sure DpcProcedure is valid
+ //
+ if (DpcProcedure == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Assume this function will succeed
+ //
+ ReturnStatus = EFI_SUCCESS;
+
+ //
+ // Raise the TPL level to TPL_HIGH_LEVEL for DPC list operation and save the
+ // current TPL value so it can be restored when this function returns.
+ //
+ OriginalTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
+
+ //
+ // Check to see if there are any entries in the DPC free list
+ //
+ if (IsListEmpty (&mDpcEntryFreeList)) {
+ //
+ // If the current TPL is greater than TPL_NOTIFY, then memory allocations
+ // can not be performed, so the free list can not be expanded. In this case
+ // return EFI_OUT_OF_RESOURCES.
+ //
+ if (OriginalTpl > TPL_NOTIFY) {
+ ReturnStatus = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ //
+ // Add 64 DPC entries to the free list
+ //
+ for (Index = 0; Index < 64; Index++) {
+ //
+ // Lower the TPL level to perform a memory allocation
+ //
+ gBS->RestoreTPL (OriginalTpl);
+
+ //
+ // Allocate a new DPC entry
+ //
+ DpcEntry = AllocatePool (sizeof (DPC_ENTRY));
+
+ //
+ // Raise the TPL level back to TPL_HIGH_LEVEL for DPC list operations
+ //
+ gBS->RaiseTPL (TPL_HIGH_LEVEL);
+
+ //
+ // If the allocation of a DPC entry fails, and the free list is empty,
+ // then return EFI_OUT_OF_RESOURCES.
+ //
+ if (DpcEntry == NULL) {
+ if (IsListEmpty (&mDpcEntryFreeList)) {
+ ReturnStatus = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+ }
+
+ //
+ // Add the newly allocated DPC entry to the DPC free list
+ //
+ InsertTailList (&mDpcEntryFreeList, &DpcEntry->ListEntry);
+ }
+ }
+
+ //
+ // Retrieve the first node from the free list of DPCs
+ //
+ DpcEntry = (DPC_ENTRY *)(GetFirstNode (&mDpcEntryFreeList));
+
+ //
+ // Remove the first node from the free list of DPCs
+ //
+ RemoveEntryList (&DpcEntry->ListEntry);
+
+ //
+ // Fill in the DPC entry with the DpcProcedure and DpcContext
+ //
+ DpcEntry->DpcProcedure = DpcProcedure;
+ DpcEntry->DpcContext = DpcContext;
+
+ //
+ // Add the DPC entry to the end of the list for the specified DplTpl.
+ //
+ InsertTailList (&mDpcQueue[DpcTpl], &DpcEntry->ListEntry);
+
+ //
+ // Increment the measured DPC queue depth across all TPLs
+ //
+ mDpcQueueDepth++;
+
+ //
+ // Measure the maximum DPC queue depth across all TPLs
+ //
+ if (mDpcQueueDepth > mMaxDpcQueueDepth) {
+ mMaxDpcQueueDepth = mDpcQueueDepth;
+ }
+
+Done:
+ //
+ // Restore the original TPL level when this function was called
+ //
+ gBS->RestoreTPL (OriginalTpl);
+
+ return ReturnStatus;
+}
+
+/**
+ Dispatch the queue of DPCs. ALL DPCs that have been queued with a DpcTpl
+ value greater than or equal to the current TPL are invoked in the order that
+ they were queued. DPCs with higher DpcTpl values are invoked before DPCs with
+ lower DpcTpl values.
+
+ @param This Protocol instance pointer.
+
+ @retval EFI_SUCCESS One or more DPCs were invoked.
+ @retval EFI_NOT_FOUND No DPCs were invoked.
+
+**/
+EFI_STATUS
+EFIAPI
+DpcDispatchDpc (
+ IN EFI_DPC_PROTOCOL *This
+ )
+{
+ EFI_STATUS ReturnStatus;
+ EFI_TPL OriginalTpl;
+ EFI_TPL Tpl;
+ DPC_ENTRY *DpcEntry;
+
+ //
+ // Assume that no DPCs will be invoked
+ //
+ ReturnStatus = EFI_NOT_FOUND;
+
+ //
+ // Raise the TPL level to TPL_HIGH_LEVEL for DPC list operation and save the
+ // current TPL value so it can be restored when this function returns.
+ //
+ OriginalTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
+
+ //
+ // Check to see if there are 1 or more DPCs currently queued
+ //
+ if (mDpcQueueDepth > 0) {
+ //
+ // Loop from TPL_HIGH_LEVEL down to the current TPL value
+ //
+ for (Tpl = TPL_HIGH_LEVEL; Tpl >= OriginalTpl; Tpl--) {
+ //
+ // Check to see if the DPC queue is empty
+ //
+ while (!IsListEmpty (&mDpcQueue[Tpl])) {
+ //
+ // Retrieve the first DPC entry from the DPC queue specified by Tpl
+ //
+ DpcEntry = (DPC_ENTRY *)(GetFirstNode (&mDpcQueue[Tpl]));
+
+ //
+ // Remove the first DPC entry from the DPC queue specified by Tpl
+ //
+ RemoveEntryList (&DpcEntry->ListEntry);
+
+ //
+ // Decrement the measured DPC Queue Depth across all TPLs
+ //
+ mDpcQueueDepth--;
+
+ //
+ // Lower the TPL to TPL value of the current DPC queue
+ //
+ gBS->RestoreTPL (Tpl);
+
+ //
+ // Invoke the DPC passing in its context
+ //
+ (DpcEntry->DpcProcedure) (DpcEntry->DpcContext);
+
+ //
+ // At least one DPC has been invoked, so set the return status to EFI_SUCCESS
+ //
+ ReturnStatus = EFI_SUCCESS;
+
+ //
+ // Raise the TPL level back to TPL_HIGH_LEVEL for DPC list operations
+ //
+ gBS->RaiseTPL (TPL_HIGH_LEVEL);
+
+ //
+ // Add the invoked DPC entry to the DPC free list
+ //
+ InsertTailList (&mDpcEntryFreeList, &DpcEntry->ListEntry);
+ }
+ }
+ }
+
+ //
+ // Restore the original TPL level when this function was called
+ //
+ gBS->RestoreTPL (OriginalTpl);
+
+ return ReturnStatus;
+}
+
+/**
+ The entry point for DPC driver which installs the EFI_DPC_PROTOCOL onto a new handle.
+
+ @param ImageHandle The image handle of the driver.
+ @param SystemTable The system table.
+
+ @retval EFI_SUCCES The DPC queues were initialized and the EFI_DPC_PROTOCOL was
+ installed onto a new handle.
+ @retval Others Failed to install EFI_DPC_PROTOCOL.
+
+**/
+EFI_STATUS
+EFIAPI
+DpcDriverEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+
+ //
+ // ASSERT() if the EFI_DPC_PROTOCOL is already present in the handle database
+ //
+ ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEfiDpcProtocolGuid);
+
+ //
+ // Initialize the DPC queue for all possible TPL values
+ //
+ for (Index = 0; Index <= TPL_HIGH_LEVEL; Index++) {
+ InitializeListHead (&mDpcQueue[Index]);
+ }
+
+ //
+ // Install the EFI_DPC_PROTOCOL instance onto a new handle
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &mDpcHandle,
+ &gEfiDpcProtocolGuid,
+ &mDpc,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}