@@ -416,9 +416,19 @@ int cxl_hdm_decode_init(struct cxl_dev_state *cxlds, struct cxl_hdm *cxlhdm,
416416 if (global_ctrl & CXL_HDM_DECODER_ENABLE || (!hdm && info -> mem_enabled ))
417417 return devm_cxl_enable_mem (& port -> dev , cxlds );
418418
419+ /*
420+ * If the HDM Decoder Capability does not exist and DVSEC was
421+ * not setup, the DVSEC based emulation cannot be used.
422+ */
419423 if (!hdm )
420424 return - ENODEV ;
421425
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+ */
422432 if (!info -> mem_enabled ) {
423433 rc = devm_cxl_enable_hdm (& port -> dev , cxlhdm );
424434 if (rc )
@@ -427,6 +437,18 @@ int cxl_hdm_decode_init(struct cxl_dev_state *cxlds, struct cxl_hdm *cxlhdm,
427437 return devm_cxl_enable_mem (& port -> dev , cxlds );
428438 }
429439
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+
430452 root = to_cxl_port (port -> dev .parent );
431453 while (!is_cxl_root (root ) && is_cxl_port (root -> dev .parent ))
432454 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,
454476 return - ENXIO ;
455477 }
456478
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- */
466479 return 0 ;
467480}
468481EXPORT_SYMBOL_NS_GPL (cxl_hdm_decode_init , "CXL" );
0 commit comments