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 AD826390233; Sat, 20 Jun 2026 11:25:29 +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=1781954731; cv=none; b=WQembcmX3RMONeSiClXm9TXNd0NTMWTENh1Ohaofc7YmltINiTgFv3LP4tHhh8G2OuJmKFC1xJzHsBSxL2TcfqlPLWJBY95FEQTU1G2oCjCiT/P5UMactEOzOTvza7ILqm/3V8ltGReF6XLCjm75GFGAcU9754pHEfZA/Zjy9Lo= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1781954731; c=relaxed/simple; bh=mrFFxkLN19cs5V9GGb+1fWyNRpuBEhfkohqbXApaVi8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=DtwqFfmptTJQZUqWzVfqgvo94vHH5oL5Gt7efy+hLqIAXIUt1Sp4VdCHnN6Y1qOF0rJum76kbM8kvxdg8IUbXTE5MZKIMZZttjEibX0Kfe/lDKwzOk8Z3BGUTmF5Qp0Lcw8GaK6ngZ4YsVVy+1jPAkkeKg+e8yjOP+XHWAkUP4s= 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=hEdhVEOJ; 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="hEdhVEOJ" Received: from localhost (localhost [127.0.0.1]) by szelinsky.de (Postfix) with ESMTP id F1F0CE837CA; Sat, 20 Jun 2026 13:25:27 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=szelinsky.de; s=mail; t=1781954728; 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=mI9IzuuOTJ4zfJMwEn9HzWqhaOIT0kxXEPTQjGt58us=; b=hEdhVEOJPNnd4jrFG+ejhtgd1wYyDROy65iSRMyekozPlGMIjO7Tip/FEcLJEhX+tdJb94 L6nKJl4UJjlvMXkRSZO4zCr9xEpT5JLHhGTZ6me7CUGqVH/9zfCdjShJoQLtZcQOSNiXJR Re52dpc+Yk3/zVL6X7ZhnWOLVrtl4Cuwr9dYyh7yzVrI7/FgHHeOSMdyxImFqgTaq1LaZN XggdiS+29PrUO74v9L5L8IX80pZh3hdThEiziWVd+AMvcXWlQageLBxBal4qUWL/BDnonw xULBYp+2NVgaDZDKCkI/C+lNVqUjbrbh/czndGeU7I+riMgvTj/9ID2wt/qRpA== 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 ymvqNL6gRvE5; Sat, 20 Jun 2026 13:25:27 +0200 (CEST) Received: from p14sgen5.lanhh (dslb-002-205-089-174.002.205.pools.vodafone-ip.de [2.205.89.174]) by szelinsky.de (Postfix) with ESMTPSA; Sat, 20 Jun 2026 13:25:27 +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 , netdev@vger.kernel.org, linux-kernel@vger.kernel.org, Carlo Szelinsky Subject: [PATCH net-next v2 2/4] net: pse-pd: add notifier chain for controller lifecycle events Date: Sat, 20 Jun 2026 13:24:38 +0200 Message-ID: <20260620112440.1734404-3-github@szelinsky.de> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260620112440.1734404-1-github@szelinsky.de> References: <20260423-pse-notifier-decouple-v1-0-86ed750a9d62@leavitt.info> <20260620112440.1734404-1-github@szelinsky.de> Precedence: bulk X-Mailing-List: netdev@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 will take rtnl_lock and call back into pse_core via of_pse_control_get(). 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 --- drivers/net/pse-pd/pse_core.c | 34 ++++++++++++++++++++++++++++++++++ include/linux/pse-pd/pse.h | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 66 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..78fe3a2b1ea8 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,24 @@ 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 about to be removed from + * pse_controller_list. 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 +385,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 +438,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