A link-layer engineer is asked a simple question during debug: "Is the link up?" The honest answer is "which part of it?" Lanes may be detected but not locked, locked but not configured, configured but with flow-control credits still uninitialised, or fully up but about to retrain. Each of those is a different state, with different rules about what may be sent. A link is not up or down. It is a state machine.
What does the state machine that runs a link look like, and what does each state allow?
The obvious design is a single "link up" bit. It hides the cases that cause bugs: traffic sent before credits are initialised, requests queued while the link is retraining, a low-power entry while packets are still in flight. Each of those needs a distinct state, explicit transitions, and a rule for what the layers above may do in it.
State | What may be sent | What the layers above see |
|---|---|---|
DOWN | Nothing (maybe detection pulses) | Link down: outstanding requests failed, new ones refused or errored |
TRAINING | Training patterns only | Not yet available |
INIT | Link-layer initialisation (credits, sequence numbers) | Not yet available |
ACTIVE | Everything | Link up |
RECOVERY | Training patterns only; packets wait | Link up, stalled: requests queue, replay buffer keeps its contents |
SLEEP (low power) | Nothing until wake | Link up, with added latency on the next request |
Both ends must agree on every transition, using training patterns or explicit messages. A side that thinks it is active while the other is training sends packets into a receiver that ignores them.
Recovery keeps state, down discards it: retraining should not lose sequence numbers or buffered packets; dropping to DOWN must fail everything outstanding (lesson 11.3).
Every state needs a timeout: a link stuck in TRAINING or RECOVERY for ever is a hang (lesson 9.9); time out to DOWN and start again.
Expose the state: debug depends on knowing which state the link is in and how often it has visited RECOVERY.
Protocol | Link state machine |
|---|---|
PCI Express | The LTSSM: Detect, Polling, Configuration, L0 (active), Recovery, the low-power states L0s, L1 and L2, plus Disabled, Loopback and Hot Reset. Flow-control initialisation completes in the data link layer before transactions flow. Controllers expose the current LTSSM state for debug. |
DCLink | Step 10 negotiation ends in ACTIVE; the replay of step 9 runs inside it; step 11 adds a low-power state. |
A link controller (illustrative) left RECOVERY one cycle earlier on one side than the other. For that cycle, the first side sent a packet the second still treated as a training pattern and discarded. Usually replay fixed it, but when the packet was an acknowledgement, the sender waited for a replay timeout every time. Making the exit depend on receiving the partner's exit pattern, not on a local timer, fixed it.
The physical link works, but link-layer state such as credits and sequence numbers must be initialised before packets can be sent safely.
The partner's pattern, so both ends leave together; a local timer lets them drift apart by a cycle or more.
A link is a state machine: down, training, initialisation, active, recovery and low power.
Each state defines what may be sent and what the upper layers see; recovery keeps state, down discards it.
Agree every transition with the partner, time out every state, and expose the state for debug.