diff --git a/doc/pmon/precoding_via_media_settings_hld.md b/doc/pmon/precoding_via_media_settings_hld.md new file mode 100644 index 00000000000..5f53f8f6faf --- /dev/null +++ b/doc/pmon/precoding_via_media_settings_hld.md @@ -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
+ tx_precoding
+ rx_precoding"]] + XCVRD["xcvrd
(field-agnostic parser)"] + DB[("APP_DB:PORT_TABLE")] + ORCH["orchagent
(PortsOrch)"] + SAI["SAI_PORT_SERDES_ATTR_
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 `-` and active ``. +2. **xcvrd writes the matched SI fields to `APP_DB:PORT_TABLE|`** 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:` 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 `-` of the inserted module. | +| `speed:200GAUI-1` | Lane-speed bucket — `speed:` + first whitespace-token of CMIS `host_electrical_interface_id`. | +| `lane0` … `lane` | 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 `` entry under the relevant `` of the platform's `media_settings.json`, with the per-lane values from step 1 under each `speed:` 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 +