From: "Michael Brown" <mcb30@ipxe.org>
To: devel@edk2.groups.io, "RichardHo [何明忠]" <richardho@ami.com>
Subject: Re: [edk2-devel] [PATCH 1/3] UsbNetworkPkg/UsbRndis: Add USB RNDIS devices support
Date: Wed, 11 Jan 2023 01:11:22 +0000 [thread overview]
Message-ID: <010201859e61b891-f355ea1c-08c2-4a5f-8568-f47097af6994-000000@eu-west-1.amazonses.com> (raw)
In-Reply-To: <53d2211e-d8ad-fafe-38ad-814ed77d19cf@ipxe.org>
On 09/01/2023 23:50, Michael Brown wrote:
> Coincidentally, I have just implemented a fix for this. It works by
> implementing a simple credit-based rate limiter. Calls to
> UsbEthReceive() are limited to 10 per second while the receive datapath
> is idle. No limiting takes place while the receive datapath is active.
>
> Richard Ho: please consider using this rate limiting approach (or
> something very similar).
I have updated the patch to run the timer callback at TPL_NOTIFY. This
seems to be required to avoid a long delay when the timer is disabled.
(I have not investigated the root cause of this delay, but it is 100%
reproducible.)
With this updated patch, I get almost no noticeable slowdown of the
system and I am still able to receive data at around 100Mbps (which is
about as good as it's likely to get, given the fundamental design flaws
in EFI_USB_IO_PROTOCOL).
Updated patch:
diff --git a/UsbNetworkPkg/Include/Protocol/EdkIIUsbEthernetProtocol.h
b/UsbNetworkPkg/Include/Protocol/EdkIIUsbEthernetProtocol.h
index df6ebc64ef..d0e2048114 100644
--- a/UsbNetworkPkg/Include/Protocol/EdkIIUsbEthernetProtocol.h
+++ b/UsbNetworkPkg/Include/Protocol/EdkIIUsbEthernetProtocol.h
@@ -160,6 +160,8 @@ typedef struct {
UINT8 CurrentNodeAddress[PXE_MAC_LENGTH];
UINT8 BroadcastNodeAddress[PXE_MAC_LENGTH];
EFI_USB_DEVICE_REQUEST Request;
+ EFI_EVENT RateLimiter;
+ UINTN RateLimitCredit;
} NIC_DATA;
#define NIC_DATA_SIGNATURE SIGNATURE_32('n', 'i', 'c', 'd')
diff --git a/UsbNetworkPkg/NetworkCommon/DriverBinding.h
b/UsbNetworkPkg/NetworkCommon/DriverBinding.h
index 946727ffc9..ae1d3c201e 100644
--- a/UsbNetworkPkg/NetworkCommon/DriverBinding.h
+++ b/UsbNetworkPkg/NetworkCommon/DriverBinding.h
@@ -25,6 +25,8 @@
#define RX_BUFFER_COUNT 32
#define TX_BUFFER_COUNT 32
#define MEMORY_REQUIRE 0
+#define RATE_LIMITER_INTERVAL 1000000 // 10Hz
+#define RATE_LIMITER_BURST 10
#define UNDI_DEV_SIGNATURE SIGNATURE_32('u','n','d','i')
#define UNDI_DEV_FROM_THIS(a) CR(a, NIC_DEVICE, NiiProtocol,
UNDI_DEV_SIGNATURE)
diff --git a/UsbNetworkPkg/NetworkCommon/PxeFunction.c
b/UsbNetworkPkg/NetworkCommon/PxeFunction.c
index fd53a215a4..e02402dc57 100644
--- a/UsbNetworkPkg/NetworkCommon/PxeFunction.c
+++ b/UsbNetworkPkg/NetworkCommon/PxeFunction.c
@@ -29,6 +29,21 @@ API_FUNC gUndiApiTable[] = {
UndiReceive
};
+STATIC
+VOID
+EFIAPI
+UndiRateLimiterCallback (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ NIC_DATA *Nic = Context;
+
+ if (Nic->RateLimitCredit < RATE_LIMITER_BURST) {
+ Nic->RateLimitCredit++;
+ }
+}
+
/**
This command is used to determine the operational state of the UNDI.
@@ -100,9 +115,6 @@ UndiStart (
Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
Cdb->StatCode = PXE_STATCODE_INVALID_CDB;
return;
- } else {
- Cdb->StatFlags = PXE_STATFLAGS_COMMAND_COMPLETE;
- Cdb->StatCode = PXE_STATCODE_SUCCESS;
}
if (Nic->State != PXE_STATFLAGS_GET_STATE_STOPPED) {
@@ -120,14 +132,46 @@ UndiStart (
Nic->PxeStart.UnMap_Mem = 0;
Nic->PxeStart.Sync_Mem = Cpb->Sync_Mem;
Nic->PxeStart.Unique_ID = Cpb->Unique_ID;
- Nic->State = PXE_STATFLAGS_GET_STATE_STARTED;
+
+ Status = gBS->CreateEvent (
+ EVT_TIMER | EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ UndiRateLimiterCallback,
+ Nic,
+ &Nic->RateLimiter
+ );
+ if (EFI_ERROR (Status)) {
+ goto ErrorCreateEvent;
+ }
+
+ Status = gBS->SetTimer (
+ Nic->RateLimiter,
+ TimerPeriodic,
+ RATE_LIMITER_INTERVAL
+ );
+ if (EFI_ERROR (Status)) {
+ goto ErrorSetTimer;
+ }
if (Nic->UsbEth->UsbEthUndi.UsbEthUndiStart != NULL) {
Status = Nic->UsbEth->UsbEthUndi.UsbEthUndiStart (Cdb, Nic);
if (EFI_ERROR (Status)) {
- Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
+ goto ErrorUndiStart;
}
}
+
+ Nic->State = PXE_STATFLAGS_GET_STATE_STARTED;
+ Cdb->StatFlags = PXE_STATFLAGS_COMMAND_COMPLETE;
+ Cdb->StatCode = PXE_STATCODE_SUCCESS;
+ return;
+
+ ErrorUndiStart:
+ gBS->SetTimer (&Nic->RateLimiter, TimerCancel, 0);
+ ErrorSetTimer:
+ gBS->CloseEvent (&Nic->RateLimiter);
+ ErrorCreateEvent:
+ Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
+ Cdb->StatCode = PXE_STATCODE_DEVICE_FAILURE;
}
/**
@@ -183,6 +227,10 @@ UndiStop (
Nic->PxeStart.Sync_Mem = 0;
Nic->State = PXE_STATFLAGS_GET_STATE_STOPPED;
+ gBS->SetTimer (&Nic->RateLimiter, TimerCancel, 0);
+
+ gBS->CloseEvent (&Nic->RateLimiter);
+
if (Nic->UsbEth->UsbEthUndi.UsbEthUndiStop != NULL) {
Status = Nic->UsbEth->UsbEthUndi.UsbEthUndiStop (Cdb, Nic);
if (EFI_ERROR (Status)) {
@@ -1483,6 +1531,7 @@ Receive (
)
{
EFI_STATUS Status;
+ EFI_TPL OriginalTpl;
UINTN Index;
UINT16 StatCode;
PXE_FRAME_TYPE FrameType;
@@ -1506,8 +1555,15 @@ Receive (
}
while (1) {
+ if (Nic->RateLimitCredit == 0) {
+ break;
+ }
+
Status = Nic->UsbEth->UsbEthReceive (Cdb, Nic->UsbEth, (VOID
*)BulkInData, &DataLength);
if (EFI_ERROR (Status)) {
+ OriginalTpl = gBS->RaiseTPL (TPL_NOTIFY);
+ Nic->RateLimitCredit--;
+ gBS->RestoreTPL (OriginalTpl);
break;
}
Thanks,
Michael
next prev parent reply other threads:[~2023-01-11 1:11 UTC|newest]
Thread overview: 23+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-12-08 3:44 [PATCH 1/3] UsbNetworkPkg/UsbRndis: Add USB RNDIS devices support RichardHo [何明忠]
2022-12-08 4:41 ` [edk2-devel] " Rebecca Cran
2022-12-08 4:57 ` Rebecca Cran
2022-12-12 5:48 ` RichardHo [何明忠]
2023-01-08 10:41 ` tinhnguyen
2023-01-09 23:50 ` Michael Brown
2023-01-12 8:36 ` RichardHo [何明忠]
2023-01-20 21:36 ` Rebecca Cran
2023-02-05 8:04 ` Tinh Nguyen
2023-02-05 10:26 ` Michael Brown
2023-01-10 5:07 ` Rebecca Cran
2023-01-11 7:34 ` tinhnguyen
2023-01-11 9:55 ` Michael Brown
2023-01-11 10:56 ` Tinh Nguyen
[not found] ` <53d2211e-d8ad-fafe-38ad-814ed77d19cf@ipxe.org>
2023-01-11 1:11 ` Michael Brown [this message]
2023-01-11 1:17 ` Michael Brown
2023-01-11 9:47 ` RichardHo [何明忠]
-- strict thread matches above, loose matches on Subject: below --
2022-10-03 9:26 RichardHo [何明忠]
2022-12-01 15:46 ` [edk2-devel] " Rebecca Cran
2022-12-02 10:42 ` RichardHo [何明忠]
2022-12-02 10:09 ` Michael Brown
2022-12-02 10:42 ` RichardHo [何明忠]
2022-12-02 11:49 ` Chang, Abner
2022-12-02 23:27 ` Rebecca Cran
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-list from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=010201859e61b891-f355ea1c-08c2-4a5f-8568-f47097af6994-000000@eu-west-1.amazonses.com \
--to=devel@edk2.groups.io \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox