]> git.hungrycats.org Git - linux/commitdiff
cxl/region: Flag partially torn down regions as unusable
authorDan Williams <dan.j.williams@intel.com>
Sat, 17 Jun 2023 01:24:34 +0000 (18:24 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 11 Jul 2023 17:39:50 +0000 (19:39 +0200)
[ Upstream commit 2ab47045ac96a605e3037d479a7d5854570ee5bf ]

cxl_region_decode_reset() walks all the decoders associated with a given
region and disables them. Due to decoder ordering rules it is possible
that a switch in the topology notices that a given decoder can not be
shutdown before another region with a higher HPA is shutdown first. That
can leave the region in a partially committed state.

Capture that state in a new CXL_REGION_F_NEEDS_RESET flag and require
that a successful cxl_region_decode_reset() attempt must be completed
before cxl_region_probe() accepts the region.

This is a corollary for the bug that Jonathan identified in "CXL/region
:  commit reset of out of order region appears to succeed." [1].

Cc: Jonathan Cameron <Jonathan.Cameron@Huawei.com>
Link: http://lore.kernel.org/r/20230316171441.0000205b@Huawei.com
Fixes: 176baefb2eb5 ("cxl/hdm: Commit decoder state to hardware")
Reviewed-by: Dave Jiang <dave.jiang@intel.com>
Link: https://lore.kernel.org/r/168696507423.3590522.16254212607926684429.stgit@dwillia2-xfh.jf.intel.com
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/cxl/core/region.c
drivers/cxl/cxl.h

index 3b3bbd98e99d5bfe9f0eee82f697adff97871920..c1422167ab02b4d2464eb7e895c71d22f7fb7af6 100644 (file)
@@ -182,14 +182,19 @@ static int cxl_region_decode_reset(struct cxl_region *cxlr, int count)
                                rc = cxld->reset(cxld);
                        if (rc)
                                return rc;
+                       set_bit(CXL_REGION_F_NEEDS_RESET, &cxlr->flags);
                }
 
 endpoint_reset:
                rc = cxled->cxld.reset(&cxled->cxld);
                if (rc)
                        return rc;
+               set_bit(CXL_REGION_F_NEEDS_RESET, &cxlr->flags);
        }
 
+       /* all decoders associated with this region have been torn down */
+       clear_bit(CXL_REGION_F_NEEDS_RESET, &cxlr->flags);
+
        return 0;
 }
 
@@ -2740,6 +2745,13 @@ static int cxl_region_probe(struct device *dev)
                goto out;
        }
 
+       if (test_bit(CXL_REGION_F_NEEDS_RESET, &cxlr->flags)) {
+               dev_err(&cxlr->dev,
+                       "failed to activate, re-commit region and retry\n");
+               rc = -ENXIO;
+               goto out;
+       }
+
        /*
         * From this point on any path that changes the region's state away from
         * CXL_CONFIG_COMMIT is also responsible for releasing the driver.
index 70ab8fcd0377c3456374bfb135df4b4fd7abfb53..dcebe48bb5bb5604379ad84fe93d8eb32a4c06d2 100644 (file)
@@ -469,6 +469,14 @@ struct cxl_region_params {
  */
 #define CXL_REGION_F_AUTO 0
 
+/*
+ * Require that a committed region successfully complete a teardown once
+ * any of its associated decoders have been torn down. This maintains
+ * the commit state for the region since there are committed decoders,
+ * but blocks cxl_region_probe().
+ */
+#define CXL_REGION_F_NEEDS_RESET 1
+
 /**
  * struct cxl_region - CXL region
  * @dev: This region's device