All of lore.kernel.org
 help / color / mirror / Atom feed
From: Dave Jiang <dave.jiang@intel.com>
To: "Lucero Palau, Alejandro" <alejandro.lucero-palau@amd.com>,
	alucerop@amd.com, linux-cxl@vger.kernel.org,
	netdev@vger.kernel.org
Cc: davem@davemloft.net, kuba@kernel.org, pabeni@redhat.com,
	edumazet@google.com, ecree.xilinx@gmail.com, icheng@nvidia.com,
	rafael@kernel.org
Subject: Re: [PATCH v2 1/4] driver core: Check for supplier requiring PM at link creation
Date: Fri, 2 Oct 2026 08:31:33 -0700	[thread overview]
Message-ID: <86f1bc50-65ef-4894-a2f0-211ccd394fdc@intel.com> (raw)
In-Reply-To: <b7fd6cc3-1aca-440f-a87d-d0d94ae9eed3@amd.com>

[-- Attachment #1: Type: text/plain, Size: 3516 bytes --]



On 10/1/26 9:32 PM, Lucero Palau, Alejandro wrote:
> 
> On 01/10/2026 21:31, Dave Jiang wrote:
>>
>> On 10/1/26 6:20 AM, alucerop@amd.com wrote:
>>> From: Alejandro Lucero <alucerop@amd.com>
>>>
>>> PM initialization could not be necessary for some devices.
>>>
>>> Avoid checking for supplier PM initialization if so.
>>>
>>> Signed-off-by: Alejandro Lucero <alucerop@amd.com>
>>> ---
>>>   drivers/base/core.c | 2 +-
>>>   1 file changed, 1 insertion(+), 1 deletion(-)
>>>
>>> diff --git a/drivers/base/core.c b/drivers/base/core.c
>>> index 4c0c373998a1..bf0513beafad 100644
>>> --- a/drivers/base/core.c
>>> +++ b/drivers/base/core.c
>>> @@ -840,7 +840,7 @@ struct device_link *device_link_add(struct device *consumer,
>>>        * SYNC_STATE_ONLY link, we don't check for reverse dependencies
>>>        * because it only affects sync_state() callbacks.
>>>        */
>>> -    if (!device_pm_initialized(supplier)
>>> +    if ((!device_pm_not_required(supplier) && !device_pm_initialized(supplier))
>>>           || (!(flags & DL_FLAG_SYNC_STATE_ONLY) &&
>>>             device_is_dependent(consumer, supplier))) {
>>>           link = NULL;
>> A no PM supplier can now be linked at any point: before device_add(), while it fails, or after device_del(). Maybe replace with a helper like this?
> 
> 
> I would say you can not use a device as supplier before device_add() happens for such a supplier, and if it does happen after device_del(), something is wrong with the caller.

Yes that would be a bug, and device_link_add() is suppose to catch it. For PM devices, the device_pm_initialized() test is the gate. The change you made skips that test for no PM device case. I had LLM created a test module for verification, attached.

Essentially the logic in this patch removed the check for 2 states that the original code used to block.
1. before device_add(supplier)
2. after device_del(supplier) 

> 
> 
> Your suggestion is likely making the code more legible, but it does not change the functionality I added. Does it? Not saying it would not help, but I can not understand your comment for suggesting it which seems to point to potential problems I did not see.
> 

It does.
- before device_add(supplier): this patch creates the link, and the helper refuses it.
- after device_add(supplier): both create it.
- after device_del(supplier), before last put_device: this patch creates the link, and the helper refuses it.

delete_region() or root decoder teardown can unregister the region while the endpoint is still bound. cxl_get_range_and_link() can still be called on a region that has already been through device_del().

Without the helper, it's possible where the PFx driver can device_link_add() a deleted region that is still around due to endpoint still holds a reference.

DJ


> 
>> static bool device_link_supplier_ready(struct device *supplier)
>> {
>>        /* no PM devices never enter dpm_list, so check registration directly */
>>        if (device_pm_not_required(supplier))
>>                return device_is_registered(supplier);
>>
>>        return device_pm_initialized(supplier);
>> }
>>
>> ...
>>
>>        if (!device_link_supplier_ready(supplier) ||
>>            (!(flags & DL_FLAG_SYNC_STATE_ONLY) &&
>>             device_is_dependent(consumer, supplier))) {
>>                link = NULL;
>>                goto out;
>>        }

[-- Attachment #2: mock-pfx.patch --]
[-- Type: text/x-patch, Size: 4509 bytes --]

commit 0551e91e63c6009b71792133e0ef0cff1c0af6dd
Author: Dave Jiang <dave.jiang@intel.com>
Date:   Thu Oct 1 14:13:19 2026 -0700

    TEST ONLY: cxl/test: mock non-PF0 consumer for cxl_get_range_and_link()
    
    Not for submission. Exercises the multi-PF device-link path against the
    cxl_test type-2 accelerator, and self-tests device_link_add() on a no_pm
    supplier across registration.

diff --git a/tools/testing/cxl/test/Kbuild b/tools/testing/cxl/test/Kbuild
index 9a24ddc28488..279d89be4a4d 100644
--- a/tools/testing/cxl/test/Kbuild
+++ b/tools/testing/cxl/test/Kbuild
@@ -6,11 +6,13 @@ obj-m += cxl_mock.o
 obj-m += cxl_mock_mem.o
 obj-m += cxl_translate.o
 obj-m += cxl_mock_accel.o
+obj-m += cxl_mock_pfx.o
 
 cxl_test-y := cxl.o
 cxl_test-y += hmem_test.o
 cxl_mock-y := mock.o
 cxl_mock_mem-y := mem.o
 cxl_mock_accel-y := accel.o
+cxl_mock_pfx-y := pfx.o
 
 KBUILD_CFLAGS := $(filter-out -Wmissing-prototypes -Wmissing-declarations, $(KBUILD_CFLAGS))
diff --git a/tools/testing/cxl/test/pfx.c b/tools/testing/cxl/test/pfx.c
new file mode 100644
index 000000000000..55b752ebe9ca
--- /dev/null
+++ b/tools/testing/cxl/test/pfx.c
@@ -0,0 +1,134 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * TEST ONLY: mock non-PF0 consumer. Its probe links to the region attached
+ * to the cxl_test type-2 accelerator via cxl_get_range_and_link().
+ */
+
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <cxl/cxl.h>
+
+static char *pf0_name = "cxl_type2_accel.0";
+module_param(pf0_name, charp, 0444);
+
+static struct platform_device *pfx_pdev;
+
+static int cxl_mock_pfx_probe(struct platform_device *pdev)
+{
+	struct device *pf0;
+	struct range range;
+	int rc;
+
+	pf0 = bus_find_device_by_name(&platform_bus_type, NULL, pf0_name);
+	if (!pf0) {
+		dev_info(&pdev->dev, "pfx_test: %s not found\n", pf0_name);
+		return -ENODEV;
+	}
+
+	rc = cxl_get_range_and_link(pf0, &pdev->dev, &range);
+	put_device(pf0);
+	if (rc) {
+		dev_info(&pdev->dev, "pfx_test: link rc=%d\n", rc);
+		/* don't let -EPROBE_DEFER requeue us behind the test's back */
+		return rc == -EPROBE_DEFER ? -EAGAIN : rc;
+	}
+
+	dev_info(&pdev->dev, "pfx_test: link rc=0 range=%pra\n", &range);
+	return 0;
+}
+
+static void cxl_mock_pfx_remove(struct platform_device *pdev)
+{
+	dev_info(&pdev->dev, "pfx_test: removed\n");
+}
+
+static struct platform_driver cxl_mock_pfx_driver = {
+	.probe = cxl_mock_pfx_probe,
+	.remove = cxl_mock_pfx_remove,
+	.driver = {
+		.name = "cxl_mock_pfx",
+	},
+};
+
+static void dev_release(struct device *dev)
+{
+	kfree(dev);
+}
+
+/* device_link_add() must refuse a no_pm supplier that is not registered */
+static void devlink_no_pm_selftest(struct device *consumer)
+{
+	struct device_link *link;
+	struct device *sup;
+	int pass = 0;
+
+	sup = kzalloc_obj(*sup);
+	if (!sup)
+		return;
+	device_initialize(sup);
+	sup->release = dev_release;
+	device_set_pm_not_required(sup);
+	dev_set_name(sup, "pfx_test_supplier");
+
+	link = device_link_add(consumer, sup, DL_FLAG_STATELESS);
+	pr_info("pfx_test: no_pm before device_add: link %s\n",
+		link ? "CREATED (FAIL)" : "refused (PASS)");
+	if (link)
+		device_link_del(link);
+	else
+		pass++;
+
+	if (device_add(sup)) {
+		put_device(sup);
+		return;
+	}
+
+	link = device_link_add(consumer, sup, DL_FLAG_STATELESS);
+	pr_info("pfx_test: no_pm after device_add: link %s\n",
+		link ? "created (PASS)" : "REFUSED (FAIL)");
+	if (link) {
+		device_link_del(link);
+		pass++;
+	}
+
+	device_del(sup);
+	link = device_link_add(consumer, sup, DL_FLAG_STATELESS);
+	pr_info("pfx_test: no_pm after device_del: link %s\n",
+		link ? "CREATED (FAIL)" : "refused (PASS)");
+	if (link)
+		device_link_del(link);
+	else
+		pass++;
+
+	put_device(sup);
+	pr_info("pfx_test: no_pm selftest %d/3 passed\n", pass);
+}
+
+static int __init cxl_mock_pfx_init(void)
+{
+	int rc;
+
+	pfx_pdev = platform_device_register_simple("cxl_mock_pfx", 1, NULL, 0);
+	if (IS_ERR(pfx_pdev))
+		return PTR_ERR(pfx_pdev);
+
+	devlink_no_pm_selftest(&pfx_pdev->dev);
+
+	rc = platform_driver_register(&cxl_mock_pfx_driver);
+	if (rc)
+		platform_device_unregister(pfx_pdev);
+	return rc;
+}
+module_init(cxl_mock_pfx_init);
+
+static void __exit cxl_mock_pfx_exit(void)
+{
+	platform_driver_unregister(&cxl_mock_pfx_driver);
+	platform_device_unregister(pfx_pdev);
+}
+module_exit(cxl_mock_pfx_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("cxl_test: TEST ONLY mock non-PF0 consumer");
+MODULE_IMPORT_NS("CXL");

  reply	other threads:[~2026-10-02 15:31 UTC|newest]

Thread overview: 28+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-01 13:20 [PATCH v2 0/4] Type2 multipf support alucerop
2026-10-01 13:20 ` [PATCH v2 1/4] driver core: Check for supplier requiring PM at link creation alucerop
2026-10-01 20:31   ` Dave Jiang
2026-10-02  4:32     ` Lucero Palau, Alejandro
2026-10-02 15:31       ` Dave Jiang [this message]
2026-10-02 12:02   ` sashiko-bot
2026-10-01 13:20 ` [PATCH v2 2/4] cxl/region: Add region reference in memdev attach alucerop
2026-10-01 21:38   ` Dave Jiang
2026-10-02  4:41     ` Lucero Palau, Alejandro
2026-10-02 15:52       ` Dave Jiang
2026-10-08 13:50         ` Lucero Palau, Alejandro
2026-10-08 16:18           ` Dave Jiang
2026-10-08 18:07             ` Lucero Palau, Alejandro
2026-10-08 21:05               ` Dave Jiang
2026-10-09  6:58                 ` Lucero Palau, Alejandro
2026-10-09 16:57                   ` Dave Jiang
2026-10-02 12:02   ` sashiko-bot
2026-10-01 13:20 ` [PATCH v2 3/4] cxl/memdev: Add support for multi PF devices alucerop
2026-10-01 22:11   ` Dave Jiang
2026-10-01 22:41     ` Dave Jiang
2026-10-02  4:50     ` Lucero Palau, Alejandro
2026-10-02 15:55       ` Dave Jiang
2026-10-02 12:02   ` sashiko-bot
2026-10-01 13:20 ` [PATCH v2 4/4] sfc: add multipf support alucerop
2026-10-01 22:32   ` Dave Jiang
2026-10-02  5:33     ` Lucero Palau, Alejandro
2026-10-02 12:02   ` sashiko-bot
2026-10-10  1:20 ` [PATCH v2 0/4] Type2 " Alison Schofield

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=86f1bc50-65ef-4894-a2f0-211ccd394fdc@intel.com \
    --to=dave.jiang@intel.com \
    --cc=alejandro.lucero-palau@amd.com \
    --cc=alucerop@amd.com \
    --cc=davem@davemloft.net \
    --cc=ecree.xilinx@gmail.com \
    --cc=edumazet@google.com \
    --cc=icheng@nvidia.com \
    --cc=kuba@kernel.org \
    --cc=linux-cxl@vger.kernel.org \
    --cc=netdev@vger.kernel.org \
    --cc=pabeni@redhat.com \
    --cc=rafael@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.