mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Konstantin Sinyuk <ksinyuk@kernel.org>
To: dri-devel@lists.freedesktop.org
Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>,
	Francois Dugast <francois.dugast@intel.com>,
	David Airlie <airlied@gmail.com>, Simona Vetter <simona@ffwll.ch>,
	Maxime Ripard <mripard@kernel.org>,
	Thomas Zimmermann <tzimmermann@suse.de>,
	Jonathan Corbet <corbet@lwn.net>,
	Shuah Khan <skhan@linuxfoundation.org>,
	Donald Hunter <donald.hunter@gmail.com>,
	Jakub Kicinski <kuba@kernel.org>,
	"David S. Miller" <davem@davemloft.net>,
	Eric Dumazet <edumazet@google.com>,
	Paolo Abeni <pabeni@redhat.com>, Simon Horman <horms@kernel.org>,
	Ilia Levi <ilia.levi@intel.com>,
	Rodrigo Vivi <rodrigo.vivi@intel.com>,
	linux-doc@vger.kernel.org, linux-kselftest@vger.kernel.org,
	netdev@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [RFC PATCH 09/12] drm/fabric: implement mutation netlink operations
Date: Mon, 24 Aug 2026 11:09:37 +0300	[thread overview]
Message-ID: <5b008798364477a2740ebb18544bddfa16f7d512.1787552412.git.ksinyuk@kernel.org> (raw)
In-Reply-To: <cover.1787552412.git.ksinyuk@kernel.org>

Connect the six provisioning operations to the core mutation helpers and
add the generated operation and policy source that dispatches to them.

Resolve and pin mutation targets in pre_doit, run each transaction under
drm_fabric_mutation_lock, call the provider without drm_fabric_lock held,
and release references in post_doit. All six require GENL_ADMIN_PERM and
are confined to init_net.

A failed provider callback returns its error with core state unchanged.
Successful mutations emit notifications after commit, carrying the
resulting topology generation.

Co-developed-by: Ilia Levi <ilia.levi@intel.com>
Signed-off-by: Ilia Levi <ilia.levi@intel.com>
Signed-off-by: Konstantin Sinyuk <ksinyuk@kernel.org>
Assisted-by: GitHub-Copilot:claude-opus-4.8
---
 drivers/gpu/drm/fabric/drm_fabric.c         |   5 +-
 drivers/gpu/drm/fabric/drm_fabric_netlink.c | 275 ++++++++++++++++++++
 drivers/gpu/drm/fabric/drm_fabric_nl.c      | 106 ++++++++
 3 files changed, 384 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/fabric/drm_fabric.c b/drivers/gpu/drm/fabric/drm_fabric.c
index 1aae5ff68798..50c34b4fd722 100644
--- a/drivers/gpu/drm/fabric/drm_fabric.c
+++ b/drivers/gpu/drm/fabric/drm_fabric.c
@@ -793,7 +793,8 @@ int drm_fabric_user_fabric_del(u32 fabric_id)
 		/* Symmetric with FABRIC_NEW: only an empty fabric may be removed. */
 		if (drm_fabric_has_members(fabric))
 			return -EBUSY;
-		drm_fabric_base_seq_inc();
+		/* Notify while the userspace-owned fabric is still addressable by id. */
+		drm_fabric_emit_fabric_delete(fabric, drm_fabric_base_seq_inc());
 		xa_erase(&drm_fabric_xa, fabric->id);
 	}
 
@@ -906,7 +907,7 @@ int drm_fabric_endpoint_set(struct drm_fabric_endpoint *ep,
 		if (change.valid & DRM_FABRIC_EP_CHANGE_ADMIN)
 			ep->admin_state = change.admin;
 
-		drm_fabric_base_seq_inc();
+		drm_fabric_emit_endpoint_change(ep, drm_fabric_base_seq_inc());
 	}
 
 	return 0;
diff --git a/drivers/gpu/drm/fabric/drm_fabric_netlink.c b/drivers/gpu/drm/fabric/drm_fabric_netlink.c
index fef2d4c8f5bb..1a0f293723e9 100644
--- a/drivers/gpu/drm/fabric/drm_fabric_netlink.c
+++ b/drivers/gpu/drm/fabric/drm_fabric_netlink.c
@@ -80,6 +80,7 @@ static int drm_fabric_fill_endpoint(struct sk_buff *skb,
 	    nla_put_u64_64bit(skb, DRM_FABRIC_A_ENDPOINT_ATTRS_FABRIC_EP_ID,
 			      ep->fabric_ep_id, DRM_FABRIC_A_ENDPOINT_ATTRS_PAD) ||
 	    nla_put_string(skb, DRM_FABRIC_A_ENDPOINT_ATTRS_NAME, ep->name) ||
+	    nla_put_u32(skb, DRM_FABRIC_A_ENDPOINT_ATTRS_ADMIN_STATE, ep->admin_state) ||
 	    nla_put_string(skb, DRM_FABRIC_A_ENDPOINT_ATTRS_DEV_NAME,
 			   dev_name(ep->parent)) ||
 	    nla_put_string(skb, DRM_FABRIC_A_ENDPOINT_ATTRS_BUS_NAME,
@@ -132,6 +133,8 @@ static int drm_fabric_fill_port(struct sk_buff *skb,
 	    nla_put_u32(skb, DRM_FABRIC_A_PORT_ATTRS_ENDPOINT_ID, port->endpoint->id) ||
 	    nla_put_u32(skb, DRM_FABRIC_A_PORT_ATTRS_OPER_STATE,
 			port->oper_state) ||
+	    nla_put_u32(skb, DRM_FABRIC_A_PORT_ATTRS_ADMIN_STATE,
+			port->admin_state) ||
 	    nla_put_u32(skb, DRM_FABRIC_A_PORT_ATTRS_MAX_LANE_COUNT,
 			port->max_lane_count) ||
 	    nla_put_u32(skb, DRM_FABRIC_A_PORT_ATTRS_MAX_LANE_SIGNALING_RATE_MBPS,
@@ -846,6 +849,272 @@ int drm_fabric_nl_port_stats_get_dumpit(struct sk_buff *skb,
 	return ret;
 }
 
+/* Fabric create/delete have no target to resolve; only serialize mutation. */
+int drm_fabric_nl_pre_doit(const struct genl_split_ops *ops,
+			   struct sk_buff *skb, struct genl_info *info)
+{
+	int ret = drm_fabric_nl_host_only(genl_info_net(info));
+
+	if (ret)
+		return ret;
+
+	mutex_lock(&drm_fabric_mutation_lock);
+	return 0;
+}
+
+void drm_fabric_nl_post_doit(const struct genl_split_ops *ops,
+			     struct sk_buff *skb, struct genl_info *info)
+{
+	mutex_unlock(&drm_fabric_mutation_lock);
+}
+
+/*
+ * Pin the target in user_ptr[0]. Drop the mutation lock on failure because
+ * post_doit does not run when pre_doit fails.
+ */
+int drm_fabric_nl_endpoint_pre_doit(const struct genl_split_ops *ops,
+				    struct sk_buff *skb, struct genl_info *info)
+{
+	struct drm_fabric_endpoint *ep;
+	int ret = drm_fabric_nl_host_only(genl_info_net(info));
+
+	if (ret)
+		return ret;
+
+	mutex_lock(&drm_fabric_mutation_lock);
+
+	scoped_guard(mutex, &drm_fabric_lock) {
+		ep = drm_fabric_resolve_endpoint(info);
+		if (!IS_ERR(ep))
+			drm_fabric_endpoint_get(ep);
+	}
+
+	if (IS_ERR(ep)) {
+		mutex_unlock(&drm_fabric_mutation_lock);
+		return PTR_ERR(ep);
+	}
+
+	info->user_ptr[0] = ep;
+	return 0;
+}
+
+void drm_fabric_nl_endpoint_post_doit(const struct genl_split_ops *ops,
+				      struct sk_buff *skb,
+				      struct genl_info *info)
+{
+	drm_fabric_endpoint_put(info->user_ptr[0]);
+	mutex_unlock(&drm_fabric_mutation_lock);
+}
+
+int drm_fabric_nl_port_pre_doit(const struct genl_split_ops *ops,
+				struct sk_buff *skb, struct genl_info *info)
+{
+	struct drm_fabric_port *port;
+	u32 ep_id, port_idx;
+	int ret;
+
+	ret = drm_fabric_nl_host_only(genl_info_net(info));
+	if (ret)
+		return ret;
+
+	ret = drm_fabric_port_key(info, &ep_id, &port_idx);
+	if (ret)
+		return ret;
+
+	mutex_lock(&drm_fabric_mutation_lock);
+
+	port = drm_fabric_port_find_get(ep_id, port_idx);
+	if (IS_ERR(port)) {
+		mutex_unlock(&drm_fabric_mutation_lock);
+		return PTR_ERR(port);
+	}
+
+	info->user_ptr[0] = port;
+	return 0;
+}
+
+void drm_fabric_nl_port_post_doit(const struct genl_split_ops *ops,
+				  struct sk_buff *skb, struct genl_info *info)
+{
+	drm_fabric_port_put(info->user_ptr[0]);
+	mutex_unlock(&drm_fabric_mutation_lock);
+}
+
+/* A nested policy cannot mark members required; check type and instance-id here. */
+static int drm_fabric_parse_new_params(struct genl_info *info,
+					enum drm_fabric_type *type,
+					const char **name, u64 *instance_id)
+{
+	struct nlattr *pa[DRM_FABRIC_A_FABRIC_NEW_PARAMS_MAX + 1];
+	struct nlattr *nest;
+	int ret;
+
+	if (GENL_REQ_ATTR_CHECK(info, DRM_FABRIC_A_FABRIC_NEW_PARAMS))
+		return -EINVAL;
+
+	nest = info->attrs[DRM_FABRIC_A_FABRIC_NEW_PARAMS];
+	ret = nla_parse_nested(pa, DRM_FABRIC_A_FABRIC_NEW_PARAMS_MAX, nest,
+			       drm_fabric_fabric_new_params_nl_policy,
+			       info->extack);
+	if (ret)
+		return ret;
+
+	if (NL_REQ_ATTR_CHECK(info->extack, nest, pa,
+			      DRM_FABRIC_A_FABRIC_NEW_PARAMS_TYPE) ||
+	    NL_REQ_ATTR_CHECK(info->extack, nest, pa,
+			      DRM_FABRIC_A_FABRIC_NEW_PARAMS_INSTANCE_ID))
+		return -EINVAL;
+
+	*type = nla_get_u32(pa[DRM_FABRIC_A_FABRIC_NEW_PARAMS_TYPE]);
+	*instance_id = nla_get_u64(pa[DRM_FABRIC_A_FABRIC_NEW_PARAMS_INSTANCE_ID]);
+	*name = pa[DRM_FABRIC_A_FABRIC_NEW_PARAMS_NAME] ?
+		nla_data(pa[DRM_FABRIC_A_FABRIC_NEW_PARAMS_NAME]) : NULL;
+	return 0;
+}
+
+int drm_fabric_nl_fabric_new_doit(struct sk_buff *skb,
+				  struct genl_info *info)
+{
+	enum drm_fabric_type type;
+	const char *name = NULL;
+	u64 instance_id;
+	struct sk_buff *msg;
+	struct nlattr *id_attr;
+	u32 fabric_id;
+	void *hdr;
+	int ret;
+
+	ret = drm_fabric_parse_new_params(info, &type, &name, &instance_id);
+	if (ret)
+		return ret;
+
+	/*
+	 * Reserve the id attribute before publishing: with the space already
+	 * committed the store cannot fail, so there is no create-then-withdraw
+	 * window.
+	 */
+	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
+	if (!msg)
+		return -ENOMEM;
+
+	hdr = genlmsg_put(msg, info->snd_portid, info->snd_seq,
+			  &drm_fabric_nl_family, 0,
+			  DRM_FABRIC_CMD_FABRIC_NEW);
+	if (!hdr) {
+		nlmsg_free(msg);
+		return -EMSGSIZE;
+	}
+
+	id_attr = nla_reserve(msg, DRM_FABRIC_A_FABRIC_ID, sizeof(u32));
+	if (!id_attr) {
+		nlmsg_free(msg);
+		return -EMSGSIZE;
+	}
+
+	ret = drm_fabric_user_fabric_new(type, instance_id, name, &fabric_id);
+	if (ret) {
+		nlmsg_free(msg);
+		return ret;
+	}
+
+	/* nla_put_u32() copies a host-order u32 verbatim; so does this store. */
+	*(u32 *)nla_data(id_attr) = fabric_id;
+
+	genlmsg_end(msg, hdr);
+	return genlmsg_reply(msg, info);
+}
+
+int drm_fabric_nl_fabric_del_doit(struct sk_buff *skb,
+				  struct genl_info *info)
+{
+	u32 fabric_id;
+
+	if (GENL_REQ_ATTR_CHECK(info, DRM_FABRIC_A_FABRIC_ID))
+		return -EINVAL;
+
+	fabric_id = nla_get_u32(info->attrs[DRM_FABRIC_A_FABRIC_ID]);
+	return drm_fabric_user_fabric_del(fabric_id);
+}
+
+int drm_fabric_nl_endpoint_set_doit(struct sk_buff *skb,
+				    struct genl_info *info)
+{
+	struct drm_fabric_endpoint *ep = info->user_ptr[0];
+	struct drm_fabric_endpoint_change change = {};
+
+	if (info->attrs[DRM_FABRIC_A_FABRIC_ID]) {
+		change.valid |= DRM_FABRIC_EP_CHANGE_FABRIC;
+		change.fabric_id =
+			nla_get_u32(info->attrs[DRM_FABRIC_A_FABRIC_ID]);
+	}
+
+	if (info->attrs[DRM_FABRIC_A_ADMIN_STATE]) {
+		change.valid |= DRM_FABRIC_EP_CHANGE_ADMIN;
+		change.admin =
+			nla_get_u32(info->attrs[DRM_FABRIC_A_ADMIN_STATE]);
+	}
+
+	if (!change.valid)
+		return -EINVAL;
+
+	return drm_fabric_endpoint_set(ep, &change);
+}
+
+int drm_fabric_nl_port_set_doit(struct sk_buff *skb,
+				struct genl_info *info)
+{
+	struct drm_fabric_port *port = info->user_ptr[0];
+	enum drm_fabric_admin_state admin;
+
+	if (GENL_REQ_ATTR_CHECK(info, DRM_FABRIC_A_ADMIN_STATE))
+		return -EINVAL;
+
+	admin = nla_get_u32(info->attrs[DRM_FABRIC_A_ADMIN_STATE]);
+
+	return drm_fabric_port_set_admin(port, admin);
+}
+
+int drm_fabric_nl_port_peer_new_doit(struct sk_buff *skb,
+				     struct genl_info *info)
+{
+	struct drm_fabric_port *port = info->user_ptr[0];
+	struct nlattr *pa[DRM_FABRIC_A_PEER_ATTRS_MAX + 1];
+	struct drm_fabric_peer peer = {};
+	int ret;
+
+	if (GENL_REQ_ATTR_CHECK(info, DRM_FABRIC_A_PEER))
+		return -EINVAL;
+
+	ret = nla_parse_nested(pa, DRM_FABRIC_A_PEER_ATTRS_MAX,
+			       info->attrs[DRM_FABRIC_A_PEER],
+			       drm_fabric_peer_nl_policy, info->extack);
+	if (ret)
+		return ret;
+
+	/*
+	 * A nested policy cannot require members; require the complete peer
+	 * descriptor here.
+	 */
+	if (!pa[DRM_FABRIC_A_PEER_ATTRS_PEER_ID] ||
+	    !pa[DRM_FABRIC_A_PEER_ATTRS_TYPE] ||
+	    !pa[DRM_FABRIC_A_PEER_ATTRS_PORT_INDEX])
+		return -EINVAL;
+
+	peer.peer_id = nla_get_u64(pa[DRM_FABRIC_A_PEER_ATTRS_PEER_ID]);
+	peer.peer_type = nla_get_u32(pa[DRM_FABRIC_A_PEER_ATTRS_TYPE]);
+	peer.port_index = nla_get_u32(pa[DRM_FABRIC_A_PEER_ATTRS_PORT_INDEX]);
+
+	return drm_fabric_port_peer_new(port, &peer);
+}
+
+int drm_fabric_nl_port_peer_del_doit(struct sk_buff *skb,
+				     struct genl_info *info)
+{
+	struct drm_fabric_port *port = info->user_ptr[0];
+
+	return drm_fabric_port_peer_del(port);
+}
+
 void drm_fabric_emit_port_change(struct drm_fabric_port *port, u32 generation)
 {
 	struct sk_buff *msg;
@@ -982,6 +1251,12 @@ void drm_fabric_emit_endpoint_delete(struct drm_fabric_endpoint *ep, u32 generat
 				       generation);
 }
 
+void drm_fabric_emit_endpoint_change(struct drm_fabric_endpoint *ep, u32 generation)
+{
+	drm_fabric_endpoint_event_send(DRM_FABRIC_CMD_ENDPOINT_CHANGE_NTF, ep,
+				       generation);
+}
+
 static void drm_fabric_fabric_event_send(enum drm_fabric_cmd cmd,
 					 struct drm_fabric *fabric,
 					 u32 generation)
diff --git a/drivers/gpu/drm/fabric/drm_fabric_nl.c b/drivers/gpu/drm/fabric/drm_fabric_nl.c
index 032548405146..20b277f27ae9 100644
--- a/drivers/gpu/drm/fabric/drm_fabric_nl.c
+++ b/drivers/gpu/drm/fabric/drm_fabric_nl.c
@@ -11,6 +11,19 @@
 
 #include <uapi/drm/drm_fabric.h>
 
+/* Common nested types */
+const struct nla_policy drm_fabric_fabric_new_params_nl_policy[DRM_FABRIC_A_FABRIC_NEW_PARAMS_INSTANCE_ID + 1] = {
+	[DRM_FABRIC_A_FABRIC_NEW_PARAMS_TYPE] = NLA_POLICY_RANGE(NLA_U32, 1, 1),
+	[DRM_FABRIC_A_FABRIC_NEW_PARAMS_NAME] = { .type = NLA_NUL_STRING, .len = 31, },
+	[DRM_FABRIC_A_FABRIC_NEW_PARAMS_INSTANCE_ID] = { .type = NLA_U64, },
+};
+
+const struct nla_policy drm_fabric_peer_nl_policy[DRM_FABRIC_A_PEER_ATTRS_PORT_INDEX + 1] = {
+	[DRM_FABRIC_A_PEER_ATTRS_PEER_ID] = { .type = NLA_U64, },
+	[DRM_FABRIC_A_PEER_ATTRS_TYPE] = NLA_POLICY_RANGE(NLA_U32, 1, 2),
+	[DRM_FABRIC_A_PEER_ATTRS_PORT_INDEX] = { .type = NLA_U32, },
+};
+
 /* DRM_FABRIC_CMD_FABRIC_GET - do */
 static const struct nla_policy drm_fabric_fabric_get_nl_policy[DRM_FABRIC_A_FABRIC_ID + 1] = {
 	[DRM_FABRIC_A_FABRIC_ID] = { .type = NLA_U32, },
@@ -50,6 +63,45 @@ static const struct nla_policy drm_fabric_port_stats_get_dump_nl_policy[DRM_FABR
 	[DRM_FABRIC_A_ENDPOINT_ID] = { .type = NLA_U32, },
 };
 
+/* DRM_FABRIC_CMD_FABRIC_NEW - do */
+static const struct nla_policy drm_fabric_fabric_new_nl_policy[DRM_FABRIC_A_FABRIC_NEW_PARAMS + 1] = {
+	[DRM_FABRIC_A_FABRIC_NEW_PARAMS] = NLA_POLICY_NESTED(drm_fabric_fabric_new_params_nl_policy),
+};
+
+/* DRM_FABRIC_CMD_FABRIC_DEL - do */
+static const struct nla_policy drm_fabric_fabric_del_nl_policy[DRM_FABRIC_A_FABRIC_ID + 1] = {
+	[DRM_FABRIC_A_FABRIC_ID] = { .type = NLA_U32, },
+};
+
+/* DRM_FABRIC_CMD_ENDPOINT_SET - do */
+static const struct nla_policy drm_fabric_endpoint_set_nl_policy[DRM_FABRIC_A_ADMIN_STATE + 1] = {
+	[DRM_FABRIC_A_ENDPOINT_ID] = { .type = NLA_U32, },
+	[DRM_FABRIC_A_DEV_NAME] = { .type = NLA_NUL_STRING, },
+	[DRM_FABRIC_A_BUS_NAME] = { .type = NLA_NUL_STRING, },
+	[DRM_FABRIC_A_FABRIC_ID] = { .type = NLA_U32, },
+	[DRM_FABRIC_A_ADMIN_STATE] = NLA_POLICY_RANGE(NLA_U32, 1, 2),
+};
+
+/* DRM_FABRIC_CMD_PORT_SET - do */
+static const struct nla_policy drm_fabric_port_set_nl_policy[DRM_FABRIC_A_ADMIN_STATE + 1] = {
+	[DRM_FABRIC_A_ENDPOINT_ID] = { .type = NLA_U32, },
+	[DRM_FABRIC_A_PORT_INDEX] = { .type = NLA_U32, },
+	[DRM_FABRIC_A_ADMIN_STATE] = NLA_POLICY_RANGE(NLA_U32, 1, 2),
+};
+
+/* DRM_FABRIC_CMD_PORT_PEER_NEW - do */
+static const struct nla_policy drm_fabric_port_peer_new_nl_policy[DRM_FABRIC_A_PEER + 1] = {
+	[DRM_FABRIC_A_ENDPOINT_ID] = { .type = NLA_U32, },
+	[DRM_FABRIC_A_PORT_INDEX] = { .type = NLA_U32, },
+	[DRM_FABRIC_A_PEER] = NLA_POLICY_NESTED(drm_fabric_peer_nl_policy),
+};
+
+/* DRM_FABRIC_CMD_PORT_PEER_DEL - do */
+static const struct nla_policy drm_fabric_port_peer_del_nl_policy[DRM_FABRIC_A_PORT_INDEX + 1] = {
+	[DRM_FABRIC_A_ENDPOINT_ID] = { .type = NLA_U32, },
+	[DRM_FABRIC_A_PORT_INDEX] = { .type = NLA_U32, },
+};
+
 /* Ops table for drm_fabric */
 static const struct genl_split_ops drm_fabric_nl_ops[] = {
 	{
@@ -106,6 +158,60 @@ static const struct genl_split_ops drm_fabric_nl_ops[] = {
 		.maxattr	= DRM_FABRIC_A_ENDPOINT_ID,
 		.flags		= GENL_CMD_CAP_DUMP,
 	},
+	{
+		.cmd		= DRM_FABRIC_CMD_FABRIC_NEW,
+		.pre_doit	= drm_fabric_nl_pre_doit,
+		.doit		= drm_fabric_nl_fabric_new_doit,
+		.post_doit	= drm_fabric_nl_post_doit,
+		.policy		= drm_fabric_fabric_new_nl_policy,
+		.maxattr	= DRM_FABRIC_A_FABRIC_NEW_PARAMS,
+		.flags		= GENL_ADMIN_PERM | GENL_CMD_CAP_DO,
+	},
+	{
+		.cmd		= DRM_FABRIC_CMD_FABRIC_DEL,
+		.pre_doit	= drm_fabric_nl_pre_doit,
+		.doit		= drm_fabric_nl_fabric_del_doit,
+		.post_doit	= drm_fabric_nl_post_doit,
+		.policy		= drm_fabric_fabric_del_nl_policy,
+		.maxattr	= DRM_FABRIC_A_FABRIC_ID,
+		.flags		= GENL_ADMIN_PERM | GENL_CMD_CAP_DO,
+	},
+	{
+		.cmd		= DRM_FABRIC_CMD_ENDPOINT_SET,
+		.pre_doit	= drm_fabric_nl_endpoint_pre_doit,
+		.doit		= drm_fabric_nl_endpoint_set_doit,
+		.post_doit	= drm_fabric_nl_endpoint_post_doit,
+		.policy		= drm_fabric_endpoint_set_nl_policy,
+		.maxattr	= DRM_FABRIC_A_ADMIN_STATE,
+		.flags		= GENL_ADMIN_PERM | GENL_CMD_CAP_DO,
+	},
+	{
+		.cmd		= DRM_FABRIC_CMD_PORT_SET,
+		.pre_doit	= drm_fabric_nl_port_pre_doit,
+		.doit		= drm_fabric_nl_port_set_doit,
+		.post_doit	= drm_fabric_nl_port_post_doit,
+		.policy		= drm_fabric_port_set_nl_policy,
+		.maxattr	= DRM_FABRIC_A_ADMIN_STATE,
+		.flags		= GENL_ADMIN_PERM | GENL_CMD_CAP_DO,
+	},
+	{
+		.cmd		= DRM_FABRIC_CMD_PORT_PEER_NEW,
+		.pre_doit	= drm_fabric_nl_port_pre_doit,
+		.doit		= drm_fabric_nl_port_peer_new_doit,
+		.post_doit	= drm_fabric_nl_port_post_doit,
+		.policy		= drm_fabric_port_peer_new_nl_policy,
+		.maxattr	= DRM_FABRIC_A_PEER,
+		.flags		= GENL_ADMIN_PERM | GENL_CMD_CAP_DO,
+	},
+	{
+		.cmd		= DRM_FABRIC_CMD_PORT_PEER_DEL,
+		.pre_doit	= drm_fabric_nl_port_pre_doit,
+		.doit		= drm_fabric_nl_port_peer_del_doit,
+		.post_doit	= drm_fabric_nl_port_post_doit,
+		.policy		= drm_fabric_port_peer_del_nl_policy,
+		.maxattr	= DRM_FABRIC_A_PORT_INDEX,
+		.flags		= GENL_ADMIN_PERM | GENL_CMD_CAP_DO,
+	},
 };
 
 static const struct genl_multicast_group drm_fabric_nl_mcgrps[] = {
-- 
2.43.0


  parent reply	other threads:[~2026-08-24  8:10 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-24  8:09 [RFC PATCH 0/12] drm/fabric: vendor-neutral topology infrastructure for scale-up accelerator interconnects Konstantin Sinyuk
2026-08-24  8:09 ` [RFC PATCH 01/12] drm/fabric: add core object model and provider API Konstantin Sinyuk
2026-08-24  8:09 ` [RFC PATCH 02/12] drm/fabric: add query uAPI and generated headers Konstantin Sinyuk
2026-08-24  8:09 ` [RFC PATCH 03/12] drm/fabric: implement query netlink operations Konstantin Sinyuk
2026-08-24  8:09 ` [RFC PATCH 04/12] drm/fabric: add read-only synthetic provider Konstantin Sinyuk
2026-08-24  8:09 ` [RFC PATCH 05/12] drm/fabric: add object-model KUnit tests Konstantin Sinyuk
2026-08-24  8:09 ` [RFC PATCH 06/12] drm/fabric: add YNL query and policy selftests Konstantin Sinyuk
2026-08-24  8:09 ` [RFC PATCH 07/12] drm/fabric: add topology-provisioning core Konstantin Sinyuk
2026-08-24  8:09 ` [RFC PATCH 08/12] drm/fabric: add provisioning netlink uAPI Konstantin Sinyuk
2026-08-24  8:09 ` Konstantin Sinyuk [this message]
2026-08-24  8:09 ` [RFC PATCH 10/12] drm/fabric: make the synthetic provider writable Konstantin Sinyuk
2026-08-24  8:09 ` [RFC PATCH 11/12] drm/fabric: add mutation KUnit tests Konstantin Sinyuk
2026-08-24  8:09 ` [RFC PATCH 12/12] drm/fabric: add mutation netlink selftests Konstantin Sinyuk
2026-08-26  9:32 ` [RFC PATCH 0/12] drm/fabric: vendor-neutral topology infrastructure for scale-up accelerator interconnects Leon Romanovsky
2026-08-26 15:38   ` Konstantin Sinyuk
2026-08-27 17:09     ` Leon Romanovsky
2026-08-28 16:13       ` Rodrigo Vivi
2026-08-27 12:35 ` Jiri Pirko
2026-08-28 16:28   ` Rodrigo Vivi
2026-08-28 17:03     ` Jason Gunthorpe

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=5b008798364477a2740ebb18544bddfa16f7d512.1787552412.git.ksinyuk@kernel.org \
    --to=ksinyuk@kernel.org \
    --cc=airlied@gmail.com \
    --cc=corbet@lwn.net \
    --cc=davem@davemloft.net \
    --cc=donald.hunter@gmail.com \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=edumazet@google.com \
    --cc=francois.dugast@intel.com \
    --cc=horms@kernel.org \
    --cc=ilia.levi@intel.com \
    --cc=kuba@kernel.org \
    --cc=linux-doc@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-kselftest@vger.kernel.org \
    --cc=maarten.lankhorst@linux.intel.com \
    --cc=mripard@kernel.org \
    --cc=netdev@vger.kernel.org \
    --cc=pabeni@redhat.com \
    --cc=rodrigo.vivi@intel.com \
    --cc=simona@ffwll.ch \
    --cc=skhan@linuxfoundation.org \
    --cc=tzimmermann@suse.de \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®