From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from szelinsky.de (szelinsky.de [85.214.127.56]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7CCCC3F23CF; Sun, 27 Sep 2026 19:19:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=85.214.127.56 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790536759; cv=none; b=sMES9YKNo9r8ZlqFg0dSkKf3xxAdCaJvD2FuytOu7vte2AXMkx7L4zsOAGbjEcfTCRAlN6XapZsy60XggDKKlUC8sahOL2YrwYle+2S8OFC6BZUSpfUTL/7SQE2ZBpspkz2o7MpCytdNVCoYIb2sVYJTzWIjLYyvb3fya5WVYp8= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790536759; c=relaxed/simple; bh=IDmmi+7J149wO/JMaeH8+aCq0zKkokDoiRYDinEvlvo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=nXbIATIj55Wt027jIXJo02GAG2ji3fKYMQUQGZ0mIb3spgX5PhC5gu8BKUFyJY5YRnPGcNtbZtwqArxxZrinsz3h6Si8OEnbujqaS5vYlMbTDu0eADbao3drlEhDzx9HziWFhRD/LzYbRT2o5Fpetu5Al6VvPakZQ+b/x022LTM= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=szelinsky.de; spf=pass smtp.mailfrom=szelinsky.de; dkim=temperror (0-bit key) header.d=szelinsky.de header.i=@szelinsky.de header.b=kOcK2GRw; arc=none smtp.client-ip=85.214.127.56 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=szelinsky.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=szelinsky.de Authentication-Results: smtp.subspace.kernel.org; dkim=temperror (0-bit key) header.d=szelinsky.de header.i=@szelinsky.de header.b="kOcK2GRw" Received: from localhost (localhost [127.0.0.1]) by szelinsky.de (Postfix) with ESMTP id 374A9E839CD; Sun, 27 Sep 2026 21:19:15 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=szelinsky.de; s=mail; t=1790536755; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=upkv3HPkC1NiRDWGYGA5elk+6m9OQm69gi4ZDs/va5A=; b=kOcK2GRwnTfKGxym5us7hkUsH35NueH6roMiiEiOp6xHYchEs5+UxD4g2jIQAggS3wSGJP t46s0uMDcaTTdHpK8/u7wpWU/2fyEahLpNbuWKeGIM/gLH5jus2hqZWV8Kfa4yGCrJkhc/ EqNelhlURk6/aBR+0krrndoIuNRQlhTh1JjxPCJTFtfsx261IZVnHMDKszDLZg/aob9I2v 6jfDUb7eynCIsnSbF+IhKId50stR4v2YvjjB/gdPkzpzqi7zcCNDsnaspRFawlUatKhk8s +vLGQsW2TajhAZEWbDuJ/erN3Tm41sMai8j+ikuLiM7abBTMnBuLx63p5l19EQ== X-Virus-Scanned: Debian amavis at szelinsky.de Received: from szelinsky.de ([127.0.0.1]) by localhost (szelinsky.de [127.0.0.1]) (amavis, port 10025) with ESMTP id cZV6ZF8Td6Lr; Sun, 27 Sep 2026 21:19:15 +0200 (CEST) Received: from p14sgen5.. (ip-077-020-250-175.vkd66.pools.vodafone-ip.de [77.20.250.175]) by szelinsky.de (Postfix) with ESMTPSA; Sun, 27 Sep 2026 21:19:14 +0200 (CEST) From: Carlo Szelinsky To: Oleksij Rempel , Kory Maincent , Andrew Lunn , Heiner Kallweit , Russell King , "David S . Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni Cc: Corey Leavitt , Jonas Jelonek , Simon Horman , Aleksander Jan Bajkowski , Mark Brown , Liam Girdwood , netdev-bot+sashiko@kernel.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org, Carlo Szelinsky Subject: [PATCH net-next v7 1/5] net: pse-pd: add notifier chain for controller lifecycle events Date: Sun, 27 Sep 2026 21:18:46 +0200 Message-ID: <20260927191850.1370515-2-github@szelinsky.de> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260927191850.1370515-1-github@szelinsky.de> References: <20260927191850.1370515-1-github@szelinsky.de> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit From: Corey Leavitt Introduce a blocking notifier chain that allows other subsystems to be informed when a PSE controller is registered or unregistered, and provide pse_register_notifier() / pse_unregister_notifier() as the subscriber interface. Subsequent patches will use this to let the phy subsystem own the phydev->psec lifecycle directly, decoupling PSE lookup from fwnode_mdiobus_register_phy() and removing the probe-time -EPROBE_DEFER coupling that currently exists between mdio, phy and pse-pd when the PSE controller driver is modular. A blocking chain (rather than atomic) is used because callbacks sleep. The phy subscriber added later takes a mutex, and of_pse_control_get() reaches the controller over i2c. The contract also lets a subscriber take rtnl, which is why a controller driver must not hold it across pse_controller_register() or pse_controller_unregister(). The enum pse_controller_event is placed outside the IS_ENABLED(CONFIG_PSE_CONTROLLER) guard so that subscribers compiled into a kernel without PSE support can still reference the event values in dead-code paths without breaking the build. This patch is pure infrastructure: nothing fires events yet, and nothing subscribes. No observable behavior change. Signed-off-by: Corey Leavitt Signed-off-by: Carlo Szelinsky Tested-by: Jonas Jelonek --- drivers/net/pse-pd/pse_core.c | 34 ++++++++++++++++++++++++++++++++++ include/linux/pse-pd/pse.h | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+) diff --git a/drivers/net/pse-pd/pse_core.c b/drivers/net/pse-pd/pse_core.c index a5e6d7b26b9f..84c734ed4553 100644 --- a/drivers/net/pse-pd/pse_core.c +++ b/drivers/net/pse-pd/pse_core.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -23,6 +24,39 @@ static LIST_HEAD(pse_controller_list); static DEFINE_XARRAY_ALLOC(pse_pw_d_map); static DEFINE_MUTEX(pse_pw_d_mutex); +static BLOCKING_NOTIFIER_HEAD(pse_controller_notifier); + +/** + * pse_register_notifier - register a callback for PSE controller events + * @nb: notifier block to register + * + * See enum pse_controller_event for events fired and their subscriber + * contract. Callbacks run in process context; they may sleep, take + * rtnl, and call of_pse_control_get(). The chain fires synchronously, + * so a PSE controller driver's probe/unbind path must not hold any + * such lock when calling pse_controller_register() or + * pse_controller_unregister(). + * + * Return: 0 on success, negative error code otherwise. + */ +int pse_register_notifier(struct notifier_block *nb) +{ + return blocking_notifier_chain_register(&pse_controller_notifier, nb); +} +EXPORT_SYMBOL_GPL(pse_register_notifier); + +/** + * pse_unregister_notifier - unregister a previously registered callback + * @nb: notifier block previously passed to pse_register_notifier() + * + * Return: 0 on success, negative error code otherwise. + */ +int pse_unregister_notifier(struct notifier_block *nb) +{ + return blocking_notifier_chain_unregister(&pse_controller_notifier, nb); +} +EXPORT_SYMBOL_GPL(pse_unregister_notifier); + /** * struct pse_control - a PSE control * @pcdev: a pointer to the PSE controller device diff --git a/include/linux/pse-pd/pse.h b/include/linux/pse-pd/pse.h index 4e5696cfade7..bc5d36bcd993 100644 --- a/include/linux/pse-pd/pse.h +++ b/include/linux/pse-pd/pse.h @@ -21,6 +21,7 @@ struct net_device; struct phy_device; struct pse_controller_dev; struct netlink_ext_ack; +struct notifier_block; /* C33 PSE extended state and substate. */ struct ethtool_c33_pse_ext_state_info { @@ -337,6 +338,25 @@ enum pse_budget_eval_strategies { PSE_BUDGET_EVAL_STRAT_DYNAMIC = 1 << 2, }; +/** + * enum pse_controller_event - PSE controller lifecycle events + * + * Event data in callbacks is always a pointer to the struct + * pse_controller_dev firing the event. + * + * @PSE_REGISTERED: controller added to pse_controller_list and + * resolvable by of_pse_control_get(). + * @PSE_UNREGISTERED: controller already taken off pse_controller_list, so + * no longer resolvable, but still valid to dereference for the + * duration of the callback. Subscribers holding pse_control + * references targeting it must drop them before returning and must + * not acquire new references for it. + */ +enum pse_controller_event { + PSE_REGISTERED, + PSE_UNREGISTERED, +}; + #if IS_ENABLED(CONFIG_PSE_CONTROLLER) int pse_controller_register(struct pse_controller_dev *pcdev); void pse_controller_unregister(struct pse_controller_dev *pcdev); @@ -366,6 +386,9 @@ int pse_ethtool_set_prio(struct pse_control *psec, bool pse_has_podl(struct pse_control *psec); bool pse_has_c33(struct pse_control *psec); +int pse_register_notifier(struct notifier_block *nb); +int pse_unregister_notifier(struct notifier_block *nb); + #else static inline struct pse_control *of_pse_control_get(struct device_node *node, @@ -416,6 +439,16 @@ static inline bool pse_has_c33(struct pse_control *psec) return false; } +static inline int pse_register_notifier(struct notifier_block *nb) +{ + return 0; +} + +static inline int pse_unregister_notifier(struct notifier_block *nb) +{ + return 0; +} + #endif #endif -- 2.43.0