Skip to content
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
226 changes: 226 additions & 0 deletions doc/pmon/precoding_via_media_settings_hld.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,226 @@
# SPC-6 ASIC SerDes Precoding via `media_settings.json` — HLD

## Table of Content

- [SPC-6 ASIC SerDes Precoding via `media_settings.json` — HLD](#spc-6-asic-serdes-precoding-via-media_settingsjson--hld)
- [Table of Content](#table-of-content)
- [1. Revision](#1-revision)
- [2. Scope](#2-scope)
- [3. Definitions](#3-definitions)
- [4. Background](#4-background)
- [5. Requirements](#5-requirements)
- [6. Architecture Design](#6-architecture-design)
- [7. High-Level Design](#7-high-level-design)
- [7.1 `media_settings.json` schema additions](#71-media_settingsjson-schema-additions)
- [Flow — adding a new module](#flow--adding-a-new-module)
- [7.2 xcvrd](#72-xcvrd)
- [7.3 orchagent](#73-orchagent)
- [8. Configuration and Management](#8-configuration-and-management)
- [9. Testing](#9-testing)
- [10. Open Items / Future Work](#10-open-items--future-work)

---

### 1. Revision

| Rev | Date | Author | Change Description |
| --- | ---------- | ------------- | ----------------------------------------------------------------------- |
| 0.1 | 2026-05-12 | Natanel Gerbi | Initial draft. |

Tracking:

- [FR #4867218 — Modules | SPC-6 | Tx/Rx Module's pre-coding control | Independent mode](https://redmine.mellanox.com/issues/4867218)

---

### 2. Scope

This HLD covers ASIC/SerDes precoding configuration on SPC-6 platforms while APSU is not yet supported by firmware.

In scope:

1. Extending `media_settings.json` with per-lane `tx_precoding` / `rx_precoding` fields.
2. Extending orchagent (PortsOrch) to map the new fields to `SAI_PORT_SERDES_ATTR_{TX,RX}_PRECODING`.

`xcvrd` requires **no parser change** — its data path is already field-agnostic ([§7.2](#72-xcvrd)).

---

### 3. Definitions

| Term | Definition |
| --------- | ---------- |
| CMIS | Common Management Interface Specification |
| iLT | Initial Link Training — per-lane electrical handshake between switch SERDES and module host CDR |
| APSU | Autonomous Path Start-Up (IEEE 802.3dj Annex 178B) — end-to-end protocol that extends iLT with in-band precoding negotiation |
| Precoding | Gray-coding applied at Tx SERDES to prevent DFE error propagation on PAM4 links |
| SPC-6 | Spectrum-6 ASIC family |
| SAI | Switch Abstraction Interface |

---

### 4. Background

**iLT** adapts equalization on the local electrical segment between switch SERDES and module CDR. **APSU** extends iLT so that the two link ends also negotiate **precoding** in-band, without manual intervention.

Until module FW supports APSU, there is no automatic precoding negotiation: switch SERDES and module each come up with their own defaults which may not match, preventing link training. SONiC must therefore configure precoding **on the ASIC/SERDES side** to match what the module expects.

---

### 5. Requirements

| # | Requirement |
| -- | ----------- |
| R1 | Precoding shall be configured on the ASIC/SERDES side. |
| R2 | The standard SONiC/SAI flow (`media_settings.json` → APP_DB → SAI) shall be used. |
| R3 | The flow shall be a no-op on platforms / modules where `media_settings.json` does not declare precoding fields (back-compat). |

**Assumption.** `SAI_PORT_SERDES_ATTR_TX_PRECODING` and `SAI_PORT_SERDES_ATTR_RX_PRECODING` are already supported by NV SAI.

---

### 6. Architecture Design

End-to-end flow — same path used today by every other SI parameter (`pre1`, `main`, `idriver`, …):

```mermaid
flowchart TD
JSON[["media_settings.json<br/>+ tx_precoding<br/>+ rx_precoding"]]
XCVRD["xcvrd<br/>(field-agnostic parser)"]
DB[("APP_DB:PORT_TABLE")]
ORCH["orchagent<br/>(PortsOrch)"]
SAI["SAI_PORT_SERDES_ATTR_<br/>TX/RX_PRECODING"]

JSON -->|"1. read"| XCVRD
XCVRD -->|"2. HSET fields"| DB
DB -->|"3. notify on change"| ORCH
ORCH -->|"4. create port_serdes"| SAI

style JSON fill:#e8f5e9,stroke:#2e7d32,color:#000
style DB fill:#e3f2fd,stroke:#1565c0,color:#000
style SAI fill:#fff8e1,stroke:#f9a825,color:#000
```

Steps:

1. **xcvrd reads `media_settings.json`** — on module insert (or boot), it locates the entry that matches the inserted module's `<EEPROM_VENDOR_NAME>-<EEPROM_VENDOR_PN>` and active `<SPEED_KEY>`.
2. **xcvrd writes the matched SI fields to `APP_DB:PORT_TABLE|<lport>`** via `HSET`, including the new `tx_precoding` / `rx_precoding` keys when present.
3. **orchagent is notified of the `APP_DB:PORT_TABLE` change** and runs `PortsOrch::parsePortConfig`, which populates `PortSerdes_t` from the FV list — including the two new per-lane vectors.
4. **orchagent creates the port-serdes SAI object** with the resulting `PortSerdesAttrMap_t`. When `tx_precoding` / `rx_precoding` are set, the map includes `SAI_PORT_SERDES_ATTR_{TX,RX}_PRECODING` and SAI programs the ASIC SerDes accordingly.

Key property: only `media_settings.json` content and orchagent's per-field mapping table change. xcvrd and the Redis schema are reused as-is.

---

### 7. High-Level Design

#### 7.1 `media_settings.json` schema additions

Two new keys are added under each `speed:<lane_speed_key>` block, using the same per-lane shape as the existing parameters (`pre1`, `main`, etc.):

- `tx_precoding` — per-lane Tx precoding (`0x0` = DISABLE, `0x1` = ENABLE).
- `rx_precoding` — per-lane Rx precoding

Example — one global entry that matches a specific vendor + PN pattern for ports 1–64 at speed `200GAUI-1`, programming `tx_precoding` and `rx_precoding` to ENABLE on all 8 lanes alongside the existing SI parameters (`pre1`, `main`, …):

```json
{
"GLOBAL_MEDIA_SETTINGS": {
"1-64": {
"VENDOR-MODEL-XX[AB]": {
"speed:200GAUI-1": {
"pre1": { "lane0": "0x00000000",
"...": "..."
},
"main": { "lane0": "0x0000003f",
"...": "..."
},
"tx_precoding": {
"lane0": "0x00000001",
"...": "...",
"lane7": "0x00000001"
},
"rx_precoding": {
"lane0": "0x00000001",
"...": "...",
"lane7": "0x00000001"
}
}
}
}
}
}
```

Key shape:

| Element | Meaning |
| ------------------------ | ------- |
| `1-64` | Front-panel port range the entry applies to. |
| `VENDOR-MODEL-XX[AB]` | Regex matched against `<EEPROM_VENDOR_NAME_UPPER>-<EEPROM_VENDOR_PN>` of the inserted module. |
| `speed:200GAUI-1` | Lane-speed bucket — `speed:` + first whitespace-token of CMIS `host_electrical_interface_id`. |
| `lane0` … `lane<N-1>` | One per-lane value, (for precoding - hex; `0x1` = ENABLE, `0x0` = DISABLE). |

The schema is fully back-compatible — platforms that do not need precoding simply omit the fields. Concrete per-(vendor, PN, speed) values for additional modules are platform-/vendor-specific and live in the platform's `media_settings.json`; they are not enumerated in this HLD.

##### Flow — adding a new module

When a new module family is qualified for an SPC-6 platform:

1. SI/PHY team determines the per-lane `tx_precoding` and `rx_precoding` (if needed) values for that module at each relevant lane-speed bucket.
2. Platform owner adds a new `<VENDOR_PN_REGEX>` entry under the relevant `<PORT_RANGE>` of the platform's `media_settings.json`, with the per-lane values from step 1 under each `speed:<key>` block (same shape as the example above).

#### 7.2 xcvrd

**No code change.** `media_settings_parser.to_db_value()` is field-agnostic — it emits a FieldValuePair for every per-lane key in the matched JSON section. `tx_precoding` / `rx_precoding` ride the same path as `pre1`, `main`, etc.

#### 7.3 orchagent

`PortsOrch` already owns the SAI port-serdes object for every port. It keeps a per-port in-memory cache with one **slot per SI field** (`pre1`, `main`, `idriver`, …); each slot stores the per-lane values and an `is_set` marker. The SAI attributes are `CREATE_ONLY`, so any change to the cache is applied by `remove_port_serdes` + `create_port_serdes`, with the cumulative set of slots currently marked as set.

Adding precoding means giving that cache two new slots — one for `tx_precoding`, one for `rx_precoding` — and wiring them into the same machinery. The flow below is the existing PortsOrch pipeline; **this HLD plugs in at steps 2 and 3** only.

1. **Receive change.** PortsOrch reads the FV pairs that xcvrd just `HSET`-ed into `APP_DB:PORT_TABLE` for the port.
2. **Parse into cache.** PortsOrch matches each field name against its schema; for every known SI field it stores the per-lane values into the matching cache slot and marks the slot as set.
*This HLD adds two new field-name matches — `tx_precoding` and `rx_precoding` — each writing into its own new cache slot.*
3. **Build attribute list.** PortsOrch walks the cache and assembles the SAI attribute list, **including only slots that are marked as set**.
*This HLD adds two new "if marked-set → SAI attribute" entries:* `tx_precoding` → `SAI_PORT_SERDES_ATTR_TX_PRECODING`, `rx_precoding` → `SAI_PORT_SERDES_ATTR_RX_PRECODING`.
4. **Re-create SAI object.** PortsOrch removes the existing port-serdes SAI object and creates a new one with the attribute list from step 3.
5. **Program ASIC.** SAI / SDK translate the attributes into per-lane SerDes register writes.

No new control flow, no new DB consumer, no new object lifecycle.

| APP_DB field | `PortSerdes_t` member | SAI attribute |
| -------------- | --------------------- | ----------------------------------- |
| `tx_precoding` | `serdes.tx_precoding` | `SAI_PORT_SERDES_ATTR_TX_PRECODING` |
| `rx_precoding` | `serdes.rx_precoding` | `SAI_PORT_SERDES_ATTR_RX_PRECODING` |

Files touched (each row maps to the step it implements):

| File | Step | Change |
| ----------------------------------- | :--: | ------ |
| `orchagent/port/portschema.h` | 2 | Two new field-name string constants (`PORT_TX_PRECODING`, `PORT_RX_PRECODING`) — the strings the parser matches against when walking the FV list. |
| `orchagent/port/portcnt.h` | 2 | Two new per-lane slots under `PortSerdes_t` (`tx_precoding`, `rx_precoding`) — the in-memory cache entries that hold parsed values + `is_set`. |
| `orchagent/port/porthlpr.cpp` | 2 | Two new `else if` branches in the parser dispatch that route the new field names into the slots above, plus the corresponding `parsePortSerdes` template instantiations. |
| `orchagent/portsorch.cpp` | 3 | Two new `if (serdes.{tx,rx}_precoding.is_set)` blocks in the SerDes attribute-map builder — each emits the matching SAI attribute (`SAI_PORT_SERDES_ATTR_{TX,RX}_PRECODING`) only when its slot is marked set. |

---

### 8. Configuration and Management


---

### 9. Testing

| # | Test | Validates |
| - | ------------------------------------------------- | --------- |
| UT1 | `portsorch_ut.cpp::PortAdvancedConfig` (extended) | `PortHelper::parsePortSerdes` accepts `tx_precoding` / `rx_precoding`; the resulting SAI attribute map contains `SAI_PORT_SERDES_ATTR_TX_PRECODING` / `RX_PRECODING` with the per-lane values from `APP_DB`. |

System-level link bring-up testing on real SPC-6 hardware is covered by the SI / system test plan and is out of scope for this HLD.

---

### 10. Open Items / Future Work