Message ID | 167571668726.587790.16814881883553586342.stgit@djiang5-mobl3.local |
---|---|
State | Superseded |
Headers | show |
Series | cxl: Add support for QTG ID retrieval for CXL subsystem | expand |
On Mon, 06 Feb 2023 13:51:28 -0700 Dave Jiang <dave.jiang@intel.com> wrote: > CXL rev3.0 8.1.3.8.2 Memory_Info_valid field > > The Memory_Info_Valid bit indicates that the CXL Range Size High and Size > Low registers are valid. The bit must be set within 1 second of reset > deassertion to the device. Check valid bit before we check the > Memory_Active bit when waiting for cxl_await_media_ready() to ensure that > the memory info is valid for consumption. > > Signed-off-by: Dave Jiang <dave.jiang@intel.com> Fix? > --- > drivers/cxl/core/pci.c | 25 +++++++++++++++++++++++-- > drivers/cxl/port.c | 20 ++++++++++---------- > 2 files changed, 33 insertions(+), 12 deletions(-) > > diff --git a/drivers/cxl/core/pci.c b/drivers/cxl/core/pci.c > index 54ac6f8825ff..79a1348e7b98 100644 > --- a/drivers/cxl/core/pci.c > +++ b/drivers/cxl/core/pci.c > @@ -111,11 +111,32 @@ int cxl_await_media_ready(struct cxl_dev_state *cxlds) > int d = cxlds->cxl_dvsec; > bool active = false; > u64 md_status; > + u32 temp; > int rc, i; > > - for (i = media_ready_timeout; i; i--) { > - u32 temp; > + /* Check MEM INFO VALID bit first, give up after 1s */ > + i = 1; > + do { > + rc = pci_read_config_dword(pdev, > + d + CXL_DVSEC_RANGE_SIZE_LOW(0), > + &temp); > + if (rc) > + return rc; > > + active = FIELD_GET(CXL_DVSEC_MEM_INFO_VALID, temp); > + if (active) > + break; > + msleep(1000); > + } while (i--); If HDM_Count > 1, there is a second range to check and I think we need both to be valid here. > + > + if (!active) { > + dev_err(&pdev->dev, > + "timeout awaiting memory valid after 1 second.\n"); > + return -ETIMEDOUT; > + } > + > + /* Check MEM ACTIVE bit, up to 60s timeout by default */ > + for (i = media_ready_timeout; i; i--) { > rc = pci_read_config_dword( > pdev, d + CXL_DVSEC_RANGE_SIZE_LOW(0), &temp); > if (rc) > diff --git a/drivers/cxl/port.c b/drivers/cxl/port.c > index d72e38f9ae44..03380c18fc52 100644 > --- a/drivers/cxl/port.c > +++ b/drivers/cxl/port.c > @@ -99,6 +99,16 @@ static int cxl_port_probe(struct device *dev) > if (rc) > return rc; > > + rc = cxl_hdm_decode_init(cxlds, cxlhdm); > + if (rc) > + return rc; > + > + rc = cxl_await_media_ready(cxlds); > + if (rc) { > + dev_err(dev, "Media not active (%d)\n", rc); > + return rc; > + } > + > if (port->cdat.table) { > rc = cdat_table_parse_dsmas(port->cdat.table, > cxl_dsmas_parse_entry, > @@ -117,16 +127,6 @@ static int cxl_port_probe(struct device *dev) > if (rc) > dev_dbg(dev, "Failed to do QoS calculations\n"); > } > - > - rc = cxl_hdm_decode_init(cxlds, cxlhdm); > - if (rc) > - return rc; > - > - rc = cxl_await_media_ready(cxlds); > - if (rc) { > - dev_err(dev, "Media not active (%d)\n", rc); > - return rc; > - } > } > > rc = devm_cxl_enumerate_decoders(cxlhdm); > >
diff --git a/drivers/cxl/core/pci.c b/drivers/cxl/core/pci.c index 54ac6f8825ff..79a1348e7b98 100644 --- a/drivers/cxl/core/pci.c +++ b/drivers/cxl/core/pci.c @@ -111,11 +111,32 @@ int cxl_await_media_ready(struct cxl_dev_state *cxlds) int d = cxlds->cxl_dvsec; bool active = false; u64 md_status; + u32 temp; int rc, i; - for (i = media_ready_timeout; i; i--) { - u32 temp; + /* Check MEM INFO VALID bit first, give up after 1s */ + i = 1; + do { + rc = pci_read_config_dword(pdev, + d + CXL_DVSEC_RANGE_SIZE_LOW(0), + &temp); + if (rc) + return rc; + active = FIELD_GET(CXL_DVSEC_MEM_INFO_VALID, temp); + if (active) + break; + msleep(1000); + } while (i--); + + if (!active) { + dev_err(&pdev->dev, + "timeout awaiting memory valid after 1 second.\n"); + return -ETIMEDOUT; + } + + /* Check MEM ACTIVE bit, up to 60s timeout by default */ + for (i = media_ready_timeout; i; i--) { rc = pci_read_config_dword( pdev, d + CXL_DVSEC_RANGE_SIZE_LOW(0), &temp); if (rc) diff --git a/drivers/cxl/port.c b/drivers/cxl/port.c index d72e38f9ae44..03380c18fc52 100644 --- a/drivers/cxl/port.c +++ b/drivers/cxl/port.c @@ -99,6 +99,16 @@ static int cxl_port_probe(struct device *dev) if (rc) return rc; + rc = cxl_hdm_decode_init(cxlds, cxlhdm); + if (rc) + return rc; + + rc = cxl_await_media_ready(cxlds); + if (rc) { + dev_err(dev, "Media not active (%d)\n", rc); + return rc; + } + if (port->cdat.table) { rc = cdat_table_parse_dsmas(port->cdat.table, cxl_dsmas_parse_entry, @@ -117,16 +127,6 @@ static int cxl_port_probe(struct device *dev) if (rc) dev_dbg(dev, "Failed to do QoS calculations\n"); } - - rc = cxl_hdm_decode_init(cxlds, cxlhdm); - if (rc) - return rc; - - rc = cxl_await_media_ready(cxlds); - if (rc) { - dev_err(dev, "Media not active (%d)\n", rc); - return rc; - } } rc = devm_cxl_enumerate_decoders(cxlhdm);
CXL rev3.0 8.1.3.8.2 Memory_Info_valid field The Memory_Info_Valid bit indicates that the CXL Range Size High and Size Low registers are valid. The bit must be set within 1 second of reset deassertion to the device. Check valid bit before we check the Memory_Active bit when waiting for cxl_await_media_ready() to ensure that the memory info is valid for consumption. Signed-off-by: Dave Jiang <dave.jiang@intel.com> --- drivers/cxl/core/pci.c | 25 +++++++++++++++++++++++-- drivers/cxl/port.c | 20 ++++++++++---------- 2 files changed, 33 insertions(+), 12 deletions(-)