14
14
struct dsmas_entry {
15
15
struct range dpa_range ;
16
16
u8 handle ;
17
- struct access_coordinate coord ;
17
+ struct access_coordinate coord [ ACCESS_COORDINATE_MAX ] ;
18
18
19
19
int entries ;
20
20
int qos_class ;
21
21
};
22
22
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
+
23
53
static int cdat_dsmas_handler (union acpi_subtable_headers * header , void * arg ,
24
54
const unsigned long end )
25
55
{
@@ -58,8 +88,8 @@ static int cdat_dsmas_handler(union acpi_subtable_headers *header, void *arg,
58
88
return 0 ;
59
89
}
60
90
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 )
63
93
{
64
94
switch (access ) {
65
95
case ACPI_HMAT_ACCESS_LATENCY :
@@ -85,6 +115,13 @@ static void cxl_access_coordinate_set(struct access_coordinate *coord,
85
115
}
86
116
}
87
117
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
+
88
125
static int cdat_dslbis_handler (union acpi_subtable_headers * header , void * arg ,
89
126
const unsigned long end )
90
127
{
@@ -97,7 +134,6 @@ static int cdat_dslbis_handler(union acpi_subtable_headers *header, void *arg,
97
134
__le16 le_val ;
98
135
u64 val ;
99
136
u16 len ;
100
- int rc ;
101
137
102
138
len = le16_to_cpu ((__force __le16 )hdr -> length );
103
139
if (len != size || (unsigned long )hdr + len > end ) {
@@ -124,12 +160,10 @@ static int cdat_dslbis_handler(union acpi_subtable_headers *header, void *arg,
124
160
125
161
le_base = (__force __le64 )dslbis -> entry_base_unit ;
126
162
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 );
131
165
132
- cxl_access_coordinate_set (& dent -> coord , dslbis -> data_type , val );
166
+ cxl_access_coordinate_set (dent -> coord , dslbis -> data_type , val );
133
167
134
168
return 0 ;
135
169
}
@@ -163,25 +197,18 @@ static int cxl_cdat_endpoint_process(struct cxl_port *port,
163
197
static int cxl_port_perf_data_calculate (struct cxl_port * port ,
164
198
struct xarray * dsmas_xa )
165
199
{
166
- struct access_coordinate ep_c ;
167
- struct access_coordinate coord [ACCESS_COORDINATE_MAX ];
200
+ struct access_coordinate ep_c [ACCESS_COORDINATE_MAX ];
168
201
struct dsmas_entry * dent ;
169
202
int valid_entries = 0 ;
170
203
unsigned long index ;
171
204
int rc ;
172
205
173
- rc = cxl_endpoint_get_perf_coordinates (port , & ep_c );
206
+ rc = cxl_endpoint_get_perf_coordinates (port , ep_c );
174
207
if (rc ) {
175
208
dev_dbg (& port -> dev , "Failed to retrieve ep perf coordinates.\n" );
176
209
return rc ;
177
210
}
178
211
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
-
185
212
struct cxl_root * cxl_root __free (put_cxl_root ) = find_cxl_root (port );
186
213
187
214
if (!cxl_root )
@@ -193,18 +220,10 @@ static int cxl_port_perf_data_calculate(struct cxl_port *port,
193
220
xa_for_each (dsmas_xa , index , dent ) {
194
221
int qos_class ;
195
222
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 );
205
224
dent -> entries = 1 ;
206
225
rc = cxl_root -> ops -> qos_class (cxl_root ,
207
- & coord [ACCESS_COORDINATE_CPU ],
226
+ & dent -> coord [ACCESS_COORDINATE_CPU ],
208
227
1 , & qos_class );
209
228
if (rc != 1 )
210
229
continue ;
@@ -222,14 +241,17 @@ static int cxl_port_perf_data_calculate(struct cxl_port *port,
222
241
static void update_perf_entry (struct device * dev , struct dsmas_entry * dent ,
223
242
struct cxl_dpa_perf * dpa_perf )
224
243
{
244
+ for (int i = 0 ; i < ACCESS_COORDINATE_MAX ; i ++ )
245
+ dpa_perf -> coord [i ] = dent -> coord [i ];
225
246
dpa_perf -> dpa_range = dent -> dpa_range ;
226
- dpa_perf -> coord = dent -> coord ;
227
247
dpa_perf -> qos_class = dent -> qos_class ;
228
248
dev_dbg (dev ,
229
249
"DSMAS: dpa: %#llx qos: %d read_bw: %d write_bw %d read_lat: %d write_lat: %d\n" ,
230
250
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 );
233
255
}
234
256
235
257
static 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,
461
483
462
484
le_base = (__force __le64 )tbl -> sslbis_header .entry_base_unit ;
463
485
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 );
468
488
469
489
xa_for_each (& port -> dports , index , dport ) {
470
490
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 ,
473
493
sslbis -> data_type ,
474
494
val );
495
+ }
475
496
}
476
497
}
477
498
@@ -493,6 +514,21 @@ void cxl_switch_parse_cdat(struct cxl_port *port)
493
514
}
494
515
EXPORT_SYMBOL_NS_GPL (cxl_switch_parse_cdat , CXL );
495
516
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
+
496
532
/**
497
533
* cxl_coordinates_combine - Combine the two input coordinates
498
534
*
@@ -504,15 +540,8 @@ void cxl_coordinates_combine(struct access_coordinate *out,
504
540
struct access_coordinate * c1 ,
505
541
struct access_coordinate * c2 )
506
542
{
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 ]);
516
545
}
517
546
518
547
MODULE_IMPORT_NS (CXL );
@@ -521,17 +550,13 @@ void cxl_region_perf_data_calculate(struct cxl_region *cxlr,
521
550
struct cxl_endpoint_decoder * cxled )
522
551
{
523
552
struct cxl_memdev * cxlmd = cxled_to_memdev (cxled );
524
- struct cxl_port * port = cxlmd -> endpoint ;
525
553
struct cxl_dev_state * cxlds = cxlmd -> cxlds ;
526
554
struct cxl_memdev_state * mds = to_cxl_memdev_state (cxlds );
527
- struct access_coordinate hb_coord [ACCESS_COORDINATE_MAX ];
528
- struct access_coordinate coord ;
529
555
struct range dpa = {
530
556
.start = cxled -> dpa_res -> start ,
531
557
.end = cxled -> dpa_res -> end ,
532
558
};
533
559
struct cxl_dpa_perf * perf ;
534
- int rc ;
535
560
536
561
switch (cxlr -> mode ) {
537
562
case CXL_DECODER_RAM :
@@ -549,35 +574,16 @@ void cxl_region_perf_data_calculate(struct cxl_region *cxlr,
549
574
if (!range_contains (& perf -> dpa_range , & dpa ))
550
575
return ;
551
576
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
-
558
577
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
-
562
578
/* Get total bandwidth and the worst latency for the cxl region */
563
579
cxlr -> coord [i ].read_latency = max_t (unsigned int ,
564
580
cxlr -> coord [i ].read_latency ,
565
- coord .read_latency );
581
+ perf -> coord [ i ] .read_latency );
566
582
cxlr -> coord [i ].write_latency = max_t (unsigned int ,
567
583
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 ;
581
587
}
582
588
}
583
589
0 commit comments