if (!cxld->region) {
cxld->region = cxlr;
+
+ /*
+ * Now that cxld->region is set the intermediate staging state
+ * can be cleared.
+ */
+ if (cxld == &cxled->cxld &&
+ cxled->state == CXL_DECODER_STATE_AUTO_STAGED)
+ cxled->state = CXL_DECODER_STATE_AUTO;
get_device(&cxlr->dev);
}
pos = p->nr_targets;
p->targets[pos] = cxled;
cxled->pos = pos;
+ cxled->state = CXL_DECODER_STATE_AUTO_STAGED;
p->nr_targets++;
return 0;
return 0;
}
+static int cxl_region_by_target(struct device *dev, const void *data)
+{
+ const struct cxl_endpoint_decoder *cxled = data;
+ struct cxl_region_params *p;
+ struct cxl_region *cxlr;
+
+ if (!is_cxl_region(dev))
+ return 0;
+
+ cxlr = to_cxl_region(dev);
+ p = &cxlr->params;
+ return p->targets[cxled->pos] == cxled;
+}
+
+/*
+ * When an auto-region fails to assemble the decoder may be listed as a target,
+ * but not fully attached.
+ */
+static void cxl_cancel_auto_attach(struct cxl_endpoint_decoder *cxled)
+{
+ struct cxl_region_params *p;
+ struct cxl_region *cxlr;
+ int pos = cxled->pos;
+
+ if (cxled->state != CXL_DECODER_STATE_AUTO_STAGED)
+ return;
+
+ struct device *dev __free(put_device) =
+ bus_find_device(&cxl_bus_type, NULL, cxled, cxl_region_by_target);
+ if (!dev)
+ return;
+
+ cxlr = to_cxl_region(dev);
+ p = &cxlr->params;
+
+ p->nr_targets--;
+ cxled->state = CXL_DECODER_STATE_AUTO;
+ cxled->pos = -1;
+ p->targets[pos] = NULL;
+}
+
static struct cxl_region *
__cxl_decoder_detach(struct cxl_region *cxlr,
struct cxl_endpoint_decoder *cxled, int pos,
cxled = p->targets[pos];
} else {
cxlr = cxled->cxld.region;
- if (!cxlr)
+ if (!cxlr) {
+ cxl_cancel_auto_attach(cxled);
return NULL;
+ }
p = &cxlr->params;
}
};
/*
- * Track whether this decoder is reserved for region autodiscovery, or
- * free for userspace provisioning.
+ * Track whether this decoder is free for userspace provisioning, reserved for
+ * region autodiscovery, whether it is started connecting (awaiting other
+ * peers), or has completed auto assembly.
*/
enum cxl_decoder_state {
CXL_DECODER_STATE_MANUAL,
CXL_DECODER_STATE_AUTO,
+ CXL_DECODER_STATE_AUTO_STAGED,
};
/**