Skip to content

Commit

Permalink
dwc_eqos - Load ACPI configuration information
Browse files Browse the repository at this point in the history
Changes to acpiutil:

- `acpiutil.hpp` depends on definitions from `acpiioct.h`, so `#include`
  it.
- Fix code analysis warnings about SAL annotations.
- Make `AcpiEvaluateMethod` be public.
- Fix C++ conformance issues with goto jumping past variable initialization.

Changes to driver:

- Define a DeviceConfig struct with all of the configuration
  information.
- Pass DeviceConfig to queues.
- Queues use DeviceConfig instead of constants.
- Initialize DeviceConfig based on feature registers and ACPI.

Notes:

- Current ACPI sets mixed-burst=1, tso=1, wr_osr_lmt=4, rd_osr_lmt=8,
  blen=16,8,4.
- NetBSD driver references other settings that are not present in the
  current ACPI, and sets defaults for them: pbl=8, txpbl=8, rxpbl=8,
  fixed-burst=0.
- I invented a new value `pblx8` (default = 1) to control whether the X8
  flag is set. Existing code assumes that it is set.
- I don't use the `tso` value for anything. I assume it is to
  enable/disable TCP segmentation offload, which seems more appropriate
  to configure in the registry.
- The docs say that mixed-burst=1 should translate into FB=0 (same as
  fixed-burst=0), but the NetBSD driver translates mixed-burst=1 into
  Reserved14=1. I'll keep that behavior since it doesn't seem to cause any
  harm.
  • Loading branch information
idigdoug committed Dec 31, 2023
1 parent 0bb5ea0 commit af08b2c
Show file tree
Hide file tree
Showing 14 changed files with 261 additions and 68 deletions.
16 changes: 13 additions & 3 deletions drivers/include/acpiutil.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@

#ifndef __ACPIUTIL_HPP__
#define __ACPIUTIL_HPP__
#pragma once
#include <acpiioct.h>

#define NONPAGED_SEGMENT_BEGIN \
__pragma(code_seg(push)) \
Expand Down Expand Up @@ -112,7 +114,7 @@ _IRQL_requires_max_(PASSIVE_LEVEL)
NTSTATUS
AcpiQueryDsd(
_In_ DEVICE_OBJECT* PdoPtr,
_Outptr_result_bytebuffer_((*DsdBufferPptr)->Length) ACPI_EVAL_OUTPUT_BUFFER UNALIGNED** DsdBufferPptr);
_Outptr_result_bytebuffer_maybenull_((*DsdBufferPptr)->Length) ACPI_EVAL_OUTPUT_BUFFER UNALIGNED** DsdBufferPptr);

_IRQL_requires_max_(DISPATCH_LEVEL)
NTSTATUS
Expand Down Expand Up @@ -198,16 +200,24 @@ AcpiQueryDsm(
_In_ UINT32 RevisionId,
_Out_ UINT32* SupportedFunctionsMaskPtr);

_IRQL_requires_max_(APC_LEVEL)
NTSTATUS
AcpiEvaluateMethod(
_In_ DEVICE_OBJECT* PdoPtr,
_In_reads_bytes_(InputBufferSize) ACPI_EVAL_INPUT_BUFFER* InputBufferPtr,
_In_ UINT32 InputBufferSize,
_Outptr_result_bytebuffer_maybenull_((*ReturnBufferPptr)->Length) ACPI_EVAL_OUTPUT_BUFFER UNALIGNED** ReturnBufferPptr);

_IRQL_requires_max_(APC_LEVEL)
NTSTATUS
AcpiExecuteDsmFunction(
_In_ DEVICE_OBJECT* PdoPtr,
_In_reads_bytes_(sizeof(GUID)) const GUID* GuidPtr,
_In_ UINT32 RevisionId,
_In_ UINT32 FunctionIdx,
_In_opt_ ACPI_METHOD_ARGUMENT* FunctionArgumentsPtr,
_In_reads_bytes_(FunctionArgumentsSize) ACPI_METHOD_ARGUMENT* FunctionArgumentsPtr,
_In_ USHORT FunctionArgumentsSize,
_Outptr_opt_result_bytebuffer_((*ReturnBufferPptr)->Length) ACPI_EVAL_OUTPUT_BUFFER UNALIGNED** ReturnBufferPptr);
_Outptr_opt_result_bytebuffer_maybenull_((*ReturnBufferPptr)->Length) ACPI_EVAL_OUTPUT_BUFFER UNALIGNED** ReturnBufferPptr);

_IRQL_requires_same_
NTSTATUS
Expand Down
2 changes: 2 additions & 0 deletions drivers/net/dwc_eqos/_acpiutil.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#include "precomp.h"
#include <acpiutil.cpp>
190 changes: 177 additions & 13 deletions drivers/net/dwc_eqos/device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#define CTRPP_VERIFY_COUNTER_SIZES 1
#include <dwc_eqos_perf.h>

#include <acpiutil.hpp>
#include <bcrypt.h>

/*
Expand All @@ -24,8 +25,6 @@ CreateTxQueue DestroyCallback
(DisarmWake) (ArmWake)
*/

static auto constexpr DefaultAxiMaxWriteOutstanding = 4u;
static auto constexpr DefaultAxiMaxReadOutstanding = 8u;
static auto constexpr DefaultCsrRate = 125'000'000u;
static auto constexpr BusBytes = 8u;
static auto constexpr QueuesSupported = 1u; // TODO: Support multiple queues?
Expand Down Expand Up @@ -62,6 +61,7 @@ struct DeviceContext
MacHwFeature3_t feature3;
UINT8 permanentMacAddress[ETHERNET_LENGTH_OF_ADDRESS];
UINT8 currentMacAddress[ETHERNET_LENGTH_OF_ADDRESS];
DeviceConfig config;

// Mutable.

Expand Down Expand Up @@ -421,11 +421,11 @@ AdapterCreateTxQueue(
NT_ASSERT(context->txQueue == nullptr);
return TxQueueCreate(
context,
context->config,
queueInit,
context->dma,
&context->regs->Dma_Ch[0],
&context->regs->Mtl_Q[0],
context->feature0.TxChecksumOffload != 0);
&context->regs->Mtl_Q[0]);
}

static EVT_NET_ADAPTER_CREATE_RXQUEUE AdapterCreateRxQueue;
Expand All @@ -439,6 +439,7 @@ AdapterCreateRxQueue(
NT_ASSERT(context->rxQueue == nullptr);
return RxQueueCreate(
context,
context->config,
queueInit,
context->dma,
&context->regs->Dma_Ch[0]);
Expand Down Expand Up @@ -591,7 +592,7 @@ DeviceD0Entry(
macConfig.PacketBurstEnable = true;
macConfig.ReceiverEnable = true;
macConfig.TransmitterEnable = true;
macConfig.ChecksumOffloadEnable = context->feature0.TxChecksumOffload | context->feature0.RxChecksumOffload;
macConfig.ChecksumOffloadEnable = context->config.txCoeSel || context->config.rxCoeSel;
Write32(&context->regs->Mac_Configuration, macConfig);

// Clear and then enable interrupts.
Expand Down Expand Up @@ -855,6 +856,169 @@ DevicePrepareHardware(
}
}

// Device Config

{
context->config.txCoeSel = context->feature0.TxChecksumOffload;
context->config.rxCoeSel = context->feature0.RxChecksumOffload;
context->config.pblX8 = true;
context->config.pbl = 8;
context->config.txPbl = context->config.pbl;
context->config.rxPbl = context->config.pbl;
context->config.fixed_burst = false;
context->config.mixed_burst = true;
context->config.wr_osr_lmt = 4;
context->config.rd_osr_lmt = 8;
context->config.blen = 0x7; // 0x7 = 4, 8, 16

auto const deviceObject = WdfDeviceWdmGetPhysicalDevice(device);
PACPI_EVAL_OUTPUT_BUFFER outputBuffer = nullptr;
ACPI_METHOD_ARGUMENT const UNALIGNED* properties = nullptr;
ACPI_METHOD_ARGUMENT const UNALIGNED* blenProperties = nullptr;
UINT32 valueI32;
UINT32 valueLength;

status = AcpiQueryDsd(deviceObject, &outputBuffer);
if (!NT_SUCCESS(status))
{
TraceWrite("AcpiQueryDsd-failed", LEVEL_WARNING,
TraceLoggingNTStatus(status));
goto DeviceConfigDone;
}

status = AcpiParseDsdAsDeviceProperties(outputBuffer, &properties);
if (!NT_SUCCESS(status))
{
TraceWrite("AcpiParseDsdAsDeviceProperties-DSD-failed", LEVEL_WARNING,
TraceLoggingNTStatus(status));
goto DeviceConfigDone;
}

status = AcpiDevicePropertiesQueryIntegerValue(properties, "snps,pblx8", &valueI32);
if (NT_SUCCESS(status) && valueI32 <= 1)
{
context->config.pblX8 = valueI32 != 0;
}

status = AcpiDevicePropertiesQueryIntegerValue(properties, "snps,pbl", &valueI32);
if (NT_SUCCESS(status) && valueI32 <= 0x3F)
{
context->config.pbl = static_cast<UINT8>(valueI32);
context->config.txPbl = context->config.pbl;
context->config.rxPbl = context->config.pbl;
}

status = AcpiDevicePropertiesQueryIntegerValue(properties, "snps,txpbl", &valueI32);
if (NT_SUCCESS(status) && valueI32 <= 0x3F)
{
context->config.txPbl = static_cast<UINT8>(valueI32);
}

status = AcpiDevicePropertiesQueryIntegerValue(properties, "snps,rxpbl", &valueI32);
if (NT_SUCCESS(status) && valueI32 <= 0x3F)
{
context->config.rxPbl = static_cast<UINT8>(valueI32);
}

status = AcpiDevicePropertiesQueryIntegerValue(properties, "snps,fixed-burst", &valueI32);
if (NT_SUCCESS(status) && valueI32 <= 1)
{
context->config.fixed_burst = valueI32 != 0;
}

status = AcpiDevicePropertiesQueryIntegerValue(properties, "snps,mixed-burst", &valueI32);
if (NT_SUCCESS(status) && valueI32 <= 1)
{
context->config.mixed_burst = valueI32 != 0;
}

CHAR valueString[5];
status = AcpiDevicePropertiesQueryStringValue(properties, "snps,axi-config", sizeof(valueString), &valueLength, valueString);
if (!NT_SUCCESS(status) || valueLength != 5)
{
goto DeviceConfigDone;
}

ExFreePoolWithTag(outputBuffer, ACPI_TAG_EVAL_OUTPUT_BUFFER);
outputBuffer = nullptr;

ACPI_EVAL_INPUT_BUFFER inputBuffer;
inputBuffer = {};
inputBuffer.Signature = ACPI_EVAL_INPUT_BUFFER_SIGNATURE;

memcpy(inputBuffer.MethodName, valueString, sizeof(inputBuffer.MethodName));
status = AcpiEvaluateMethod(deviceObject, &inputBuffer, sizeof(ACPI_EVAL_INPUT_BUFFER), &outputBuffer);
if (!NT_SUCCESS(status))
{
TraceWrite("AcpiEvaluateMethod-AXIC-failed", LEVEL_WARNING,
TraceLoggingNTStatus(status));
goto DeviceConfigDone;
}

status = AcpiParseDsdAsDeviceProperties(outputBuffer, &properties);
if (!NT_SUCCESS(status))
{
TraceWrite("AcpiParseDsdAsDeviceProperties-AXIC-failed", LEVEL_WARNING,
TraceLoggingNTStatus(status));
goto DeviceConfigDone;
}

status = AcpiDevicePropertiesQueryIntegerValue(properties, "snps,wr_osr_lmt", &valueI32);
if (NT_SUCCESS(status) && valueI32 <= 0x0F)
{
context->config.wr_osr_lmt = static_cast<UINT8>(valueI32);
}

status = AcpiDevicePropertiesQueryIntegerValue(properties, "snps,rd_osr_lmt", &valueI32);
if (NT_SUCCESS(status) && valueI32 <= 0x0F)
{
context->config.rd_osr_lmt = static_cast<UINT8>(valueI32);
}

status = AcpiDevicePropertiesQueryValue(properties, "snps,blen", &blenProperties);
if (NT_SUCCESS(status) && blenProperties->Type == ACPI_METHOD_ARGUMENT_PACKAGE)
{
UINT8 blen = 0;
unsigned count = 0;

for (ACPI_METHOD_ARGUMENT const UNALIGNED* blenVal = nullptr;;)
{
status = AcpiPackageGetNextArgument(blenProperties, &blenVal);
if (!NT_SUCCESS(status) ||
blenVal->Type != ACPI_METHOD_ARGUMENT_INTEGER ||
blenVal->DataLength != sizeof(UINT32))
{
break;
}

count += 1;
switch (blenVal->Argument)
{
case 4: blen |= 0x1; break;
case 8: blen |= 0x2; break;
case 16: blen |= 0x4; break;
case 32: blen |= 0x8; break;
case 64: blen |= 0x10; break;
case 128: blen |= 0x20; break;
case 256: blen |= 0x40; break;
}
}

if (count != 0)
{
context->config.blen = blen;
}
}

DeviceConfigDone:

if (outputBuffer)
{
ExFreePoolWithTag(outputBuffer, ACPI_TAG_EVAL_OUTPUT_BUFFER);
outputBuffer = nullptr;
}
}

// Create DMA enabler

{
Expand Down Expand Up @@ -943,7 +1107,7 @@ DevicePrepareHardware(
NetPacketFilterFlagPromiscuous;
NetAdapterSetReceiveFilterCapabilities(context->adapter, &rxFilterCaps);

if (context->feature0.TxChecksumOffload)
if (context->config.txCoeSel)
{
NET_ADAPTER_OFFLOAD_TX_CHECKSUM_CAPABILITIES txChecksumCaps;
NET_ADAPTER_OFFLOAD_TX_CHECKSUM_CAPABILITIES_INIT(&txChecksumCaps, {}, AdapterOffloadSetTxChecksum);
Expand Down Expand Up @@ -981,14 +1145,14 @@ DevicePrepareHardware(
auto busMode = Read32(&regs->Dma_SysBus_Mode);
busMode.EnableLpi = true; // true = allow LPI, honor AXI LPI request.
busMode.UnlockOnPacket = false; // false = Wake for any received packet, true = only wake for magic packet.
busMode.AxiMaxWriteOutstanding = DefaultAxiMaxWriteOutstanding;
busMode.AxiMaxReadOutstanding = DefaultAxiMaxReadOutstanding;
busMode.AxiMaxWriteOutstanding = context->config.wr_osr_lmt;
busMode.AxiMaxReadOutstanding = context->config.rd_osr_lmt;
busMode.Reserved14 = context->config.mixed_burst; // ??? This is what the NetBSD driver does.
busMode.AddressAlignedBeats = true; // Seemed to have fewer Rx FIFO overflows with this set to true.
busMode.AutoAxiLpi = true; // true = enter LPI after (Axi_Lpi_Entry_Interval + 1) * 64 idle clocks.
busMode.BurstLength16 = true; // true = allow 16-beat bursts.
busMode.BurstLength8 = true; // true = allow 8-beat bursts.
busMode.BurstLength4 = true; // true = allow 4-beat bursts.
busMode.FixedBurst = true; // true = fixed-burst, false = mixed-burst.
busMode.BurstLengths = context->config.blen;

busMode.FixedBurst = context->config.fixed_burst;
Write32(&regs->Dma_SysBus_Mode, busMode);

Write32(&regs->Mac_1us_Tic_Counter, DefaultCsrRate / 1'000'000u - 1);
Expand All @@ -999,7 +1163,7 @@ DevicePrepareHardware(
"RxDescriptor must be a multiple of bus width.");
ChannelDmaControl_t dmaControl = {};
dmaControl.DescriptorSkipLength = (sizeof(RxDescriptor) - 16) / BusBytes;
dmaControl.PblX8 = QueueBurstLengthX8;
dmaControl.PblX8 = context->config.pblX8;
Write32(&regs->Dma_Ch[0].Control, dmaControl);

// Disable MMC counter interrupts.
Expand Down
18 changes: 17 additions & 1 deletion drivers/net/dwc_eqos/device.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,23 @@ Device behavior. Includes adapter and interrupt since they are 1:1 with the devi
*/
#pragma once

struct DeviceContext;
struct DeviceContext; // Multi-queue: change to DeviceQueueContext.

// Information about the device provided to the queues.
struct DeviceConfig
{
bool txCoeSel; // MAC_HW_Feature0\TXCOESEL (hardware support for tx checksum offload).
bool rxCoeSel; // MAC_HW_Feature0\RXCOESEL (hardware support for rx checksum offload).
bool pblX8; // _DSD\snps,pblx8 (default = 1).
UINT8 pbl; // _DSD\snps,pbl (default = 8).
UINT8 txPbl; // _DSD\snps,txpbl (default = pbl; effect depends on pblX8).
UINT8 rxPbl; // _DSD\snps,rxpbl (default = pbl; effect depends on pblX8).
bool fixed_burst; // _DSD\snps,fixed-burst (default = 0).
bool mixed_burst; // _DSD\snps,mixed-burst (default = 1).
UINT8 wr_osr_lmt; // AXIC\snps,wr_osr_lmt (default = 4).
UINT8 rd_osr_lmt; // AXIC\snps,rd_osr_lmt (default = 8).
UINT8 blen : 7; // AXIC\snps,blen bitmask of 7 booleans 4..256 (default = 4, 8, 16).
};

// Referenced in driver.cpp DriverEntry.
// Called by WDF.
Expand Down
1 change: 0 additions & 1 deletion drivers/net/dwc_eqos/driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
/*
TODO list:
- Support for 10/100 Mbps modes (requires ACPI support).
- Use ACPI to get AXI configuration (and/or tune AXI config).
- Jumbo frames.
- Receive queue memory optimization?
- Configuration in registry (e.g. flow control).
Expand Down
6 changes: 5 additions & 1 deletion drivers/net/dwc_eqos/dwc_eqos.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,14 @@
<ClCompile Include="queue_common.cpp" />
<ClCompile Include="rxqueue.cpp" />
<ClCompile Include="txqueue.cpp" />
<ClCompile Include="_acpiutil.cpp" />
<ClCompile Include="_precomp.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">Create</PrecompiledHeader>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\include\acpiutil.hpp" />
<ClInclude Include="device.h" />
<ClInclude Include="dwc_eqos_perf_data.h" />
<ClInclude Include="queue_common.h" />
Expand Down Expand Up @@ -92,6 +94,7 @@
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>precomp.h</PrecompiledHeaderFile>
<LanguageStandard>stdcpp20</LanguageStandard>
<AdditionalIncludeDirectories>../../include;../../shared;$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<DriverSign>
<FileDigestAlgorithm>sha256</FileDigestAlgorithm>
Expand All @@ -116,6 +119,7 @@
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>precomp.h</PrecompiledHeaderFile>
<LanguageStandard>stdcpp20</LanguageStandard>
<AdditionalIncludeDirectories>../../include;../../shared;$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<DriverSign>
<FileDigestAlgorithm>sha256</FileDigestAlgorithm>
Expand Down Expand Up @@ -149,4 +153,4 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
</Project>
Loading

0 comments on commit af08b2c

Please sign in to comment.