Skip to content

Commit

Permalink
dwc_eqos - vlan, flow, INF config options (#32)
Browse files Browse the repository at this point in the history
- Change checksum offload INF options from granular to combined.
- Add INF options for FlowControl, PriorityVlanTag.
- Respect INF option for FlowControl at MAC level.
- Set DisableReceiveOwn on MAC options.
- Correct Rx VLAN tag behavior: always strip tag, always copy tag to OOB.
- Correct Tx VLAN tag behavior: add tag if present in OOB.
- Stop tracking Tx-Own statistics. They don't seem useful.

The Tx VLAN tag behavior required significant refactoring of
TxQueueAdvance. Previously we depended on one-to-one mapping between
descriptor and fragment, but VLAN tags require context descriptors so
there can now be descriptors without a matching fragment, so our
descriptor drain code needs to deal with that.
  • Loading branch information
idigdoug authored Jan 5, 2024
1 parent 84454c1 commit 3a000eb
Show file tree
Hide file tree
Showing 11 changed files with 306 additions and 167 deletions.
1 change: 1 addition & 0 deletions drivers/net/dwc_eqos/descriptors.h
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ struct TxDescriptorContext
UINT8 OneStepEnable : 1; // OSTC
UINT8 Reserved28 : 2;
UINT8 ContextType : 1; // CTXT = 1
UINT8 Own : 1; // OWN

#if DBG
UINT32 FragmentIndex;
Expand Down
75 changes: 65 additions & 10 deletions drivers/net/dwc_eqos/device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,6 @@ struct DeviceContext
UINT32 dpcFatalBusError; // Updated only in DPC.
UINT32 rxOwnDescriptors; // Updated only during RxQueueAdvance.
UINT32 rxDoneFragments; // Updated only during RxQueueAdvance.
UINT32 txOwnDescriptors; // Updated only during TxQueueAdvance.
UINT32 txDoneFragments; // Updated only during TxQueueAdvance.
};
WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(DeviceContext, DeviceGetContext)
Expand Down Expand Up @@ -593,7 +592,7 @@ DeviceD0Entry(
: txFifoSize / QueuesSupported;

MacTxFlowCtrl_t txFlowCtrl = {};
txFlowCtrl.TransmitFlowControlEnable = true;
txFlowCtrl.TransmitFlowControlEnable = context->config.txFlowControl;
txFlowCtrl.PauseTime = 0xFFFF;
Write32(&context->regs->Mac_Tx_Flow_Ctrl, txFlowCtrl); // TxFlow control, pause time.

Expand All @@ -617,7 +616,7 @@ DeviceD0Entry(
UINT32 const rxFlowControlDeactivate =
rxFlowControlActivate + rxFlowControlActivate / 2u; // Unpause when 3/4 or 48KB remains.

Write32(&context->regs->Mac_Rx_Flow_Ctrl, 0x3); // Rx flow control, pause packet detect.
Write32(&context->regs->Mac_Rx_Flow_Ctrl, context->config.rxFlowControl ? 0x3 : 0x0); // Rx flow control, pause packet detect.
Write32(&context->regs->Mac_RxQ_Ctrl0, 0x2); // RxQ0 enabled for DCB/generic.

MtlRxOperationMode_t rxOperationMode = {};
Expand All @@ -626,21 +625,29 @@ DeviceD0Entry(
rxOperationMode.ForwardErrorPackets = false;
rxOperationMode.ForwardUndersizedGoodPackets = true;
rxOperationMode.QueueSize = rxQueueSize / 256u - 1;
rxOperationMode.HardwareFlowControl = rxQueueSize >= 2048;
rxOperationMode.HardwareFlowControl = context->config.rxFlowControl && rxQueueSize >= 2048;
rxOperationMode.FlowControlActivate = (rxFlowControlActivate / 512u) - 2u;
rxOperationMode.FlowControlDeactivate = (rxFlowControlDeactivate / 512u) - 2u;
Write32(&context->regs->Mtl_Q[0].Rx_Operation_Mode, rxOperationMode);

// MAC configuration.

MacConfiguration_t macConfig = {};
macConfig.DisableCarrierSenseDuringTransmit = true;
macConfig.PacketBurstEnable = true;
macConfig.ReceiverEnable = true;
macConfig.TransmitterEnable = true;
macConfig.DisableCarrierSenseDuringTransmit = true;
macConfig.DisableReceiveOwn = true;
macConfig.PacketBurstEnable = true;
//macConfig.PadOrCrcStripEnable = true; // Why doesn't this work?
//macConfig.CrcStripEnableForType = true; // Why doesn't this work?
macConfig.ChecksumOffloadEnable = context->config.txCoeSel || context->config.rxCoeSel;
Write32(&context->regs->Mac_Configuration, macConfig);

Mac_Vlan_Tag_Ctrl_t vlanTagCtrl = {};
vlanTagCtrl.StripOnReceive = VlanTagStripOnReceive_Always;
vlanTagCtrl.RxStatusEnable = true;
Write32(&context->regs->Mac_Vlan_Tag_Ctrl, vlanTagCtrl);

// Clear any pending interrupts, then unmask them.

NT_ASSERT(ReadNoFence8(&context->updateLinkStateBusy) == 0);
Expand Down Expand Up @@ -707,6 +714,7 @@ DevicePrepareHardware(
PHYSICAL_ADDRESS maxPhysicalAddress;
auto const context = DeviceGetContext(device);
bool configHasMacAddress = false;
ULONG flowControlConfiguration;

// Read configuration

Expand Down Expand Up @@ -746,6 +754,15 @@ DevicePrepareHardware(
memcpy(context->currentMacAddress, configAddress.Address, sizeof(context->currentMacAddress));
configHasMacAddress = true;
}

DECLARE_CONST_UNICODE_STRING(FlowControl_Name, L"FlowControl");
status = NetConfigurationQueryUlong(configuration, NET_CONFIGURATION_QUERY_ULONG_NO_FLAGS, &FlowControl_Name, &flowControlConfiguration);
if (!NT_SUCCESS(status))
{
TraceWrite("QueryFlowControl-not-found", LEVEL_VERBOSE,
TraceLoggingNTStatus(status));
flowControlConfiguration = 3; // Default = TxRxEnabled
}
}

// Configure resources
Expand Down Expand Up @@ -908,6 +925,14 @@ DevicePrepareHardware(
status = STATUS_DEVICE_CONFIGURATION_ERROR;
goto Done;
}

if (!context->feature0.SaVlanIns)
{
// Could adapt at runtime if needed, but assume it's present for now.
TraceWrite("DevicePrepareHardware-SaVlanIns-required", LEVEL_ERROR);
status = STATUS_DEVICE_CONFIGURATION_ERROR;
goto Done;
}
}

// Device Config
Expand All @@ -925,6 +950,33 @@ DevicePrepareHardware(
context->config.rd_osr_lmt = 8;
context->config.blen = 0x7; // 0x7 = 4, 8, 16

switch (flowControlConfiguration)
{
case 0: // Disabled
context->config.txFlowControl = false;
context->config.rxFlowControl = false;
break;
case 1: // TxEnabled
context->config.txFlowControl = true;
context->config.rxFlowControl = false;
break;
case 2: // RxEnabled
context->config.txFlowControl = false;
context->config.rxFlowControl = true;
break;
case 3: // TxRxEnabled
case 4: // AutoNegotiate
context->config.txFlowControl = true;
context->config.rxFlowControl = true;
break;
default:
TraceWrite("QueryFlowControl-bad-value", LEVEL_WARNING,
TraceLoggingUInt32(flowControlConfiguration, "value"));
context->config.txFlowControl = true;
context->config.rxFlowControl = true;
break;
}

auto const deviceObject = WdfDeviceWdmGetPhysicalDevice(device);
PACPI_EVAL_OUTPUT_BUFFER outputBuffer = nullptr;
ACPI_METHOD_ARGUMENT const UNALIGNED* properties = nullptr;
Expand Down Expand Up @@ -1139,7 +1191,7 @@ DevicePrepareHardware(

NET_ADAPTER_TX_CAPABILITIES txCaps;
NET_ADAPTER_TX_CAPABILITIES_INIT_FOR_DMA(&txCaps, &dmaCaps, QueuesSupported);
txCaps.MaximumNumberOfFragments = QueueDescriptorMinCount - 1;
txCaps.MaximumNumberOfFragments = QueueDescriptorMinCount - 2; // = 1 hole in the ring + 1 context descriptor.

NET_ADAPTER_RX_CAPABILITIES rxCaps; // TODO: Might use less memory if driver-managed.
NET_ADAPTER_RX_CAPABILITIES_INIT_SYSTEM_MANAGED_DMA(&rxCaps, &dmaCaps, RxBufferSize, QueuesSupported); // TODO: Jumbo packets.
Expand Down Expand Up @@ -1181,6 +1233,12 @@ DevicePrepareHardware(
NET_ADAPTER_OFFLOAD_RX_CHECKSUM_CAPABILITIES_INIT(&rxChecksumCaps,
AdapterOffloadSetRxChecksum);
NetAdapterOffloadSetRxChecksumCapabilities(context->adapter, &rxChecksumCaps);

NET_ADAPTER_OFFLOAD_IEEE8021Q_TAG_CAPABILITIES ieee8021qCaps;
NET_ADAPTER_OFFLOAD_IEEE8021Q_TAG_CAPABILITIES_INIT(&ieee8021qCaps,
NetAdapterOffloadIeee8021PriorityTaggingFlag |
NetAdapterOffloadIeee8021VlanTaggingFlag);
NetAdapterOffloadSetIeee8021qTagCapabilities(context->adapter, &ieee8021qCaps);
}

// Initialize adapter.
Expand Down Expand Up @@ -1325,11 +1383,9 @@ _IRQL_requires_max_(DISPATCH_LEVEL)
void
DeviceAddStatisticsTxQueue(
_Inout_ DeviceContext* context,
UINT32 ownDescriptors,
UINT32 doneFragments)
{
// DISPATCH_LEVEL
context->txOwnDescriptors += ownDescriptors;
context->txDoneFragments += doneFragments;
}

Expand Down Expand Up @@ -1544,7 +1600,6 @@ PerfDataInit(
data->DpcFatalBusError = context->dpcFatalBusError;
data->RxOwnDescriptors = context->rxOwnDescriptors;
data->RxDoneFragments = context->rxDoneFragments;
data->TxOwnDescriptors = context->txOwnDescriptors;
data->TxDoneFragments = context->txDoneFragments;
}

Expand Down
3 changes: 2 additions & 1 deletion drivers/net/dwc_eqos/device.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ struct DeviceConfig
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).
bool txFlowControl; // Adapter configuration (Ndi\params\*FlowControl).
bool rxFlowControl; // Adapter configuration (Ndi\params\*FlowControl).
};

// Referenced in driver.cpp DriverEntry.
Expand Down Expand Up @@ -66,5 +68,4 @@ _IRQL_requires_max_(DISPATCH_LEVEL)
void
DeviceAddStatisticsTxQueue(
_Inout_ DeviceContext* context,
UINT32 ownDescriptors,
UINT32 doneFragments);
9 changes: 4 additions & 5 deletions drivers/net/dwc_eqos/driver.cpp
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
#include "precomp.h"
#include "device.h" // DeviceAdd
#include "device.h"
#include "trace.h"

/*
Possible areas for improvement:
- Run against network test suites and fix any issues.
- Jumbo frames.
- Configuration in registry (e.g. flow control, speed, duplex).
- Tx segmentation offload.
- Wake-on-LAN.
- ARP offload.
- Run against network test suites and fix any issues.
- Power control, wake-on-LAN, ARP offload.
- Configure speed, duplex in Ndi\params.
- Multi-queue support?
*/

Expand Down
100 changes: 47 additions & 53 deletions drivers/net/dwc_eqos/dwc_eqos.inf
Original file line number Diff line number Diff line change
Expand Up @@ -77,52 +77,44 @@ HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"

[DWCEQOS_AddReg_Ndi_params]

HKR, Ndi\params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
HKR, Ndi\params\NetworkAddress, type, 0, "edit"
HKR, Ndi\params\NetworkAddress, default, 0, ""
HKR, Ndi\params\NetworkAddress, LimitText, 0, "12"
HKR, Ndi\params\NetworkAddress, UpperCase, 0, "1"
HKR, Ndi\params\NetworkAddress, Optional, 0, "1"

HKR, Ndi\params\*IPChecksumOffloadIPv4, ParamDesc, 0, %IPChksumOffV4%
HKR, Ndi\params\*IPChecksumOffloadIPv4, default, 0, "3"
HKR, Ndi\params\*IPChecksumOffloadIPv4, type, 0, "enum"
HKR, Ndi\params\*IPChecksumOffloadIPv4\enum, "0", 0, %Disabled%
HKR, Ndi\params\*IPChecksumOffloadIPv4\enum, "1", 0, %TxEnabled%
HKR, Ndi\params\*IPChecksumOffloadIPv4\enum, "2", 0, %RxEnabled%
HKR, Ndi\params\*IPChecksumOffloadIPv4\enum, "3", 0, %RxTxEnabled%

HKR, Ndi\params\*TCPChecksumOffloadIPv4, ParamDesc, 0, %TCPChksumOffV4%
HKR, Ndi\params\*TCPChecksumOffloadIPv4, default, 0, "3"
HKR, Ndi\params\*TCPChecksumOffloadIPv4, type, 0, "enum"
HKR, Ndi\params\*TCPChecksumOffloadIPv4\enum, "0", 0, %Disabled%
HKR, Ndi\params\*TCPChecksumOffloadIPv4\enum, "1", 0, %TxEnabled%
HKR, Ndi\params\*TCPChecksumOffloadIPv4\enum, "2", 0, %RxEnabled%
HKR, Ndi\params\*TCPChecksumOffloadIPv4\enum, "3", 0, %RxTxEnabled%

HKR, Ndi\params\*UDPChecksumOffloadIPv4, ParamDesc, 0, %UDPChksumOffV4%
HKR, Ndi\params\*UDPChecksumOffloadIPv4, default, 0, "3"
HKR, Ndi\params\*UDPChecksumOffloadIPv4, type, 0, "enum"
HKR, Ndi\params\*UDPChecksumOffloadIPv4\enum, "0", 0, %Disabled%
HKR, Ndi\params\*UDPChecksumOffloadIPv4\enum, "1", 0, %TxEnabled%
HKR, Ndi\params\*UDPChecksumOffloadIPv4\enum, "2", 0, %RxEnabled%
HKR, Ndi\params\*UDPChecksumOffloadIPv4\enum, "3", 0, %RxTxEnabled%

HKR, Ndi\params\*TCPChecksumOffloadIPv6, ParamDesc, 0, %TCPChksumOffV6%
HKR, Ndi\params\*TCPChecksumOffloadIPv6, default, 0, "3"
HKR, Ndi\params\*TCPChecksumOffloadIPv6, type, 0, "enum"
HKR, Ndi\params\*TCPChecksumOffloadIPv6\enum, "0", 0, %Disabled%
HKR, Ndi\params\*TCPChecksumOffloadIPv6\enum, "1", 0, %TxEnabled%
HKR, Ndi\params\*TCPChecksumOffloadIPv6\enum, "2", 0, %RxEnabled%
HKR, Ndi\params\*TCPChecksumOffloadIPv6\enum, "3", 0, %RxTxEnabled%

HKR, Ndi\params\*UDPChecksumOffloadIPv6, ParamDesc, 0, %UDPChksumOffV6%
HKR, Ndi\params\*UDPChecksumOffloadIPv6, default, 0, "3"
HKR, Ndi\params\*UDPChecksumOffloadIPv6, type, 0, "enum"
HKR, Ndi\params\*UDPChecksumOffloadIPv6\enum, "0", 0, %Disabled%
HKR, Ndi\params\*UDPChecksumOffloadIPv6\enum, "1", 0, %TxEnabled%
HKR, Ndi\params\*UDPChecksumOffloadIPv6\enum, "2", 0, %RxEnabled%
HKR, Ndi\params\*UDPChecksumOffloadIPv6\enum, "3", 0, %RxTxEnabled%
HKR, Ndi\params\NetworkAddress, ParamDesc, 0, %NetworkAddress%
HKR, Ndi\params\NetworkAddress, type, 0, "edit"
HKR, Ndi\params\NetworkAddress, default, 0, ""
HKR, Ndi\params\NetworkAddress, LimitText, 0, "12"
HKR, Ndi\params\NetworkAddress, UpperCase, 0, "1"
HKR, Ndi\params\NetworkAddress, Optional, 0, "1"

HKR, Ndi\params\*FlowControl, ParamDesc, 0, %FlowControl%
HKR, Ndi\params\*FlowControl, default, 0, "3"
HKR, Ndi\params\*FlowControl, type, 0, "enum"
HKR, Ndi\params\*FlowControl\enum, "0", 0, %Disabled%
HKR, Ndi\params\*FlowControl\enum, "1", 0, %TxEnabled%
HKR, Ndi\params\*FlowControl\enum, "2", 0, %RxEnabled%
HKR, Ndi\params\*FlowControl\enum, "3", 0, %TxRxEnabled%

HKR, Ndi\Params\*PriorityVLANTag, ParamDesc, 0, %PriorityVlanTag%
HKR, Ndi\Params\*PriorityVLANTag, Default, 0, "3"
HKR, Ndi\Params\*PriorityVLANTag, Type, 0, "enum"
HKR, Ndi\Params\*PriorityVLANTag\enum, "0", 0, %Disabled%
HKR, Ndi\Params\*PriorityVLANTag\enum, "1", 0, %PriorityEnabled%
HKR, Ndi\Params\*PriorityVLANTag\enum, "2", 0, %VlanEnabled%
HKR, Ndi\Params\*PriorityVLANTag\enum, "3", 0, %PriorityVlanEnabled%

HKR, Ndi\params\*TCPUDPChecksumOffloadIPv4, ParamDesc, 0, %TCPUDPChecksumOffloadIPv4%
HKR, Ndi\params\*TCPUDPChecksumOffloadIPv4, default, 0, "3"
HKR, Ndi\params\*TCPUDPChecksumOffloadIPv4, type, 0, "enum"
HKR, Ndi\params\*TCPUDPChecksumOffloadIPv4\enum, "0", 0, %Disabled%
HKR, Ndi\params\*TCPUDPChecksumOffloadIPv4\enum, "1", 0, %TxEnabled%
HKR, Ndi\params\*TCPUDPChecksumOffloadIPv4\enum, "2", 0, %RxEnabled%
HKR, Ndi\params\*TCPUDPChecksumOffloadIPv4\enum, "3", 0, %TxRxEnabled%

HKR, Ndi\params\*TCPUDPChecksumOffloadIPv6, ParamDesc, 0, %TCPUDPChecksumOffloadIPv6%
HKR, Ndi\params\*TCPUDPChecksumOffloadIPv6, default, 0, "3"
HKR, Ndi\params\*TCPUDPChecksumOffloadIPv6, type, 0, "enum"
HKR, Ndi\params\*TCPUDPChecksumOffloadIPv6\enum, "0", 0, %Disabled%
HKR, Ndi\params\*TCPUDPChecksumOffloadIPv6\enum, "1", 0, %TxEnabled%
HKR, Ndi\params\*TCPUDPChecksumOffloadIPv6\enum, "2", 0, %RxEnabled%
HKR, Ndi\params\*TCPUDPChecksumOffloadIPv6\enum, "3", 0, %TxRxEnabled%

[DWCEQOS_Device.NT.Services]
AddService = %ServiceName%, 2, DWCEQOS_AddService, DWCEQOS_AddService_EventLog
Expand Down Expand Up @@ -153,19 +145,21 @@ KmdfLibraryVersion = $KMDFVERSION$

[Strings]
ProviderName = "Open Source"
NetworkAddress = "Network Address"
RKCP = "Rockchip"
DWCEQOS.DeviceDesc = "Synopsys DesignWare Ethernet Quality of Service (GMAC)"
DWCEQOS.ServiceDesc = "DesignWare Ethernet"
IPChksumOffV4 = "IPv4 Checksum Offload"
TCPChksumOffV4 = "TCP Checksum Offload (IPv4)"
UDPChksumOffV4 = "UDP Checksum Offload (IPv4)"
TCPChksumOffV6 = "TCP Checksum Offload (IPv6)"
UDPChksumOffV6 = "UDP Checksum Offload (IPv6)"
NetworkAddress = "Network Address"
FlowControl = "Flow Control"
PriorityVlanTag = "Packet Priority & VLAN"
TCPUDPChecksumOffloadIPv4 = "TCP/UDP Checksum Offload (IPv4)"
TCPUDPChecksumOffloadIPv6 = "TCP/UDP Checksum Offload (IPv6)"
Disabled = "Disabled"
TxEnabled = "Tx Enabled"
RxEnabled = "Rx Enabled"
RxTxEnabled = "Rx & Tx Enabled"
TxRxEnabled = "Tx and Rx Enabled"
PriorityEnabled = "Packet Priority Enabled"
VlanEnabled = "VLAN Enabled"
PriorityVlanEnabled = "Packet Priority & VLAN Enabled"

; Not localized
ServiceName = "dwc_eqos"
13 changes: 2 additions & 11 deletions drivers/net/dwc_eqos/dwc_eqos_perf.man
Original file line number Diff line number Diff line change
Expand Up @@ -452,21 +452,12 @@
type="perf_counter_rawcount"
uri="uri:opensource/dwc_eqos/perf/debug/RxDoneFragments"
/>
<counter
detailLevel="standard"
field="TxOwnDescriptors"
id="9"
name="TxOwnDescriptors"
nameID="278"
type="perf_counter_rawcount"
uri="uri:opensource/dwc_eqos/perf/debug/TxOwnDescriptors"
/>
<counter
detailLevel="standard"
field="TxDoneFragments"
id="10"
id="9"
name="TxDoneFragments"
nameID="280"
nameID="278"
type="perf_counter_rawcount"
uri="uri:opensource/dwc_eqos/perf/debug/TxDoneFragments"
/>
Expand Down
1 change: 0 additions & 1 deletion drivers/net/dwc_eqos/dwc_eqos_perf_data.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ struct PERF_DEBUG_DATA
UINT32 DpcFatalBusError;
UINT32 RxOwnDescriptors;
UINT32 RxDoneFragments;
UINT32 TxOwnDescriptors;
UINT32 TxDoneFragments;
};

Expand Down
1 change: 1 addition & 0 deletions drivers/net/dwc_eqos/precomp.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#pragma warning(pop)

#include <netadaptercx.h>
#include <net/ieee8021q.h>
#include <net/logicaladdress.h>
#include <net/virtualaddress.h>
#include <net/checksum.h>
Expand Down
Loading

0 comments on commit 3a000eb

Please sign in to comment.