From: Zijun Hu quic_zijuhu@quicinc.com
match_free_decoder()'s logic for finding a free cxl decoder depends on a prerequisite that all child decoders are sorted by ID in ascending order but the prerequisite may not be guaranteed, fix by finding a free cxl decoder with minimal ID.
Fixes: 384e624bb211 ("cxl/region: Attach endpoint decoders") Closes: https://lore.kernel.org/all/cdfc6f98-1aa0-4cb5-bd7d-93256552c39b@icloud.com/ Cc: stable@vger.kernel.org Signed-off-by: Zijun Hu quic_zijuhu@quicinc.com --- drivers/cxl/core/region.c | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-)
diff --git a/drivers/cxl/core/region.c b/drivers/cxl/core/region.c index 21ad5f242875..b9607b4fc40b 100644 --- a/drivers/cxl/core/region.c +++ b/drivers/cxl/core/region.c @@ -797,21 +797,26 @@ static size_t show_targetN(struct cxl_region *cxlr, char *buf, int pos) static int match_free_decoder(struct device *dev, void *data) { struct cxl_decoder *cxld; - int *id = data; + struct cxl_decoder *target_cxld; + struct device **target_device = data;
if (!is_switch_decoder(dev)) return 0;
cxld = to_cxl_decoder(dev); - - /* enforce ordered allocation */ - if (cxld->id != *id) + if (cxld->region) return 0;
- if (!cxld->region) - return 1; - - (*id)++; + if (!*target_device) { + *target_device = get_device(dev); + return 0; + } + /* enforce ordered allocation */ + target_cxld = to_cxl_decoder(*target_device); + if (cxld->id < target_cxld->id) { + put_device(*target_device); + *target_device = get_device(dev); + }
return 0; } @@ -839,8 +844,7 @@ cxl_region_find_decoder(struct cxl_port *port, struct cxl_endpoint_decoder *cxled, struct cxl_region *cxlr) { - struct device *dev; - int id = 0; + struct device *dev = NULL;
if (port == cxled_to_port(cxled)) return &cxled->cxld; @@ -849,7 +853,8 @@ cxl_region_find_decoder(struct cxl_port *port, dev = device_find_child(&port->dev, &cxlr->params, match_auto_decoder); else - dev = device_find_child(&port->dev, &id, match_free_decoder); + /* Need to put_device(@dev) after use */ + device_for_each_child(&port->dev, &dev, match_free_decoder); if (!dev) return NULL; /*
--- base-commit: 67784a74e258a467225f0e68335df77acd67b7ab change-id: 20240903-fix_cxld-4f6575a90619
Best regards,
On Tue, Sep 03, 2024 at 08:41:44PM +0800, Zijun Hu wrote:
From: Zijun Hu quic_zijuhu@quicinc.com
match_free_decoder()'s logic for finding a free cxl decoder depends on a prerequisite that all child decoders are sorted by ID in ascending order but the prerequisite may not be guaranteed, fix by finding a free cxl decoder with minimal ID.
After reading the 'Closes' tag below I have a better understanding of why you may be doing this, but I don't want to have to jump to that Link. Can you describe here examples of when the ordered allocation may not be guaranteed, and the impact when that happens.
This includes a change to device_for_each_child() which I see mentioned in the Closes tag discussion too. Is that required for this fix?
It's feeling like the fix and api update are comingled. Please clarify.
Thanks, Alison
Fixes: 384e624bb211 ("cxl/region: Attach endpoint decoders") Closes: https://lore.kernel.org/all/cdfc6f98-1aa0-4cb5-bd7d-93256552c39b@icloud.com/ Cc: stable@vger.kernel.org Signed-off-by: Zijun Hu quic_zijuhu@quicinc.com
drivers/cxl/core/region.c | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-)
diff --git a/drivers/cxl/core/region.c b/drivers/cxl/core/region.c index 21ad5f242875..b9607b4fc40b 100644 --- a/drivers/cxl/core/region.c +++ b/drivers/cxl/core/region.c @@ -797,21 +797,26 @@ static size_t show_targetN(struct cxl_region *cxlr, char *buf, int pos) static int match_free_decoder(struct device *dev, void *data) { struct cxl_decoder *cxld;
- int *id = data;
- struct cxl_decoder *target_cxld;
- struct device **target_device = data;
if (!is_switch_decoder(dev)) return 0; cxld = to_cxl_decoder(dev);
- /* enforce ordered allocation */
- if (cxld->id != *id)
- if (cxld->region) return 0;
- if (!cxld->region)
return 1;
- (*id)++;
- if (!*target_device) {
*target_device = get_device(dev);
return 0;
- }
- /* enforce ordered allocation */
- target_cxld = to_cxl_decoder(*target_device);
- if (cxld->id < target_cxld->id) {
put_device(*target_device);
*target_device = get_device(dev);
- }
return 0; } @@ -839,8 +844,7 @@ cxl_region_find_decoder(struct cxl_port *port, struct cxl_endpoint_decoder *cxled, struct cxl_region *cxlr) {
- struct device *dev;
- int id = 0;
- struct device *dev = NULL;
if (port == cxled_to_port(cxled)) return &cxled->cxld; @@ -849,7 +853,8 @@ cxl_region_find_decoder(struct cxl_port *port, dev = device_find_child(&port->dev, &cxlr->params, match_auto_decoder); else
dev = device_find_child(&port->dev, &id, match_free_decoder);
/* Need to put_device(@dev) after use */
if (!dev) return NULL; /*device_for_each_child(&port->dev, &dev, match_free_decoder);
base-commit: 67784a74e258a467225f0e68335df77acd67b7ab change-id: 20240903-fix_cxld-4f6575a90619
Best regards,
Zijun Hu quic_zijuhu@quicinc.com
On 2024/9/4 04:14, Alison Schofield wrote:
On Tue, Sep 03, 2024 at 08:41:44PM +0800, Zijun Hu wrote:
From: Zijun Hu quic_zijuhu@quicinc.com
match_free_decoder()'s logic for finding a free cxl decoder depends on a prerequisite that all child decoders are sorted by ID in ascending order but the prerequisite may not be guaranteed, fix by finding a free cxl decoder with minimal ID.
After reading the 'Closes' tag below I have a better understanding of why you may be doing this, but I don't want to have to jump to that Link. Can you describe here examples of when the ordered allocation may not be guaranteed, and the impact when that happens.
thank you for code review. let me try to do it.
This includes a change to device_for_each_child() which I see mentioned in the Closes tag discussion too. Is that required for this fix?
yes, device_for_each_child() is better than device_find_child() to correct logic for finding a free cxl decoder.
It's feeling like the fix and api update are comingled. Please clarify.
actually, there are two concerns as shown below:
concern A: device_find_child() modifies caller's match data. concern B: weird logic for finding a free cxl decoder
this patch focuses on concern B, and it also solve concern A in passing.
the following exclusive patch only solves concern A. https://lore.kernel.org/all/20240905-const_dfc_prepare-v4-1-4180e1d5a244@qui...
either will solve concern A i care about.
Thanks, Alison
linux-stable-mirror@lists.linaro.org