1414struct dsmas_entry {
1515 struct range dpa_range ;
1616 u8 handle ;
17- struct access_coordinate coord ;
17+ struct access_coordinate coord [ ACCESS_COORDINATE_MAX ] ;
1818
1919 int entries ;
2020 int qos_class ;
2121};
2222
23+ static u32 cdat_normalize (u16 entry , u64 base , u8 type )
24+ {
25+ u32 value ;
26+
27+ /*
28+ * Check for invalid and overflow values
29+ */
30+ if (entry == 0xffff || !entry )
31+ return 0 ;
32+ else if (base > (UINT_MAX / (entry )))
33+ return 0 ;
34+
35+ /*
36+ * CDAT fields follow the format of HMAT fields. See table 5 Device
37+ * Scoped Latency and Bandwidth Information Structure in Coherent Device
38+ * Attribute Table (CDAT) Specification v1.01.
39+ */
40+ value = entry * base ;
41+ switch (type ) {
42+ case ACPI_HMAT_ACCESS_LATENCY :
43+ case ACPI_HMAT_READ_LATENCY :
44+ case ACPI_HMAT_WRITE_LATENCY :
45+ value = DIV_ROUND_UP (value , 1000 );
46+ break ;
47+ default :
48+ break ;
49+ }
50+ return value ;
51+ }
52+
2353static int cdat_dsmas_handler (union acpi_subtable_headers * header , void * arg ,
2454 const unsigned long end )
2555{
@@ -58,8 +88,8 @@ static int cdat_dsmas_handler(union acpi_subtable_headers *header, void *arg,
5888 return 0 ;
5989}
6090
61- static void cxl_access_coordinate_set (struct access_coordinate * coord ,
62- int access , unsigned int val )
91+ static void __cxl_access_coordinate_set (struct access_coordinate * coord ,
92+ int access , unsigned int val )
6393{
6494 switch (access ) {
6595 case ACPI_HMAT_ACCESS_LATENCY :
@@ -85,6 +115,13 @@ static void cxl_access_coordinate_set(struct access_coordinate *coord,
85115 }
86116}
87117
118+ static void cxl_access_coordinate_set (struct access_coordinate * coord ,
119+ int access , unsigned int val )
120+ {
121+ for (int i = 0 ; i < ACCESS_COORDINATE_MAX ; i ++ )
122+ __cxl_access_coordinate_set (& coord [i ], access , val );
123+ }
124+
88125static int cdat_dslbis_handler (union acpi_subtable_headers * header , void * arg ,
89126 const unsigned long end )
90127{
@@ -97,7 +134,6 @@ static int cdat_dslbis_handler(union acpi_subtable_headers *header, void *arg,
97134 __le16 le_val ;
98135 u64 val ;
99136 u16 len ;
100- int rc ;
101137
102138 len = le16_to_cpu ((__force __le16 )hdr -> length );
103139 if (len != size || (unsigned long )hdr + len > end ) {
@@ -124,12 +160,10 @@ static int cdat_dslbis_handler(union acpi_subtable_headers *header, void *arg,
124160
125161 le_base = (__force __le64 )dslbis -> entry_base_unit ;
126162 le_val = (__force __le16 )dslbis -> entry [0 ];
127- rc = check_mul_overflow (le64_to_cpu (le_base ),
128- le16_to_cpu (le_val ), & val );
129- if (rc )
130- pr_warn ("DSLBIS value overflowed.\n" );
163+ val = cdat_normalize (le16_to_cpu (le_val ), le64_to_cpu (le_base ),
164+ dslbis -> data_type );
131165
132- cxl_access_coordinate_set (& dent -> coord , dslbis -> data_type , val );
166+ cxl_access_coordinate_set (dent -> coord , dslbis -> data_type , val );
133167
134168 return 0 ;
135169}
@@ -163,25 +197,18 @@ static int cxl_cdat_endpoint_process(struct cxl_port *port,
163197static int cxl_port_perf_data_calculate (struct cxl_port * port ,
164198 struct xarray * dsmas_xa )
165199{
166- struct access_coordinate ep_c ;
167- struct access_coordinate coord [ACCESS_COORDINATE_MAX ];
200+ struct access_coordinate ep_c [ACCESS_COORDINATE_MAX ];
168201 struct dsmas_entry * dent ;
169202 int valid_entries = 0 ;
170203 unsigned long index ;
171204 int rc ;
172205
173- rc = cxl_endpoint_get_perf_coordinates (port , & ep_c );
206+ rc = cxl_endpoint_get_perf_coordinates (port , ep_c );
174207 if (rc ) {
175208 dev_dbg (& port -> dev , "Failed to retrieve ep perf coordinates.\n" );
176209 return rc ;
177210 }
178211
179- rc = cxl_hb_get_perf_coordinates (port , coord );
180- if (rc ) {
181- dev_dbg (& port -> dev , "Failed to retrieve hb perf coordinates.\n" );
182- return rc ;
183- }
184-
185212 struct cxl_root * cxl_root __free (put_cxl_root ) = find_cxl_root (port );
186213
187214 if (!cxl_root )
@@ -193,18 +220,10 @@ static int cxl_port_perf_data_calculate(struct cxl_port *port,
193220 xa_for_each (dsmas_xa , index , dent ) {
194221 int qos_class ;
195222
196- cxl_coordinates_combine (& dent -> coord , & dent -> coord , & ep_c );
197- /*
198- * Keeping the host bridge coordinates separate from the dsmas
199- * coordinates in order to allow calculation of access class
200- * 0 and 1 for region later.
201- */
202- cxl_coordinates_combine (& coord [ACCESS_COORDINATE_CPU ],
203- & coord [ACCESS_COORDINATE_CPU ],
204- & dent -> coord );
223+ cxl_coordinates_combine (dent -> coord , dent -> coord , ep_c );
205224 dent -> entries = 1 ;
206225 rc = cxl_root -> ops -> qos_class (cxl_root ,
207- & coord [ACCESS_COORDINATE_CPU ],
226+ & dent -> coord [ACCESS_COORDINATE_CPU ],
208227 1 , & qos_class );
209228 if (rc != 1 )
210229 continue ;
@@ -222,14 +241,17 @@ static int cxl_port_perf_data_calculate(struct cxl_port *port,
222241static void update_perf_entry (struct device * dev , struct dsmas_entry * dent ,
223242 struct cxl_dpa_perf * dpa_perf )
224243{
244+ for (int i = 0 ; i < ACCESS_COORDINATE_MAX ; i ++ )
245+ dpa_perf -> coord [i ] = dent -> coord [i ];
225246 dpa_perf -> dpa_range = dent -> dpa_range ;
226- dpa_perf -> coord = dent -> coord ;
227247 dpa_perf -> qos_class = dent -> qos_class ;
228248 dev_dbg (dev ,
229249 "DSMAS: dpa: %#llx qos: %d read_bw: %d write_bw %d read_lat: %d write_lat: %d\n" ,
230250 dent -> dpa_range .start , dpa_perf -> qos_class ,
231- dent -> coord .read_bandwidth , dent -> coord .write_bandwidth ,
232- dent -> coord .read_latency , dent -> coord .write_latency );
251+ dent -> coord [ACCESS_COORDINATE_CPU ].read_bandwidth ,
252+ dent -> coord [ACCESS_COORDINATE_CPU ].write_bandwidth ,
253+ dent -> coord [ACCESS_COORDINATE_CPU ].read_latency ,
254+ dent -> coord [ACCESS_COORDINATE_CPU ].write_latency );
233255}
234256
235257static void cxl_memdev_set_qos_class (struct cxl_dev_state * cxlds ,
@@ -461,17 +483,16 @@ static int cdat_sslbis_handler(union acpi_subtable_headers *header, void *arg,
461483
462484 le_base = (__force __le64 )tbl -> sslbis_header .entry_base_unit ;
463485 le_val = (__force __le16 )tbl -> entries [i ].latency_or_bandwidth ;
464-
465- if (check_mul_overflow (le64_to_cpu (le_base ),
466- le16_to_cpu (le_val ), & val ))
467- dev_warn (dev , "SSLBIS value overflowed!\n" );
486+ val = cdat_normalize (le16_to_cpu (le_val ), le64_to_cpu (le_base ),
487+ sslbis -> data_type );
468488
469489 xa_for_each (& port -> dports , index , dport ) {
470490 if (dsp_id == ACPI_CDAT_SSLBIS_ANY_PORT ||
471- dsp_id == dport -> port_id )
472- cxl_access_coordinate_set (& dport -> sw_coord ,
491+ dsp_id == dport -> port_id ) {
492+ cxl_access_coordinate_set (dport -> coord ,
473493 sslbis -> data_type ,
474494 val );
495+ }
475496 }
476497 }
477498
@@ -493,6 +514,21 @@ void cxl_switch_parse_cdat(struct cxl_port *port)
493514}
494515EXPORT_SYMBOL_NS_GPL (cxl_switch_parse_cdat , CXL );
495516
517+ static void __cxl_coordinates_combine (struct access_coordinate * out ,
518+ struct access_coordinate * c1 ,
519+ struct access_coordinate * c2 )
520+ {
521+ if (c1 -> write_bandwidth && c2 -> write_bandwidth )
522+ out -> write_bandwidth = min (c1 -> write_bandwidth ,
523+ c2 -> write_bandwidth );
524+ out -> write_latency = c1 -> write_latency + c2 -> write_latency ;
525+
526+ if (c1 -> read_bandwidth && c2 -> read_bandwidth )
527+ out -> read_bandwidth = min (c1 -> read_bandwidth ,
528+ c2 -> read_bandwidth );
529+ out -> read_latency = c1 -> read_latency + c2 -> read_latency ;
530+ }
531+
496532/**
497533 * cxl_coordinates_combine - Combine the two input coordinates
498534 *
@@ -504,15 +540,8 @@ void cxl_coordinates_combine(struct access_coordinate *out,
504540 struct access_coordinate * c1 ,
505541 struct access_coordinate * c2 )
506542{
507- if (c1 -> write_bandwidth && c2 -> write_bandwidth )
508- out -> write_bandwidth = min (c1 -> write_bandwidth ,
509- c2 -> write_bandwidth );
510- out -> write_latency = c1 -> write_latency + c2 -> write_latency ;
511-
512- if (c1 -> read_bandwidth && c2 -> read_bandwidth )
513- out -> read_bandwidth = min (c1 -> read_bandwidth ,
514- c2 -> read_bandwidth );
515- out -> read_latency = c1 -> read_latency + c2 -> read_latency ;
543+ for (int i = 0 ; i < ACCESS_COORDINATE_MAX ; i ++ )
544+ __cxl_coordinates_combine (& out [i ], & c1 [i ], & c2 [i ]);
516545}
517546
518547MODULE_IMPORT_NS (CXL );
@@ -521,17 +550,13 @@ void cxl_region_perf_data_calculate(struct cxl_region *cxlr,
521550 struct cxl_endpoint_decoder * cxled )
522551{
523552 struct cxl_memdev * cxlmd = cxled_to_memdev (cxled );
524- struct cxl_port * port = cxlmd -> endpoint ;
525553 struct cxl_dev_state * cxlds = cxlmd -> cxlds ;
526554 struct cxl_memdev_state * mds = to_cxl_memdev_state (cxlds );
527- struct access_coordinate hb_coord [ACCESS_COORDINATE_MAX ];
528- struct access_coordinate coord ;
529555 struct range dpa = {
530556 .start = cxled -> dpa_res -> start ,
531557 .end = cxled -> dpa_res -> end ,
532558 };
533559 struct cxl_dpa_perf * perf ;
534- int rc ;
535560
536561 switch (cxlr -> mode ) {
537562 case CXL_DECODER_RAM :
@@ -549,35 +574,16 @@ void cxl_region_perf_data_calculate(struct cxl_region *cxlr,
549574 if (!range_contains (& perf -> dpa_range , & dpa ))
550575 return ;
551576
552- rc = cxl_hb_get_perf_coordinates (port , hb_coord );
553- if (rc ) {
554- dev_dbg (& port -> dev , "Failed to retrieve hb perf coordinates.\n" );
555- return ;
556- }
557-
558577 for (int i = 0 ; i < ACCESS_COORDINATE_MAX ; i ++ ) {
559- /* Pickup the host bridge coords */
560- cxl_coordinates_combine (& coord , & hb_coord [i ], & perf -> coord );
561-
562578 /* Get total bandwidth and the worst latency for the cxl region */
563579 cxlr -> coord [i ].read_latency = max_t (unsigned int ,
564580 cxlr -> coord [i ].read_latency ,
565- coord .read_latency );
581+ perf -> coord [ i ] .read_latency );
566582 cxlr -> coord [i ].write_latency = max_t (unsigned int ,
567583 cxlr -> coord [i ].write_latency ,
568- coord .write_latency );
569- cxlr -> coord [i ].read_bandwidth += coord .read_bandwidth ;
570- cxlr -> coord [i ].write_bandwidth += coord .write_bandwidth ;
571-
572- /*
573- * Convert latency to nanosec from picosec to be consistent
574- * with the resulting latency coordinates computed by the
575- * HMAT_REPORTING code.
576- */
577- cxlr -> coord [i ].read_latency =
578- DIV_ROUND_UP (cxlr -> coord [i ].read_latency , 1000 );
579- cxlr -> coord [i ].write_latency =
580- DIV_ROUND_UP (cxlr -> coord [i ].write_latency , 1000 );
584+ perf -> coord [i ].write_latency );
585+ cxlr -> coord [i ].read_bandwidth += perf -> coord [i ].read_bandwidth ;
586+ cxlr -> coord [i ].write_bandwidth += perf -> coord [i ].write_bandwidth ;
581587 }
582588}
583589
0 commit comments