@@ -416,9 +416,19 @@ int cxl_hdm_decode_init(struct cxl_dev_state *cxlds, struct cxl_hdm *cxlhdm,
416
416
if (global_ctrl & CXL_HDM_DECODER_ENABLE || (!hdm && info -> mem_enabled ))
417
417
return devm_cxl_enable_mem (& port -> dev , cxlds );
418
418
419
+ /*
420
+ * If the HDM Decoder Capability does not exist and DVSEC was
421
+ * not setup, the DVSEC based emulation cannot be used.
422
+ */
419
423
if (!hdm )
420
424
return - ENODEV ;
421
425
426
+ /* The HDM Decoder Capability exists but is globally disabled. */
427
+
428
+ /*
429
+ * If the DVSEC CXL Range registers are not enabled, just
430
+ * enable and use the HDM Decoder Capability registers.
431
+ */
422
432
if (!info -> mem_enabled ) {
423
433
rc = devm_cxl_enable_hdm (& port -> dev , cxlhdm );
424
434
if (rc )
@@ -427,6 +437,18 @@ int cxl_hdm_decode_init(struct cxl_dev_state *cxlds, struct cxl_hdm *cxlhdm,
427
437
return devm_cxl_enable_mem (& port -> dev , cxlds );
428
438
}
429
439
440
+ /*
441
+ * Per CXL 2.0 Section 8.1.3.8.3 and 8.1.3.8.4 DVSEC CXL Range 1 Base
442
+ * [High,Low] when HDM operation is enabled the range register values
443
+ * are ignored by the device, but the spec also recommends matching the
444
+ * DVSEC Range 1,2 to HDM Decoder Range 0,1. So, non-zero info->ranges
445
+ * are expected even though Linux does not require or maintain that
446
+ * match. Check if at least one DVSEC range is enabled and allowed by
447
+ * the platform. That is, the DVSEC range must be covered by a locked
448
+ * platform window (CFMWS). Fail otherwise as the endpoint's decoders
449
+ * cannot be used.
450
+ */
451
+
430
452
root = to_cxl_port (port -> dev .parent );
431
453
while (!is_cxl_root (root ) && is_cxl_port (root -> dev .parent ))
432
454
root = to_cxl_port (root -> dev .parent );
@@ -454,15 +476,6 @@ int cxl_hdm_decode_init(struct cxl_dev_state *cxlds, struct cxl_hdm *cxlhdm,
454
476
return - ENXIO ;
455
477
}
456
478
457
- /*
458
- * Per CXL 2.0 Section 8.1.3.8.3 and 8.1.3.8.4 DVSEC CXL Range 1 Base
459
- * [High,Low] when HDM operation is enabled the range register values
460
- * are ignored by the device, but the spec also recommends matching the
461
- * DVSEC Range 1,2 to HDM Decoder Range 0,1. So, non-zero info->ranges
462
- * are expected even though Linux does not require or maintain that
463
- * match. If at least one DVSEC range is enabled and allowed, skip HDM
464
- * Decoder Capability Enable.
465
- */
466
479
return 0 ;
467
480
}
468
481
EXPORT_SYMBOL_NS_GPL (cxl_hdm_decode_init , "CXL" );
0 commit comments