summaryrefslogtreecommitdiff
path: root/MdeModulePkg
diff options
context:
space:
mode:
authorJack Pham <jackp@qti.qualcomm.com>2025-03-06 11:03:55 -0800
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>2025-03-18 20:29:20 +0000
commitf1a2bd23337b274dbc79826a07a742604ad26a7a (patch)
tree60f3894cddc65d72c27f50e7793780b300102f73 /MdeModulePkg
parent70db6510d1b40978dcb8877de55bc6915fa1145a (diff)
downloadedk2-master.zip
edk2-master.tar.gz
edk2-master.tar.bz2
MdeModulePkg/XhciDxe: Adjust out-of-range bInterval valuesHEADmaster
When a USB device is enumerated it will report one or more endpoint descriptors which contains a bInterval field which specifies the interval a host should periodically poll for that particular endpoint when scheduling transfers. But the units this value is expressed in (in whole ms, a power of 2 x 1ms, or a power of 2 x 125us) may differ depending on the speed of the device and whether the endpoint is isochronous or interrupt. Some high/super-speed devices, which are supposed to report isoc/int bInterval as a power of 2 x 125us, incorrectly report full-speed bInterval values (that is, in whole units of ms) in their interrupt endpoint descriptors which results in an assertion error due to being out of range of the spec-expected values. Rather than asserting, try to adjust those assuming they were expressed in units of ms with an upper limit of 128ms. Signed-off-by: Jack Pham <jackp@qti.qualcomm.com>
Diffstat (limited to 'MdeModulePkg')
-rw-r--r--MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.c24
1 files changed, 22 insertions, 2 deletions
diff --git a/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.c b/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.c
index c5ca834..50d7d4b 100644
--- a/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.c
+++ b/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.c
@@ -2829,6 +2829,8 @@ CalculateInterval (
UINT8 Interval
)
{
+ UINT8 OriginalInterval = Interval;
+
if ((EpType == USB_ENDPOINT_ISO) && (DeviceSpeed == EFI_USB_SPEED_FULL)) {
ASSERT (Interval >= 1 && Interval <= 16);
Interval = Interval + 2;
@@ -2836,8 +2838,26 @@ CalculateInterval (
ASSERT (Interval != 0);
Interval = (UINT8)HighBitSet32 ((UINT32)Interval) + 3;
} else if ((DeviceSpeed == EFI_USB_SPEED_HIGH) || (DeviceSpeed == EFI_USB_SPEED_SUPER)) {
- ASSERT (Interval >= 1 && Interval <= 16);
- Interval = Interval - 1;
+ ASSERT (Interval != 0);
+
+ //
+ // Some devices incorrectly report full-speed bInterval values in
+ // their high/super-speed interrupt endpoint descriptors. Try to
+ // adjust those assuming they were expressed in units of ms with an
+ // upper limit of 128ms.
+ //
+ if (Interval > 16) {
+ Interval = (UINT8)HighBitSet32 ((UINT32)Interval*8);
+
+ DEBUG ((
+ DEBUG_WARN,
+ "EpDesc->Interval (%u) out of range. Adjusted to %u\n",
+ OriginalInterval,
+ Interval
+ ));
+ } else {
+ Interval = Interval - 1;
+ }
}
return Interval;