diff --git a/drivers/cxl/core/hdm.c b/drivers/cxl/core/hdm.c index c222e98ae736..3930e130d6b6 100644 --- a/drivers/cxl/core/hdm.c +++ b/drivers/cxl/core/hdm.c @@ -177,7 +177,7 @@ static struct cxl_hdm *devm_cxl_setup_hdm(struct cxl_port *port, } parse_hdm_decoder_caps(cxlhdm); - if (cxlhdm->decoder_count == 0) { + if (cxlhdm->decoder_count < 0) { dev_err(dev, "Spec violation. Caps invalid\n"); return ERR_PTR(-ENXIO); } diff --git a/drivers/cxl/cxl.h b/drivers/cxl/cxl.h index 28a49c20df58..1297594beaec 100644 --- a/drivers/cxl/cxl.h +++ b/drivers/cxl/cxl.h @@ -78,7 +78,16 @@ static inline int cxl_hdm_decoder_count(u32 cap_hdr) { int val = FIELD_GET(CXL_HDM_DECODER_COUNT_MASK, cap_hdr); - return val ? val * 2 : 1; + switch (val) { + case 0: + return 1; + case 1 ... 8: + return val * 2; + case 9 ... 12: + return (val - 4) * 4; + default: + return -ENXIO; + } } /* Encode defined in CXL 2.0 8.2.5.12.7 HDM Decoder Control Register */ diff --git a/drivers/cxl/cxlmem.h b/drivers/cxl/cxlmem.h index 02054f233fc5..776c50d1db51 100644 --- a/drivers/cxl/cxlmem.h +++ b/drivers/cxl/cxlmem.h @@ -841,7 +841,7 @@ int cxl_mem_sanitize(struct cxl_memdev *cxlmd, u16 cmd); */ struct cxl_hdm { struct cxl_component_regs regs; - unsigned int decoder_count; + int decoder_count; unsigned int target_count; unsigned int interleave_mask; unsigned long iw_cap_mask;