8
8
#include <linux/pci.h>
9
9
#include "cxl.h"
10
10
11
- static struct acpi_table_header * acpi_cedt ;
12
-
13
11
/* Encode defined in CXL 2.0 8.2.5.12.7 HDM Decoder Control Register */
14
12
#define CFMWS_INTERLEAVE_WAYS (x ) (1 << (x)->interleave_ways)
15
13
#define CFMWS_INTERLEAVE_GRANULARITY (x ) ((x)->granularity + 8)
@@ -74,134 +72,63 @@ static int cxl_acpi_cfmws_verify(struct device *dev,
74
72
return 0 ;
75
73
}
76
74
77
- static void cxl_add_cfmws_decoders (struct device * dev ,
78
- struct cxl_port * root_port )
75
+ struct cxl_cfmws_context {
76
+ struct device * dev ;
77
+ struct cxl_port * root_port ;
78
+ };
79
+
80
+ static int cxl_parse_cfmws (union acpi_subtable_headers * header , void * arg ,
81
+ const unsigned long end )
79
82
{
80
83
int target_map [CXL_DECODER_MAX_INTERLEAVE ];
84
+ struct cxl_cfmws_context * ctx = arg ;
85
+ struct cxl_port * root_port = ctx -> root_port ;
86
+ struct device * dev = ctx -> dev ;
81
87
struct acpi_cedt_cfmws * cfmws ;
82
88
struct cxl_decoder * cxld ;
83
- acpi_size len , cur = 0 ;
84
- void * cedt_subtable ;
85
- int rc ;
86
-
87
- len = acpi_cedt -> length - sizeof (* acpi_cedt );
88
- cedt_subtable = acpi_cedt + 1 ;
89
-
90
- while (cur < len ) {
91
- struct acpi_cedt_header * c = cedt_subtable + cur ;
92
- int i ;
93
-
94
- if (c -> type != ACPI_CEDT_TYPE_CFMWS ) {
95
- cur += c -> length ;
96
- continue ;
97
- }
89
+ int rc , i ;
98
90
99
- cfmws = cedt_subtable + cur ;
91
+ cfmws = ( struct acpi_cedt_cfmws * ) header ;
100
92
101
- if (cfmws -> header .length < sizeof (* cfmws )) {
102
- dev_warn_once (dev ,
103
- "CFMWS entry skipped:invalid length:%u\n" ,
104
- cfmws -> header .length );
105
- cur += c -> length ;
106
- continue ;
107
- }
108
-
109
- rc = cxl_acpi_cfmws_verify (dev , cfmws );
110
- if (rc ) {
111
- dev_err (dev , "CFMWS range %#llx-%#llx not registered\n" ,
112
- cfmws -> base_hpa , cfmws -> base_hpa +
113
- cfmws -> window_size - 1 );
114
- cur += c -> length ;
115
- continue ;
116
- }
117
-
118
- for (i = 0 ; i < CFMWS_INTERLEAVE_WAYS (cfmws ); i ++ )
119
- target_map [i ] = cfmws -> interleave_targets [i ];
120
-
121
- cxld = cxl_decoder_alloc (root_port ,
122
- CFMWS_INTERLEAVE_WAYS (cfmws ));
123
- if (IS_ERR (cxld ))
124
- goto next ;
125
-
126
- cxld -> flags = cfmws_to_decoder_flags (cfmws -> restrictions );
127
- cxld -> target_type = CXL_DECODER_EXPANDER ;
128
- cxld -> range = (struct range ) {
129
- .start = cfmws -> base_hpa ,
130
- .end = cfmws -> base_hpa + cfmws -> window_size - 1 ,
131
- };
132
- cxld -> interleave_ways = CFMWS_INTERLEAVE_WAYS (cfmws );
133
- cxld -> interleave_granularity =
134
- CFMWS_INTERLEAVE_GRANULARITY (cfmws );
135
-
136
- rc = cxl_decoder_add (cxld , target_map );
137
- if (rc )
138
- put_device (& cxld -> dev );
139
- else
140
- rc = cxl_decoder_autoremove (dev , cxld );
141
- if (rc ) {
142
- dev_err (dev , "Failed to add decoder for %#llx-%#llx\n" ,
143
- cfmws -> base_hpa , cfmws -> base_hpa +
144
- cfmws -> window_size - 1 );
145
- goto next ;
146
- }
147
- dev_dbg (dev , "add: %s range %#llx-%#llx\n" ,
148
- dev_name (& cxld -> dev ), cfmws -> base_hpa ,
93
+ rc = cxl_acpi_cfmws_verify (dev , cfmws );
94
+ if (rc ) {
95
+ dev_err (dev , "CFMWS range %#llx-%#llx not registered\n" ,
96
+ cfmws -> base_hpa ,
149
97
cfmws -> base_hpa + cfmws -> window_size - 1 );
150
- next :
151
- cur += c -> length ;
98
+ return 0 ;
152
99
}
153
- }
154
-
155
- static struct acpi_cedt_chbs * cxl_acpi_match_chbs (struct device * dev , u32 uid )
156
- {
157
- struct acpi_cedt_chbs * chbs , * chbs_match = NULL ;
158
- acpi_size len , cur = 0 ;
159
- void * cedt_subtable ;
160
100
161
- len = acpi_cedt -> length - sizeof ( * acpi_cedt );
162
- cedt_subtable = acpi_cedt + 1 ;
101
+ for ( i = 0 ; i < CFMWS_INTERLEAVE_WAYS ( cfmws ); i ++ )
102
+ target_map [ i ] = cfmws -> interleave_targets [ i ] ;
163
103
164
- while (cur < len ) {
165
- struct acpi_cedt_header * c = cedt_subtable + cur ;
166
-
167
- if (c -> type != ACPI_CEDT_TYPE_CHBS ) {
168
- cur += c -> length ;
169
- continue ;
170
- }
171
-
172
- chbs = cedt_subtable + cur ;
173
-
174
- if (chbs -> header .length < sizeof (* chbs )) {
175
- dev_warn_once (dev ,
176
- "CHBS entry skipped: invalid length:%u\n" ,
177
- chbs -> header .length );
178
- cur += c -> length ;
179
- continue ;
180
- }
181
-
182
- if (chbs -> uid != uid ) {
183
- cur += c -> length ;
184
- continue ;
185
- }
104
+ cxld = cxl_decoder_alloc (root_port , CFMWS_INTERLEAVE_WAYS (cfmws ));
105
+ if (IS_ERR (cxld ))
106
+ return 0 ;
186
107
187
- if (chbs_match ) {
188
- dev_warn_once (dev ,
189
- "CHBS entry skipped: duplicate UID:%u\n" ,
190
- uid );
191
- cur += c -> length ;
192
- continue ;
193
- }
108
+ cxld -> flags = cfmws_to_decoder_flags (cfmws -> restrictions );
109
+ cxld -> target_type = CXL_DECODER_EXPANDER ;
110
+ cxld -> range = (struct range ){
111
+ .start = cfmws -> base_hpa ,
112
+ .end = cfmws -> base_hpa + cfmws -> window_size - 1 ,
113
+ };
114
+ cxld -> interleave_ways = CFMWS_INTERLEAVE_WAYS (cfmws );
115
+ cxld -> interleave_granularity = CFMWS_INTERLEAVE_GRANULARITY (cfmws );
194
116
195
- chbs_match = chbs ;
196
- cur += c -> length ;
117
+ rc = cxl_decoder_add (cxld , target_map );
118
+ if (rc )
119
+ put_device (& cxld -> dev );
120
+ else
121
+ rc = cxl_decoder_autoremove (dev , cxld );
122
+ if (rc ) {
123
+ dev_err (dev , "Failed to add decoder for %#llx-%#llx\n" ,
124
+ cfmws -> base_hpa ,
125
+ cfmws -> base_hpa + cfmws -> window_size - 1 );
126
+ return 0 ;
197
127
}
128
+ dev_dbg (dev , "add: %s range %#llx-%#llx\n" , dev_name (& cxld -> dev ),
129
+ cfmws -> base_hpa , cfmws -> base_hpa + cfmws -> window_size - 1 );
198
130
199
- return chbs_match ? chbs_match : ERR_PTR (- ENODEV );
200
- }
201
-
202
- static resource_size_t get_chbcr (struct acpi_cedt_chbs * chbs )
203
- {
204
- return IS_ERR (chbs ) ? CXL_RESOURCE_NONE : chbs -> base ;
131
+ return 0 ;
205
132
}
206
133
207
134
__mock int match_add_root_ports (struct pci_dev * pdev , void * data )
@@ -355,12 +282,35 @@ static int add_host_bridge_uport(struct device *match, void *arg)
355
282
return rc ;
356
283
}
357
284
285
+ struct cxl_chbs_context {
286
+ unsigned long long uid ;
287
+ resource_size_t chbcr ;
288
+ };
289
+
290
+ static int cxl_get_chbcr (union acpi_subtable_headers * header , void * arg ,
291
+ const unsigned long end )
292
+ {
293
+ struct cxl_chbs_context * ctx = arg ;
294
+ struct acpi_cedt_chbs * chbs ;
295
+
296
+ if (ctx -> chbcr )
297
+ return 0 ;
298
+
299
+ chbs = (struct acpi_cedt_chbs * ) header ;
300
+
301
+ if (ctx -> uid != chbs -> uid )
302
+ return 0 ;
303
+ ctx -> chbcr = chbs -> base ;
304
+
305
+ return 0 ;
306
+ }
307
+
358
308
static int add_host_bridge_dport (struct device * match , void * arg )
359
309
{
360
310
int rc ;
361
311
acpi_status status ;
362
312
unsigned long long uid ;
363
- struct acpi_cedt_chbs * chbs ;
313
+ struct cxl_chbs_context ctx ;
364
314
struct cxl_port * root_port = arg ;
365
315
struct device * host = root_port -> dev .parent ;
366
316
struct acpi_device * bridge = to_cxl_host_bridge (host , match );
@@ -376,14 +326,18 @@ static int add_host_bridge_dport(struct device *match, void *arg)
376
326
return - ENODEV ;
377
327
}
378
328
379
- chbs = cxl_acpi_match_chbs (host , uid );
380
- if (IS_ERR (chbs )) {
329
+ ctx = (struct cxl_chbs_context ) {
330
+ .uid = uid ,
331
+ };
332
+ acpi_table_parse_cedt (ACPI_CEDT_TYPE_CHBS , cxl_get_chbcr , & ctx );
333
+
334
+ if (ctx .chbcr == 0 ) {
381
335
dev_warn (host , "No CHBS found for Host Bridge: %s\n" ,
382
336
dev_name (match ));
383
337
return 0 ;
384
338
}
385
339
386
- rc = cxl_add_dport (root_port , match , uid , get_chbcr ( chbs ) );
340
+ rc = cxl_add_dport (root_port , match , uid , ctx . chbcr );
387
341
if (rc ) {
388
342
dev_err (host , "failed to add downstream port: %s\n" ,
389
343
dev_name (match ));
@@ -417,65 +371,50 @@ static int add_root_nvdimm_bridge(struct device *match, void *data)
417
371
return 1 ;
418
372
}
419
373
420
- static u32 cedt_instance (struct platform_device * pdev )
421
- {
422
- const bool * native_acpi0017 = acpi_device_get_match_data (& pdev -> dev );
423
-
424
- if (native_acpi0017 && * native_acpi0017 )
425
- return 0 ;
426
-
427
- /* for cxl_test request a non-canonical instance */
428
- return U32_MAX ;
429
- }
430
-
431
374
static int cxl_acpi_probe (struct platform_device * pdev )
432
375
{
433
376
int rc ;
434
- acpi_status status ;
435
377
struct cxl_port * root_port ;
436
378
struct device * host = & pdev -> dev ;
437
379
struct acpi_device * adev = ACPI_COMPANION (host );
380
+ struct cxl_cfmws_context ctx ;
438
381
439
382
root_port = devm_cxl_add_port (host , host , CXL_RESOURCE_NONE , NULL );
440
383
if (IS_ERR (root_port ))
441
384
return PTR_ERR (root_port );
442
385
dev_dbg (host , "add: %s\n" , dev_name (& root_port -> dev ));
443
386
444
- status = acpi_get_table (ACPI_SIG_CEDT , cedt_instance (pdev ), & acpi_cedt );
445
- if (ACPI_FAILURE (status ))
446
- return - ENXIO ;
447
-
448
387
rc = bus_for_each_dev (adev -> dev .bus , NULL , root_port ,
449
388
add_host_bridge_dport );
450
- if (rc )
451
- goto out ;
389
+ if (rc < 0 )
390
+ return rc ;
452
391
453
- cxl_add_cfmws_decoders (host , root_port );
392
+ ctx = (struct cxl_cfmws_context ) {
393
+ .dev = host ,
394
+ .root_port = root_port ,
395
+ };
396
+ acpi_table_parse_cedt (ACPI_CEDT_TYPE_CFMWS , cxl_parse_cfmws , & ctx );
454
397
455
398
/*
456
399
* Root level scanned with host-bridge as dports, now scan host-bridges
457
400
* for their role as CXL uports to their CXL-capable PCIe Root Ports.
458
401
*/
459
402
rc = bus_for_each_dev (adev -> dev .bus , NULL , root_port ,
460
403
add_host_bridge_uport );
461
- if (rc )
462
- goto out ;
404
+ if (rc < 0 )
405
+ return rc ;
463
406
464
407
if (IS_ENABLED (CONFIG_CXL_PMEM ))
465
408
rc = device_for_each_child (& root_port -> dev , root_port ,
466
409
add_root_nvdimm_bridge );
467
-
468
- out :
469
- acpi_put_table (acpi_cedt );
470
410
if (rc < 0 )
471
411
return rc ;
412
+
472
413
return 0 ;
473
414
}
474
415
475
- static bool native_acpi0017 = true;
476
-
477
416
static const struct acpi_device_id cxl_acpi_ids [] = {
478
- { "ACPI0017" , ( unsigned long ) & native_acpi0017 },
417
+ { "ACPI0017" },
479
418
{ },
480
419
};
481
420
MODULE_DEVICE_TABLE (acpi , cxl_acpi_ids );
@@ -491,3 +430,4 @@ static struct platform_driver cxl_acpi_driver = {
491
430
module_platform_driver (cxl_acpi_driver );
492
431
MODULE_LICENSE ("GPL v2" );
493
432
MODULE_IMPORT_NS (CXL );
433
+ MODULE_IMPORT_NS (ACPI );
0 commit comments