netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Jiri Pirko <jiri@resnulli.us>
To: netdev@vger.kernel.org
Cc: davem@davemloft.net, idosch@mellanox.com, eladr@mellanox.com,
	sfeldma@gmail.com, f.fainelli@gmail.com, linux@roeck-us.net,
	vivien.didelot@savoirfairelinux.com, andrew@lunn.ch,
	john.fastabend@gmail.com, David.Laight@ACULAB.COM,
	stephen@networkplumber.org
Subject: [patch net-next v5 1/8] switchdev: introduce switchdev deferred ops infrastructure
Date: Wed, 14 Oct 2015 19:40:48 +0200	[thread overview]
Message-ID: <1444844455-12508-2-git-send-email-jiri@resnulli.us> (raw)
In-Reply-To: <1444844455-12508-1-git-send-email-jiri@resnulli.us>

From: Jiri Pirko <jiri@mellanox.com>

Introduce infrastructure which will be used internally to defer ops.
Note that the deferred ops are queued up and either are processed by
scheduled work or explicitly by user calling deferred_process function.

Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
 include/net/switchdev.h   |  5 +++
 net/switchdev/switchdev.c | 80 +++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 85 insertions(+)

diff --git a/include/net/switchdev.h b/include/net/switchdev.h
index 1ce7083..31b9038 100644
--- a/include/net/switchdev.h
+++ b/include/net/switchdev.h
@@ -167,6 +167,7 @@ switchdev_notifier_info_to_dev(const struct switchdev_notifier_info *info)
 
 #ifdef CONFIG_NET_SWITCHDEV
 
+void switchdev_deferred_process(void);
 int switchdev_port_attr_get(struct net_device *dev,
 			    struct switchdev_attr *attr);
 int switchdev_port_attr_set(struct net_device *dev,
@@ -208,6 +209,10 @@ void switchdev_port_fwd_mark_set(struct net_device *dev,
 
 #else
 
+static inline void switchdev_deferred_process(void)
+{
+}
+
 static inline int switchdev_port_attr_get(struct net_device *dev,
 					  struct switchdev_attr *attr)
 {
diff --git a/net/switchdev/switchdev.c b/net/switchdev/switchdev.c
index b8aaf820..5e64b59 100644
--- a/net/switchdev/switchdev.c
+++ b/net/switchdev/switchdev.c
@@ -17,6 +17,7 @@
 #include <linux/netdevice.h>
 #include <linux/if_bridge.h>
 #include <linux/list.h>
+#include <linux/workqueue.h>
 #include <net/ip_fib.h>
 #include <net/switchdev.h>
 
@@ -92,6 +93,85 @@ static void switchdev_trans_items_warn_destroy(struct net_device *dev,
 	switchdev_trans_items_destroy(trans);
 }
 
+static LIST_HEAD(deferred);
+static DEFINE_SPINLOCK(deferred_lock);
+
+typedef void switchdev_deferred_func_t(struct net_device *dev,
+				       const void *data);
+
+struct switchdev_deferred_item {
+	struct list_head list;
+	struct net_device *dev;
+	switchdev_deferred_func_t *func;
+	unsigned long data[0];
+};
+
+static struct switchdev_deferred_item *switchdev_deferred_dequeue(void)
+{
+	struct switchdev_deferred_item *dfitem;
+
+	spin_lock_bh(&deferred_lock);
+	if (list_empty(&deferred)) {
+		dfitem = NULL;
+		goto unlock;
+	}
+	dfitem = list_first_entry(&deferred,
+				  struct switchdev_deferred_item, list);
+	list_del(&dfitem->list);
+unlock:
+	spin_unlock_bh(&deferred_lock);
+	return dfitem;
+}
+
+/**
+ *	switchdev_deferred_process - Process ops in deferred queue
+ *
+ *	Called to flush the ops currently queued in deferred ops queue.
+ *	rtnl_lock must be held.
+ */
+void switchdev_deferred_process(void)
+{
+	struct switchdev_deferred_item *dfitem;
+
+	ASSERT_RTNL();
+
+	while ((dfitem = switchdev_deferred_dequeue())) {
+		dfitem->func(dfitem->dev, dfitem->data);
+		dev_put(dfitem->dev);
+		kfree(dfitem);
+	}
+}
+EXPORT_SYMBOL_GPL(switchdev_deferred_process);
+
+static void switchdev_deferred_process_work(struct work_struct *work)
+{
+	rtnl_lock();
+	switchdev_deferred_process();
+	rtnl_unlock();
+}
+
+static DECLARE_WORK(deferred_process_work, switchdev_deferred_process_work);
+
+static int switchdev_deferred_enqueue(struct net_device *dev,
+				      const void *data, size_t data_len,
+				      switchdev_deferred_func_t *func)
+{
+	struct switchdev_deferred_item *dfitem;
+
+	dfitem = kmalloc(sizeof(*dfitem) + data_len, GFP_ATOMIC);
+	if (!dfitem)
+		return -ENOMEM;
+	dfitem->dev = dev;
+	dfitem->func = func;
+	memcpy(dfitem->data, data, data_len);
+	dev_hold(dev);
+	spin_lock_bh(&deferred_lock);
+	list_add_tail(&dfitem->list, &deferred);
+	spin_unlock_bh(&deferred_lock);
+	schedule_work(&deferred_process_work);
+	return 0;
+}
+
 /**
  *	switchdev_port_attr_get - Get port attribute
  *
-- 
1.9.3

  reply	other threads:[~2015-10-14 17:40 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-10-14 17:40 [patch net-next v5 0/8] switchdev: change locking Jiri Pirko
2015-10-14 17:40 ` Jiri Pirko [this message]
2015-10-14 17:40 ` [patch net-next v5 2/8] switchdev: make struct switchdev_attr parameter const for attr_set calls Jiri Pirko
2015-10-14 19:01   ` Vivien Didelot
2015-10-14 17:40 ` [patch net-next v5 3/8] switchdev: allow caller to explicitly request attr_set as deferred Jiri Pirko
2015-10-15  4:34   ` Scott Feldman
2015-10-15  5:57     ` Jiri Pirko
2015-10-15 15:21   ` John Fastabend
2015-10-16  8:23     ` Jiri Pirko
2015-10-16 16:20       ` Scott Feldman
2015-10-16 17:16         ` John Fastabend
2015-10-17  2:11       ` John Fastabend
2015-10-14 17:40 ` [patch net-next v5 4/8] switchdev: remove pointers from switchdev objects Jiri Pirko
2015-10-14 17:40 ` [patch net-next v5 5/8] switchdev: introduce possibility to defer obj_add/del Jiri Pirko
2015-10-19  7:55   ` Scott Feldman
2015-10-19  8:24     ` Jiri Pirko
2015-10-14 17:40 ` [patch net-next v5 6/8] bridge: defer switchdev fdb del call in fdb_del_external_learn Jiri Pirko
2015-10-14 17:40 ` [patch net-next v5 7/8] rocker: remove nowait from switchdev callbacks Jiri Pirko
2015-10-14 17:40 ` [patch net-next v5 8/8] switchdev: assert rtnl mutex when going over lower netdevs Jiri Pirko
2015-10-15 13:10 ` [patch net-next v5 0/8] switchdev: change locking David Miller

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=1444844455-12508-2-git-send-email-jiri@resnulli.us \
    --to=jiri@resnulli.us \
    --cc=David.Laight@ACULAB.COM \
    --cc=andrew@lunn.ch \
    --cc=davem@davemloft.net \
    --cc=eladr@mellanox.com \
    --cc=f.fainelli@gmail.com \
    --cc=idosch@mellanox.com \
    --cc=john.fastabend@gmail.com \
    --cc=linux@roeck-us.net \
    --cc=netdev@vger.kernel.org \
    --cc=sfeldma@gmail.com \
    --cc=stephen@networkplumber.org \
    --cc=vivien.didelot@savoirfairelinux.com \
    /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;
as well as URLs for NNTP newsgroup(s).