From patchwork Thu Apr 25 13:59:53 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiri Pirko X-Patchwork-Id: 1090852 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=resnulli.us Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=resnulli-us.20150623.gappssmtp.com header.i=@resnulli-us.20150623.gappssmtp.com header.b="jsaD2PAL"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 44qf2x1Kf3z9s7T for ; Fri, 26 Apr 2019 00:00:25 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729274AbfDYOAY (ORCPT ); Thu, 25 Apr 2019 10:00:24 -0400 Received: from mail-wm1-f68.google.com ([209.85.128.68]:34864 "EHLO mail-wm1-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728969AbfDYOAS (ORCPT ); Thu, 25 Apr 2019 10:00:18 -0400 Received: by mail-wm1-f68.google.com with SMTP id y197so10784491wmd.0 for ; Thu, 25 Apr 2019 07:00:16 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=resnulli-us.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=u4lNmHq1KKBP6qtL97jsUSkSMSw7zlVFCMQwrmDmkvQ=; b=jsaD2PAL6EJltSG8GSN3uC9GCiFYeAqqQQLrH0VkK7suSoqUXRe65G++Q9sUd2ajso 1h9ecHp1WOHJ7DTGWrHWKJnCUGRoSgl8rJxmVx3/2UcmRh40l6zKJjyC0lpQl9jqjb3i eCEIkkD7xYGoBBkOu8gtQKSRYNO6K8ITYYgkDaZYsXBLn7VR/J6+tJiI9At9iFhS54lk YDdhI7Ejop+ERfNu+6xfuRuHAGfbtOGE8IUQBZ99r/P65vVIMUjnEhV7dcbZoyE/4VJe Rq4BPFq4/JACNnvJEYg6SQq7XbKps7XhixCYlu5cKgYO1LnJzdUUVHbsvmPNeAMzdmhf NpsQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=u4lNmHq1KKBP6qtL97jsUSkSMSw7zlVFCMQwrmDmkvQ=; b=NzNHG0iElAKJ+fBSZngt8No9APyi1KcIwU+SxoD0pIjP1/xylzlukj82dICcBHWV4e aXOq+VTEhuE92AecKjVohj7lzC637n+Goj5BvasQYRbxMf5C8J3iruqrcGS+PB2BAB4t DjiS6y3mxP1aKdr5DpxIy7/4mmgpsUIdQsqtwGhixikS09194idsBlzwfW372oOqBbyV fotESH/IZQDIHCqTRVGLUMpOOXVF1qbvq4YM+OH+KXg6lx9mFxcLi1dS/l1RzZsZJRij 0/nTbP1WWNirVkZ2Iru+esvIdJ+Nkv7nJUEWvjOGRUBqSX6CPRjU2M0EHST/xFyiWJay 4j1g== X-Gm-Message-State: APjAAAUJU2HYnktg+afyXHXIzMtRPiEUJ43T4poIja0dk9uwQro1BLIq O3E/XBFGUBcCmknyo+mnEGIzaj5fe2g= X-Google-Smtp-Source: APXvYqykQ2hsKj9APtq8E2T2dwT0pQIJt2D/C/bxSJdkKMrDf6eRnZp+/4aLGXuP3QIQ6/h1i82qkQ== X-Received: by 2002:a1c:eb03:: with SMTP id j3mr3755182wmh.15.1556200815536; Thu, 25 Apr 2019 07:00:15 -0700 (PDT) Received: from localhost (jirka.pirko.cz. [84.16.102.26]) by smtp.gmail.com with ESMTPSA id a17sm13831358wrm.53.2019.04.25.07.00.14 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Thu, 25 Apr 2019 07:00:15 -0700 (PDT) From: Jiri Pirko To: netdev@vger.kernel.org Cc: davem@davemloft.net, mlxsw@mellanox.com, jakub.kicinski@netronome.com, dsahern@gmail.com Subject: [patch net-next v4 13/16] netdevsim: implement dev probe/remove skeleton with port initialization Date: Thu, 25 Apr 2019 15:59:53 +0200 Message-Id: <20190425135956.3970-14-jiri@resnulli.us> X-Mailer: git-send-email 2.17.2 In-Reply-To: <20190425135956.3970-1-jiri@resnulli.us> References: <20190425135956.3970-1-jiri@resnulli.us> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Jiri Pirko Implement netdevsim bus probing of netdevsim devices. For every probed device create a devlink instance. According to the user-passed value, create a number of ports represented by devlink port instances. Signed-off-by: Jiri Pirko --- v3->v4: - fix wrapping of function declararions according to Jakub's rules. - rebased v1->v2: - changed port array to port list - port struct are allocated separately --- drivers/net/netdevsim/bus.c | 29 +++++++ drivers/net/netdevsim/dev.c | 130 ++++++++++++++++++++++++++---- drivers/net/netdevsim/netdev.c | 15 +--- drivers/net/netdevsim/netdevsim.h | 16 +++- 4 files changed, 160 insertions(+), 30 deletions(-) diff --git a/drivers/net/netdevsim/bus.c b/drivers/net/netdevsim/bus.c index c30692f17374..1ee14e1bb12d 100644 --- a/drivers/net/netdevsim/bus.c +++ b/drivers/net/netdevsim/bus.c @@ -194,6 +194,21 @@ static struct attribute *nsim_bus_attrs[] = { }; ATTRIBUTE_GROUPS(nsim_bus); +static int nsim_bus_probe(struct device *dev) +{ + struct nsim_bus_dev *nsim_bus_dev = to_nsim_bus_dev(dev); + + return nsim_dev_probe(nsim_bus_dev); +} + +static int nsim_bus_remove(struct device *dev) +{ + struct nsim_bus_dev *nsim_bus_dev = to_nsim_bus_dev(dev); + + nsim_dev_remove(nsim_bus_dev); + return 0; +} + int nsim_num_vf(struct device *dev) { struct nsim_bus_dev *nsim_bus_dev = to_nsim_bus_dev(dev); @@ -205,6 +220,8 @@ static struct bus_type nsim_bus = { .name = DRV_NAME, .dev_name = DRV_NAME, .bus_groups = nsim_bus_groups, + .probe = nsim_bus_probe, + .remove = nsim_bus_remove, .num_vf = nsim_num_vf, }; @@ -238,6 +255,18 @@ struct nsim_bus_dev *nsim_bus_dev_new(unsigned int id, unsigned int port_count) return ERR_PTR(err); } +struct nsim_bus_dev *nsim_bus_dev_new_with_ns(struct netdevsim *ns) +{ + struct nsim_bus_dev *nsim_bus_dev; + + dev_hold(ns->netdev); + rtnl_unlock(); + nsim_bus_dev = nsim_bus_dev_new(~0, 0); + rtnl_lock(); + dev_put(ns->netdev); + return nsim_bus_dev; +} + void nsim_bus_dev_del(struct nsim_bus_dev *nsim_bus_dev) { device_unregister(&nsim_bus_dev->dev); diff --git a/drivers/net/netdevsim/dev.c b/drivers/net/netdevsim/dev.c index 14946d162e53..6ee9d43ae252 100644 --- a/drivers/net/netdevsim/dev.c +++ b/drivers/net/netdevsim/dev.c @@ -17,6 +17,7 @@ #include #include +#include #include #include #include @@ -45,6 +46,30 @@ static void nsim_dev_debugfs_exit(struct nsim_dev *nsim_dev) debugfs_remove_recursive(nsim_dev->ddir); } +static int nsim_dev_port_debugfs_init(struct nsim_dev *nsim_dev, + struct nsim_dev_port *nsim_dev_port) +{ + char port_ddir_name[16]; + char dev_link_name[32]; + + sprintf(port_ddir_name, "%u", nsim_dev_port->port_index); + nsim_dev_port->ddir = debugfs_create_dir(port_ddir_name, + nsim_dev->ports_ddir); + if (IS_ERR_OR_NULL(nsim_dev_port->ddir)) + return -ENOMEM; + + sprintf(dev_link_name, "../../../" DRV_NAME "%u", + nsim_dev->nsim_bus_dev->dev.id); + debugfs_create_symlink("dev", nsim_dev_port->ddir, dev_link_name); + + return 0; +} + +static void nsim_dev_port_debugfs_exit(struct nsim_dev_port *nsim_dev_port) +{ + debugfs_remove_recursive(nsim_dev_port->ddir); +} + static u64 nsim_dev_ipv4_fib_resource_occ_get(void *priv) { struct nsim_dev *nsim_dev = priv; @@ -198,7 +223,8 @@ static const struct devlink_ops nsim_dev_devlink_ops = { .reload = nsim_dev_reload, }; -static struct nsim_dev *nsim_dev_create(struct nsim_bus_dev *nsim_bus_dev) +static struct nsim_dev * +nsim_dev_create(struct nsim_bus_dev *nsim_bus_dev, unsigned int port_count) { struct nsim_dev *nsim_dev; struct devlink *devlink; @@ -211,6 +237,7 @@ static struct nsim_dev *nsim_dev_create(struct nsim_bus_dev *nsim_bus_dev) nsim_dev->nsim_bus_dev = nsim_bus_dev; nsim_dev->switch_id.id_len = sizeof(nsim_dev->switch_id.id); get_random_bytes(nsim_dev->switch_id.id, nsim_dev->switch_id.id_len); + INIT_LIST_HEAD(&nsim_dev->port_list); nsim_dev->fib_data = nsim_fib_create(); if (IS_ERR(nsim_dev->fib_data)) { @@ -249,20 +276,6 @@ static struct nsim_dev *nsim_dev_create(struct nsim_bus_dev *nsim_bus_dev) return ERR_PTR(err); } -struct nsim_dev * -nsim_dev_create_with_ns(struct nsim_bus_dev *nsim_bus_dev, - struct netdevsim *ns) -{ - struct nsim_dev *nsim_dev; - - dev_hold(ns->netdev); - rtnl_unlock(); - nsim_dev = nsim_dev_create(nsim_bus_dev); - rtnl_lock(); - dev_put(ns->netdev); - return nsim_dev; -} - void nsim_dev_destroy(struct nsim_dev *nsim_dev) { struct devlink *devlink = priv_to_devlink(nsim_dev); @@ -275,6 +288,93 @@ void nsim_dev_destroy(struct nsim_dev *nsim_dev) devlink_free(devlink); } +static int nsim_dev_port_add(struct nsim_dev *nsim_dev, unsigned int port_index) +{ + struct nsim_dev_port *nsim_dev_port; + struct devlink_port *devlink_port; + int err; + + nsim_dev_port = kzalloc(sizeof(*nsim_dev_port), GFP_KERNEL); + if (!nsim_dev_port) + return -ENOMEM; + nsim_dev_port->port_index = port_index; + + devlink_port = &nsim_dev_port->devlink_port; + devlink_port_attrs_set(devlink_port, DEVLINK_PORT_FLAVOUR_PHYSICAL, + port_index + 1, 0, 0, + nsim_dev->switch_id.id, + nsim_dev->switch_id.id_len); + err = devlink_port_register(priv_to_devlink(nsim_dev), devlink_port, + port_index); + if (err) + goto err_port_free; + + err = nsim_dev_port_debugfs_init(nsim_dev, nsim_dev_port); + if (err) + goto err_dl_port_unregister; + + list_add(&nsim_dev_port->list, &nsim_dev->port_list); + + return 0; + +err_dl_port_unregister: + devlink_port_unregister(devlink_port); +err_port_free: + kfree(nsim_dev_port); + return err; +} + +static void nsim_dev_port_del(struct nsim_dev_port *nsim_dev_port) +{ + struct devlink_port *devlink_port = &nsim_dev_port->devlink_port; + + list_del(&nsim_dev_port->list); + nsim_dev_port_debugfs_exit(nsim_dev_port); + devlink_port_unregister(devlink_port); + kfree(nsim_dev_port); +} + +static void nsim_dev_port_del_all(struct nsim_dev *nsim_dev) +{ + struct nsim_dev_port *nsim_dev_port, *tmp; + + list_for_each_entry_safe(nsim_dev_port, tmp, + &nsim_dev->port_list, list) + nsim_dev_port_del(nsim_dev_port); +} + +int nsim_dev_probe(struct nsim_bus_dev *nsim_bus_dev) +{ + struct nsim_dev *nsim_dev; + int i; + int err; + + nsim_dev = nsim_dev_create(nsim_bus_dev, nsim_bus_dev->port_count); + if (IS_ERR(nsim_dev)) + return PTR_ERR(nsim_dev); + dev_set_drvdata(&nsim_bus_dev->dev, nsim_dev); + + for (i = 0; i < nsim_bus_dev->port_count; i++) { + err = nsim_dev_port_add(nsim_dev, i); + if (err) + goto err_port_del_all; + } + return 0; + +err_port_del_all: + nsim_dev_port_del_all(nsim_dev); + nsim_dev_destroy(nsim_dev); + return err; +} + +void nsim_dev_remove(struct nsim_bus_dev *nsim_bus_dev) +{ + struct nsim_dev *nsim_dev = dev_get_drvdata(&nsim_bus_dev->dev); + + nsim_dev_port_del_all(nsim_dev); + nsim_dev_destroy(nsim_dev); +} + int nsim_dev_init(void) { nsim_dev_ddir = debugfs_create_dir(DRV_NAME, NULL); diff --git a/drivers/net/netdevsim/netdev.c b/drivers/net/netdevsim/netdev.c index eb823bd0dc39..99169fe521f2 100644 --- a/drivers/net/netdevsim/netdev.c +++ b/drivers/net/netdevsim/netdev.c @@ -74,7 +74,6 @@ static void nsim_free(struct net_device *dev) { struct netdevsim *ns = netdev_priv(dev); - nsim_dev_destroy(ns->nsim_dev); nsim_bus_dev_del(ns->nsim_bus_dev); /* netdev and vf state will be freed out of device_release() */ } @@ -364,26 +363,20 @@ static int nsim_newlink(struct net *src_net, struct net_device *dev, struct netdevsim *ns = netdev_priv(dev); int err; - ns->nsim_bus_dev = nsim_bus_dev_new(~0, 0); + ns->netdev = dev; + ns->nsim_bus_dev = nsim_bus_dev_new_with_ns(ns); if (IS_ERR(ns->nsim_bus_dev)) return PTR_ERR(ns->nsim_bus_dev); SET_NETDEV_DEV(dev, &ns->nsim_bus_dev->dev); - ns->netdev = dev; - ns->nsim_dev = nsim_dev_create_with_ns(ns->nsim_bus_dev, ns); - if (IS_ERR(ns->nsim_dev)) { - err = PTR_ERR(ns->nsim_dev); - goto err_dev_del; - } + ns->nsim_dev = dev_get_drvdata(&ns->nsim_bus_dev->dev); err = register_netdevice(dev); if (err) - goto err_dev_destroy; + goto err_dev_del; return 0; -err_dev_destroy: - nsim_dev_destroy(ns->nsim_dev); err_dev_del: nsim_bus_dev_del(ns->nsim_bus_dev); return err; diff --git a/drivers/net/netdevsim/netdevsim.h b/drivers/net/netdevsim/netdevsim.h index e951b1ccc3f2..0e6ca85e5487 100644 --- a/drivers/net/netdevsim/netdevsim.h +++ b/drivers/net/netdevsim/netdevsim.h @@ -18,6 +18,7 @@ #include #include #include +#include #include #define DRV_NAME "netdevsim" @@ -130,6 +131,13 @@ enum nsim_resource_id { NSIM_RESOURCE_IPV6_FIB_RULES, }; +struct nsim_dev_port { + struct list_head list; + struct devlink_port devlink_port; + unsigned int port_index; + struct dentry *ddir; +}; + struct nsim_dev { struct nsim_bus_dev *nsim_bus_dev; struct nsim_fib_data *fib_data; @@ -143,14 +151,13 @@ struct nsim_dev { struct list_head bpf_bound_progs; struct list_head bpf_bound_maps; struct netdev_phys_item_id switch_id; + struct list_head port_list; }; -struct nsim_dev * -nsim_dev_create_with_ns(struct nsim_bus_dev *nsim_bus_dev, - struct netdevsim *ns); -void nsim_dev_destroy(struct nsim_dev *nsim_dev); int nsim_dev_init(void); void nsim_dev_exit(void); +int nsim_dev_probe(struct nsim_bus_dev *nsim_bus_dev); +void nsim_dev_remove(struct nsim_bus_dev *nsim_bus_dev); struct nsim_fib_data *nsim_fib_create(void); void nsim_fib_destroy(struct nsim_fib_data *fib_data); @@ -201,6 +208,7 @@ struct nsim_bus_dev { }; struct nsim_bus_dev *nsim_bus_dev_new(unsigned int id, unsigned int port_count); +struct nsim_bus_dev *nsim_bus_dev_new_with_ns(struct netdevsim *ns); void nsim_bus_dev_del(struct nsim_bus_dev *nsim_bus_dev); int nsim_bus_init(void); void nsim_bus_exit(void);