Welcome back. In the previous lesson, you built a manual-fact ledger and learned to stop when a hardware claim is unclear, incomplete, or contradictory. That gives you a safe answer to: “What does this switch actually do?”
This lesson adds a second kind of investigation: comparison. You will split the driver into small hardware traits, then find upstream drivers, kernel changes, and mailing-list discussions that are relevant to each trait. The objective is not to find code to copy. It is to find narrowly applicable implementation patterns and the reasoning behind them, while keeping your switch’s documented behavior separate from another chip’s behavior.
By the end, you should have a trait research log that tells an agent exactly what to investigate, which upstream references are useful, which differences block reuse, and when it must ask a human rather than infer an answer.
A hardware trait is a bounded behavior, not a driver file
A DSA driver may have one main C file, one tagger, a binding YAML file, and perhaps PHY support. Those are source-file boundaries. They are not good investigation boundaries.
A hardware trait is one independently checkable part of the switch’s behavior. It has:
- A specific hardware question.
- A manual-evidence requirement.
- A DSA or kernel integration question.
- A small set of plausible upstream comparators.
- Explicit differences that might make a comparator unsafe.
For example, “CPU-port tagging” is a trait. “The tagger source file” is not. CPU-port tagging includes at least these separate questions:
- Where is the tag placed: before Ethernet headers, before EtherType, or at the packet tail?
- Does hardware insert it on traffic toward the CPU, consume it on traffic from the CPU, or both?
- Which fields identify source and destination ports?
- Is tag length fixed or variable?
- Does the tag change frame length, FCS treatment, MTU requirements, checksum handling, or packet parsing?
- Which chip mode, strap, or register setting enables it?
A comparable upstream tagger may be useful for how Linux adjusts an sk_buff, handles headroom, or maps a source-port field to a DSA port. It cannot prove that your chip uses the same tag position, byte order, field encoding, or enable sequence.
The same rule applies throughout the driver:
Similar code can establish a candidate Linux pattern. Only evidence for your hardware can establish your hardware behavior.
The Kernel DSA Architecture documentation provides the shared vocabulary needed to make this split. Read it as a description of the DSA-side contract, then verify API details against the exact target kernel tree for the V1 revision.
Read the Linux kernel’s DSA Architecture documentation to separate switch roles, tagging mechanics, registration responsibilities, and bridge or VLAN operations into distinct investigation traits.
In the “Design principles” section, read the port-role model. Distinguish the conduit or CPU-facing connection from user ports and possible DSA cascade ports. Then, in “Switch tagging protocols,” read the tag contract, followed by the three tag-placement categories and the discussion of headroom, tailroom, and MTU handling. Focus on what the DSA tagger must do after the hardware format is known; do not treat these general categories as proof of your switch’s format. In “Driver development,” under “Probing, registration and device lifetime,” read the registration and shutdown discussion. Under “Switch configuration,” read from the core callbacks. Note which traits affect setup, isolation, tag selection, and teardown. Finally, in “Bridge layer” and “Bridge VLAN filtering,” scan the callback descriptions. Use them to identify separate forwarding, learning, FDB, bridge, STP, and VLAN traits rather than treating “bridge offload” as one indivisible feature.
A useful first trait inventory for a DSA V1 is below. Do not assume every row applies to the target switch. Mark a row OUT OF SCOPE if V1 does not expose it and no review comment requires it.
| Trait | Hardware question | Typical V1 surfaces | High-risk assumption to avoid |
|---|---|---|---|
| Chip access | How are registers addressed, synchronized, and error-checked? | Bus read/write helpers, probe | A similar indirect-access engine has identical completion or error semantics |
| Port topology | Which logical ports are CPU, user, internal PHY, unused, or cascade ports? | num_ports, port tables, Device Tree | A port number in another package or board layout applies here |
| CPU-port interface | Which MAC mode, clocks, delays, and link-management method apply? | CPU port node, phy-mode, phylink setup | The board’s straps match a reference board |
| Packet tagging | What is inserted, consumed, and encoded in each direction? | Tagger, get_tag_protocol | Same vendor means same tag format |
| Reset and bootstrap | What is reset, when is it complete, and what state remains? | Probe, setup, reset controller | Another driver’s delay or polling loop is safe |
| Initial isolation | What forwarding state protects ports before bridge configuration? | setup, port setup | Default bootloader forwarding state is safe |
| PHY and link management | Are PHYs internal or external, and how is link state read or configured? | MDIO callbacks, phylink, PHY driver | A PHY driver’s behavior proves switch MAC behavior |
| VLAN, FDB, and MDB tables | What table model and resource limits exist? | VLAN/FDB callbacks, bridge operations | Similar table names have identical keys or isolation rules |
| Interrupts and status | Which bits mask, acknowledge, clear, or latch events? | IRQ handler, status helpers | Read-clear and write-one-to-clear behave alike |
| Statistics and tables | What widths, clear behavior, and access ordering apply? | ethtool statistics, table access | Counter reads are safe concurrently or never wrap |
This decomposition avoids a common AI-agent failure: it sees a broad review comment such as “please use the standard DSA flow” and makes a large rewrite touching probe, tagger, binding, and VLAN code together. Instead, it should identify the exact traits involved and investigate each one separately.
Build a trait card before searching for analogies
For every trait that is connected to V1 or a reviewer comment, create a short card. The card is a research request, not yet a design decision.
id: "TR-TAG-001"
trait: "CPU-port packet tagging"
question: >-
What framing and port-selection behavior does the target switch require
for packets sent to and received from the CPU-facing Ethernet link?
v1_locations:
- "net/dsa/tag_<driver>.c: <function or hunk>"
- "drivers/net/dsa/<driver>.c: <get tag protocol callback>"
review_tasks:
- "RV-<id>"
hardware_evidence_needed:
- "RX packet-layout description"
- "TX packet-layout description"
- "Tag enable conditions"
- "Port-number encoding"
- "Frame-size, FCS, and checksum notes if documented"
kernel_questions:
- "Which target-tree DSA tag protocol interface is required?"
- "Does tag placement require headroom, tailroom, or special parsing?"
- "Which offload assumptions must the tagger preserve?"
comparison_dimensions:
- "tag position"
- "RX and TX directionality"
- "tag length"
- "source and destination field semantics"
- "CPU-port mode"
- "target-kernel tagger API"
blocked_by:
- "MF-TAG-<id>, if packet direction or field meaning is unclear"
The comparison_dimensions field is especially important. It prevents the agent from writing “Driver X has a 4-byte tag too” and treating that as meaningful similarity. Equal length alone says almost nothing. A tag can have the same length while placing fields in different bytes, using different port numbering, or having opposite TX and RX meaning.
For each trait, write the narrowest question first. Avoid vague cards such as:
Investigate VLAN support.
Prefer:
Determine whether the hardware assigns a filtering domain per VLAN, per bridge, per port, or through a shared global table, and whether V1’s callback set can represent that model safely.
That question tells the agent which manual material to find and which comparable drivers may be relevant.
Find comparators by mechanism, not by vendor name
Start with three kinds of candidate reference for each trait.
-
Family neighbor
A driver for the same vendor, hardware family, bus controller, or tag format. It may reveal naming, register-access conventions, or known silicon workarounds. It is still only a lead until the target chip’s manual supports the same behavior. -
Mechanism neighbor
A driver from any vendor that uses the same DSA-relevant mechanism: tail tagging, internal PHY access, a shared VLAN table, indirect FDB access, or a particular phylink arrangement. This is often more useful than a vendor neighbor for Linux-side code structure. -
Target-kernel API neighbor
A driver changed recently near the target kernel version and using the same callback or helper. This helps avoid copying an obsolete DSA interface from an older branch.
Use the local target kernel tree first. It gives reproducible results and avoids mixing code from a newer development branch into a V1 repair based on an older submission base.
# Locate candidate users of a DSA callback or feature.
git grep -n -E 'get_tag_protocol|change_tag_protocol' drivers/net/dsa net/dsa
git grep -n -E 'port_vlan_add|port_vlan_del|port_fdb_add' drivers/net/dsa
git grep -n 'dsa_switch_shutdown' drivers/net/dsa
# Find the history of one candidate implementation.
git log --follow -p -- drivers/net/dsa/<candidate>.c
git log --follow -p -- net/dsa/tag_<candidate>.c
# Find why an exact helper, callback, or lifecycle rule was introduced.
git log -S'dsa_switch_shutdown' -p -- drivers/net/dsa net/dsa
git log -S'<relevant helper name>' -p -- drivers/net/dsa net/dsa
# Inspect commit metadata, including any recorded discussion reference.
git show --format=fuller <commit-id>
When an upstream commit contains a discussion reference, record the exact commit ID, message ID or thread locator, author, date, and patch version. Read the discussion for rationale: perhaps a maintainer explains why an allocation must happen in setup, why a YAML property was rejected, or why a callback cannot safely return success.
A mailing-list statement is useful context, but it is not a timeless rule. Check whether:
- it concerns the same kernel API generation;
- a later patch or follow-up changed the conclusion;
- it depends on a particular hardware limitation;
- the final merged code actually matches the proposal.
The provided MT7628 patch-series history is a concise example of the kind of evidence you should preserve. It shows that one DSA support series can have independent review-driven changes in bindings, tagger code, MDIO handling, teardown, reset error paths, and object lifetime.
net: dsa: mt7628 embedded switch initial support [LWN.net]
Read this LWN-hosted patch-series record as an example of how upstream review separates DSA support into independent traits and how version histories preserve the reason for a change.
Read the stated scope first. It establishes what this particular driver claims to support, including its explicit bridge-offload limitation. Then read the revision notes from “Changes since v4” through “Changes since v1.” In particular, follow the v4 and v3 changes. Notice that the series treats MDIO object lifetime, VLAN behavior, reset error checking, binding schema structure, and integrated-PHY topology as separate issues. Finally, inspect the changed-file list. It shows that binding YAML, main switch driver, PHY support, and the DSA tagger are separate implementation components. Do not infer that your switch needs the same files, topology, or fixes; use the series only as a model for recording narrowly scoped changes and their review history.
The MT7628 series supports several process lessons:
- A binding correction does not establish a hardware correction.
- A tagger cleanup does not establish that the target switch has the same tag format.
- A lifetime fix may be broadly relevant as a device-model pattern, but its exact allocation and teardown conditions still need target-tree analysis.
- “No external MDIO bus” is a chip-specific claim. It must never be transferred to another switch merely because both have integrated PHYs.
Compare traits with explicit similarities and differences
The table below gives a focused search strategy for common DSA traits. Treat it as a query plan, not a list of features your driver must implement.
| Trait | Search for upstream code that shares | Confirm from your manual before reuse | Differences that block transfer |
|---|---|---|---|
| Register access | Same bus type, indirect register engine, timeout pattern, locking model | Command format, completion bit, error status, sleepability | Different busy semantics, bank selection, read-clear status, or atomic context |
| CPU-port interface | Same phylink or fixed-link model, similar MAC-side interface | Supported mode, clock direction, delays, strap state, link source | Different board wiring, in-band status support, or CPU-port number |
| Tagging | Same tag placement and target-tree tagger interface | Exact bytes, field encoding, RX/TX behavior, maximum overhead | Same tag length but different port fields, frame position, or checksum behavior |
| Reset | Similar device-managed reset use and error unwinding | Reset scope, completion indication, required ordering, retained state | Different reset controller, self-clearing behavior, or post-reset register state |
| Internal PHY | Similar user-MDIO access or built-in PHY topology | PHY addresses, MDIO visibility, link-status source, initialization needs | PHY access is indirect, external, or controlled by another block |
| Isolation and bridging | Similar port matrix, private VLAN, FID, or bridge-domain model | Initial forwarding state, learning behavior, CPU-port flooding rules | Global rather than per-port control, limited domains, no independent FIDs |
| VLAN and FDB | Similar table access and VLAN resource accounting | Key fields, table size, command completion, VID and FID semantics | Different table key, asynchronous engine, global table, or shared resource |
| IRQ and status | Similar threaded IRQ or polling structure | Masking, acknowledgement, clear operation, and source ownership | Read-clear versus write-one-to-clear, level versus edge behavior |
| Statistics | Similar ethtool layout and counter collection model | Width, wrap behavior, latch requirements, clear side effects | Counter read resets data, requires a table command, or is not per-port |
A comparison is acceptable only when its shared dimensions are documented. A useful record looks like this:
comparator:
name: "<upstream driver or commit>"
kind: "mechanism neighbor"
target_tree_ref: "<commit ID or target branch path>"
trait: "CPU-port packet tagging"
demonstrated_pattern: >-
The tagger reserves packet expansion space and updates packet layout
according to the selected tag placement.
similarities_confirmed:
- "Both formats are documented as tail tags."
- "Both require destination selection on CPU-originated frames."
- "Both drivers use the target kernel's DSA tagger interface."
differences_confirmed:
- "Target tag source-port field encoding is not yet established."
- "Comparator documents fixed tag length; target manual does not."
- "Comparator's checksum note does not mention the target hardware."
permitted_use: >-
Inspect its target-kernel packet-buffer handling and test expectations.
Do not copy field masks, tag length, destination encoding, or checksum
logic.
prohibited_claim: >-
The comparator does not prove that the target switch is compatible with
its tag protocol.
This is more valuable than a similarity score. A numerical score can hide the one difference that makes copying unsafe: a different field polarity, port numbering base, or reset completion condition.
Apply four gates before transferring any pattern
Before the agent converts a comparator into a code proposal, require these gates in order.
1. Hardware gate
The target manual must establish the required target behavior. For a tagger, that means the direction, layout, and field semantics needed by the proposed code. For reset, it means the reset effect and completion conditions.
If the manual record is UNCLEAR, INCOMPLETE, or CONFLICT, the agent may continue researching comparable code but must not implement the unproven behavior.
2. DSA-contract gate
The target kernel’s DSA contract must support the intended behavior. This includes callback lifetime, return-value rules, required isolation, tagger interface, and helper expectations.
A comparator from a different kernel era can explain why an operation exists but can still be unusable code.
3. Platform and binding gate
The board’s Device Tree and documented board configuration must support the proposal. A chip may support several CPU-port modes, while the board permits only one. The binding must describe properties that V1 consumes correctly and that are valid for the target kernel schema.
4. Lifecycle gate
The code must safely handle success, partial setup, failure, remove, and shutdown. A pattern that is functionally correct in normal probe may still leak an object or call DSA teardown twice on an error path.
If any gate fails, record the result as one of these outcomes:
| Outcome | Meaning | Agent action |
|---|---|---|
USABLE PATTERN | Hardware facts, target-kernel contract, and lifecycle preconditions all match | Propose a minimal change and send it through the normal check loop |
RESEARCH LEAD | Comparator suggests where to look, but target evidence is missing | Add manual or target-tree investigation tasks; do not edit |
REJECTED COMPARATOR | A documented difference makes it inapplicable | Preserve the reason and stop using it as support |
HUMAN QUESTION | A missing hardware or board fact blocks a decision | Ask the focused question format from the previous lesson |
This is how you prevent “upstream does it this way” from appearing as a substitute for evidence in a reviewer response.
A practical 35-minute research pass
Use the following pass for the V1 series now. Keep it deliberately small: three traits are enough for the first run.
-
Choose three review-linked traits — 5 minutes
Prioritize a hardware-dependent concern, a DSA integration concern, and a binding or lifecycle concern. For example: CPU-port tagging, reset sequencing, and internal-PHY topology. -
Create one trait card for each — 5 minutes
Include V1 locations, reviewer task IDs, missing manual fact IDs, and comparison dimensions. Do not decide on a fix. -
Find one family neighbor and one mechanism neighbor per trait — 10 minutes
Use the target kernel tree. Record candidate paths or commits, not just driver names. -
Inspect the relevant history and discussion metadata — 8 minutes
Look for why the callback, helper, or cleanup path changed. Record the exact commit and the thread reference if available. -
Write the comparison boundaries — 5 minutes
List confirmed similarities, confirmed differences, and unknowns. Unknowns are blockers, not similarities. -
Choose the next action — 2 minutes
Select one: inspect target-kernel API details, extract another manual fact, repair an independent issue, or ask a human question.
Keep the output in a version-controlled research file, for example:
evidence/
manual-facts.yaml
trait-research.yaml
upstream-history/
<trait>-commits.md
<trait>-threads.md
questions/
hardware-questions.md
The agent should be allowed to add research records and propose candidates. It should not change kernel code merely because it has found a close-looking driver.
When a failure is outside this lesson’s scope, use the course map rather than improvising:
- A missing, ambiguous, or conflicting manual claim returns to the previous lesson’s fact-ledger method.
- A callback, lock, sleepability, setup, shutdown, MDIO, or phylink question belongs in Module 4.
- A YAML schema, example, compatibility, or property-handling question belongs in Module 4’s binding lesson.
- Repeatable builds, saved logs, guarded worktrees, and agent permissions belong in Module 5.
- A Sashiko finding is handled through Module 6 after the normal checks pass.
Key takeaways
A good upstream comparison is narrow, documented, and honest about its limits.
- Split V1 into hardware traits such as tag format, reset behavior, CPU-port interface, PHY topology, forwarding isolation, and table access.
- Search for comparators by mechanism and target-kernel API use, not only by vendor or source-file similarity.
- Use driver code to learn implementation patterns, commits to learn change history, and mailing-list discussions to learn rationale.
- Require documented target-hardware behavior, target-kernel compatibility, board or binding validity, and safe lifecycle handling before reusing a pattern.
- Record confirmed similarities, confirmed differences, and unknowns separately. An unknown is never permission to copy.
- When manual evidence is insufficient, keep the comparison as a research lead and ask a focused human question rather than implementing a plausible guess.
Next, you will combine these results into one evidence table that keeps manual facts, V1 behavior, DSA rules, upstream patterns, assumptions, and open hardware questions visibly separate.
Can't find a good explanation? Sign up and we'll make it for you
Sign up