Received: by 2002:ac0:aed5:0:0:0:0:0 with SMTP id t21csp214805imb; Thu, 28 Feb 2019 21:41:02 -0800 (PST) X-Google-Smtp-Source: APXvYqxb3QWhfKwqgANWlcqY251u1eYEn1G0bCuCVd2zSwzJCD/XPYxZC787vNVODK0MZwqZtadw X-Received: by 2002:a17:902:4124:: with SMTP id e33mr3641237pld.236.1551418862350; Thu, 28 Feb 2019 21:41:02 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1551418862; cv=none; d=google.com; s=arc-20160816; b=uQh1rUH9SBQOQ1s7FyqfaXP6UgWnGrWWtey/4ysCUI5Ao3wJvJ008fUcdF+hLoljxF wecrF2TSCo6NSfG3Q9znxFRswEheI9JsQz17H+EXPwI8gLhFG6zRQowXb5ohU6yf9a0j hSlQ9FsInjBxEMnsVUtt02U6LuKPEZqrxaCIMkQB3LcuSphcGMC74juUde5Juy30fAcw qXCdXX81G3h5s517dzu94OJfIZMC4m3An8Cl3EV8Hv3E3tja400N+S0vy+WLbP98UiyC 1Lqnkq4Xw0plqMKXEwpMVBRg0hSPOzlzXV4kOKaH3GnR+NPi4zwsJnClVhSuk40kfj65 D0Lw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from; bh=aMHHbfSjVAk3BcbrnxwJtk+1YM7x5O8RxdxXPe+AgJg=; b=mvRqdd2cVsaVI1Dxytx9QVMlhfci3Xb3QJ99lVfIsryJP21phhpeucU4clfOENCOPy bRZP69y25wKK3AC5hDNn9gErPs7K7Mk9QwYKCUNU2o+TVorynIOvUP/OzUSBEgSq9bCn kXoU3KDIgn6oli4W7nD2lfcfKQW+Jd5YMuHSvPyvT69/wDAsDOHvSzhe1MZbPJ3eAxmX LP9ZGpszFL6Dn/XPiYeo78e/bcfJTHwroZj2Xt1uYoTFSrSI1foKYYxpNzMVkicdoolP K4v5XWtKm90kGnSMI4jWN/LySBzZJnXZ4mXg7OYshRBI+gNfX/7lqWtxegBUKEFvSoFG kixw== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=mellanox.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id s4si19926552pgh.540.2019.02.28.21.40.47; Thu, 28 Feb 2019 21:41:02 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=mellanox.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1731854AbfCAFiW (ORCPT + 99 others); Fri, 1 Mar 2019 00:38:22 -0500 Received: from mail-il-dmz.mellanox.com ([193.47.165.129]:42728 "EHLO mellanox.co.il" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1731008AbfCAFiU (ORCPT ); Fri, 1 Mar 2019 00:38:20 -0500 Received: from Internal Mail-Server by MTLPINE1 (envelope-from parav@mellanox.com) with ESMTPS (AES256-SHA encrypted); 1 Mar 2019 07:38:17 +0200 Received: from sw-mtx-036.mtx.labs.mlnx (sw-mtx-036.mtx.labs.mlnx [10.12.150.149]) by labmailer.mlnx (8.13.8/8.13.8) with ESMTP id x215brYb016903; Fri, 1 Mar 2019 07:38:14 +0200 From: Parav Pandit To: netdev@vger.kernel.org, linux-kernel@vger.kernel.org, michal.lkml@markovi.net, davem@davemloft.net, gregkh@linuxfoundation.org, jiri@mellanox.com Cc: parav@mellanox.com Subject: [RFC net-next 6/8] devlink: Add support for devlink subdev lifecycle Date: Thu, 28 Feb 2019 23:37:50 -0600 Message-Id: <1551418672-12822-7-git-send-email-parav@mellanox.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1551418672-12822-1-git-send-email-parav@mellanox.com> References: <1551418672-12822-1-git-send-email-parav@mellanox.com> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Add support for creating and deleting devlink subdevices. For every subdev created on subdev bus, has corresponding devlink device. This devlink device serves the control point for any internal device configuration which is usually required before setting up the protocol specific devices such as netdev, block or infiniband devices. devlink subdev are created using iproute2 devlink tool command such as: (a) create devlink subdev $devlink dev add DEV output: subdev/subdev0 (b) delete a devlink subdev $devlink dev del DEV $devlink dev del subdev/subdev0 Signed-off-by: Parav Pandit --- include/net/devlink.h | 6 ++- include/uapi/linux/devlink.h | 3 ++ net/core/devlink.c | 97 ++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 102 insertions(+), 4 deletions(-) diff --git a/include/net/devlink.h b/include/net/devlink.h index 9a067b1..3265508 100644 --- a/include/net/devlink.h +++ b/include/net/devlink.h @@ -36,6 +36,7 @@ struct devlink { struct device *dev; possible_net_t _net; struct mutex lock; + struct devlink *parent; /* optional if this is child devlink device */ char priv[0] __aligned(NETDEV_ALIGN); }; @@ -524,6 +525,8 @@ struct devlink_ops { int (*flash_update)(struct devlink *devlink, const char *file_name, const char *component, struct netlink_ext_ack *extack); + struct devlink* (*dev_add)(struct devlink *devlink); + void (*dev_del)(struct devlink *del_dev); }; static inline void *devlink_priv(struct devlink *devlink) @@ -545,7 +548,8 @@ static inline struct devlink *priv_to_devlink(void *priv) void devlink_init(struct devlink *devlink, const struct devlink_ops *ops); void devlink_cleanup(struct devlink *devlink); struct devlink *devlink_alloc(const struct devlink_ops *ops, size_t priv_size); -void __devlink_register(struct devlink *devlink, struct device *dev); +int __devlink_register(struct devlink *devlink, struct device *dev, + struct devlink *parent); int devlink_register(struct devlink *devlink, struct device *dev); void __devlink_unregister(struct devlink *devlink); void devlink_unregister(struct devlink *devlink); diff --git a/include/uapi/linux/devlink.h b/include/uapi/linux/devlink.h index 53de880..233f5bc 100644 --- a/include/uapi/linux/devlink.h +++ b/include/uapi/linux/devlink.h @@ -105,6 +105,9 @@ enum devlink_command { DEVLINK_CMD_FLASH_UPDATE, + DEVLINK_CMD_DEV_ADD, + DEVLINK_CMD_DEV_DEL, + /* add new commands above here */ __DEVLINK_CMD_MAX, DEVLINK_CMD_MAX = __DEVLINK_CMD_MAX - 1 diff --git a/net/core/devlink.c b/net/core/devlink.c index cfbad2c..3b5c961 100644 --- a/net/core/devlink.c +++ b/net/core/devlink.c @@ -3759,6 +3759,57 @@ static int devlink_nl_cmd_region_read_dumpit(struct sk_buff *skb, return err; } +static int +devlink_nl_cmd_dev_add_doit(struct sk_buff *skb, struct genl_info *info) +{ + struct devlink *devlink = info->user_ptr[0]; + struct devlink *new_devlink; + struct sk_buff *msg; + int err; + + if (!devlink->ops->dev_add || !devlink->ops->dev_del) + return -EOPNOTSUPP; + + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); + if (!msg) + return -ENOMEM; + + new_devlink = devlink->ops->dev_add(devlink); + if (IS_ERR(new_devlink)) { + err = PTR_ERR(new_devlink); + goto dev_err; + } + + err = devlink_nl_put_handle(msg, new_devlink); + if (err) + goto put_err; + + return genlmsg_reply(msg, info); + +put_err: + devlink->ops->dev_del(new_devlink); +dev_err: + nlmsg_free(msg); + return err; +} + +static int +devlink_nl_cmd_dev_del_doit(struct sk_buff *skb, struct genl_info *info) +{ + struct devlink *devlink; + struct devlink *parent; + + devlink = devlink_get_from_info(info); + if (!devlink) + return -ENODEV; + parent = devlink->parent; + if (!parent) + return -EOPNOTSUPP; + + parent->ops->dev_del(devlink); + return 0; +} + struct devlink_info_req { struct sk_buff *msg; }; @@ -5201,6 +5252,20 @@ static int devlink_nl_cmd_health_reporter_dump_get_doit(struct sk_buff *skb, .flags = GENL_ADMIN_PERM, .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, }, + { + .cmd = DEVLINK_CMD_DEV_ADD, + .doit = devlink_nl_cmd_dev_add_doit, + .policy = devlink_nl_policy, + .flags = GENL_ADMIN_PERM, + .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, + }, + { + .cmd = DEVLINK_CMD_DEV_DEL, + .doit = devlink_nl_cmd_dev_del_doit, + .policy = devlink_nl_policy, + .flags = GENL_ADMIN_PERM, + .internal_flags = DEVLINK_NL_FLAG_NO_LOCK, + }, }; static struct genl_family devlink_nl_family __ro_after_init = { @@ -5266,13 +5331,24 @@ struct devlink *devlink_alloc(const struct devlink_ops *ops, size_t priv_size) * Caller must hold devlink_mutex. * * @devlink: devlink + * @parent: pointer to parent devlink instance for which child devlink + * device is created. It must be set when child devlink + * device is created. It is optional otherwise. */ -void __devlink_register(struct devlink *devlink, struct device *dev) +int __devlink_register(struct devlink *devlink, struct device *dev, + struct devlink *parent) { lockdep_assert_held(&devlink_mutex); + + if (parent && (!parent->ops || !parent->ops->dev_add || + !parent->ops->dev_del)) + return -EINVAL; + devlink->dev = dev; + devlink->parent = parent; list_add_tail(&devlink->list, &devlink_list); devlink_notify(devlink, DEVLINK_CMD_NEW); + return 0; } EXPORT_SYMBOL_GPL(__devlink_register); @@ -5283,13 +5359,27 @@ void __devlink_register(struct devlink *devlink, struct device *dev) */ int devlink_register(struct devlink *devlink, struct device *dev) { + int ret; + mutex_lock(&devlink_mutex); - __devlink_register(devlink, dev); + ret = __devlink_register(devlink, dev, NULL); mutex_unlock(&devlink_mutex); - return 0; + return ret; } EXPORT_SYMBOL_GPL(devlink_register); +static void devlink_child_devices_delete(struct devlink *devlink) +{ + struct devlink *cur, *tmp; + + list_for_each_entry_safe(cur, tmp, &devlink_list, list) { + struct devlink *parent = cur->parent; + + if (devlink == parent) + parent->ops->dev_del(cur); + } +} + /** * __devlink_unregister - Unregister devlink instance * Caller must hold the devlink_mutex while invoking this API. @@ -5299,6 +5389,7 @@ int devlink_register(struct devlink *devlink, struct device *dev) void __devlink_unregister(struct devlink *devlink) { lockdep_assert_held(&devlink_mutex); + devlink_child_devices_delete(devlink); devlink_notify(devlink, DEVLINK_CMD_DEL); list_del(&devlink->list); } -- 1.8.3.1