Skip to content

Commit

Permalink
dwc_eqos - fix transmitted vlan tags (#40)
Browse files Browse the repository at this point in the history
All transmitted VLAN tags were 0. We weren't setting the VlanInput flag,
so when inserting VLAN tags, the adapter was using a global value (0)
instead of the value from the descriptor ring. Fix.

- Set the VlanInput flag so that inserted VLAN tags are taken from
  context descriptor.
- Add a VLAN ID configuration setting. This is a semi-standard tag, and
  I couldn't find great details on how it is supposed to work. At
  present, it just controls the default VLAN tag to use when transmitting.
  I think some adapters also use it to filter received packets, but I
  don't think that's a good idea for this driver since NetAdapterCx
  doesn't support OID_GEN_VLAN_ID.
- Update Tx path to handle a default VLAN tag. Ended up cleaning things
  up a bit so the result is shorter.
  • Loading branch information
idigdoug authored Jan 19, 2024
1 parent 87e3e62 commit 07fa5d6
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 46 deletions.
17 changes: 16 additions & 1 deletion drivers/net/dwc_eqos/device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -675,6 +675,10 @@ DeviceD0Entry(
vlanTagCtrl.RxStatusEnable = true;
Write32(&context->regs->Mac_Vlan_Tag_Ctrl, vlanTagCtrl);

MacVlanIncl_t vlanIncl = {};
vlanIncl.VlanInput = true; // Get packet's VLAN tag from context descriptor.
Write32(&context->regs->Mac_Vlan_Incl, vlanIncl);

MacWatchdogTimeout_t watchdogTimeout = {};
// 0 = 2KB, 1 = 3KB, ... 14 = 16KB, 15 = Reserved.
// jumboFrame value doesn't include VLAN or CRC, so add 8.
Expand Down Expand Up @@ -752,6 +756,7 @@ DevicePrepareHardware(
bool configHasMacAddress = false;
ULONG flowControlConfiguration;
ULONG jumboPacketConfiguration;
ULONG vlanIdConfiguration;

// Read configuration

Expand Down Expand Up @@ -809,6 +814,15 @@ DevicePrepareHardware(
TraceLoggingNTStatus(status));
jumboPacketConfiguration = JumboPacketMin;
}

DECLARE_CONST_UNICODE_STRING(VlanID_Name, L"VlanID");
status = NetConfigurationQueryUlong(configuration, NET_CONFIGURATION_QUERY_ULONG_NO_FLAGS, &VlanID_Name, &vlanIdConfiguration);
if (!NT_SUCCESS(status))
{
TraceWrite("QueryVlanID-not-found", LEVEL_VERBOSE,
TraceLoggingNTStatus(status));
vlanIdConfiguration = 0;
}
}

// Configure resources
Expand Down Expand Up @@ -1021,6 +1035,7 @@ DevicePrepareHardware(
jumboPacketConfiguration < JumboPacketMin ? JumboPacketMin
: jumboPacketConfiguration > JumboPacketMax ? JumboPacketMax
: jumboPacketConfiguration);
context->config.vlanId = static_cast<UINT16>(vlanIdConfiguration <= 0xFFF ? vlanIdConfiguration : 0u);

switch (flowControlConfiguration)
{
Expand Down Expand Up @@ -1339,6 +1354,7 @@ DevicePrepareHardware(
}

Write32(&regs->Axi_Lpi_Entry_Interval, 15); // AutoAxiLpi after (interval + 1) * 64 clocks. Max value is 15.

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.
Expand All @@ -1348,7 +1364,6 @@ DevicePrepareHardware(
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.BurstLengths = context->config.blen;

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

Expand Down
1 change: 1 addition & 0 deletions drivers/net/dwc_eqos/device.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ struct DeviceConfig
bool txFlowControl; // Adapter configuration (Ndi\params\*FlowControl).
bool rxFlowControl; // Adapter configuration (Ndi\params\*FlowControl).
UINT16 jumboFrame; // Adapter configuration (Ndi\params\*JumboFrame). 1514..9014.
UINT16 vlanId; // Adapter configuration (Ndi\params\*VlanID). 0..4095.

UINT16 RxBufferSize() const
{
Expand Down
7 changes: 7 additions & 0 deletions drivers/net/dwc_eqos/dwc_eqos.inf
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,12 @@ HKR, Ndi\params\NetworkAddress, LimitText, 0, "12"
HKR, Ndi\params\NetworkAddress, UpperCase, 0, "1"
HKR, Ndi\params\NetworkAddress, Optional, 0, "1"

HKR, Ndi\params\VlanID, ParamDesc, 0, %VlanID%
HKR, Ndi\params\VlanID, type, 0, "int"
HKR, Ndi\params\VlanID, default, 0, "0"
HKR, Ndi\params\VlanID, min, 0, "0"
HKR, Ndi\params\VlanID, max, 0, "4094"

HKR, Ndi\params\*JumboPacket, ParamDesc, 0, %JumboPacket%
HKR, Ndi\params\*JumboPacket, type, 0, "int"
HKR, Ndi\params\*JumboPacket, default, 0, "1514"
Expand Down Expand Up @@ -203,6 +209,7 @@ RKCP = "Rockchip"
DWCEQOS.DeviceDesc = "Synopsys DesignWare Ethernet Quality of Service (GMAC)"
DWCEQOS.ServiceDesc = "DesignWare Ethernet"
NetworkAddress = "Network Address"
VlanID = "VLAN ID"
JumboPacket = "Jumbo Packet"
FlowControl = "Flow Control"
PriorityVlanTag = "Packet Priority & VLAN"
Expand Down
21 changes: 20 additions & 1 deletion drivers/net/dwc_eqos/registers.h
Original file line number Diff line number Diff line change
Expand Up @@ -676,6 +676,25 @@ union MacVlanTagCtrl_t
};
};

union MacVlanIncl_t
{
UINT32 Value32;
struct
{
UINT16 VlanTagTx; // VLT

UINT8 VlanControl : 2; // VLC
UINT8 VlanControlPriority : 1; // VLP
UINT8 VlanS : 1; // CSVL
UINT8 VlanInput : 1; // VLTI
UINT8 VLanChannelInsertion : 1;
UINT8 Reserved22 : 2;
UINT8 Addr : 6; // ADDR
UINT8 ReadWriteControl : 1; // RDWR
UINT8 Busy : 1; // BUSY
};
};

union MacInterruptStatus_t
{
UINT32 Value32;
Expand Down Expand Up @@ -995,7 +1014,7 @@ struct MacRegisters
// The VLAN Tag Inclusion or Replacement register contains the VLAN tag for
// insertion or replacement in the Transmit packets. It also contains the VLAN tag
// insertion controls.
ULONG Mac_Vlan_Incl;
MacVlanIncl_t Mac_Vlan_Incl;

// MAC_Inner_VLAN_Incl @ 0x0064 = 0x0:
// The Inner VLAN Tag Inclusion or Replacement register contains the inner VLAN
Expand Down
70 changes: 26 additions & 44 deletions drivers/net/dwc_eqos/txqueue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ struct TxQueueContext
NET_EXTENSION packetChecksum;
NET_EXTENSION fragmentLogical;
UINT32 descCount; // A power of 2 between QueueDescriptorMinCount and QueueDescriptorMaxCount.
UINT16 vlanId;
UINT8 txPbl;

UINT16 lastMss; // MSS set by the most recent context descriptor.
Expand Down Expand Up @@ -65,8 +66,8 @@ TxQueueStart(_In_ NETPACKETQUEUE queue)
// PASSIVE_LEVEL, nonpaged (resume path)
auto const context = TxQueueGetContext(queue);

context->lastMss = 0; // Make no assumptions about the device's current MSS.
context->lastVlanTag = 0; // Make no assumptions about the device's current vlan tag.
context->lastMss = 0xFFFF; // Make no assumptions about the device's current MSS.
context->lastVlanTag = 0; // Make no assumptions about the device's current vlan tag.
context->descBegin = 0;
context->descEnd = 0;

Expand Down Expand Up @@ -211,11 +212,17 @@ TxQueueAdvance(_In_ NETPACKETQUEUE queue)
NT_ASSERT(fragmentCount != 0);

auto const ieee8021Q = *NetExtensionGetPacketIeee8021Q(&context->packetIeee8021Q, pktIndex);
UINT16 const ieee8021QPriority = (ieee8021Q.TxTagging & NetPacketTxIeee8021qActionFlagPriorityRequired)
? ieee8021Q.PriorityCodePoint : 0u;
UINT16 const ieee8021QVlan = (ieee8021Q.TxTagging & NetPacketTxIeee8021qActionFlagVlanRequired)
? ieee8021Q.VlanIdentifier : context->vlanId;
UINT16 const vlanTag = (ieee8021QPriority << 13) | ieee8021QVlan;
auto const vlanTagControl = vlanTag != 0 ? TxVlanTagControlInsert : TxVlanTagControlNone;
auto const contextTagNeeded = vlanTag != 0 && vlanTag != context->lastVlanTag;

auto const gso = NetExtensionGetPacketGso(&context->packetGso, pktIndex);
NT_ASSERT(gso->TCP.Mss <= 0x3FFF); // 14 bits
auto const gsoMss = static_cast<UINT16>(gso->TCP.Mss);
auto const vlanTagControl = ieee8021Q.TxTagging != 0 ? TxVlanTagControlInsert : TxVlanTagControlNone;

if (gsoMss != 0) // segmentation offload enabled
{
Expand Down Expand Up @@ -248,18 +255,6 @@ TxQueueAdvance(_In_ NETPACKETQUEUE queue)
NT_ASSERT(headerLength <= packetLength);
NT_ASSERT(userDescriptorsNeeded <= TxMaximumNumberOfFragments);

UINT16 newTag;
if (ieee8021Q.TxTagging != 0)
{
newTag = (ieee8021Q.PriorityCodePoint << 13) | ieee8021Q.VlanIdentifier;
NT_ASSERT(newTag != 0);
}
else
{
newTag = context->lastVlanTag;
}

bool const contextTagNeeded = newTag != context->lastVlanTag;
bool const contextMssNeeded = gsoMss != context->lastMss;
bool const contextNeeded = contextTagNeeded || contextMssNeeded;

Expand All @@ -275,7 +270,7 @@ TxQueueAdvance(_In_ NETPACKETQUEUE queue)
{
TxDescriptorContext descCtx = {};
descCtx.MaximumSegmentSize = gsoMss;
descCtx.VlanTag = newTag;
descCtx.VlanTag = vlanTag;
descCtx.VlanTagValid = contextTagNeeded;
descCtx.OneStepInputOrMssValid = true;
descCtx.ContextType = true;
Expand All @@ -289,7 +284,10 @@ TxQueueAdvance(_In_ NETPACKETQUEUE queue)
context->descVirtual[descIndex].Context = descCtx;
descIndex = (descIndex + 1) & descMask;
context->lastMss = gsoMss;
context->lastVlanTag = newTag;
if (contextTagNeeded)
{
context->lastVlanTag = vlanTag;
}
}

auto const frag0LogicalAddress = NetExtensionGetFragmentLogicalAddress(&context->fragmentLogical, fragIndex)->LogicalAddress;
Expand Down Expand Up @@ -365,25 +363,17 @@ TxQueueAdvance(_In_ NETPACKETQUEUE queue)
: checksum.Layer3 ? TxChecksumInsertionEnabledHeaderOnly
: TxChecksumInsertionDisabled;

if (ieee8021Q.TxTagging != 0)
// We might need a context descriptor.
if (fragmentCount + contextTagNeeded > EMPTY_DESC_REMAINING(descIndex))
{
UINT16 const newTag = (ieee8021Q.PriorityCodePoint << 13) | ieee8021Q.VlanIdentifier;
NT_ASSERT(newTag != 0);
if (newTag == context->lastVlanTag)
{
goto NoContextPacket;
}

// We will need a context descriptor.
if (fragmentCount + 1u > EMPTY_DESC_REMAINING(descIndex))
{
// Wait until more descriptors are free.
break;
}
// Wait until more descriptors are free.
break;
}

if (contextTagNeeded)
{
TxDescriptorContext descCtx = {};
descCtx.MaximumSegmentSize = context->lastMss;
descCtx.VlanTag = newTag;
descCtx.VlanTag = vlanTag;
descCtx.VlanTagValid = true;
descCtx.ContextType = true;
descCtx.Own = true;
Expand All @@ -395,17 +385,8 @@ TxQueueAdvance(_In_ NETPACKETQUEUE queue)
NT_ASSERT(EMPTY_DESC_REMAINING(descIndex) != 0);
context->descVirtual[descIndex].Context = descCtx;
descIndex = (descIndex + 1) & descMask;
context->lastVlanTag = newTag;
}
else
{
NoContextPacket:

if (fragmentCount > EMPTY_DESC_REMAINING(descIndex))
{
// Wait until more descriptors are free.
break;
}
TraceWrite("TxTag", LEVEL_INFO, TraceLoggingHexInt16(vlanTag));
context->lastVlanTag = vlanTag;
}

UINT32 frameLength = 0;
Expand Down Expand Up @@ -635,6 +616,7 @@ TxQueueCreate(
context->packetRing = NetRingCollectionGetPacketRing(rings);
context->fragmentRing = NetRingCollectionGetFragmentRing(rings);
context->descCount = QueueDescriptorCount(context->fragmentRing->NumberOfElements);
context->vlanId = deviceConfig.vlanId;
context->txPbl = deviceConfig.txPbl;

TraceWrite("TxQueueCreate-size", LEVEL_VERBOSE,
Expand Down

0 comments on commit 07fa5d6

Please sign in to comment.