@@ -327,66 +327,21 @@ __mock struct acpi_device *to_cxl_host_bridge(struct device *host,
327327 return NULL ;
328328}
329329
330- /*
331- * A host bridge is a dport to a CFMWS decode and it is a uport to the
332- * dport (PCIe Root Ports) in the host bridge.
333- */
334- static int add_host_bridge_uport (struct device * match , void * arg )
335- {
336- struct cxl_port * root_port = arg ;
337- struct device * host = root_port -> dev .parent ;
338- struct acpi_device * hb = to_cxl_host_bridge (host , match );
339- struct acpi_pci_root * pci_root ;
340- struct cxl_dport * dport ;
341- struct cxl_port * port ;
342- struct device * bridge ;
343- int rc ;
344-
345- if (!hb )
346- return 0 ;
347-
348- pci_root = acpi_pci_find_root (hb -> handle );
349- bridge = pci_root -> bus -> bridge ;
350- dport = cxl_find_dport_by_dev (root_port , bridge );
351- if (!dport ) {
352- dev_dbg (host , "host bridge expected and not found\n" );
353- return 0 ;
354- }
355-
356- if (dport -> rch ) {
357- dev_info (bridge , "host supports CXL (restricted)\n" );
358- return 0 ;
359- }
360-
361- rc = devm_cxl_register_pci_bus (host , bridge , pci_root -> bus );
362- if (rc )
363- return rc ;
364-
365- port = devm_cxl_add_port (host , bridge , dport -> component_reg_phys ,
366- dport );
367- if (IS_ERR (port ))
368- return PTR_ERR (port );
369-
370- dev_info (bridge , "host supports CXL\n" );
371-
372- return 0 ;
373- }
374-
330+ /* Note, @dev is used by mock_acpi_table_parse_cedt() */
375331struct cxl_chbs_context {
376332 struct device * dev ;
377333 unsigned long long uid ;
378- resource_size_t rcrb ;
379- resource_size_t chbcr ;
334+ resource_size_t base ;
380335 u32 cxl_version ;
381336};
382337
383- static int cxl_get_chbcr (union acpi_subtable_headers * header , void * arg ,
384- const unsigned long end )
338+ static int cxl_get_chbs_iter (union acpi_subtable_headers * header , void * arg ,
339+ const unsigned long end )
385340{
386341 struct cxl_chbs_context * ctx = arg ;
387342 struct acpi_cedt_chbs * chbs ;
388343
389- if (ctx -> chbcr )
344+ if (ctx -> base != CXL_RESOURCE_NONE )
390345 return 0 ;
391346
392347 chbs = (struct acpi_cedt_chbs * ) header ;
@@ -395,23 +350,39 @@ static int cxl_get_chbcr(union acpi_subtable_headers *header, void *arg,
395350 return 0 ;
396351
397352 ctx -> cxl_version = chbs -> cxl_version ;
398- ctx -> rcrb = CXL_RESOURCE_NONE ;
399- ctx -> chbcr = CXL_RESOURCE_NONE ;
400-
401353 if (!chbs -> base )
402354 return 0 ;
403355
404- if (chbs -> cxl_version != ACPI_CEDT_CHBS_VERSION_CXL11 ) {
405- ctx -> chbcr = chbs -> base ;
356+ if (chbs -> cxl_version == ACPI_CEDT_CHBS_VERSION_CXL11 &&
357+ chbs -> length != CXL_RCRB_SIZE )
406358 return 0 ;
359+
360+ ctx -> base = chbs -> base ;
361+
362+ return 0 ;
363+ }
364+
365+ static int cxl_get_chbs (struct device * dev , struct acpi_device * hb ,
366+ struct cxl_chbs_context * ctx )
367+ {
368+ unsigned long long uid ;
369+ int rc ;
370+
371+ rc = acpi_evaluate_integer (hb -> handle , METHOD_NAME__UID , NULL , & uid );
372+ if (rc != AE_OK ) {
373+ dev_err (dev , "unable to retrieve _UID\n" );
374+ return - ENOENT ;
407375 }
408376
409- if (chbs -> length != CXL_RCRB_SIZE )
410- return 0 ;
377+ dev_dbg (dev , "UID found: %lld\n" , uid );
378+ * ctx = (struct cxl_chbs_context ) {
379+ .dev = dev ,
380+ .uid = uid ,
381+ .base = CXL_RESOURCE_NONE ,
382+ .cxl_version = UINT_MAX ,
383+ };
411384
412- ctx -> rcrb = chbs -> base ;
413- ctx -> chbcr = cxl_rcrb_to_component (ctx -> dev , chbs -> base ,
414- CXL_RCRB_DOWNSTREAM );
385+ acpi_table_parse_cedt (ACPI_CEDT_TYPE_CHBS , cxl_get_chbs_iter , ctx );
415386
416387 return 0 ;
417388}
@@ -420,7 +391,6 @@ static int add_host_bridge_dport(struct device *match, void *arg)
420391{
421392 acpi_status rc ;
422393 struct device * bridge ;
423- unsigned long long uid ;
424394 struct cxl_dport * dport ;
425395 struct cxl_chbs_context ctx ;
426396 struct acpi_pci_root * pci_root ;
@@ -431,51 +401,107 @@ static int add_host_bridge_dport(struct device *match, void *arg)
431401 if (!hb )
432402 return 0 ;
433403
434- rc = acpi_evaluate_integer (hb -> handle , METHOD_NAME__UID , NULL , & uid );
435- if (rc != AE_OK ) {
436- dev_err (match , "unable to retrieve _UID\n" );
437- return - ENODEV ;
438- }
439-
440- dev_dbg (match , "UID found: %lld\n" , uid );
441-
442- ctx = (struct cxl_chbs_context ) {
443- .dev = match ,
444- .uid = uid ,
445- };
446- acpi_table_parse_cedt (ACPI_CEDT_TYPE_CHBS , cxl_get_chbcr , & ctx );
404+ rc = cxl_get_chbs (match , hb , & ctx );
405+ if (rc )
406+ return rc ;
447407
448- if (! ctx .chbcr ) {
408+ if (ctx .cxl_version == UINT_MAX ) {
449409 dev_warn (match , "No CHBS found for Host Bridge (UID %lld)\n" ,
450- uid );
410+ ctx . uid );
451411 return 0 ;
452412 }
453413
454- if (ctx .rcrb != CXL_RESOURCE_NONE )
455- dev_dbg (match , "RCRB found for UID %lld: %pa\n" , uid , & ctx .rcrb );
456-
457- if (ctx .chbcr == CXL_RESOURCE_NONE ) {
458- dev_warn (match , "CHBCR invalid for Host Bridge (UID %lld)\n" ,
459- uid );
414+ if (ctx .base == CXL_RESOURCE_NONE ) {
415+ dev_warn (match , "CHBS invalid for Host Bridge (UID %lld)\n" ,
416+ ctx .uid );
460417 return 0 ;
461418 }
462419
463- dev_dbg (match , "CHBCR found: %pa\n" , & ctx .chbcr );
464-
465420 pci_root = acpi_pci_find_root (hb -> handle );
466421 bridge = pci_root -> bus -> bridge ;
467- if (ctx .cxl_version == ACPI_CEDT_CHBS_VERSION_CXL11 )
468- dport = devm_cxl_add_rch_dport (root_port , bridge , uid ,
469- ctx .chbcr , ctx .rcrb );
470- else
471- dport = devm_cxl_add_dport (root_port , bridge , uid ,
472- ctx .chbcr );
422+
423+ /*
424+ * In RCH mode, bind the component regs base to the dport. In
425+ * VH mode it will be bound to the CXL host bridge's port
426+ * object later in add_host_bridge_uport().
427+ */
428+ if (ctx .cxl_version == ACPI_CEDT_CHBS_VERSION_CXL11 ) {
429+ dev_dbg (match , "RCRB found for UID %lld: %pa\n" , ctx .uid ,
430+ & ctx .base );
431+ dport = devm_cxl_add_rch_dport (root_port , bridge , ctx .uid ,
432+ ctx .base );
433+ } else {
434+ dport = devm_cxl_add_dport (root_port , bridge , ctx .uid ,
435+ CXL_RESOURCE_NONE );
436+ }
437+
473438 if (IS_ERR (dport ))
474439 return PTR_ERR (dport );
475440
476441 return 0 ;
477442}
478443
444+ /*
445+ * A host bridge is a dport to a CFMWS decode and it is a uport to the
446+ * dport (PCIe Root Ports) in the host bridge.
447+ */
448+ static int add_host_bridge_uport (struct device * match , void * arg )
449+ {
450+ struct cxl_port * root_port = arg ;
451+ struct device * host = root_port -> dev .parent ;
452+ struct acpi_device * hb = to_cxl_host_bridge (host , match );
453+ struct acpi_pci_root * pci_root ;
454+ struct cxl_dport * dport ;
455+ struct cxl_port * port ;
456+ struct device * bridge ;
457+ struct cxl_chbs_context ctx ;
458+ resource_size_t component_reg_phys ;
459+ int rc ;
460+
461+ if (!hb )
462+ return 0 ;
463+
464+ pci_root = acpi_pci_find_root (hb -> handle );
465+ bridge = pci_root -> bus -> bridge ;
466+ dport = cxl_find_dport_by_dev (root_port , bridge );
467+ if (!dport ) {
468+ dev_dbg (host , "host bridge expected and not found\n" );
469+ return 0 ;
470+ }
471+
472+ if (dport -> rch ) {
473+ dev_info (bridge , "host supports CXL (restricted)\n" );
474+ return 0 ;
475+ }
476+
477+ rc = cxl_get_chbs (match , hb , & ctx );
478+ if (rc )
479+ return rc ;
480+
481+ if (ctx .cxl_version == ACPI_CEDT_CHBS_VERSION_CXL11 ) {
482+ dev_warn (bridge ,
483+ "CXL CHBS version mismatch, skip port registration\n" );
484+ return 0 ;
485+ }
486+
487+ component_reg_phys = ctx .base ;
488+ if (component_reg_phys != CXL_RESOURCE_NONE )
489+ dev_dbg (match , "CHBCR found for UID %lld: %pa\n" ,
490+ ctx .uid , & component_reg_phys );
491+
492+ rc = devm_cxl_register_pci_bus (host , bridge , pci_root -> bus );
493+ if (rc )
494+ return rc ;
495+
496+ port = devm_cxl_add_port (host , bridge , component_reg_phys , dport );
497+ if (IS_ERR (port ))
498+ return PTR_ERR (port );
499+
500+ dev_info (bridge , "host supports CXL\n" );
501+
502+ return 0 ;
503+ }
504+
479505static int add_root_nvdimm_bridge (struct device * match , void * data )
480506{
481507 struct cxl_decoder * cxld ;
0 commit comments