Skip to content

Commit 19f3224

Browse files
Per Lane PRBS statuses and statistics (#2204)
Signed-off-by: Spandan Dasgupta <[email protected]>
1 parent 2c74f46 commit 19f3224

File tree

5 files changed

+546
-0
lines changed

5 files changed

+546
-0
lines changed
Lines changed: 341 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,341 @@
1+
# [SAI] PRBS Per Lane Enhancements
2+
3+
-------------------------------------------------------------------------------
4+
5+
Title | PRBS Per Lane Enhancements
6+
-------------|-----------------------------------------------------------------
7+
Authors | Spandan Dasgupta, Chris Nitin Adonis Petrus, Rajkumar P R, Ravindranath C K (Marvell)
8+
Status | In review
9+
Type | Standards track
10+
Created | 2025-09-10
11+
SAI-Version | 1.17
12+
13+
-------------------------------------------------------------------------------
14+
15+
## 1.0 Introduction
16+
17+
PRBS (Pseudo-Random Bit Sequence) is used to test the integrity of high-speed serial links by generating and checking random data patterns. It helps validate serdes performance and physical connectivity.
18+
19+
SAI currently provides the following port attributes to fetch PRBS related status.
20+
21+
```c
22+
/**
23+
* @brief Attribute data for #SAI_PORT_ATTR_PRBS_LOCK_STATUS
24+
*
25+
* PRBS lock status: 1 for locked, 0 for unlocked
26+
*
27+
* @type bool
28+
* @flags READ_ONLY
29+
*/
30+
SAI_PORT_ATTR_PRBS_LOCK_STATUS,
31+
32+
/**
33+
* @brief Attribute data for #SAI_PORT_ATTR_PRBS_RX_STATUS
34+
*
35+
* @type sai_port_prbs_rx_status_t
36+
* @flags READ_ONLY
37+
*/
38+
SAI_PORT_ATTR_PRBS_RX_STATUS,
39+
40+
/**
41+
* @brief Attribute data for #SAI_PORT_ATTR_PRBS_RX_STATE
42+
* Used for clear on read status/count register.
43+
* Adapter should return SAI_STATUS_NOT_SUPPORTED if not supported.
44+
*
45+
* @type sai_prbs_rx_state_t
46+
* @flags READ_ONLY
47+
*/
48+
SAI_PORT_ATTR_PRBS_RX_STATE,
49+
```
50+
51+
In addition, SAI also provides **SAI_PORT_STAT_PRBS_ERROR_COUNT** as a port stat to fetch error count for PRBS.
52+
53+
```c
54+
/** PRBS Error Count */
55+
SAI_PORT_STAT_PRBS_ERROR_COUNT,
56+
```
57+
58+
## 2.0 Problem Statement
59+
60+
Link quality and error characteristics can vary significantly between lanes due to manufacturing variations, signal integrity issues, or physical connectivity problems. Existing SAI PRBS (Pseudo-Random Bit Sequence) support provides only port-level statistics, which can mask lane-specific issues and hinder effective diagnostics.
61+
62+
To address this limitation, there is a need for per-lane PRBS status and error reporting. By exposing PRBS lock status, receive state, and error counters for each individual lane, operators and diagnostic tools can more accurately pinpoint the source of link degradation and perform targeted corrective actions.
63+
64+
However, simply reporting raw error counts per lane is insufficient for comprehensive link assessment. Error counts are affected by test duration and link speed, making it difficult to compare results across links or over time. To provide a normalized, meaningful metric, Bit Error Rate (BER) is commonly used.
65+
66+
In practice, BER values are extremely small and are typically represented as floating-point numbers. However, SAI does not support floating-point data types. To enable accurate and portable BER representation, a new datatype is introduced.
67+
68+
69+
## 3.0 Proposed SAI Enhancement
70+
71+
1) New structure for a Lane specific PRBS Rx state and status and list of each:
72+
73+
```c
74+
75+
typedef struct _sai_prbs_per_lane_rx_status_t
76+
{
77+
uint32_t lane;
78+
sai_port_prbs_rx_status_t rx_status;
79+
} sai_prbs_per_lane_rx_status_t;
80+
81+
/**
82+
* @brief Defines PRBS Rx stateus for list of all serdes lanes
83+
*/
84+
typedef struct _sai_prbs_per_lane_rx_status_list_t
85+
{
86+
uint32_t count;
87+
sai_prbs_per_lane_rx_status_t *list;
88+
} sai_prbs_per_lane_rx_status_list_t;
89+
90+
typedef struct _sai_prbs_per_lane_rx_state_t
91+
{
92+
uint32_t lane;
93+
sai_prbs_rx_state_t rx_state;
94+
} sai_prbs_per_lane_rx_state_t;
95+
96+
/**
97+
* @brief Defines PRBS Rx states for list of all serdes lanes
98+
*/
99+
typedef struct _sai_prbs_per_lane_rx_state_list_t
100+
{
101+
uint32_t count;
102+
sai_prbs_per_lane_rx_state_t *list;
103+
} sai_prbs_per_lane_rx_state_list_t;
104+
105+
106+
```
107+
108+
Also, include the new list to **sai_attribute_value_t** union.
109+
110+
```c
111+
...Existing union members
112+
/** @validonly meta->attrvaluetype == SAI_ATTR_VALUE_TYPE_PRBS_PER_LANE_RX_STATUS_LIST */
113+
sai_prbs_per_lane_rx_status_list_t prbs_rx_status_list;
114+
/** @validonly meta->attrvaluetype == SAI_ATTR_VALUE_TYPE_PRBS_PER_LANE_RX_STATE_LIST */
115+
sai_prbs_per_lane_rx_state_list_t prbs_rx_state_list;
116+
} sai_attribute_value_t;
117+
118+
```
119+
120+
2) New port attributes for per lane alternative of existing attributes **SAI_PORT_ATTR_PRBS_LOCK_STATUS**, **SAI_PORT_ATTR_PRBS_RX_STATUS** and **SAI_PORT_ATTR_PRBS_RX_STATE**:
121+
122+
```c
123+
/**
124+
* @brief Per Lane PRBS Lock Status
125+
*
126+
* Per lane list of lock status for PRBS.
127+
* The values are of type sai_port_lane_latch_status_list where the count is the number of lanes in
128+
* a port and the list specifies list of lane id and lock status for each lane
129+
* Lock status will have both lock status and changed status.
130+
*
131+
* @type sai_port_lane_latch_status_list
132+
* @flags READ_ONLY
133+
*/
134+
SAI_PORT_ATTR_PRBS_PER_LANE_LOCK_STATUS_LIST,
135+
136+
/**
137+
* @brief Per Lane PRBS Rx Status
138+
*
139+
* Per lane list of Rx status for PRBS.
140+
* The values are of type sai_prbs_per_lane_rx_status_list_t where the count is the number of lanes in
141+
* a port and the list specifies list of values of type sai_port_prbs_rx_status_t and the lane id
142+
* for each lane.
143+
*
144+
* @type sai_prbs_per_lane_rx_status_list_t
145+
* @flags READ_ONLY
146+
*/
147+
SAI_PORT_ATTR_PRBS_PER_LANE_RX_STATUS_LIST,
148+
149+
/**
150+
* @brief Per Lane PRBS Rx State
151+
*
152+
* Per lane list of Rx state for PRBS.
153+
* The values are of type sai_prbs_per_lane_rx_state_list_t where the count is the number
154+
* of lanes in a port and the list specifies list of values of type sai_prbs_rx_state_t
155+
* for each lane and its lane id.
156+
* Used for clear on read status/count register.
157+
* Adapter should return SAI_STATUS_NOT_SUPPORTED if not supported.
158+
*
159+
* @type sai_prbs_per_lane_rx_state_list_t
160+
* @flags READ_ONLY
161+
*/
162+
SAI_PORT_ATTR_PRBS_PER_LANE_RX_STATE_LIST,
163+
```
164+
165+
3) New port stats for PRBS error count per lane for relative lanes 0 to 15:
166+
167+
For this we are reserving 256 values for future lane expansions
168+
```c
169+
170+
/** Per Lane PRBS Error Count Range Start */
171+
SAI_PORT_STAT_PRBS_ERROR_COUNT_LANE_RANGE_BASE = 0x00004000,
172+
173+
/** Per Lane PRBS Error Count For lane in index 0 */
174+
SAI_PORT_STAT_PRBS_ERROR_COUNT_LANE_0 = SAI_PORT_STAT_PRBS_ERROR_COUNT_LANE_RANGE_BASE,
175+
176+
/** Per Lane PRBS Error Count For lane in index 1 */
177+
SAI_PORT_STAT_PRBS_ERROR_COUNT_LANE_1,
178+
179+
/** Per Lane PRBS Error Count For lane in index 2 */
180+
SAI_PORT_STAT_PRBS_ERROR_COUNT_LANE_2,
181+
182+
/** Per Lane PRBS Error Count For lane in index 3 */
183+
SAI_PORT_STAT_PRBS_ERROR_COUNT_LANE_3,
184+
185+
/** Per Lane PRBS Error Count For lane in index 4 */
186+
SAI_PORT_STAT_PRBS_ERROR_COUNT_LANE_4,
187+
188+
/** Per Lane PRBS Error Count For lane in index 5 */
189+
SAI_PORT_STAT_PRBS_ERROR_COUNT_LANE_5,
190+
191+
/** Per Lane PRBS Error Count For lane in index 6 */
192+
SAI_PORT_STAT_PRBS_ERROR_COUNT_LANE_6,
193+
194+
/** Per Lane PRBS Error Count For lane in index 7 */
195+
SAI_PORT_STAT_PRBS_ERROR_COUNT_LANE_7,
196+
197+
/** Per Lane PRBS Error Count For lane in index 8 */
198+
SAI_PORT_STAT_PRBS_ERROR_COUNT_LANE_8,
199+
200+
/** Per Lane PRBS Error Count For lane in index 9 */
201+
SAI_PORT_STAT_PRBS_ERROR_COUNT_LANE_9,
202+
203+
/** Per Lane PRBS Error Count For lane in index 10 */
204+
SAI_PORT_STAT_PRBS_ERROR_COUNT_LANE_10,
205+
206+
/** Per Lane PRBS Error Count For lane in index 11 */
207+
SAI_PORT_STAT_PRBS_ERROR_COUNT_LANE_11,
208+
209+
/** Per Lane PRBS Error Count For lane in index 12 */
210+
SAI_PORT_STAT_PRBS_ERROR_COUNT_LANE_12,
211+
212+
/** Per Lane PRBS Error Count For lane in index 13 */
213+
SAI_PORT_STAT_PRBS_ERROR_COUNT_LANE_13,
214+
215+
/** Per Lane PRBS Error Count For lane in index 14 */
216+
SAI_PORT_STAT_PRBS_ERROR_COUNT_LANE_14,
217+
218+
/** Per Lane PRBS Error Count For lane in index 15 */
219+
SAI_PORT_STAT_PRBS_ERROR_COUNT_LANE_15,
220+
221+
/** Per Lane PRBS Error Count Range END */
222+
SAI_PORT_STAT_PRBS_ERROR_COUNT_LANE_RANGE_END = 0x000040ff,
223+
```
224+
225+
4) New datatype to represent PRBS Bit Error Rate (BER):
226+
227+
Bit error rate (BER) offers a more precise evaluation of PRBS than error counts, as it normalizes errors against the total number of transmitted bits. This enables consistent and meaningful assessment of link quality across varying data rates and test durations.
228+
229+
BER is typically a floating point number. SAI does not support floating point data types. Hence, introduce a new datatype to represent the exponent and mantissa information.
230+
231+
```c
232+
/*
233+
*Represents BER as: mantissa * 10^(-exponent)
234+
*/
235+
typedef struct _sai_prbs_bit_error_rate_t
236+
{
237+
uint8_t exponent; /* Negative exponent as in 10^-exponent */
238+
uint64_t mantissa; /* Significant digits of the BER, to be multiplied by 10^(-exponent) */
239+
} sai_prbs_bit_error_rate_t;
240+
```
241+
242+
Consider an example BER of 1.83258 x 10^-14. **mantissa** can be 183528 and **exponent** can be 19, i.e. **mantissa x 10^exponent**. The **mantissa** can contain at max 19 digits as 10^21 > MAX_UINT64 > 10^20.
243+
244+
Also, introduce a per lane version and its list for the above datatype.
245+
246+
```c
247+
typedef struct _sai_prbs_per_lane_bit_error_rate_t
248+
{
249+
uint32_t lane;
250+
sai_prbs_bit_error_rate_t ber;
251+
} sai_prbs_per_lane_bit_error_rate_t;
252+
253+
typedef struct _sai_prbs_per_lane_bit_error_rate_list_t
254+
{
255+
uint32_t count;
256+
sai_prbs_per_lane_bit_error_rate_t *list;
257+
} sai_prbs_per_lane_bit_error_rate_list_t;
258+
259+
```
260+
261+
Add both the above types to **sai_attribute_value_t** union.
262+
263+
```c
264+
...Existing union members
265+
/** @validonly meta->attrvaluetype == SAI_ATTR_VALUE_TYPE_PRBS_BIT_ERROR_RATE */
266+
sai_prbs_bit_error_rate_t prbs_ber;
267+
268+
/** @validonly meta->attrvaluetype == SAI_ATTR_VALUE_TYPE_PRBS_PER_LANE_BIT_ERROR_RATE_LIST */
269+
sai_prbs_per_lane_bit_error_rate_list_t prbs_ber_list;
270+
} sai_attribute_value_t;
271+
272+
```
273+
274+
5) New port attributes for PRBS Bit Error Rate (BER):
275+
276+
```c
277+
278+
/**
279+
* @brief Per Lane PRBS Bit Error Rate (BER)
280+
*
281+
* Per lane list of PRBS Bit Error Rate (BER).
282+
* The values are of type sai_prbs_per_lane_bit_error_rate_list_t where the count is the number
283+
* of lanes in a port and the list specifies list of values of type sai_prbs_bit_error_rate_t
284+
* and lane id for each lane.
285+
* BER will be (error count/bits transmitted) = BER.mantissa * (10^-BER.exponent)
286+
*
287+
* @type sai_prbs_per_lane_bit_error_rate_list_t
288+
* @flags READ_ONLY
289+
*/
290+
SAI_PORT_ATTR_PRBS_PER_LANE_BER_LIST,
291+
```
292+
293+
## 4.0 API Example
294+
295+
Let us take an example port **prbs_port_oid** with 8 lanes.
296+
297+
### Get PRBS per lane lock status, lock loss status, rx status, rx state and bit error rate
298+
299+
```c
300+
sai_attr_list[attr_count].id = SAI_PORT_ATTR_PRBS_PER_LANE_LOCK_STATUS_LIST;
301+
sai_attr_list[attr_count].value.portlanelatchstatuslist.count = 8;
302+
sai_attr_list[attr_count].value.portlanelatchstatuslist.list = malloc(sizeof(sai_port_lane_latch_status_t)*sai_attr_list[attr_count++].value.portlanelatchstatuslist.count);
303+
304+
sai_attr_list[attr_count].id = SAI_PORT_ATTR_PRBS_PER_LANE_RX_STATUS_LIST;
305+
sai_attr_list[attr_count].value.prbs_rx_status_list.count = 8;
306+
sai_attr_list[attr_count].value.prbs_rx_status_list.list = malloc(sizeof(sai_prbs_per_lane_rx_status_t)*sai_attr_list[attr_count++].value.prbs_rx_status_list.count);
307+
308+
sai_attr_list[attr_count].id = SAI_PORT_ATTR_PRBS_PER_LANE_RX_STATE_LIST;
309+
sai_attr_list[attr_count].value.prbs_rx_state_list.count = 8;
310+
sai_attr_list[attr_count].value.prbs_rx_state_list.list = malloc(sizeof(sai_prbs_per_lane_rx_state_t)*sai_attr_list[attr_count++].value.prbs_rx_state_list.count);
311+
312+
sai_attr_list[attr_count].id = SAI_PORT_ATTR_PRBS_PER_LANE_BER_LIST;
313+
sai_attr_list[attr_count].value.prbs_ber_list.count = 8;
314+
sai_attr_list[attr_count].value.prbs_ber_list.list = malloc(sizeof(sai_prbs_per_lane_bit_error_rate_t)*sai_attr_list[attr_count++].value.prbs_ber_list.count);
315+
316+
sai_get_port_attribute_fn(
317+
prbs_port_oid,
318+
attr_count,
319+
sai_attr_list);
320+
321+
```
322+
323+
### Get PRBS per lane error count stat
324+
325+
```c
326+
counter_id_list[num_counters++].id = SAI_PORT_STAT_PRBS_ERROR_COUNT_LANE_0;
327+
counter_id_list[num_counters++].id = SAI_PORT_STAT_PRBS_ERROR_COUNT_LANE_1;
328+
counter_id_list[num_counters++].id = SAI_PORT_STAT_PRBS_ERROR_COUNT_LANE_2;
329+
counter_id_list[num_counters++].id = SAI_PORT_STAT_PRBS_ERROR_COUNT_LANE_3;
330+
counter_id_list[num_counters++].id = SAI_PORT_STAT_PRBS_ERROR_COUNT_LANE_4;
331+
counter_id_list[num_counters++].id = SAI_PORT_STAT_PRBS_ERROR_COUNT_LANE_5;
332+
counter_id_list[num_counters++].id = SAI_PORT_STAT_PRBS_ERROR_COUNT_LANE_6;
333+
counter_id_list[num_counters++].id = SAI_PORT_STAT_PRBS_ERROR_COUNT_LANE_7;
334+
335+
sai_get_port_stats_fn(
336+
prbs_port_oid,
337+
num_counters,
338+
counter_id_list,
339+
&counters);
340+
```
341+

0 commit comments

Comments
 (0)