* Re: [PATCH v4 20/20] kbuild: add a new kselftest_install make target to install selftests
From: Shuah Khan @ 2015-01-15 23:41 UTC (permalink / raw)
To: Michael Ellerman
Cc: mmarek-AlSwsSmVLrQ, masami.hiramatsu.pt-FCd8Q96Dh0JBDgjK7y7TUQ,
gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r,
akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b,
rostedt-nx8X9YLhiw1AfugRpC6u6w, mingo-H+wXaHxf7aLQT0dZR+AlfA,
davem-fT/PcQaiUtIeIZ0/mPfg9Q, keescook-F7+t8E8rja9g9hUCZPvPmw,
tranmanphong-Re5JQEeQqe8AvxtiuMwx3w, cov-sgV2jX0FEOL9JmXXK+q4OQ,
dh.herrmann-Re5JQEeQqe8AvxtiuMwx3w, hughd-hpIqsD4AKlfQT0dZR+AlfA,
bobby.prani-Re5JQEeQqe8AvxtiuMwx3w,
serge.hallyn-GeWIH/nMZzLQT0dZR+AlfA,
ebiederm-aS9lmoZGLiVWk0Htik3J/w, tim.bird-/MT0OVThwyLZJqsBc5GL+g,
josh-iaAMLnmF4UmaiuxdJuQwMA, koct9i-Re5JQEeQqe8AvxtiuMwx3w,
linux-kbuild-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-api-u79uwXL29TY76Z2rM5mHXA, netdev-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1421362698.23332.6.camel-Gsx/Oe8HsFggBc27wqDAHg@public.gmane.org>
On 01/15/2015 03:58 PM, Michael Ellerman wrote:
> On Wed, 2015-01-14 at 09:32 -0700, Shuah Khan wrote:
>> On 01/06/2015 12:43 PM, Shuah Khan wrote:
>>> Add a new make target to install to install kernel selftests.
>>> This new target will build and install selftests. kselftest
>>> target now depends on kselftest_install and runs the generated
>>> kselftest script to reduce duplicate work and for common look
>>> and feel when running tests.
>>>
>>> make kselftest_target:
>>> -- exports kselftest INSTALL_KSFT_PATH
>>> default $(INSTALL_MOD_PATH)/lib/kselftest/$(KERNELRELEASE)
>>> -- exports INSTALL_KSFT_PATH
>>> -- runs selftests make install target
>>>
>>> Signed-off-by: Shuah Khan <shuahkh-JPH+aEBZ4P+UEJcrhfAQsw@public.gmane.org>
>>
>> Hi Marek,
>>
>> Could you please Ack this patch, if this version looks good,
>> so I can take this through ksefltest tree.
>
> Hi Shuah,
>
> I posted what I think is a better approach last week. It's less code and less
> repetition, and installs the majority of tests this series missed - ie. the
> powerpc ones.
>
> Please at least respond to it before you put this series into next.
>
> https://lkml.org/lkml/2015/1/9/45
>
Michael,
I didn't get a chance to review your patches yet. I plan to
review and give you feedback by end of this week. This patch
is needed in any case for either approach.
thanks,
-- Shuah
--
Shuah Khan
Sr. Linux Kernel Developer
Open Source Innovation Group
Samsung Research America (Silicon Valley)
shuahkh-JPH+aEBZ4P+UEJcrhfAQsw@public.gmane.org | (970) 217-8978
^ permalink raw reply
* Re: [PATCH net-next] ipv4: per cpu uncached list
From: David Miller @ 2015-01-15 23:26 UTC (permalink / raw)
To: eric.dumazet; +Cc: netdev, willemb
In-Reply-To: <1421277426.11734.36.camel@edumazet-glaptop2.roam.corp.google.com>
From: Eric Dumazet <eric.dumazet@gmail.com>
Date: Wed, 14 Jan 2015 15:17:06 -0800
> From: Eric Dumazet <edumazet@google.com>
>
> RAW sockets with hdrinc suffer from contention on rt_uncached_lock
> spinlock.
>
> One solution is to use percpu lists, since most routes are destroyed
> by the cpu that created them.
>
> It is unclear why we even have to put these routes in uncached_list,
> as all outgoing packets should be freed when a device is dismantled.
>
> Signed-off-by: Eric Dumazet <edumazet@google.com>
> Fixes: caacf05e5ad1 ("ipv4: Properly purge netdev references on uncached routes.")
This looks fine, applied, thanks Eric.
^ permalink raw reply
* Re: [PATCH net-next 1/2] net: ipv4: handle DSA enabled master network devices
From: David Miller @ 2015-01-15 23:19 UTC (permalink / raw)
To: f.fainelli; +Cc: netdev, bridge, kaber, buytenh
In-Reply-To: <1421257932-11073-2-git-send-email-f.fainelli@gmail.com>
From: Florian Fainelli <f.fainelli@gmail.com>
Date: Wed, 14 Jan 2015 09:52:11 -0800
> - /* bring loopback device up first */
> + /* bring loopback an DSA master network devices up first */
Typo: "an" should be "and"
> - if (dev != ic_dev) {
> + /* Only bring down unused devices and not DSA enabled master
> + * devices
> + */
> + if (dev != ic_dev && !netdev_uses_dsa(dev)) {
You don't have to add a comment which just reads the code, I'm
a programmer so I am able to do that all on my own :-)
^ permalink raw reply
* Re: [patch-net-next v2 3/3] net: ethernet: cpsw: don't requests IRQs we don't use
From: David Miller @ 2015-01-15 23:16 UTC (permalink / raw)
To: balbi; +Cc: mugunthanvnm, tony, linux-omap, netdev
In-Reply-To: <20150115152053.GA16409@saruman>
From: Felipe Balbi <balbi@ti.com>
Date: Thu, 15 Jan 2015 09:20:53 -0600
> On Thu, Jan 15, 2015 at 01:19:16PM +0530, Mugunthan V N wrote:
>> On Wednesday 14 January 2015 10:28 PM, Felipe Balbi wrote:
>> > CPSW never uses RX_THRESHOLD or MISC interrupts. In
>> > fact, they are always kept masked in their appropriate
>> > IRQ Enable register.
>> >
>> > Instead of allocating an IRQ that never fires, it's best
>> > to remove that code altogether and let future patches
>> > implement it if anybody needs those.
>> >
>> > Signed-off-by: Felipe Balbi <balbi@ti.com>
>>
>> Instead of introducing dummy ISR in previous patch and then removing in
>> this patch, both can be squashed into a single patch.
>
> sure they can. I decided to split to ease review and to make sure only
> one thing happens in a single patch.
Indeed, I agree that adding something as a placeholder that just gets
immediately removed should be avoided unless it is extremely difficult
to do so.
^ permalink raw reply
* Re: [net-next 10/17] i40e: clean up PTP log messages
From: David Miller @ 2015-01-15 23:12 UTC (permalink / raw)
To: shannon.nelson
Cc: David.Laight, jeffrey.t.kirsher, netdev, nhorman, sassmann,
jogreene, jacob.e.keller
In-Reply-To: <FC41C24E35F18A40888AACA1A36F3E418ADD4215@fmsmsx115.amr.corp.intel.com>
From: "Nelson, Shannon" <shannon.nelson@intel.com>
Date: Thu, 15 Jan 2015 22:44:48 +0000
> Yes, the driver should print the unvarnished truth. What's
> frustrating about UDEV is that it ends up making the driver look
> like it is confused and/or lying in the log messages. We'd prefer
> to minimize this unnecessary user-confusion where possible.
The only way to resolve this is to have some kind of synchronized
event wherein when a device is instantiated we get userland to
assign the final name before the device has any visibility anywhere
(basically before register_netdevice() puts the device into the
hashes where it can be found).
^ permalink raw reply
* Re: net_test_tools: add ipv6 support for kbench_mod
From: David Miller @ 2015-01-15 23:08 UTC (permalink / raw)
To: shli; +Cc: netdev, kafai
In-Reply-To: <20150115211737.GA2587066@devbig257.prn2.facebook.com>
From: Shaohua Li <shli@fb.com>
Date: Thu, 15 Jan 2015 13:17:37 -0800
> On Wed, Jan 14, 2015 at 01:35:40AM -0500, David Miller wrote:
>> From: Shaohua Li <shli@fb.com>
>> Date: Tue, 13 Jan 2015 21:45:48 -0800
>>
>> > This patch adds ipv6 support for kbench_mod test module
>>
>> This doesn't even link because ip6_route_input is not an
>> exported symbol.
>>
>> So you either didn't test this, or it depends upon custom
>> kernel changes which you didn't mention.
>>
>> Either way I can't apply this, sorry
>
> Yes, we need export the sysmbol for the test. Can we export the symbol?
> or I can delete the route input test, which one do you prefer?
There is no justification upstream to export that symbol since
there are no modular users in-tree.
^ permalink raw reply
* Re: [PATCH 3/3] genetlink: synchronize socket closing and family removal
From: David Miller @ 2015-01-15 23:06 UTC (permalink / raw)
To: johannes; +Cc: netdev, jeff.layton, sedat.dilek
In-Reply-To: <1421355306.1962.14.camel@sipsolutions.net>
From: Johannes Berg <johannes@sipsolutions.net>
Date: Thu, 15 Jan 2015 21:55:06 +0100
> On Thu, 2015-01-15 at 14:50 -0500, David Miller wrote:
>> From: Johannes Berg <johannes@sipsolutions.net>
>> Date: Thu, 15 Jan 2015 12:04:45 +0100
>>
>> > + atomic_dec(&genl_sk_destructing_cnt);
>> > + printk(KERN_DEBUG "dec destructing\n");
>> > + wake_up(&genl_sk_destructing_waitq);
>>
>> Hmmm, maybe only wakeup if "!atomic_dec_and_test()"?
>
> Yes, good point.
>
> And, umm, how the hell did I manage to leave the printk() in there?
Johannes, please repost the whole series when you have to make
changes to one or more of the patches within.
Thanks.
^ permalink raw reply
* Re: [PATCH v4 20/20] kbuild: add a new kselftest_install make target to install selftests
From: Michael Ellerman @ 2015-01-15 22:58 UTC (permalink / raw)
To: Shuah Khan
Cc: mmarek-AlSwsSmVLrQ, masami.hiramatsu.pt-FCd8Q96Dh0JBDgjK7y7TUQ,
gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r,
akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b,
rostedt-nx8X9YLhiw1AfugRpC6u6w, mingo-H+wXaHxf7aLQT0dZR+AlfA,
davem-fT/PcQaiUtIeIZ0/mPfg9Q, keescook-F7+t8E8rja9g9hUCZPvPmw,
tranmanphong-Re5JQEeQqe8AvxtiuMwx3w, cov-sgV2jX0FEOL9JmXXK+q4OQ,
dh.herrmann-Re5JQEeQqe8AvxtiuMwx3w, hughd-hpIqsD4AKlfQT0dZR+AlfA,
bobby.prani-Re5JQEeQqe8AvxtiuMwx3w,
serge.hallyn-GeWIH/nMZzLQT0dZR+AlfA,
ebiederm-aS9lmoZGLiVWk0Htik3J/w, tim.bird-/MT0OVThwyLZJqsBc5GL+g,
josh-iaAMLnmF4UmaiuxdJuQwMA, koct9i-Re5JQEeQqe8AvxtiuMwx3w,
linux-kbuild-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-api-u79uwXL29TY76Z2rM5mHXA, netdev-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <54B69A1B.80006-JPH+aEBZ4P+UEJcrhfAQsw@public.gmane.org>
On Wed, 2015-01-14 at 09:32 -0700, Shuah Khan wrote:
> On 01/06/2015 12:43 PM, Shuah Khan wrote:
> > Add a new make target to install to install kernel selftests.
> > This new target will build and install selftests. kselftest
> > target now depends on kselftest_install and runs the generated
> > kselftest script to reduce duplicate work and for common look
> > and feel when running tests.
> >
> > make kselftest_target:
> > -- exports kselftest INSTALL_KSFT_PATH
> > default $(INSTALL_MOD_PATH)/lib/kselftest/$(KERNELRELEASE)
> > -- exports INSTALL_KSFT_PATH
> > -- runs selftests make install target
> >
> > Signed-off-by: Shuah Khan <shuahkh-JPH+aEBZ4P+UEJcrhfAQsw@public.gmane.org>
>
> Hi Marek,
>
> Could you please Ack this patch, if this version looks good,
> so I can take this through ksefltest tree.
Hi Shuah,
I posted what I think is a better approach last week. It's less code and less
repetition, and installs the majority of tests this series missed - ie. the
powerpc ones.
Please at least respond to it before you put this series into next.
https://lkml.org/lkml/2015/1/9/45
cheers
^ permalink raw reply
* Re: ANNOUNCEMENT: linux-can repos are now at kernel.org
From: Marc Kleine-Budde @ 2015-01-15 22:52 UTC (permalink / raw)
To: Oliver Hartkopp, linux-can@vger.kernel.org; +Cc: netdev
In-Reply-To: <54B7F2FB.6070301@hartkopp.net>
[-- Attachment #1: Type: text/plain, Size: 477 bytes --]
On 01/15/2015 06:03 PM, Oliver Hartkopp wrote:
> Very cool!
>
> That was really fast.
Yes Konstantin at the helpdesk is really fast (and I had collected some
GPG signatures at ELCE).
Marc
--
Pengutronix e.K. | Marc Kleine-Budde |
Industrial Linux Solutions | Phone: +49-231-2826-924 |
Vertretung West/Dortmund | Fax: +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686 | http://www.pengutronix.de |
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]
^ permalink raw reply
* [patch net-next 2/2] net: replace br_fdb_external_learn_* calls with switchdev notifier events
From: Jiri Pirko @ 2015-01-15 22:49 UTC (permalink / raw)
To: netdev; +Cc: davem, jhs, sfeldma, stephen, linus.luessing, tgraf
In-Reply-To: <1421362177-10719-1-git-send-email-jiri@resnulli.us>
This patch benefits from newly introduced switchdev notifier and uses it
to propagate fdb learn events from rocker driver to bridge. That avoids
direct function calls and possible use by other listeners (ovs).
Suggested-by: Thomas Graf <tgraf@suug.ch>
Signed-off-by: Jiri Pirko <jiri@resnulli.us>
---
drivers/net/ethernet/rocker/rocker.c | 10 +++++--
include/linux/if_bridge.h | 18 -------------
include/net/switchdev.h | 11 ++++++++
net/bridge/br.c | 52 +++++++++++++++++++++++++++++++++++-
net/bridge/br_fdb.c | 38 +++-----------------------
net/bridge/br_private.h | 4 +++
6 files changed, 78 insertions(+), 55 deletions(-)
diff --git a/drivers/net/ethernet/rocker/rocker.c b/drivers/net/ethernet/rocker/rocker.c
index cad8cf9..964d719 100644
--- a/drivers/net/ethernet/rocker/rocker.c
+++ b/drivers/net/ethernet/rocker/rocker.c
@@ -3026,11 +3026,17 @@ static void rocker_port_fdb_learn_work(struct work_struct *work)
container_of(work, struct rocker_fdb_learn_work, work);
bool removing = (lw->flags & ROCKER_OP_FLAG_REMOVE);
bool learned = (lw->flags & ROCKER_OP_FLAG_LEARNED);
+ struct netdev_switch_notifier_fdb_info info;
+
+ info.addr = lw->addr;
+ info.vid = lw->vid;
if (learned && removing)
- br_fdb_external_learn_del(lw->dev, lw->addr, lw->vid);
+ call_netdev_switch_notifiers(NETDEV_SWITCH_FDB_DEL,
+ lw->dev, &info.info);
else if (learned && !removing)
- br_fdb_external_learn_add(lw->dev, lw->addr, lw->vid);
+ call_netdev_switch_notifiers(NETDEV_SWITCH_FDB_ADD,
+ lw->dev, &info.info);
kfree(work);
}
diff --git a/include/linux/if_bridge.h b/include/linux/if_bridge.h
index 0a8ce76..a57bca2 100644
--- a/include/linux/if_bridge.h
+++ b/include/linux/if_bridge.h
@@ -50,24 +50,6 @@ extern void brioctl_set(int (*ioctl_hook)(struct net *, unsigned int, void __use
typedef int br_should_route_hook_t(struct sk_buff *skb);
extern br_should_route_hook_t __rcu *br_should_route_hook;
-#if IS_ENABLED(CONFIG_BRIDGE)
-int br_fdb_external_learn_add(struct net_device *dev,
- const unsigned char *addr, u16 vid);
-int br_fdb_external_learn_del(struct net_device *dev,
- const unsigned char *addr, u16 vid);
-#else
-static inline int br_fdb_external_learn_add(struct net_device *dev,
- const unsigned char *addr, u16 vid)
-{
- return 0;
-}
-static inline int br_fdb_external_learn_del(struct net_device *dev,
- const unsigned char *addr, u16 vid)
-{
- return 0;
-}
-#endif
-
#if IS_ENABLED(CONFIG_BRIDGE) && IS_ENABLED(CONFIG_BRIDGE_IGMP_SNOOPING)
int br_multicast_list_adjacent(struct net_device *dev,
struct list_head *br_ip_list);
diff --git a/include/net/switchdev.h b/include/net/switchdev.h
index 7f8d743..201120e 100644
--- a/include/net/switchdev.h
+++ b/include/net/switchdev.h
@@ -13,10 +13,21 @@
#include <linux/netdevice.h>
#include <linux/notifier.h>
+enum netdev_switch_notifier_type {
+ NETDEV_SWITCH_FDB_ADD = 1,
+ NETDEV_SWITCH_FDB_DEL,
+};
+
struct netdev_switch_notifier_info {
struct net_device *dev;
};
+struct netdev_switch_notifier_fdb_info {
+ struct netdev_switch_notifier_info info; /* must be first */
+ const unsigned char *addr;
+ u16 vid;
+};
+
static inline struct net_device *
netdev_switch_notifier_info_to_dev(const struct netdev_switch_notifier_info *info)
{
diff --git a/net/bridge/br.c b/net/bridge/br.c
index 44425af..fb57ab6 100644
--- a/net/bridge/br.c
+++ b/net/bridge/br.c
@@ -19,6 +19,7 @@
#include <linux/llc.h>
#include <net/llc.h>
#include <net/stp.h>
+#include <net/switchdev.h>
#include "br_private.h"
@@ -120,6 +121,48 @@ static struct notifier_block br_device_notifier = {
.notifier_call = br_device_event
};
+static int br_netdev_switch_event(struct notifier_block *unused,
+ unsigned long event, void *ptr)
+{
+ struct net_device *dev = netdev_switch_notifier_info_to_dev(ptr);
+ struct net_bridge_port *p;
+ struct net_bridge *br;
+ struct netdev_switch_notifier_fdb_info *fdb_info;
+ int err = NOTIFY_DONE;
+
+ rtnl_lock();
+ p = br_port_get_rtnl(dev);
+ if (!p)
+ goto out;
+
+ br = p->br;
+
+ switch (event) {
+ case NETDEV_SWITCH_FDB_ADD:
+ fdb_info = ptr;
+ err = br_fdb_external_learn_add(br, p, fdb_info->addr,
+ fdb_info->vid);
+ if (err)
+ err = notifier_from_errno(err);
+ break;
+ case NETDEV_SWITCH_FDB_DEL:
+ fdb_info = ptr;
+ err = br_fdb_external_learn_del(br, p, fdb_info->addr,
+ fdb_info->vid);
+ if (err)
+ err = notifier_from_errno(err);
+ break;
+ }
+
+out:
+ rtnl_unlock();
+ return err;
+}
+
+static struct notifier_block br_netdev_switch_notifier = {
+ .notifier_call = br_netdev_switch_event,
+};
+
static void __net_exit br_net_exit(struct net *net)
{
struct net_device *dev;
@@ -169,10 +212,14 @@ static int __init br_init(void)
if (err)
goto err_out3;
- err = br_netlink_init();
+ err = register_netdev_switch_notifier(&br_netdev_switch_notifier);
if (err)
goto err_out4;
+ err = br_netlink_init();
+ if (err)
+ goto err_out5;
+
brioctl_set(br_ioctl_deviceless_stub);
#if IS_ENABLED(CONFIG_ATM_LANE)
@@ -185,6 +232,8 @@ static int __init br_init(void)
return 0;
+err_out5:
+ unregister_netdev_switch_notifier(&br_netdev_switch_notifier);
err_out4:
unregister_netdevice_notifier(&br_device_notifier);
err_out3:
@@ -202,6 +251,7 @@ static void __exit br_deinit(void)
{
stp_proto_unregister(&br_stp_proto);
br_netlink_fini();
+ unregister_netdev_switch_notifier(&br_netdev_switch_notifier);
unregister_netdevice_notifier(&br_device_notifier);
brioctl_set(NULL);
unregister_pernet_subsys(&br_net_ops);
diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c
index e6e0372..03667e6 100644
--- a/net/bridge/br_fdb.c
+++ b/net/bridge/br_fdb.c
@@ -990,26 +990,14 @@ void br_fdb_unsync_static(struct net_bridge *br, struct net_bridge_port *p)
}
}
-int br_fdb_external_learn_add(struct net_device *dev,
+int br_fdb_external_learn_add(struct net_bridge *br, struct net_bridge_port *p,
const unsigned char *addr, u16 vid)
{
- struct net_bridge_port *p;
- struct net_bridge *br;
struct hlist_head *head;
struct net_bridge_fdb_entry *fdb;
int err = 0;
- rtnl_lock();
-
- p = br_port_get_rtnl(dev);
- if (!p) {
- pr_info("bridge: %s not a bridge port\n", dev->name);
- err = -EINVAL;
- goto err_rtnl_unlock;
- }
-
- br = p->br;
-
+ ASSERT_RTNL();
spin_lock_bh(&br->hash_lock);
head = &br->hash[br_mac_hash(addr, vid)];
@@ -1034,33 +1022,18 @@ int br_fdb_external_learn_add(struct net_device *dev,
err_unlock:
spin_unlock_bh(&br->hash_lock);
-err_rtnl_unlock:
- rtnl_unlock();
return err;
}
-EXPORT_SYMBOL(br_fdb_external_learn_add);
-int br_fdb_external_learn_del(struct net_device *dev,
+int br_fdb_external_learn_del(struct net_bridge *br, struct net_bridge_port *p,
const unsigned char *addr, u16 vid)
{
- struct net_bridge_port *p;
- struct net_bridge *br;
struct hlist_head *head;
struct net_bridge_fdb_entry *fdb;
int err = 0;
- rtnl_lock();
-
- p = br_port_get_rtnl(dev);
- if (!p) {
- pr_info("bridge: %s not a bridge port\n", dev->name);
- err = -EINVAL;
- goto err_rtnl_unlock;
- }
-
- br = p->br;
-
+ ASSERT_RTNL();
spin_lock_bh(&br->hash_lock);
head = &br->hash[br_mac_hash(addr, vid)];
@@ -1071,9 +1044,6 @@ int br_fdb_external_learn_del(struct net_device *dev,
err = -ENOENT;
spin_unlock_bh(&br->hash_lock);
-err_rtnl_unlock:
- rtnl_unlock();
return err;
}
-EXPORT_SYMBOL(br_fdb_external_learn_del);
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index d808d76..e8e3f36 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -402,6 +402,10 @@ int br_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb,
struct net_device *dev, struct net_device *fdev, int idx);
int br_fdb_sync_static(struct net_bridge *br, struct net_bridge_port *p);
void br_fdb_unsync_static(struct net_bridge *br, struct net_bridge_port *p);
+int br_fdb_external_learn_add(struct net_bridge *br, struct net_bridge_port *p,
+ const unsigned char *addr, u16 vid);
+int br_fdb_external_learn_del(struct net_bridge *br, struct net_bridge_port *p,
+ const unsigned char *addr, u16 vid);
/* br_forward.c */
void br_deliver(const struct net_bridge_port *to, struct sk_buff *skb);
--
1.9.3
^ permalink raw reply related
* [patch net-next 1/2] switchdev: introduce switchdev notifier
From: Jiri Pirko @ 2015-01-15 22:49 UTC (permalink / raw)
To: netdev; +Cc: davem, jhs, sfeldma, stephen, linus.luessing, tgraf
This patch introduces new notifier for purposes of exposing events which happen
on switch driver side. The consumers of the event messages are mainly involved
masters, namely bridge and ovs.
Suggested-by: Thomas Graf <tgraf@suug.ch>
Signed-off-by: Jiri Pirko <jiri@resnulli.us>
---
include/net/switchdev.h | 31 ++++++++++++++++++++++
net/switchdev/switchdev.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 96 insertions(+)
diff --git a/include/net/switchdev.h b/include/net/switchdev.h
index 8a6d164..7f8d743 100644
--- a/include/net/switchdev.h
+++ b/include/net/switchdev.h
@@ -11,12 +11,27 @@
#define _LINUX_SWITCHDEV_H_
#include <linux/netdevice.h>
+#include <linux/notifier.h>
+
+struct netdev_switch_notifier_info {
+ struct net_device *dev;
+};
+
+static inline struct net_device *
+netdev_switch_notifier_info_to_dev(const struct netdev_switch_notifier_info *info)
+{
+ return info->dev;
+}
#ifdef CONFIG_NET_SWITCHDEV
int netdev_switch_parent_id_get(struct net_device *dev,
struct netdev_phys_item_id *psid);
int netdev_switch_port_stp_update(struct net_device *dev, u8 state);
+int register_netdev_switch_notifier(struct notifier_block *nb);
+int unregister_netdev_switch_notifier(struct notifier_block *nb);
+int call_netdev_switch_notifiers(unsigned long val, struct net_device *dev,
+ struct netdev_switch_notifier_info *info);
#else
@@ -32,6 +47,22 @@ static inline int netdev_switch_port_stp_update(struct net_device *dev,
return -EOPNOTSUPP;
}
+static inline int register_netdev_switch_notifier(struct notifier_block *nb)
+{
+ return 0;
+}
+
+static inline int unregister_netdev_switch_notifier(struct notifier_block *nb)
+{
+ return 0;
+}
+
+static inline int call_netdev_switch_notifiers(unsigned long val, struct net_device *dev,
+ struct netdev_switch_notifier_info *info);
+{
+ return NOTIFY_DONE;
+}
+
#endif
#endif /* _LINUX_SWITCHDEV_H_ */
diff --git a/net/switchdev/switchdev.c b/net/switchdev/switchdev.c
index d162b21..22e02f4 100644
--- a/net/switchdev/switchdev.c
+++ b/net/switchdev/switchdev.c
@@ -11,6 +11,8 @@
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/init.h>
+#include <linux/mutex.h>
+#include <linux/notifier.h>
#include <linux/netdevice.h>
#include <net/switchdev.h>
@@ -50,3 +52,66 @@ int netdev_switch_port_stp_update(struct net_device *dev, u8 state)
return ops->ndo_switch_port_stp_update(dev, state);
}
EXPORT_SYMBOL(netdev_switch_port_stp_update);
+
+static DEFINE_MUTEX(netdev_switch_mutex);
+static RAW_NOTIFIER_HEAD(netdev_switch_notif_chain);
+
+/**
+ * register_netdev_switch_notifier - Register nofifier
+ * @nb: notifier_block
+ *
+ * Register switch device notifier. This should be used by code
+ * which needs to monitor events happening in particular device.
+ * Return values are same as for atomic_notifier_chain_register().
+ */
+int register_netdev_switch_notifier(struct notifier_block *nb)
+{
+ int err;
+
+ mutex_lock(&netdev_switch_mutex);
+ err = raw_notifier_chain_register(&netdev_switch_notif_chain, nb);
+ mutex_unlock(&netdev_switch_mutex);
+ return err;
+}
+EXPORT_SYMBOL(register_netdev_switch_notifier);
+
+/**
+ * unregister_netdev_switch_notifier - Unregister nofifier
+ * @nb: notifier_block
+ *
+ * Unregister switch device notifier.
+ * Return values are same as for atomic_notifier_chain_unregister().
+ */
+int unregister_netdev_switch_notifier(struct notifier_block *nb)
+{
+ int err;
+
+ mutex_lock(&netdev_switch_mutex);
+ err = raw_notifier_chain_unregister(&netdev_switch_notif_chain, nb);
+ mutex_unlock(&netdev_switch_mutex);
+ return err;
+}
+EXPORT_SYMBOL(unregister_netdev_switch_notifier);
+
+/**
+ * call_netdev_switch_notifiers - Call nofifiers
+ * @val: value passed unmodified to notifier function
+ * @dev: port device
+ * @info: notifier information data
+ *
+ * Call all network notifier blocks. This should be called by driver
+ * when it needs to propagate hardware event.
+ * Return values are same as for atomic_notifier_call_chain().
+ */
+int call_netdev_switch_notifiers(unsigned long val, struct net_device *dev,
+ struct netdev_switch_notifier_info *info)
+{
+ int err;
+
+ info->dev = dev;
+ mutex_lock(&netdev_switch_mutex);
+ err = raw_notifier_call_chain(&netdev_switch_notif_chain, val, info);
+ mutex_unlock(&netdev_switch_mutex);
+ return err;
+}
+EXPORT_SYMBOL(call_netdev_switch_notifiers);
--
1.9.3
^ permalink raw reply related
* [PATCH 5/6] net: davinci_emac: Fix ioremap for devices with MDIO within the EMAC address space
From: Tony Lindgren @ 2015-01-15 22:45 UTC (permalink / raw)
To: David Miller; +Cc: netdev, linux-omap, Brian Hutchinson, Felipe Balbi
In-Reply-To: <1421361914-4612-1-git-send-email-tony@atomide.com>
Some devices like dm816x have the MDIO registers within the first EMAC
instance address space. Let's fix the issue by allowing to pass an
optional second IO range for the EMAC control register area.
Cc: Brian Hutchinson <b.hutchman@gmail.com>
Cc: Felipe Balbi <balbi@ti.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
---
drivers/net/ethernet/ti/davinci_emac.c | 15 ++++++++++++---
1 file changed, 12 insertions(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/ti/davinci_emac.c b/drivers/net/ethernet/ti/davinci_emac.c
index e44c8d8..1e5ea81 100644
--- a/drivers/net/ethernet/ti/davinci_emac.c
+++ b/drivers/net/ethernet/ti/davinci_emac.c
@@ -1890,7 +1890,7 @@ davinci_emac_of_get_pdata(struct platform_device *pdev, struct emac_priv *priv)
static int davinci_emac_probe(struct platform_device *pdev)
{
int rc = 0;
- struct resource *res;
+ struct resource *res, *res_ctrl;
struct net_device *ndev;
struct emac_priv *priv;
unsigned long hw_ram_addr;
@@ -1949,11 +1949,20 @@ static int davinci_emac_probe(struct platform_device *pdev)
rc = PTR_ERR(priv->remap_addr);
goto no_pdata;
}
+
+ res_ctrl = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ if (res_ctrl) {
+ priv->ctrl_base =
+ devm_ioremap_resource(&pdev->dev, res_ctrl);
+ if (IS_ERR(priv->ctrl_base))
+ goto no_pdata;
+ } else {
+ priv->ctrl_base = priv->remap_addr + pdata->ctrl_mod_reg_offset;
+ }
+
priv->emac_base = priv->remap_addr + pdata->ctrl_reg_offset;
ndev->base_addr = (unsigned long)priv->remap_addr;
- priv->ctrl_base = priv->remap_addr + pdata->ctrl_mod_reg_offset;
-
hw_ram_addr = pdata->hw_ram_addr;
if (!hw_ram_addr)
hw_ram_addr = (u32 __force)res->start + pdata->ctrl_ram_offset;
--
2.1.4
^ permalink raw reply related
* [PATCH 4/6] net: davinci_emac: Fix incomplete code for getting the phy from device tree
From: Tony Lindgren @ 2015-01-15 22:45 UTC (permalink / raw)
To: David Miller; +Cc: netdev, linux-omap, Brian Hutchinson, Felipe Balbi
In-Reply-To: <1421361914-4612-1-git-send-email-tony@atomide.com>
Looks like the phy_id is never set up beyond getting the phandle.
Note that we can remove the ifdef for phy_node as there is a stub
for of_phy_connec() if CONFIG_OF is not set.
Cc: Brian Hutchinson <b.hutchman@gmail.com>
Cc: Felipe Balbi <balbi@ti.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
---
drivers/net/ethernet/ti/davinci_emac.c | 23 ++++++++++++++++++-----
1 file changed, 18 insertions(+), 5 deletions(-)
diff --git a/drivers/net/ethernet/ti/davinci_emac.c b/drivers/net/ethernet/ti/davinci_emac.c
index 59fdcdd..e44c8d8 100644
--- a/drivers/net/ethernet/ti/davinci_emac.c
+++ b/drivers/net/ethernet/ti/davinci_emac.c
@@ -62,6 +62,7 @@
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_device.h>
+#include <linux/of_mdio.h>
#include <linux/of_irq.h>
#include <linux/of_net.h>
@@ -343,9 +344,7 @@ struct emac_priv {
u32 multicast_hash_cnt[EMAC_NUM_MULTICAST_BITS];
u32 rx_addr_type;
const char *phy_id;
-#ifdef CONFIG_OF
struct device_node *phy_node;
-#endif
struct phy_device *phydev;
spinlock_t lock;
/*platform specific members*/
@@ -1603,8 +1602,20 @@ static int emac_dev_open(struct net_device *ndev)
cpdma_ctlr_start(priv->dma);
priv->phydev = NULL;
+
+ if (priv->phy_node) {
+ priv->phydev = of_phy_connect(ndev, priv->phy_node,
+ &emac_adjust_link, 0, 0);
+ if (!priv->phydev) {
+ dev_err(emac_dev, "could not connect to phy %s\n",
+ priv->phy_node->full_name);
+ ret = -ENODEV;
+ goto err;
+ }
+ }
+
/* use the first phy on the bus if pdata did not give us a phy id */
- if (!priv->phy_id) {
+ if (!priv->phydev && !priv->phy_id) {
struct device *phy;
phy = bus_find_device(&mdio_bus_type, NULL, NULL,
@@ -1613,7 +1624,7 @@ static int emac_dev_open(struct net_device *ndev)
priv->phy_id = dev_name(phy);
}
- if (priv->phy_id && *priv->phy_id) {
+ if (!priv->phydev && priv->phy_id && *priv->phy_id) {
priv->phydev = phy_connect(ndev, priv->phy_id,
&emac_adjust_link,
PHY_INTERFACE_MODE_MII);
@@ -1634,7 +1645,9 @@ static int emac_dev_open(struct net_device *ndev)
"(mii_bus:phy_addr=%s, id=%x)\n",
priv->phydev->drv->name, dev_name(&priv->phydev->dev),
priv->phydev->phy_id);
- } else {
+ }
+
+ if (!priv->phydev) {
/* No PHY , fix the link, speed and duplex settings */
dev_notice(emac_dev, "no phy, defaulting to 100/full\n");
priv->link = 1;
--
2.1.4
^ permalink raw reply related
* [PATCHv2 0/6] Fixes for davinci_emac
From: Tony Lindgren @ 2015-01-15 22:45 UTC (permalink / raw)
To: David Miller; +Cc: netdev, linux-omap
Hi,
Here's a repost of the fixes for davinci_emac with patches
updated for comments and acks collected.
Regards,
Tony
Tony Lindgren (6):
net: davinci_emac: Fix hangs with interrupts
net: davinci_emac: Fix runtime pm calls for davinci_emac
net: davinci_emac: Free clock after checking the frequency
net: davinci_emac: Fix incomplete code for getting the phy from device
tree
net: davinci_emac: Fix ioremap for devices with MDIO within the EMAC
address space
net: davinci_emac: Add support for emac on dm816x
.../devicetree/bindings/net/davinci_emac.txt | 3 +-
drivers/net/ethernet/ti/davinci_emac.c | 96 +++++++++++++++++-----
2 files changed, 77 insertions(+), 22 deletions(-)
--
2.1.4
^ permalink raw reply
* [PATCH 6/6] net: davinci_emac: Add support for emac on dm816x
From: Tony Lindgren @ 2015-01-15 22:45 UTC (permalink / raw)
To: David Miller; +Cc: netdev, linux-omap, Brian Hutchinson, Felipe Balbi
In-Reply-To: <1421361914-4612-1-git-send-email-tony@atomide.com>
On dm816x we have two emac controllers with separate memory
areas.
Cc: Brian Hutchinson <b.hutchman@gmail.com>
Cc: Felipe Balbi <balbi@ti.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
---
Documentation/devicetree/bindings/net/davinci_emac.txt | 3 ++-
drivers/net/ethernet/ti/davinci_emac.c | 5 +++++
2 files changed, 7 insertions(+), 1 deletion(-)
diff --git a/Documentation/devicetree/bindings/net/davinci_emac.txt b/Documentation/devicetree/bindings/net/davinci_emac.txt
index 0328088..24c5cda 100644
--- a/Documentation/devicetree/bindings/net/davinci_emac.txt
+++ b/Documentation/devicetree/bindings/net/davinci_emac.txt
@@ -4,7 +4,8 @@ This file provides information, what the device node
for the davinci_emac interface contains.
Required properties:
-- compatible: "ti,davinci-dm6467-emac" or "ti,am3517-emac"
+- compatible: "ti,davinci-dm6467-emac", "ti,am3517-emac" or
+ "ti,dm816-emac"
- reg: Offset and length of the register set for the device
- ti,davinci-ctrl-reg-offset: offset to control register
- ti,davinci-ctrl-mod-reg-offset: offset to control module register
diff --git a/drivers/net/ethernet/ti/davinci_emac.c b/drivers/net/ethernet/ti/davinci_emac.c
index 1e5ea81..5fae435 100644
--- a/drivers/net/ethernet/ti/davinci_emac.c
+++ b/drivers/net/ethernet/ti/davinci_emac.c
@@ -2120,9 +2120,14 @@ static const struct emac_platform_data am3517_emac_data = {
.hw_ram_addr = 0x01e20000,
};
+static const struct emac_platform_data dm816_emac_data = {
+ .version = EMAC_VERSION_2,
+};
+
static const struct of_device_id davinci_emac_of_match[] = {
{.compatible = "ti,davinci-dm6467-emac", },
{.compatible = "ti,am3517-emac", .data = &am3517_emac_data, },
+ {.compatible = "ti,dm816-emac", .data = &dm816_emac_data, },
{},
};
MODULE_DEVICE_TABLE(of, davinci_emac_of_match);
--
2.1.4
^ permalink raw reply related
* [PATCH 3/6] net: davinci_emac: Free clock after checking the frequency
From: Tony Lindgren @ 2015-01-15 22:45 UTC (permalink / raw)
To: David Miller; +Cc: netdev, linux-omap, Brian Hutchinson, Felipe Balbi
In-Reply-To: <1421361914-4612-1-git-send-email-tony@atomide.com>
We only use clk_get() to get the frequency, the rest is done by
the runtime PM calls. Let's free the clock too.
Cc: Brian Hutchinson <b.hutchman@gmail.com>
Cc: Felipe Balbi <balbi@ti.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
---
drivers/net/ethernet/ti/davinci_emac.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/net/ethernet/ti/davinci_emac.c b/drivers/net/ethernet/ti/davinci_emac.c
index 5df339e..59fdcdd 100644
--- a/drivers/net/ethernet/ti/davinci_emac.c
+++ b/drivers/net/ethernet/ti/davinci_emac.c
@@ -1894,6 +1894,7 @@ static int davinci_emac_probe(struct platform_device *pdev)
return -EBUSY;
}
emac_bus_frequency = clk_get_rate(emac_clk);
+ devm_clk_put(&pdev->dev, emac_clk);
/* TODO: Probe PHY here if possible */
--
2.1.4
^ permalink raw reply related
* [PATCH 2/6] net: davinci_emac: Fix runtime pm calls for davinci_emac
From: Tony Lindgren @ 2015-01-15 22:45 UTC (permalink / raw)
To: David Miller; +Cc: netdev, linux-omap, Brian Hutchinson
In-Reply-To: <1421361914-4612-1-git-send-email-tony@atomide.com>
Commit 3ba97381343b ("net: ethernet: davinci_emac: add pm_runtime support")
added support for runtime PM, but it causes issues on omap3 related devices
that actually gate the clocks:
Unhandled fault: external abort on non-linefetch (0x1008)
...
[<c04160f0>] (emac_dev_getnetstats) from [<c04d6a3c>] (dev_get_stats+0x78/0xc8)
[<c04d6a3c>] (dev_get_stats) from [<c04e9ccc>] (rtnl_fill_ifinfo+0x3b8/0x938)
[<c04e9ccc>] (rtnl_fill_ifinfo) from [<c04eade4>] (rtmsg_ifinfo+0x68/0xd8)
[<c04eade4>] (rtmsg_ifinfo) from [<c04dd35c>] (register_netdevice+0x3a0/0x4ec)
[<c04dd35c>] (register_netdevice) from [<c04dd4bc>] (register_netdev+0x14/0x24)
[<c04dd4bc>] (register_netdev) from [<c041755c>] (davinci_emac_probe+0x408/0x5c8)
[<c041755c>] (davinci_emac_probe) from [<c0396d78>] (platform_drv_probe+0x48/0xa4)
Let's fix it by moving the pm_runtime_get() call earlier, and also add it to
the emac_dev_getnetstats(). Also note that we want to use pm_runtime_get_sync()
as we don't want to have deferred_resume happen. And let's also check the
return value for pm_runtime_get_sync() as noted by Felipe Balbi <balbi@ti.com>.
Cc: Brian Hutchinson <b.hutchman@gmail.com>
Acked-by: Mark A. Greer <mgreer@animalcreek.com>
Reviewed-by: Felipe Balbi <balbi@ti.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
---
drivers/net/ethernet/ti/davinci_emac.c | 33 +++++++++++++++++++++++++++++----
1 file changed, 29 insertions(+), 4 deletions(-)
diff --git a/drivers/net/ethernet/ti/davinci_emac.c b/drivers/net/ethernet/ti/davinci_emac.c
index 383ed52..5df339e 100644
--- a/drivers/net/ethernet/ti/davinci_emac.c
+++ b/drivers/net/ethernet/ti/davinci_emac.c
@@ -1538,7 +1538,13 @@ static int emac_dev_open(struct net_device *ndev)
int i = 0;
struct emac_priv *priv = netdev_priv(ndev);
- pm_runtime_get(&priv->pdev->dev);
+ ret = pm_runtime_get_sync(&priv->pdev->dev);
+ if (ret < 0) {
+ pm_runtime_put_noidle(&priv->pdev->dev);
+ dev_err(&priv->pdev->dev, "%s: failed to get_sync(%d)\n",
+ __func__, ret);
+ return ret;
+ }
netif_carrier_off(ndev);
for (cnt = 0; cnt < ETH_ALEN; cnt++)
@@ -1725,6 +1731,15 @@ static struct net_device_stats *emac_dev_getnetstats(struct net_device *ndev)
struct emac_priv *priv = netdev_priv(ndev);
u32 mac_control;
u32 stats_clear_mask;
+ int err;
+
+ err = pm_runtime_get_sync(&priv->pdev->dev);
+ if (err < 0) {
+ pm_runtime_put_noidle(&priv->pdev->dev);
+ dev_err(&priv->pdev->dev, "%s: failed to get_sync(%d)\n",
+ __func__, err);
+ return &ndev->stats;
+ }
/* update emac hardware stats and reset the registers*/
@@ -1767,6 +1782,8 @@ static struct net_device_stats *emac_dev_getnetstats(struct net_device *ndev)
ndev->stats.tx_fifo_errors += emac_read(EMAC_TXUNDERRUN);
emac_write(EMAC_TXUNDERRUN, stats_clear_mask);
+ pm_runtime_put(&priv->pdev->dev);
+
return &ndev->stats;
}
@@ -1981,12 +1998,22 @@ static int davinci_emac_probe(struct platform_device *pdev)
ndev->ethtool_ops = ðtool_ops;
netif_napi_add(ndev, &priv->napi, emac_poll, EMAC_POLL_WEIGHT);
+ pm_runtime_enable(&pdev->dev);
+ rc = pm_runtime_get_sync(&pdev->dev);
+ if (rc < 0) {
+ pm_runtime_put_noidle(&pdev->dev);
+ dev_err(&pdev->dev, "%s: failed to get_sync(%d)\n",
+ __func__, rc);
+ goto no_cpdma_chan;
+ }
+
/* register the network device */
SET_NETDEV_DEV(ndev, &pdev->dev);
rc = register_netdev(ndev);
if (rc) {
dev_err(&pdev->dev, "error in register_netdev\n");
rc = -ENODEV;
+ pm_runtime_put(&pdev->dev);
goto no_cpdma_chan;
}
@@ -1996,9 +2023,7 @@ static int davinci_emac_probe(struct platform_device *pdev)
"(regs: %p, irq: %d)\n",
(void *)priv->emac_base_phys, ndev->irq);
}
-
- pm_runtime_enable(&pdev->dev);
- pm_runtime_resume(&pdev->dev);
+ pm_runtime_put(&pdev->dev);
return 0;
--
2.1.4
^ permalink raw reply related
* [PATCH 1/6] net: davinci_emac: Fix hangs with interrupts
From: Tony Lindgren @ 2015-01-15 22:45 UTC (permalink / raw)
To: David Miller; +Cc: netdev, linux-omap, Brian Hutchinson
In-Reply-To: <1421361914-4612-1-git-send-email-tony@atomide.com>
On davinci_emac, we have pulse interrupts. This means that we need to
clear the EOI bits when disabling interrupts as otherwise the interrupts
keep happening. And we also need to not clear the EOI bits again when
enabling the interrupts as otherwise we will get tons of:
unexpected IRQ trap at vector 00
These errors almost certainly mean that the omap-intc.c is signaling
a spurious interrupt with the reserved irq 127 as we've seen earlier
on omap3.
Let's fix the issue by clearing the EOI bits when disabling the
interrupts. Let's also keep the comment for "Rx Threshold and Misc
interrupts are not enabled" for both enable and disable so people
are aware of this when potentially adding more support.
Note that eventually we should handle the RX and TX interrupts
separately like cpsw is now doing. However, so far I have not seen
any issues with this based on my testing, so it seems to behave a
little different compared to the cpsw that had a similar issue.
Cc: Brian Hutchinson <b.hutchman@gmail.com>
Reviewed-by: Felipe Balbi <balbi@ti.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
---
drivers/net/ethernet/ti/davinci_emac.c | 19 ++++++++++---------
1 file changed, 10 insertions(+), 9 deletions(-)
diff --git a/drivers/net/ethernet/ti/davinci_emac.c b/drivers/net/ethernet/ti/davinci_emac.c
index ea71251..383ed52 100644
--- a/drivers/net/ethernet/ti/davinci_emac.c
+++ b/drivers/net/ethernet/ti/davinci_emac.c
@@ -922,6 +922,16 @@ static void emac_int_disable(struct emac_priv *priv)
if (priv->int_disable)
priv->int_disable();
+ /* NOTE: Rx Threshold and Misc interrupts are not enabled */
+
+ /* ack rxen only then a new pulse will be generated */
+ emac_write(EMAC_DM646X_MACEOIVECTOR,
+ EMAC_DM646X_MAC_EOI_C0_RXEN);
+
+ /* ack txen- only then a new pulse will be generated */
+ emac_write(EMAC_DM646X_MACEOIVECTOR,
+ EMAC_DM646X_MAC_EOI_C0_TXEN);
+
local_irq_restore(flags);
} else {
@@ -951,15 +961,6 @@ static void emac_int_enable(struct emac_priv *priv)
* register */
/* NOTE: Rx Threshold and Misc interrupts are not enabled */
-
- /* ack rxen only then a new pulse will be generated */
- emac_write(EMAC_DM646X_MACEOIVECTOR,
- EMAC_DM646X_MAC_EOI_C0_RXEN);
-
- /* ack txen- only then a new pulse will be generated */
- emac_write(EMAC_DM646X_MACEOIVECTOR,
- EMAC_DM646X_MAC_EOI_C0_TXEN);
-
} else {
/* Set DM644x control registers for interrupt control */
emac_ctrl_write(EMAC_CTRL_EWCTL, 0x1);
--
2.1.4
^ permalink raw reply related
* RE: [net-next 10/17] i40e: clean up PTP log messages
From: Nelson, Shannon @ 2015-01-15 22:44 UTC (permalink / raw)
To: David Miller
Cc: David.Laight@ACULAB.COM, Kirsher, Jeffrey T,
netdev@vger.kernel.org, nhorman@redhat.com, sassmann@redhat.com,
jogreene@redhat.com, Keller, Jacob E
In-Reply-To: <20150115.153846.1450539700341201746.davem@davemloft.net>
> From: David Miller [mailto:davem@davemloft.net]
> Sent: Thursday, January 15, 2015 12:39 PM
>
> From: "Nelson, Shannon" <shannon.nelson@intel.com>
> Date: Thu, 15 Jan 2015 15:01:42 +0000
>
> > The dev_info() messages have the PCI device and function number in the
> string, so it's really not too hard to track down the resulting netdev
> port:
> > Jan 13 15:46:55 snelson3-cup kernel: [621235.401627] i40e
> 0000:84:00.1: PHC enabled
> >
> > Later messages use netdev_info() and have both the device number and
> the netdev name:
> > Jan 13 15:46:56 snelson3-cup kernel: [621236.508868] i40e 0000:04:00.1
> p261p2: NIC Link is Up 10 Gbps Full Duplex, Flow Control: None
> >
> > Note that the driver name appears in both as well.
>
> I think we should consistently provide the netdev name as soon as
> register_netdevice() returns.
>
> It is unwise for every driver to have their own private policy on
> this.
>
> Please change this back.
Sure, we can simply drop this patch.
<useless whine>
Yes, the driver should print the unvarnished truth. What's frustrating about UDEV is that it ends up making the driver look like it is confused and/or lying in the log messages. We'd prefer to minimize this unnecessary user-confusion where possible.
</useless whine>
sln
^ permalink raw reply
* Re: [PATCH net] net: rps: fix cpu unplug
From: subashab @ 2015-01-15 22:29 UTC (permalink / raw)
To: Eric Dumazet; +Cc: Prasad Sodagudi, netdev, Tom Herbert
In-Reply-To: <1421358383.11734.97.camel@edumazet-glaptop2.roam.corp.google.com>
Thanks for the patch. I shall try it out and provide feedback soon.
But we think the race condition issue is different. The crash was observed
in the process_queue.
On the event of a CPU hotplug, the NAPI poll_list is copied over from the
offline CPU to the CPU on which dev_cpu_callback() was called. These
operations happens in dev_cpu_callback() in the context of the notifier
chain from hotplug framework. Also in the same hotplug notifier context
(dev_cpu_callback) the input_pkt_queue and process_queue of the offline
CPU are dequeued and sent up the network stack and this is where I think
the race/problem is.
Context1: The online CPU starts processing the poll_list from
net_rx_action since a
softIRQ was raised in dev_cpu_callback(). process_backlog() draining the
process queue
Context2: hotplug notifier dev_cpu_callback() draining the queues and
calling netif_rx().
from dev_cpu_callback()
/* Process offline CPU's input_pkt_queue */
while ((skb = __skb_dequeue(&oldsd->process_queue))) {
netif_rx(skb);
input_queue_head_incr(oldsd);
}
while ((skb = __skb_dequeue(&oldsd->input_pkt_queue))) {
netif_rx(skb);
input_queue_head_incr(oldsd);
}
Is this de-queuing(the above code snippet from dev_cpu_callback())
actually necessary since the poll_list should already have the backlog
napi struct of the old CPU? In this case when process_backlog()
actually runs it should drain these two queues of older CPU.
Let me know your thoughts.
Thanks
KS
The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
> From: Eric Dumazet <edumazet@google.com>
>
> softnet_data.input_pkt_queue is protected by a spinlock that
> we must hold when transferring packets from victim queue to an active
> one. This is because other cpus could still be trying to enqueue packets
> into victim queue.
>
> Based on initial patch from Prasad Sodagudi & Subash Abhinov
> Kasiviswanathan.
>
> This version is better because we do not slow down packet processing,
> only make migration safer.
>
> Reported-by: Prasad Sodagudi <psodagud@codeaurora.org>
> Reported-by: Subash Abhinov Kasiviswanathan <subashab@codeaurora.org>
> Signed-off-by: Eric Dumazet <edumazet@google.com>
> Cc: Tom Herbert <therbert@google.com>
> ---
>
> Could you test this fix instead of yours ? Thanks !
>
> net/core/dev.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/net/core/dev.c b/net/core/dev.c
> index
> 1e325adc43678084418ef9e1abb1fca8059ff599..76f72762b325cfa927a793af180189c51e9eaffd
> 100644
> --- a/net/core/dev.c
> +++ b/net/core/dev.c
> @@ -7089,7 +7089,7 @@ static int dev_cpu_callback(struct notifier_block
> *nfb,
> netif_rx_internal(skb);
> input_queue_head_incr(oldsd);
> }
> - while ((skb = __skb_dequeue(&oldsd->input_pkt_queue))) {
> + while ((skb = skb_dequeue(&oldsd->input_pkt_queue))) {
> netif_rx_internal(skb);
> input_queue_head_incr(oldsd);
> }
>
>
> --
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
^ permalink raw reply
* [PATCH v3 1/3] net/macb: Fix comments to meet style guidelines
From: Xander Huff @ 2015-01-15 21:55 UTC (permalink / raw)
To: davem, nicolas.ferre, david.laight
Cc: netdev, jaeden.amero, rich.tollerton, brad.mouring, linux-kernel,
cyrille.pitchen, Xander Huff
In-Reply-To: <063D6719AE5E284EB5DD2968C1650D6D1CAC999F@AcuExch.aculab.com>
Change comments to not exceed 80 characters per line.
Update block comments in macb.h to start on the line after /*.
Signed-off-by: Xander Huff <xander.huff@ni.com>
---
Re-sending to properly include David Laight
drivers/net/ethernet/cadence/macb.h | 734 ++++++++++++++----------------------
1 file changed, 284 insertions(+), 450 deletions(-)
diff --git a/drivers/net/ethernet/cadence/macb.h b/drivers/net/ethernet/cadence/macb.h
index 378b218..31dc080 100644
--- a/drivers/net/ethernet/cadence/macb.h
+++ b/drivers/net/ethernet/cadence/macb.h
@@ -15,471 +15,309 @@
#define MACB_MAX_QUEUES 8
/* MACB register offsets */
-#define MACB_NCR 0x0000 /* Network Control */
-#define MACB_NCFGR 0x0004 /* Network Config */
-#define MACB_NSR 0x0008 /* Network Status */
-#define MACB_TAR 0x000c /* AT91RM9200 only */
-#define MACB_TCR 0x0010 /* AT91RM9200 only */
-#define MACB_TSR 0x0014 /* Transmit Status */
-#define MACB_RBQP 0x0018 /* RX Q Base Address */
-#define MACB_TBQP 0x001c /* TX Q Base Address */
-#define MACB_RSR 0x0020 /* Receive Status */
-#define MACB_ISR 0x0024 /* Interrupt Status */
-#define MACB_IER 0x0028 /* Interrupt Enable */
-#define MACB_IDR 0x002c /* Interrupt Disable */
-#define MACB_IMR 0x0030 /* Interrupt Mask */
-#define MACB_MAN 0x0034 /* PHY Maintenance */
-#define MACB_PTR 0x0038
-#define MACB_PFR 0x003c
-#define MACB_FTO 0x0040
-#define MACB_SCF 0x0044
-#define MACB_MCF 0x0048
-#define MACB_FRO 0x004c
-#define MACB_FCSE 0x0050
-#define MACB_ALE 0x0054
-#define MACB_DTF 0x0058
-#define MACB_LCOL 0x005c
-#define MACB_EXCOL 0x0060
-#define MACB_TUND 0x0064
-#define MACB_CSE 0x0068
-#define MACB_RRE 0x006c
-#define MACB_ROVR 0x0070
-#define MACB_RSE 0x0074
-#define MACB_ELE 0x0078
-#define MACB_RJA 0x007c
-#define MACB_USF 0x0080
-#define MACB_STE 0x0084
-#define MACB_RLE 0x0088
-#define MACB_TPF 0x008c
-#define MACB_HRB 0x0090
-#define MACB_HRT 0x0094
-#define MACB_SA1B 0x0098
-#define MACB_SA1T 0x009c
-#define MACB_SA2B 0x00a0
-#define MACB_SA2T 0x00a4
-#define MACB_SA3B 0x00a8
-#define MACB_SA3T 0x00ac
-#define MACB_SA4B 0x00b0
-#define MACB_SA4T 0x00b4
-#define MACB_TID 0x00b8
-#define MACB_TPQ 0x00bc
-#define MACB_USRIO 0x00c0
-#define MACB_WOL 0x00c4
-#define MACB_MID 0x00fc
+#define MACB_NCR 0x0000 /* Network Control */
+#define MACB_NCFGR 0x0004 /* Network Config */
+#define MACB_NSR 0x0008 /* Network Status */
+#define MACB_TAR 0x000c /* AT91RM9200 only */
+#define MACB_TCR 0x0010 /* AT91RM9200 only */
+#define MACB_TSR 0x0014 /* Transmit Status */
+#define MACB_RBQP 0x0018 /* RX Q Base Address */
+#define MACB_TBQP 0x001c /* TX Q Base Address */
+#define MACB_RSR 0x0020 /* Receive Status */
+#define MACB_ISR 0x0024 /* Interrupt Status */
+#define MACB_IER 0x0028 /* Interrupt Enable */
+#define MACB_IDR 0x002c /* Interrupt Disable */
+#define MACB_IMR 0x0030 /* Interrupt Mask */
+#define MACB_MAN 0x0034 /* PHY Maintenance */
+#define MACB_PTR 0x0038
+#define MACB_PFR 0x003c
+#define MACB_FTO 0x0040
+#define MACB_SCF 0x0044
+#define MACB_MCF 0x0048
+#define MACB_FRO 0x004c
+#define MACB_FCSE 0x0050
+#define MACB_ALE 0x0054
+#define MACB_DTF 0x0058
+#define MACB_LCOL 0x005c
+#define MACB_EXCOL 0x0060
+#define MACB_TUND 0x0064
+#define MACB_CSE 0x0068
+#define MACB_RRE 0x006c
+#define MACB_ROVR 0x0070
+#define MACB_RSE 0x0074
+#define MACB_ELE 0x0078
+#define MACB_RJA 0x007c
+#define MACB_USF 0x0080
+#define MACB_STE 0x0084
+#define MACB_RLE 0x0088
+#define MACB_TPF 0x008c
+#define MACB_HRB 0x0090
+#define MACB_HRT 0x0094
+#define MACB_SA1B 0x0098
+#define MACB_SA1T 0x009c
+#define MACB_SA2B 0x00a0
+#define MACB_SA2T 0x00a4
+#define MACB_SA3B 0x00a8
+#define MACB_SA3T 0x00ac
+#define MACB_SA4B 0x00b0
+#define MACB_SA4T 0x00b4
+#define MACB_TID 0x00b8
+#define MACB_TPQ 0x00bc
+#define MACB_USRIO 0x00c0
+#define MACB_WOL 0x00c4
+#define MACB_MID 0x00fc
/* GEM register offsets. */
-#define GEM_NCFGR 0x0004 /* Network Config */
-#define GEM_USRIO 0x000c /* User IO */
-#define GEM_DMACFG 0x0010 /* DMA Configuration */
-#define GEM_HRB 0x0080 /* Hash Bottom */
-#define GEM_HRT 0x0084 /* Hash Top */
-#define GEM_SA1B 0x0088 /* Specific1 Bottom */
-#define GEM_SA1T 0x008C /* Specific1 Top */
-#define GEM_SA2B 0x0090 /* Specific2 Bottom */
-#define GEM_SA2T 0x0094 /* Specific2 Top */
-#define GEM_SA3B 0x0098 /* Specific3 Bottom */
-#define GEM_SA3T 0x009C /* Specific3 Top */
-#define GEM_SA4B 0x00A0 /* Specific4 Bottom */
-#define GEM_SA4T 0x00A4 /* Specific4 Top */
-#define GEM_OTX 0x0100 /* Octets transmitted */
-#define GEM_OCTTXL 0x0100 /* Octets transmitted
- * [31:0]
- */
-#define GEM_OCTTXH 0x0104 /* Octets transmitted
- * [47:32]
- */
-#define GEM_TXCNT 0x0108 /* Error-free Frames
- * Transmitted counter
- */
-#define GEM_TXBCCNT 0x010c /* Error-free Broadcast
- * Frames counter
- */
-#define GEM_TXMCCNT 0x0110 /* Error-free Multicast
- * Frames counter
- */
-#define GEM_TXPAUSECNT 0x0114 /* Pause Frames
- * Transmitted Counter
- */
-#define GEM_TX64CNT 0x0118 /* Error-free 64 byte
- * Frames Transmitted
- * counter
- */
-#define GEM_TX65CNT 0x011c /* Error-free 65-127 byte
- * Frames Transmitted
- * counter
- */
-#define GEM_TX128CNT 0x0120 /* Error-free 128-255
- * byte Frames
- * Transmitted counter
- */
-#define GEM_TX256CNT 0x0124 /* Error-free 256-511
- * byte Frames
- * transmitted counter
- */
-#define GEM_TX512CNT 0x0128 /* Error-free 512-1023
- * byte Frames
- * transmitted counter
- */
-#define GEM_TX1024CNT 0x012c /* Error-free 1024-1518
- * byte Frames
- * transmitted counter
- */
-#define GEM_TX1519CNT 0x0130 /* Error-free larger than
- * 1519 byte Frames
- * tranmitted counter
- */
-#define GEM_TXURUNCNT 0x0134 /* TX under run error
- * counter
- */
-#define GEM_SNGLCOLLCNT 0x0138 /* Single Collision Frame
- * Counter
- */
-#define GEM_MULTICOLLCNT 0x013c /* Multiple Collision
- * Frame Counter
- */
-#define GEM_EXCESSCOLLCNT 0x0140 /* Excessive Collision
- * Frame Counter
- */
-#define GEM_LATECOLLCNT 0x0144 /* Late Collision Frame
- * Counter
- */
-#define GEM_TXDEFERCNT 0x0148 /* Deferred Transmission
- * Frame Counter
- */
-#define GEM_TXCSENSECNT 0x014c /* Carrier Sense Error
- * Counter
- */
-#define GEM_ORX 0x0150 /* Octets received */
-#define GEM_OCTRXL 0x0150 /* Octets received
- * [31:0]
- */
-#define GEM_OCTRXH 0x0154 /* Octets received
- * [47:32]
- */
-#define GEM_RXCNT 0x0158 /* Error-free Frames
- * Received Counter
- */
-#define GEM_RXBROADCNT 0x015c /* Error-free Broadcast
- * Frames Received
- * Counter
- */
-#define GEM_RXMULTICNT 0x0160 /* Error-free Multicast
- * Frames Received
- * Counter
- */
-#define GEM_RXPAUSECNT 0x0164 /* Error-free Pause
- * Frames Received
- * Counter
- */
-#define GEM_RX64CNT 0x0168 /* Error-free 64 byte
- * Frames Received
- * Counter
- */
-#define GEM_RX65CNT 0x016c /* Error-free 65-127 byte
- * Frames Received
- * Counter
- */
-#define GEM_RX128CNT 0x0170 /* Error-free 128-255
- * byte Frames Received
- * Counter
- */
-#define GEM_RX256CNT 0x0174 /* Error-free 256-511
- * byte Frames Received
- * Counter
- */
-#define GEM_RX512CNT 0x0178 /* Error-free 512-1023
- * byte Frames Received
- * Counter
- */
-#define GEM_RX1024CNT 0x017c /* Error-free 1024-1518
- * byte Frames Received
- * Counter
- */
-#define GEM_RX1519CNT 0x0180 /* Error-free larger than
- * 1519 Frames Received
- * Counter
- */
-#define GEM_RXUNDRCNT 0x0184 /* Undersize Frames
- * Received Counter
- */
-#define GEM_RXOVRCNT 0x0188 /* Oversize Frames
- * Received Counter
- */
-#define GEM_RXJABCNT 0x018c /* Jabbers Received
- * Counter
- */
-#define GEM_RXFCSCNT 0x0190 /* Frame Check Sequence
- * Error Counter
- */
-#define GEM_RXLENGTHCNT 0x0194 /* Length Field Error
- * Counter
- */
-#define GEM_RXSYMBCNT 0x0198 /* Symbol Error
- * Counter
- */
-#define GEM_RXALIGNCNT 0x019c /* Alignment Error
- * Counter
- */
-#define GEM_RXRESERRCNT 0x01a0 /* Receive Resource Error
- * Counter
- */
-#define GEM_RXORCNT 0x01a4 /* Receive Overrun
- * Counter
- */
-#define GEM_RXIPCCNT 0x01a8 /* IP header Checksum
- * Error Counter
- */
-#define GEM_RXTCPCCNT 0x01ac /* TCP Checksum Error
- * Counter
- */
-#define GEM_RXUDPCCNT 0x01b0 /* UDP Checksum Error
- * Counter
- */
-#define GEM_DCFG1 0x0280 /* Design Config 1 */
-#define GEM_DCFG2 0x0284 /* Design Config 2 */
-#define GEM_DCFG3 0x0288 /* Design Config 3 */
-#define GEM_DCFG4 0x028c /* Design Config 4 */
-#define GEM_DCFG5 0x0290 /* Design Config 5 */
-#define GEM_DCFG6 0x0294 /* Design Config 6 */
-#define GEM_DCFG7 0x0298 /* Design Config 7 */
-
-#define GEM_ISR(hw_q) (0x0400 + ((hw_q) << 2))
-#define GEM_TBQP(hw_q) (0x0440 + ((hw_q) << 2))
-#define GEM_RBQP(hw_q) (0x0480 + ((hw_q) << 2))
-#define GEM_IER(hw_q) (0x0600 + ((hw_q) << 2))
-#define GEM_IDR(hw_q) (0x0620 + ((hw_q) << 2))
-#define GEM_IMR(hw_q) (0x0640 + ((hw_q) << 2))
+#define GEM_NCFGR 0x0004 /* Network Config */
+#define GEM_USRIO 0x000c /* User IO */
+#define GEM_DMACFG 0x0010 /* DMA Configuration */
+#define GEM_HRB 0x0080 /* Hash Bottom */
+#define GEM_HRT 0x0084 /* Hash Top */
+#define GEM_SA1B 0x0088 /* Specific1 Bottom */
+#define GEM_SA1T 0x008C /* Specific1 Top */
+#define GEM_SA2B 0x0090 /* Specific2 Bottom */
+#define GEM_SA2T 0x0094 /* Specific2 Top */
+#define GEM_SA3B 0x0098 /* Specific3 Bottom */
+#define GEM_SA3T 0x009C /* Specific3 Top */
+#define GEM_SA4B 0x00A0 /* Specific4 Bottom */
+#define GEM_SA4T 0x00A4 /* Specific4 Top */
+#define GEM_OTX 0x0100 /* Octets transmitted */
+#define GEM_OCTTXL 0x0100 /* Octets transmitted [31:0] */
+#define GEM_OCTTXH 0x0104 /* Octets transmitted [47:32] */
+#define GEM_TXCNT 0x0108 /* Frames Transmitted counter */
+#define GEM_TXBCCNT 0x010c /* Broadcast Frames counter */
+#define GEM_TXMCCNT 0x0110 /* Multicast Frames counter */
+#define GEM_TXPAUSECNT 0x0114 /* Pause Frames Transmitted Counter */
+#define GEM_TX64CNT 0x0118 /* 64 byte Frames TX counter */
+#define GEM_TX65CNT 0x011c /* 65-127 byte Frames TX counter */
+#define GEM_TX128CNT 0x0120 /* 128-255 byte Frames TX counter */
+#define GEM_TX256CNT 0x0124 /* 256-511 byte Frames TX counter */
+#define GEM_TX512CNT 0x0128 /* 512-1023 byte Frames TX counter */
+#define GEM_TX1024CNT 0x012c /* 1024-1518 byte Frames TX counter */
+#define GEM_TX1519CNT 0x0130 /* 1519+ byte Frames TX counter */
+#define GEM_TXURUNCNT 0x0134 /* TX under run error counter */
+#define GEM_SNGLCOLLCNT 0x0138 /* Single Collision Frame Counter */
+#define GEM_MULTICOLLCNT 0x013c /* Multiple Collision Frame Counter */
+#define GEM_EXCESSCOLLCNT 0x0140 /* Excessive Collision Frame Counter */
+#define GEM_LATECOLLCNT 0x0144 /* Late Collision Frame Counter */
+#define GEM_TXDEFERCNT 0x0148 /* Deferred Transmission Frame Counter */
+#define GEM_TXCSENSECNT 0x014c /* Carrier Sense Error Counter */
+#define GEM_ORX 0x0150 /* Octets received */
+#define GEM_OCTRXL 0x0150 /* Octets received [31:0] */
+#define GEM_OCTRXH 0x0154 /* Octets received [47:32] */
+#define GEM_RXCNT 0x0158 /* Frames Received Counter */
+#define GEM_RXBROADCNT 0x015c /* Broadcast Frames Received Counter */
+#define GEM_RXMULTICNT 0x0160 /* Multicast Frames Received Counter */
+#define GEM_RXPAUSECNT 0x0164 /* Pause Frames Received Counter */
+#define GEM_RX64CNT 0x0168 /* 64 byte Frames RX Counter */
+#define GEM_RX65CNT 0x016c /* 65-127 byte Frames RX Counter */
+#define GEM_RX128CNT 0x0170 /* 128-255 byte Frames RX Counter */
+#define GEM_RX256CNT 0x0174 /* 256-511 byte Frames RX Counter */
+#define GEM_RX512CNT 0x0178 /* 512-1023 byte Frames RX Counter */
+#define GEM_RX1024CNT 0x017c /* 1024-1518 byte Frames RX Counter */
+#define GEM_RX1519CNT 0x0180 /* 1519+ byte Frames RX Counter */
+#define GEM_RXUNDRCNT 0x0184 /* Undersize Frames Received Counter */
+#define GEM_RXOVRCNT 0x0188 /* Oversize Frames Received Counter */
+#define GEM_RXJABCNT 0x018c /* Jabbers Received Counter */
+#define GEM_RXFCSCNT 0x0190 /* Frame Check Sequence Error Counter */
+#define GEM_RXLENGTHCNT 0x0194 /* Length Field Error Counter */
+#define GEM_RXSYMBCNT 0x0198 /* Symbol Error Counter */
+#define GEM_RXALIGNCNT 0x019c /* Alignment Error Counter */
+#define GEM_RXRESERRCNT 0x01a0 /* Receive Resource Error Counter */
+#define GEM_RXORCNT 0x01a4 /* Receive Overrun Counter */
+#define GEM_RXIPCCNT 0x01a8 /* IP header Checksum Error Counter */
+#define GEM_RXTCPCCNT 0x01ac /* TCP Checksum Error Counter */
+#define GEM_RXUDPCCNT 0x01b0 /* UDP Checksum Error Counter */
+#define GEM_DCFG1 0x0280 /* Design Config 1 */
+#define GEM_DCFG2 0x0284 /* Design Config 2 */
+#define GEM_DCFG3 0x0288 /* Design Config 3 */
+#define GEM_DCFG4 0x028c /* Design Config 4 */
+#define GEM_DCFG5 0x0290 /* Design Config 5 */
+#define GEM_DCFG6 0x0294 /* Design Config 6 */
+#define GEM_DCFG7 0x0298 /* Design Config 7 */
+
+#define GEM_ISR(hw_q) (0x0400 + ((hw_q) << 2))
+#define GEM_TBQP(hw_q) (0x0440 + ((hw_q) << 2))
+#define GEM_RBQP(hw_q) (0x0480 + ((hw_q) << 2))
+#define GEM_IER(hw_q) (0x0600 + ((hw_q) << 2))
+#define GEM_IDR(hw_q) (0x0620 + ((hw_q) << 2))
+#define GEM_IMR(hw_q) (0x0640 + ((hw_q) << 2))
/* Bitfields in NCR */
-#define MACB_LB_OFFSET 0 /* reserved */
-#define MACB_LB_SIZE 1
-#define MACB_LLB_OFFSET 1 /* Loop back local */
-#define MACB_LLB_SIZE 1
-#define MACB_RE_OFFSET 2 /* Receive enable */
-#define MACB_RE_SIZE 1
-#define MACB_TE_OFFSET 3 /* Transmit enable */
-#define MACB_TE_SIZE 1
-#define MACB_MPE_OFFSET 4 /* Management port enable */
-#define MACB_MPE_SIZE 1
-#define MACB_CLRSTAT_OFFSET 5 /* Clear stats regs */
-#define MACB_CLRSTAT_SIZE 1
-#define MACB_INCSTAT_OFFSET 6 /* Incremental stats regs */
-#define MACB_INCSTAT_SIZE 1
-#define MACB_WESTAT_OFFSET 7 /* Write enable stats regs */
-#define MACB_WESTAT_SIZE 1
-#define MACB_BP_OFFSET 8 /* Back pressure */
-#define MACB_BP_SIZE 1
-#define MACB_TSTART_OFFSET 9 /* Start transmission */
-#define MACB_TSTART_SIZE 1
-#define MACB_THALT_OFFSET 10 /* Transmit halt */
-#define MACB_THALT_SIZE 1
-#define MACB_NCR_TPF_OFFSET 11 /* Transmit pause frame */
-#define MACB_NCR_TPF_SIZE 1
-#define MACB_TZQ_OFFSET 12 /* Transmit zero quantum
- * pause frame
- */
-#define MACB_TZQ_SIZE 1
+#define MACB_LB_OFFSET 0 /* reserved */
+#define MACB_LB_SIZE 1
+#define MACB_LLB_OFFSET 1 /* Loop back local */
+#define MACB_LLB_SIZE 1
+#define MACB_RE_OFFSET 2 /* Receive enable */
+#define MACB_RE_SIZE 1
+#define MACB_TE_OFFSET 3 /* Transmit enable */
+#define MACB_TE_SIZE 1
+#define MACB_MPE_OFFSET 4 /* Management port enable */
+#define MACB_MPE_SIZE 1
+#define MACB_CLRSTAT_OFFSET 5 /* Clear stats regs */
+#define MACB_CLRSTAT_SIZE 1
+#define MACB_INCSTAT_OFFSET 6 /* Incremental stats regs */
+#define MACB_INCSTAT_SIZE 1
+#define MACB_WESTAT_OFFSET 7 /* Write enable stats regs */
+#define MACB_WESTAT_SIZE 1
+#define MACB_BP_OFFSET 8 /* Back pressure */
+#define MACB_BP_SIZE 1
+#define MACB_TSTART_OFFSET 9 /* Start transmission */
+#define MACB_TSTART_SIZE 1
+#define MACB_THALT_OFFSET 10 /* Transmit halt */
+#define MACB_THALT_SIZE 1
+#define MACB_NCR_TPF_OFFSET 11 /* Transmit pause frame */
+#define MACB_NCR_TPF_SIZE 1
+#define MACB_TZQ_OFFSET 12 /* Transmit zero quantum pause frame */
+#define MACB_TZQ_SIZE 1
/* Bitfields in NCFGR */
-#define MACB_SPD_OFFSET 0 /* Speed */
-#define MACB_SPD_SIZE 1
-#define MACB_FD_OFFSET 1 /* Full duplex */
-#define MACB_FD_SIZE 1
-#define MACB_BIT_RATE_OFFSET 2 /* Discard non-VLAN frames */
-#define MACB_BIT_RATE_SIZE 1
-#define MACB_JFRAME_OFFSET 3 /* reserved */
-#define MACB_JFRAME_SIZE 1
-#define MACB_CAF_OFFSET 4 /* Copy all frames */
-#define MACB_CAF_SIZE 1
-#define MACB_NBC_OFFSET 5 /* No broadcast */
-#define MACB_NBC_SIZE 1
-#define MACB_NCFGR_MTI_OFFSET 6 /* Multicast hash enable */
-#define MACB_NCFGR_MTI_SIZE 1
-#define MACB_UNI_OFFSET 7 /* Unicast hash enable */
-#define MACB_UNI_SIZE 1
-#define MACB_BIG_OFFSET 8 /* Receive 1536 byte frames */
-#define MACB_BIG_SIZE 1
-#define MACB_EAE_OFFSET 9 /* External address match
- * enable
- */
-#define MACB_EAE_SIZE 1
-#define MACB_CLK_OFFSET 10
-#define MACB_CLK_SIZE 2
-#define MACB_RTY_OFFSET 12 /* Retry test */
-#define MACB_RTY_SIZE 1
-#define MACB_PAE_OFFSET 13 /* Pause enable */
-#define MACB_PAE_SIZE 1
-#define MACB_RM9200_RMII_OFFSET 13 /* AT91RM9200 only */
-#define MACB_RM9200_RMII_SIZE 1 /* AT91RM9200 only */
-#define MACB_RBOF_OFFSET 14 /* Receive buffer offset */
-#define MACB_RBOF_SIZE 2
-#define MACB_RLCE_OFFSET 16 /* Length field error frame
- * discard
- */
-#define MACB_RLCE_SIZE 1
-#define MACB_DRFCS_OFFSET 17 /* FCS remove */
-#define MACB_DRFCS_SIZE 1
-#define MACB_EFRHD_OFFSET 18
-#define MACB_EFRHD_SIZE 1
-#define MACB_IRXFCS_OFFSET 19
-#define MACB_IRXFCS_SIZE 1
+#define MACB_SPD_OFFSET 0 /* Speed */
+#define MACB_SPD_SIZE 1
+#define MACB_FD_OFFSET 1 /* Full duplex */
+#define MACB_FD_SIZE 1
+#define MACB_BIT_RATE_OFFSET 2 /* Discard non-VLAN frames */
+#define MACB_BIT_RATE_SIZE 1
+#define MACB_JFRAME_OFFSET 3 /* reserved */
+#define MACB_JFRAME_SIZE 1
+#define MACB_CAF_OFFSET 4 /* Copy all frames */
+#define MACB_CAF_SIZE 1
+#define MACB_NBC_OFFSET 5 /* No broadcast */
+#define MACB_NBC_SIZE 1
+#define MACB_NCFGR_MTI_OFFSET 6 /* Multicast hash enable */
+#define MACB_NCFGR_MTI_SIZE 1
+#define MACB_UNI_OFFSET 7 /* Unicast hash enable */
+#define MACB_UNI_SIZE 1
+#define MACB_BIG_OFFSET 8 /* Receive 1536 byte frames */
+#define MACB_BIG_SIZE 1
+#define MACB_EAE_OFFSET 9 /* External address match enable */
+#define MACB_EAE_SIZE 1
+#define MACB_CLK_OFFSET 10
+#define MACB_CLK_SIZE 2
+#define MACB_RTY_OFFSET 12 /* Retry test */
+#define MACB_RTY_SIZE 1
+#define MACB_PAE_OFFSET 13 /* Pause enable */
+#define MACB_PAE_SIZE 1
+#define MACB_RM9200_RMII_OFFSET 13 /* AT91RM9200 only */
+#define MACB_RM9200_RMII_SIZE 1 /* AT91RM9200 only */
+#define MACB_RBOF_OFFSET 14 /* Receive buffer offset */
+#define MACB_RBOF_SIZE 2
+#define MACB_RLCE_OFFSET 16 /* Length field error frame discard */
+#define MACB_RLCE_SIZE 1
+#define MACB_DRFCS_OFFSET 17 /* FCS remove */
+#define MACB_DRFCS_SIZE 1
+#define MACB_EFRHD_OFFSET 18
+#define MACB_EFRHD_SIZE 1
+#define MACB_IRXFCS_OFFSET 19
+#define MACB_IRXFCS_SIZE 1
/* GEM specific NCFGR bitfields. */
-#define GEM_GBE_OFFSET 10 /* Gigabit mode enable */
-#define GEM_GBE_SIZE 1
-#define GEM_CLK_OFFSET 18 /* MDC clock division */
-#define GEM_CLK_SIZE 3
-#define GEM_DBW_OFFSET 21 /* Data bus width */
-#define GEM_DBW_SIZE 2
-#define GEM_RXCOEN_OFFSET 24
-#define GEM_RXCOEN_SIZE 1
+#define GEM_GBE_OFFSET 10 /* Gigabit mode enable */
+#define GEM_GBE_SIZE 1
+#define GEM_CLK_OFFSET 18 /* MDC clock division */
+#define GEM_CLK_SIZE 3
+#define GEM_DBW_OFFSET 21 /* Data bus width */
+#define GEM_DBW_SIZE 2
+#define GEM_RXCOEN_OFFSET 24
+#define GEM_RXCOEN_SIZE 1
/* Constants for data bus width. */
-#define GEM_DBW32 0 /* 32 bit AMBA AHB data bus
- * width
- */
-#define GEM_DBW64 1 /* 64 bit AMBA AHB data bus
- * width
- */
-#define GEM_DBW128 2 /* 128 bit AMBA AHB data bus
- * width
- */
+#define GEM_DBW32 0 /* 32 bit AMBA AHB data bus width */
+#define GEM_DBW64 1 /* 64 bit AMBA AHB data bus width */
+#define GEM_DBW128 2 /* 128 bit AMBA AHB data bus width */
/* Bitfields in DMACFG. */
-#define GEM_FBLDO_OFFSET 0 /* AHB fixed burst length for
- * DMA data operations
- */
-#define GEM_FBLDO_SIZE 5
-#define GEM_ENDIA_OFFSET 7 /* AHB endian swap mode enable
- * for packet data accesses
- */
-#define GEM_ENDIA_SIZE 1
-#define GEM_RXBMS_OFFSET 8 /* Receiver packet buffer
- * memory size select
- */
-#define GEM_RXBMS_SIZE 2
-#define GEM_TXPBMS_OFFSET 10 /* Transmitter packet buffer
- * memory size select
- */
-#define GEM_TXPBMS_SIZE 1
-#define GEM_TXCOEN_OFFSET 11 /* Transmitter IP, TCP and
- * UDP checksum generation
- * offload enable
- */
-#define GEM_TXCOEN_SIZE 1
-#define GEM_RXBS_OFFSET 16 /* DMA receive buffer size in
- * AHB system memory
- */
-#define GEM_RXBS_SIZE 8
-#define GEM_DDRP_OFFSET 24 /* disc_when_no_ahb */
-#define GEM_DDRP_SIZE 1
+#define GEM_FBLDO_OFFSET 0 /* fixed burst length for DMA */
+#define GEM_FBLDO_SIZE 5
+#define GEM_ENDIA_OFFSET 7 /* endian swap mode for packet data access */
+#define GEM_ENDIA_SIZE 1
+#define GEM_RXBMS_OFFSET 8 /* RX packet buffer memory size select */
+#define GEM_RXBMS_SIZE 2
+#define GEM_TXPBMS_OFFSET 10 /* TX packet buffer memory size select */
+#define GEM_TXPBMS_SIZE 1
+#define GEM_TXCOEN_OFFSET 11 /* TX IP/TCP/UDP checksum gen offload */
+#define GEM_TXCOEN_SIZE 1
+#define GEM_RXBS_OFFSET 16 /* DMA receive buffer size */
+#define GEM_RXBS_SIZE 8
+#define GEM_DDRP_OFFSET 24 /* disc_when_no_ahb */
+#define GEM_DDRP_SIZE 1
/* Bitfields in NSR */
-#define MACB_NSR_LINK_OFFSET 0 /* pcs_link_state */
-#define MACB_NSR_LINK_SIZE 1
-#define MACB_MDIO_OFFSET 1 /* status of the mdio_in
- * pin
- */
-#define MACB_MDIO_SIZE 1
-#define MACB_IDLE_OFFSET 2 /* The PHY management logic is
- * idle (i.e. has completed)
- */
-#define MACB_IDLE_SIZE 1
+#define MACB_NSR_LINK_OFFSET 0 /* pcs_link_state */
+#define MACB_NSR_LINK_SIZE 1
+#define MACB_MDIO_OFFSET 1 /* status of the mdio_in pin */
+#define MACB_MDIO_SIZE 1
+#define MACB_IDLE_OFFSET 2 /* The PHY management logic is idle */
+#define MACB_IDLE_SIZE 1
/* Bitfields in TSR */
-#define MACB_UBR_OFFSET 0 /* Used bit read */
-#define MACB_UBR_SIZE 1
-#define MACB_COL_OFFSET 1 /* Collision occurred */
-#define MACB_COL_SIZE 1
-#define MACB_TSR_RLE_OFFSET 2 /* Retry limit exceeded */
-#define MACB_TSR_RLE_SIZE 1
-#define MACB_TGO_OFFSET 3 /* Transmit go */
-#define MACB_TGO_SIZE 1
-#define MACB_BEX_OFFSET 4 /* Transmit frame corruption
- * due to AHB error
- */
-#define MACB_BEX_SIZE 1
-#define MACB_RM9200_BNQ_OFFSET 4 /* AT91RM9200 only */
-#define MACB_RM9200_BNQ_SIZE 1 /* AT91RM9200 only */
-#define MACB_COMP_OFFSET 5 /* Trnasmit complete */
-#define MACB_COMP_SIZE 1
-#define MACB_UND_OFFSET 6 /* Trnasmit under run */
-#define MACB_UND_SIZE 1
+#define MACB_UBR_OFFSET 0 /* Used bit read */
+#define MACB_UBR_SIZE 1
+#define MACB_COL_OFFSET 1 /* Collision occurred */
+#define MACB_COL_SIZE 1
+#define MACB_TSR_RLE_OFFSET 2 /* Retry limit exceeded */
+#define MACB_TSR_RLE_SIZE 1
+#define MACB_TGO_OFFSET 3 /* Transmit go */
+#define MACB_TGO_SIZE 1
+#define MACB_BEX_OFFSET 4 /* TX frame corruption due to AHB error */
+#define MACB_BEX_SIZE 1
+#define MACB_RM9200_BNQ_OFFSET 4 /* AT91RM9200 only */
+#define MACB_RM9200_BNQ_SIZE 1 /* AT91RM9200 only */
+#define MACB_COMP_OFFSET 5 /* Trnasmit complete */
+#define MACB_COMP_SIZE 1
+#define MACB_UND_OFFSET 6 /* Trnasmit under run */
+#define MACB_UND_SIZE 1
/* Bitfields in RSR */
-#define MACB_BNA_OFFSET 0 /* Buffer not available */
-#define MACB_BNA_SIZE 1
-#define MACB_REC_OFFSET 1 /* Frame received */
-#define MACB_REC_SIZE 1
-#define MACB_OVR_OFFSET 2 /* Receive overrun */
-#define MACB_OVR_SIZE 1
+#define MACB_BNA_OFFSET 0 /* Buffer not available */
+#define MACB_BNA_SIZE 1
+#define MACB_REC_OFFSET 1 /* Frame received */
+#define MACB_REC_SIZE 1
+#define MACB_OVR_OFFSET 2 /* Receive overrun */
+#define MACB_OVR_SIZE 1
/* Bitfields in ISR/IER/IDR/IMR */
-#define MACB_MFD_OFFSET 0 /* Management frame sent */
-#define MACB_MFD_SIZE 1
-#define MACB_RCOMP_OFFSET 1 /* Receive complete */
-#define MACB_RCOMP_SIZE 1
-#define MACB_RXUBR_OFFSET 2 /* RX used bit read */
-#define MACB_RXUBR_SIZE 1
-#define MACB_TXUBR_OFFSET 3 /* TX used bit read */
-#define MACB_TXUBR_SIZE 1
-#define MACB_ISR_TUND_OFFSET 4 /* Enable trnasmit buffer
- * under run interrupt
- */
-#define MACB_ISR_TUND_SIZE 1
-#define MACB_ISR_RLE_OFFSET 5 /* Enable retry limit exceeded
- * or late collision interrupt
- */
-#define MACB_ISR_RLE_SIZE 1
-#define MACB_TXERR_OFFSET 6 /* Enable transmit frame
- * corruption due to AHB error
- * interrupt
- */
-#define MACB_TXERR_SIZE 1
-#define MACB_TCOMP_OFFSET 7 /* Enable transmit complete
- * interrupt
- */
-#define MACB_TCOMP_SIZE 1
-#define MACB_ISR_LINK_OFFSET 9 /* Enable link change
- * interrupt
- */
-#define MACB_ISR_LINK_SIZE 1
-#define MACB_ISR_ROVR_OFFSET 10 /* Enable receive overrun
- * interrupt
- */
-#define MACB_ISR_ROVR_SIZE 1
-#define MACB_HRESP_OFFSET 11 /* Enable hrsep not OK
- * interrupt
- */
-#define MACB_HRESP_SIZE 1
-#define MACB_PFR_OFFSET 12 /* Enable pause frame with
- * non-zero pause quantum
- * interrupt
- */
-#define MACB_PFR_SIZE 1
-#define MACB_PTZ_OFFSET 13 /* Enable pause time zero
- * interrupt
- */
-#define MACB_PTZ_SIZE 1
+#define MACB_MFD_OFFSET 0 /* Management frame sent */
+#define MACB_MFD_SIZE 1
+#define MACB_RCOMP_OFFSET 1 /* Receive complete */
+#define MACB_RCOMP_SIZE 1
+#define MACB_RXUBR_OFFSET 2 /* RX used bit read */
+#define MACB_RXUBR_SIZE 1
+#define MACB_TXUBR_OFFSET 3 /* TX used bit read */
+#define MACB_TXUBR_SIZE 1
+#define MACB_ISR_TUND_OFFSET 4 /* Enable TX buffer under run interrupt */
+#define MACB_ISR_TUND_SIZE 1
+#define MACB_ISR_RLE_OFFSET 5 /* EN retry exceeded/late coll interrupt */
+#define MACB_ISR_RLE_SIZE 1
+#define MACB_TXERR_OFFSET 6 /* EN TX frame corrupt from error interrupt */
+#define MACB_TXERR_SIZE 1
+#define MACB_TCOMP_OFFSET 7 /* Enable transmit complete interrupt */
+#define MACB_TCOMP_SIZE 1
+#define MACB_ISR_LINK_OFFSET 9 /* Enable link change interrupt */
+#define MACB_ISR_LINK_SIZE 1
+#define MACB_ISR_ROVR_OFFSET 10 /* Enable receive overrun interrupt */
+#define MACB_ISR_ROVR_SIZE 1
+#define MACB_HRESP_OFFSET 11 /* Enable hrsep not OK interrupt */
+#define MACB_HRESP_SIZE 1
+#define MACB_PFR_OFFSET 12 /* Enable pause frame w/ quantum interrupt */
+#define MACB_PFR_SIZE 1
+#define MACB_PTZ_OFFSET 13 /* Enable pause time zero interrupt */
+#define MACB_PTZ_SIZE 1
/* Bitfields in MAN */
-#define MACB_DATA_OFFSET 0 /* data */
-#define MACB_DATA_SIZE 16
-#define MACB_CODE_OFFSET 16 /* Must be written to 10 */
-#define MACB_CODE_SIZE 2
-#define MACB_REGA_OFFSET 18 /* Register address */
-#define MACB_REGA_SIZE 5
-#define MACB_PHYA_OFFSET 23 /* PHY address */
-#define MACB_PHYA_SIZE 5
-#define MACB_RW_OFFSET 28 /* Operation. 10 is read. 01
- * is write.
- */
-#define MACB_RW_SIZE 2
-#define MACB_SOF_OFFSET 30 /* Must be written to 1 for
- * Clause 22 operation
- */
-#define MACB_SOF_SIZE 2
+#define MACB_DATA_OFFSET 0 /* data */
+#define MACB_DATA_SIZE 16
+#define MACB_CODE_OFFSET 16 /* Must be written to 10 */
+#define MACB_CODE_SIZE 2
+#define MACB_REGA_OFFSET 18 /* Register address */
+#define MACB_REGA_SIZE 5
+#define MACB_PHYA_OFFSET 23 /* PHY address */
+#define MACB_PHYA_SIZE 5
+#define MACB_RW_OFFSET 28 /* Operation. 10 is read. 01 is write. */
+#define MACB_RW_SIZE 2
+#define MACB_SOF_OFFSET 30 /* Must be written to 1 for Clause 22 */
+#define MACB_SOF_SIZE 2
/* Bitfields in USRIO (AVR32) */
#define MACB_MII_OFFSET 0
@@ -597,8 +435,7 @@
#define queue_writel(queue, reg, value) \
__raw_writel((value), (queue)->bp->regs + (queue)->reg)
-/*
- * Conditional GEM/MACB macros. These perform the operation to the correct
+/* Conditional GEM/MACB macros. These perform the operation to the correct
* register dependent on whether the device is a GEM or a MACB. For registers
* and bitfields that are common across both devices, use macb_{read,write}l
* to avoid the cost of the conditional.
@@ -621,8 +458,7 @@
__v; \
})
-/**
- * struct macb_dma_desc - Hardware DMA descriptor
+/* struct macb_dma_desc - Hardware DMA descriptor
* @addr: DMA address of data buffer
* @ctrl: Control and status bits
*/
@@ -711,8 +547,7 @@ struct macb_dma_desc {
/* limit RX checksum offload to TCP and UDP packets */
#define GEM_RX_CSUM_CHECKED_MASK 2
-/**
- * struct macb_tx_skb - data about an skb which is being transmitted
+/* struct macb_tx_skb - data about an skb which is being transmitted
* @skb: skb currently being transmitted, only set for the last buffer
* of the frame
* @mapping: DMA address of the skb's fragment buffer
@@ -727,8 +562,7 @@ struct macb_tx_skb {
bool mapped_as_page;
};
-/*
- * Hardware-collected statistics. Used when updating the network
+/* Hardware-collected statistics. Used when updating the network
* device stats by a periodic timer.
*/
struct macb_stats {
--
1.9.1
^ permalink raw reply related
* [PATCH v3 3/3] net/macb: Create gem_ethtool_ops for new statistics functions
From: Xander Huff @ 2015-01-15 21:55 UTC (permalink / raw)
To: davem, nicolas.ferre, david.laight
Cc: netdev, jaeden.amero, rich.tollerton, brad.mouring, linux-kernel,
cyrille.pitchen, Xander Huff
In-Reply-To: <1421358920-23897-1-git-send-email-xander.huff@ni.com>
10/100 MACB does not have the same statistics possibilities as GEM. Separate
macb_ethtool_ops to make a new GEM-specific struct with the new statistics
functions included.
Signed-off-by: Xander Huff <xander.huff@ni.com>
---
Re-sending to properly include David Laight
drivers/net/ethernet/cadence/macb.c | 15 +++++++++++++--
1 file changed, 13 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/cadence/macb.c b/drivers/net/ethernet/cadence/macb.c
index 9edd787..f2f9ca0 100644
--- a/drivers/net/ethernet/cadence/macb.c
+++ b/drivers/net/ethernet/cadence/macb.c
@@ -2032,11 +2032,21 @@ const struct ethtool_ops macb_ethtool_ops = {
.get_regs = macb_get_regs,
.get_link = ethtool_op_get_link,
.get_ts_info = ethtool_op_get_ts_info,
+};
+EXPORT_SYMBOL_GPL(macb_ethtool_ops);
+
+const struct ethtool_ops gem_ethtool_ops = {
+ .get_settings = macb_get_settings,
+ .set_settings = macb_set_settings,
+ .get_regs_len = macb_get_regs_len,
+ .get_regs = macb_get_regs,
+ .get_link = ethtool_op_get_link,
+ .get_ts_info = ethtool_op_get_ts_info,
.get_ethtool_stats = gem_get_ethtool_stats,
.get_strings = gem_get_ethtool_strings,
.get_sset_count = gem_get_sset_count,
};
-EXPORT_SYMBOL_GPL(macb_ethtool_ops);
+EXPORT_SYMBOL_GPL(gem_ethtool_ops);
int macb_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
{
@@ -2325,7 +2335,6 @@ static int __init macb_probe(struct platform_device *pdev)
dev->netdev_ops = &macb_netdev_ops;
netif_napi_add(dev, &bp->napi, macb_poll, 64);
- dev->ethtool_ops = &macb_ethtool_ops;
dev->base_addr = regs->start;
@@ -2339,12 +2348,14 @@ static int __init macb_probe(struct platform_device *pdev)
bp->macbgem_ops.mog_free_rx_buffers = gem_free_rx_buffers;
bp->macbgem_ops.mog_init_rings = gem_init_rings;
bp->macbgem_ops.mog_rx = gem_rx;
+ dev->ethtool_ops = &gem_ethtool_ops;
} else {
bp->max_tx_length = MACB_MAX_TX_LEN;
bp->macbgem_ops.mog_alloc_rx_buffers = macb_alloc_rx_buffers;
bp->macbgem_ops.mog_free_rx_buffers = macb_free_rx_buffers;
bp->macbgem_ops.mog_init_rings = macb_init_rings;
bp->macbgem_ops.mog_rx = macb_rx;
+ dev->ethtool_ops = &macb_ethtool_ops;
}
/* Set features */
--
1.9.1
^ permalink raw reply related
* [PATCH v3 2/3] net/macb: Add whitespace around arithmetic operators
From: Xander Huff @ 2015-01-15 21:55 UTC (permalink / raw)
To: davem, nicolas.ferre, david.laight
Cc: netdev, jaeden.amero, rich.tollerton, brad.mouring, linux-kernel,
cyrille.pitchen, Xander Huff
In-Reply-To: <1421358920-23897-1-git-send-email-xander.huff@ni.com>
Spaces should surround add, multiply, and bitshift operators.
Signed-off-by: Xander Huff <xander.huff@ni.com>
---
Re-sending to properly include David Laight
drivers/net/ethernet/cadence/macb.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/drivers/net/ethernet/cadence/macb.c b/drivers/net/ethernet/cadence/macb.c
index dd8c202..9edd787 100644
--- a/drivers/net/ethernet/cadence/macb.c
+++ b/drivers/net/ethernet/cadence/macb.c
@@ -1691,7 +1691,7 @@ static int hash_get_index(__u8 *addr)
for (j = 0; j < 6; j++) {
for (i = 0, bitval = 0; i < 8; i++)
- bitval ^= hash_bit_value(i*6 + j, addr);
+ bitval ^= hash_bit_value(i * 6 + j, addr);
hash_index |= (bitval << j);
}
@@ -1832,15 +1832,15 @@ static void gem_update_stats(struct macb *bp)
for (i = 0; i < GEM_STATS_LEN; ++i, ++p) {
u32 offset = gem_statistics[i].offset;
- u64 val = __raw_readl(bp->regs+offset);
+ u64 val = __raw_readl(bp->regs + offset);
bp->ethtool_stats[i] += val;
*p += val;
if (offset == GEM_OCTTXL || offset == GEM_OCTRXL) {
/* Add GEM_OCTTXH, GEM_OCTRXH */
- val = __raw_readl(bp->regs+offset+4);
- bp->ethtool_stats[i] += ((u64)val)<<32;
+ val = __raw_readl(bp->regs + offset + 4);
+ bp->ethtool_stats[i] += ((u64)val) << 32;
*(++p) += val;
}
}
@@ -1891,7 +1891,7 @@ static void gem_get_ethtool_stats(struct net_device *dev,
bp = netdev_priv(dev);
gem_update_stats(bp);
- memcpy(data, &bp->ethtool_stats, sizeof(u64)*GEM_STATS_LEN);
+ memcpy(data, &bp->ethtool_stats, sizeof(u64) * GEM_STATS_LEN);
}
static int gem_get_sset_count(struct net_device *dev, int sset)
--
1.9.1
^ permalink raw reply related
* [PATCH net-next v12 5/5] openvswitch: Add support for unique flow IDs.
From: Joe Stringer @ 2015-01-15 21:48 UTC (permalink / raw)
To: netdev-u79uwXL29TY76Z2rM5mHXA
Cc: dev-yBygre7rU0TnMu66kgdUjQ, linux-kernel-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1421358507-5992-1-git-send-email-joestringer-l0M0P4e3n4LQT0dZR+AlfA@public.gmane.org>
Previously, flows were manipulated by userspace specifying a full,
unmasked flow key. This adds significant burden onto flow
serialization/deserialization, particularly when dumping flows.
This patch adds an alternative way to refer to flows using a
variable-length "unique flow identifier" (UFID). At flow setup time,
userspace may specify a UFID for a flow, which is stored with the flow
and inserted into a separate table for lookup, in addition to the
standard flow table. Flows created using a UFID must be fetched or
deleted using the UFID.
All flow dump operations may now be made more terse with OVS_UFID_F_*
flags. For example, the OVS_UFID_F_OMIT_KEY flag allows responses to
omit the flow key from a datapath operation if the flow has a
corresponding UFID. This significantly reduces the time spent assembling
and transacting netlink messages. With all OVS_UFID_F_OMIT_* flags
enabled, the datapath only returns the UFID and statistics for each flow
during flow dump, increasing ovs-vswitchd revalidator performance by 40%
or more.
Signed-off-by: Joe Stringer <joestringer@nicira.com>
---
Documentation/networking/openvswitch.txt | 13 ++
include/uapi/linux/openvswitch.h | 20 +++
net/openvswitch/datapath.c | 221 +++++++++++++++++++++++-------
net/openvswitch/flow.h | 28 +++-
net/openvswitch/flow_netlink.c | 67 ++++++++-
net/openvswitch/flow_netlink.h | 9 +-
net/openvswitch/flow_table.c | 187 ++++++++++++++++++++-----
net/openvswitch/flow_table.h | 8 +-
8 files changed, 461 insertions(+), 92 deletions(-)
diff --git a/Documentation/networking/openvswitch.txt b/Documentation/networking/openvswitch.txt
index 37c20ee..b3b9ac6 100644
--- a/Documentation/networking/openvswitch.txt
+++ b/Documentation/networking/openvswitch.txt
@@ -131,6 +131,19 @@ performs best-effort detection of overlapping wildcarded flows and may reject
some but not all of them. However, this behavior may change in future versions.
+Unique flow identifiers
+-----------------------
+
+An alternative to using the original match portion of a key as the handle for
+flow identification is a unique flow identifier, or "UFID". UFIDs are optional
+for both the kernel and user space program.
+
+User space programs that support UFID are expected to provide it during flow
+setup in addition to the flow, then refer to the flow using the UFID for all
+future operations. The kernel is not required to index flows by the original
+flow key if a UFID is specified.
+
+
Basic rule for evolving flow keys
---------------------------------
diff --git a/include/uapi/linux/openvswitch.h b/include/uapi/linux/openvswitch.h
index cd8d933..7a8785a 100644
--- a/include/uapi/linux/openvswitch.h
+++ b/include/uapi/linux/openvswitch.h
@@ -459,6 +459,14 @@ struct ovs_key_nd {
* a wildcarded match. Omitting attribute is treated as wildcarding all
* corresponding fields. Optional for all requests. If not present,
* all flow key bits are exact match bits.
+ * @OVS_FLOW_ATTR_UFID: A value between 1-16 octets specifying a unique
+ * identifier for the flow. Causes the flow to be indexed by this value rather
+ * than the value of the %OVS_FLOW_ATTR_KEY attribute. Optional for all
+ * requests. Present in notifications if the flow was created with this
+ * attribute.
+ * @OVS_FLOW_ATTR_UFID_FLAGS: A 32-bit value of OR'd %OVS_UFID_F_*
+ * flags that provide alternative semantics for flow installation and
+ * retrieval. Optional for all requests.
*
* These attributes follow the &struct ovs_header within the Generic Netlink
* payload for %OVS_FLOW_* commands.
@@ -474,12 +482,24 @@ enum ovs_flow_attr {
OVS_FLOW_ATTR_MASK, /* Sequence of OVS_KEY_ATTR_* attributes. */
OVS_FLOW_ATTR_PROBE, /* Flow operation is a feature probe, error
* logging should be suppressed. */
+ OVS_FLOW_ATTR_UFID, /* Variable length unique flow identifier. */
+ OVS_FLOW_ATTR_UFID_FLAGS,/* u32 of OVS_UFID_F_*. */
__OVS_FLOW_ATTR_MAX
};
#define OVS_FLOW_ATTR_MAX (__OVS_FLOW_ATTR_MAX - 1)
/**
+ * Omit attributes for notifications.
+ *
+ * If a datapath request contains an %OVS_UFID_F_OMIT_* flag, then the datapath
+ * may omit the corresponding %OVS_FLOW_ATTR_* from the response.
+ */
+#define OVS_UFID_F_OMIT_KEY (1 << 0)
+#define OVS_UFID_F_OMIT_MASK (1 << 1)
+#define OVS_UFID_F_OMIT_ACTIONS (1 << 2)
+
+/**
* enum ovs_sample_attr - Attributes for %OVS_ACTION_ATTR_SAMPLE action.
* @OVS_SAMPLE_ATTR_PROBABILITY: 32-bit fraction of packets to sample with
* @OVS_ACTION_ATTR_SAMPLE. A value of 0 samples no packets, a value of
diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c
index 3ded349..564e163 100644
--- a/net/openvswitch/datapath.c
+++ b/net/openvswitch/datapath.c
@@ -65,6 +65,8 @@ static struct genl_family dp_packet_genl_family;
static struct genl_family dp_flow_genl_family;
static struct genl_family dp_datapath_genl_family;
+static const struct nla_policy flow_policy[];
+
static const struct genl_multicast_group ovs_dp_flow_multicast_group = {
.name = OVS_FLOW_MCGROUP,
};
@@ -662,15 +664,48 @@ static void get_dp_stats(const struct datapath *dp, struct ovs_dp_stats *stats,
}
}
-static size_t ovs_flow_cmd_msg_size(const struct sw_flow_actions *acts)
+static bool should_fill_key(const struct sw_flow_id *sfid, uint32_t ufid_flags)
+{
+ return ovs_identifier_is_key(sfid) ||
+ !(ufid_flags & OVS_UFID_F_OMIT_KEY);
+}
+
+static bool should_fill_mask(uint32_t ufid_flags)
{
- return NLMSG_ALIGN(sizeof(struct ovs_header))
- + nla_total_size(ovs_key_attr_size()) /* OVS_FLOW_ATTR_KEY */
- + nla_total_size(ovs_key_attr_size()) /* OVS_FLOW_ATTR_MASK */
+ return !(ufid_flags & OVS_UFID_F_OMIT_MASK);
+}
+
+static bool should_fill_actions(uint32_t ufid_flags)
+{
+ return !(ufid_flags & OVS_UFID_F_OMIT_ACTIONS);
+}
+
+static size_t ovs_flow_cmd_msg_size(const struct sw_flow_actions *acts,
+ const struct sw_flow_id *sfid,
+ uint32_t ufid_flags)
+{
+ size_t len = NLMSG_ALIGN(sizeof(struct ovs_header));
+
+ /* OVS_FLOW_ATTR_UFID */
+ if (sfid && ovs_identifier_is_ufid(sfid))
+ len += nla_total_size(sfid->ufid_len);
+
+ /* OVS_FLOW_ATTR_KEY */
+ if (!sfid || should_fill_key(sfid, ufid_flags))
+ len += nla_total_size(ovs_key_attr_size());
+
+ /* OVS_FLOW_ATTR_MASK */
+ if (should_fill_mask(ufid_flags))
+ len += nla_total_size(ovs_key_attr_size());
+
+ /* OVS_FLOW_ATTR_ACTIONS */
+ if (should_fill_actions(ufid_flags))
+ len += nla_total_size(acts->actions_len);
+
+ return len
+ nla_total_size(sizeof(struct ovs_flow_stats)) /* OVS_FLOW_ATTR_STATS */
+ nla_total_size(1) /* OVS_FLOW_ATTR_TCP_FLAGS */
- + nla_total_size(8) /* OVS_FLOW_ATTR_USED */
- + nla_total_size(acts->actions_len); /* OVS_FLOW_ATTR_ACTIONS */
+ + nla_total_size(8); /* OVS_FLOW_ATTR_USED */
}
/* Called with ovs_mutex or RCU read lock. */
@@ -741,7 +776,7 @@ static int ovs_flow_cmd_fill_actions(const struct sw_flow *flow,
/* Called with ovs_mutex or RCU read lock. */
static int ovs_flow_cmd_fill_info(const struct sw_flow *flow, int dp_ifindex,
struct sk_buff *skb, u32 portid,
- u32 seq, u32 flags, u8 cmd)
+ u32 seq, u32 flags, u8 cmd, u32 ufid_flags)
{
const int skb_orig_len = skb->len;
struct ovs_header *ovs_header;
@@ -754,21 +789,31 @@ static int ovs_flow_cmd_fill_info(const struct sw_flow *flow, int dp_ifindex,
ovs_header->dp_ifindex = dp_ifindex;
- err = ovs_nla_put_unmasked_key(flow, skb);
+ err = ovs_nla_put_identifier(flow, skb);
if (err)
goto error;
- err = ovs_nla_put_mask(flow, skb);
- if (err)
- goto error;
+ if (should_fill_key(flow->id, ufid_flags)) {
+ err = ovs_nla_put_masked_key(flow, skb);
+ if (err)
+ goto error;
+ }
+
+ if (should_fill_mask(ufid_flags)) {
+ err = ovs_nla_put_mask(flow, skb);
+ if (err)
+ goto error;
+ }
err = ovs_flow_cmd_fill_stats(flow, skb);
if (err)
goto error;
- err = ovs_flow_cmd_fill_actions(flow, skb, skb_orig_len);
- if (err)
- goto error;
+ if (should_fill_actions(ufid_flags)) {
+ err = ovs_flow_cmd_fill_actions(flow, skb, skb_orig_len);
+ if (err)
+ goto error;
+ }
return genlmsg_end(skb, ovs_header);
@@ -779,15 +824,19 @@ error:
/* May not be called with RCU read lock. */
static struct sk_buff *ovs_flow_cmd_alloc_info(const struct sw_flow_actions *acts,
+ const struct sw_flow_id *sfid,
struct genl_info *info,
- bool always)
+ bool always,
+ uint32_t ufid_flags)
{
struct sk_buff *skb;
+ size_t len;
if (!always && !ovs_must_notify(&dp_flow_genl_family, info, 0))
return NULL;
- skb = genlmsg_new_unicast(ovs_flow_cmd_msg_size(acts), info, GFP_KERNEL);
+ len = ovs_flow_cmd_msg_size(acts, sfid, ufid_flags);
+ skb = genlmsg_new_unicast(len, info, GFP_KERNEL);
if (!skb)
return ERR_PTR(-ENOMEM);
@@ -798,19 +847,19 @@ static struct sk_buff *ovs_flow_cmd_alloc_info(const struct sw_flow_actions *act
static struct sk_buff *ovs_flow_cmd_build_info(const struct sw_flow *flow,
int dp_ifindex,
struct genl_info *info, u8 cmd,
- bool always)
+ bool always, u32 ufid_flags)
{
struct sk_buff *skb;
int retval;
- skb = ovs_flow_cmd_alloc_info(ovsl_dereference(flow->sf_acts), info,
- always);
+ skb = ovs_flow_cmd_alloc_info(ovsl_dereference(flow->sf_acts),
+ flow->id, info, always, ufid_flags);
if (IS_ERR_OR_NULL(skb))
return skb;
retval = ovs_flow_cmd_fill_info(flow, dp_ifindex, skb,
info->snd_portid, info->snd_seq, 0,
- cmd);
+ cmd, ufid_flags);
BUG_ON(retval < 0);
return skb;
}
@@ -819,12 +868,15 @@ static int ovs_flow_cmd_new(struct sk_buff *skb, struct genl_info *info)
{
struct nlattr **a = info->attrs;
struct ovs_header *ovs_header = info->userhdr;
- struct sw_flow *flow, *new_flow;
+ struct sw_flow *flow = NULL, *new_flow;
struct sw_flow_mask mask;
struct sk_buff *reply;
struct datapath *dp;
+ struct sw_flow_key key;
+ struct sw_flow_id *sfid;
struct sw_flow_actions *acts;
struct sw_flow_match match;
+ u32 ufid_flags = ovs_nla_get_ufid_flags(a[OVS_FLOW_ATTR_UFID_FLAGS]);
int error;
bool log = !a[OVS_FLOW_ATTR_PROBE];
@@ -849,13 +901,21 @@ static int ovs_flow_cmd_new(struct sk_buff *skb, struct genl_info *info)
}
/* Extract key. */
- ovs_match_init(&match, &new_flow->unmasked_key, &mask);
+ ovs_match_init(&match, &key, &mask);
error = ovs_nla_get_match(&match, a[OVS_FLOW_ATTR_KEY],
a[OVS_FLOW_ATTR_MASK], log);
if (error)
goto err_kfree_flow;
- ovs_flow_mask_key(&new_flow->key, &new_flow->unmasked_key, &mask);
+ ovs_flow_mask_key(&new_flow->key, &key, &mask);
+
+ /* Extract flow identifier. */
+ sfid = ovs_nla_copy_identifier(a[OVS_FLOW_ATTR_UFID], &key, log);
+ if (IS_ERR(sfid)) {
+ error = PTR_ERR(sfid);
+ goto err_kfree_flow;
+ }
+ new_flow->id = sfid;
/* Validate actions. */
error = ovs_nla_copy_actions(a[OVS_FLOW_ATTR_ACTIONS], &new_flow->key,
@@ -865,7 +925,8 @@ static int ovs_flow_cmd_new(struct sk_buff *skb, struct genl_info *info)
goto err_kfree_flow;
}
- reply = ovs_flow_cmd_alloc_info(acts, info, false);
+ reply = ovs_flow_cmd_alloc_info(acts, new_flow->id, info, false,
+ ufid_flags);
if (IS_ERR(reply)) {
error = PTR_ERR(reply);
goto err_kfree_acts;
@@ -877,8 +938,12 @@ static int ovs_flow_cmd_new(struct sk_buff *skb, struct genl_info *info)
error = -ENODEV;
goto err_unlock_ovs;
}
+
/* Check if this is a duplicate flow */
- flow = ovs_flow_tbl_lookup(&dp->table, &new_flow->unmasked_key);
+ if (ovs_identifier_is_ufid(new_flow->id))
+ flow = ovs_flow_tbl_lookup_ufid(&dp->table, new_flow->id);
+ if (!flow)
+ flow = ovs_flow_tbl_lookup(&dp->table, &new_flow->key);
if (likely(!flow)) {
rcu_assign_pointer(new_flow->sf_acts, acts);
@@ -894,7 +959,8 @@ static int ovs_flow_cmd_new(struct sk_buff *skb, struct genl_info *info)
ovs_header->dp_ifindex,
reply, info->snd_portid,
info->snd_seq, 0,
- OVS_FLOW_CMD_NEW);
+ OVS_FLOW_CMD_NEW,
+ ufid_flags);
BUG_ON(error < 0);
}
ovs_unlock();
@@ -912,10 +978,15 @@ static int ovs_flow_cmd_new(struct sk_buff *skb, struct genl_info *info)
error = -EEXIST;
goto err_unlock_ovs;
}
- /* The unmasked key has to be the same for flow updates. */
- if (unlikely(!ovs_flow_cmp_unmasked_key(flow, &match))) {
- /* Look for any overlapping flow. */
- flow = ovs_flow_tbl_lookup_exact(&dp->table, &match);
+ /* The flow identifier has to be the same for flow updates.
+ * Look for any overlapping flow.
+ */
+ if (unlikely(!ovs_flow_cmp(flow, &match))) {
+ if (ovs_identifier_is_key(flow->id))
+ flow = ovs_flow_tbl_lookup_exact(&dp->table,
+ &match);
+ else /* UFID matches but key is different */
+ flow = NULL;
if (!flow) {
error = -ENOENT;
goto err_unlock_ovs;
@@ -930,7 +1001,8 @@ static int ovs_flow_cmd_new(struct sk_buff *skb, struct genl_info *info)
ovs_header->dp_ifindex,
reply, info->snd_portid,
info->snd_seq, 0,
- OVS_FLOW_CMD_NEW);
+ OVS_FLOW_CMD_NEW,
+ ufid_flags);
BUG_ON(error < 0);
}
ovs_unlock();
@@ -986,6 +1058,8 @@ static int ovs_flow_cmd_set(struct sk_buff *skb, struct genl_info *info)
struct datapath *dp;
struct sw_flow_actions *old_acts = NULL, *acts = NULL;
struct sw_flow_match match;
+ struct sw_flow_id *sfid = NULL;
+ u32 ufid_flags = ovs_nla_get_ufid_flags(a[OVS_FLOW_ATTR_UFID_FLAGS]);
int error;
bool log = !a[OVS_FLOW_ATTR_PROBE];
@@ -1002,17 +1076,27 @@ static int ovs_flow_cmd_set(struct sk_buff *skb, struct genl_info *info)
if (error)
goto error;
+ if (a[OVS_FLOW_ATTR_UFID]) {
+ sfid = ovs_nla_copy_identifier(a[OVS_FLOW_ATTR_UFID], &key,
+ log);
+ if (IS_ERR(sfid)) {
+ error = PTR_ERR(sfid);
+ goto error;
+ }
+ }
+
/* Validate actions. */
if (a[OVS_FLOW_ATTR_ACTIONS]) {
acts = get_flow_actions(a[OVS_FLOW_ATTR_ACTIONS], &key, &mask,
log);
if (IS_ERR(acts)) {
error = PTR_ERR(acts);
- goto error;
+ goto err_kfree_id;
}
/* Can allocate before locking if have acts. */
- reply = ovs_flow_cmd_alloc_info(acts, info, false);
+ reply = ovs_flow_cmd_alloc_info(acts, sfid, info, false,
+ ufid_flags);
if (IS_ERR(reply)) {
error = PTR_ERR(reply);
goto err_kfree_acts;
@@ -1026,7 +1110,10 @@ static int ovs_flow_cmd_set(struct sk_buff *skb, struct genl_info *info)
goto err_unlock_ovs;
}
/* Check that the flow exists. */
- flow = ovs_flow_tbl_lookup_exact(&dp->table, &match);
+ if (sfid)
+ flow = ovs_flow_tbl_lookup_ufid(&dp->table, sfid);
+ else
+ flow = ovs_flow_tbl_lookup_exact(&dp->table, &match);
if (unlikely(!flow)) {
error = -ENOENT;
goto err_unlock_ovs;
@@ -1042,13 +1129,16 @@ static int ovs_flow_cmd_set(struct sk_buff *skb, struct genl_info *info)
ovs_header->dp_ifindex,
reply, info->snd_portid,
info->snd_seq, 0,
- OVS_FLOW_CMD_NEW);
+ OVS_FLOW_CMD_NEW,
+ ufid_flags);
BUG_ON(error < 0);
}
} else {
/* Could not alloc without acts before locking. */
reply = ovs_flow_cmd_build_info(flow, ovs_header->dp_ifindex,
- info, OVS_FLOW_CMD_NEW, false);
+ info, OVS_FLOW_CMD_NEW, false,
+ ufid_flags);
+
if (unlikely(IS_ERR(reply))) {
error = PTR_ERR(reply);
goto err_unlock_ovs;
@@ -1072,6 +1162,8 @@ err_unlock_ovs:
kfree_skb(reply);
err_kfree_acts:
kfree(acts);
+err_kfree_id:
+ kfree(sfid);
error:
return error;
}
@@ -1085,17 +1177,22 @@ static int ovs_flow_cmd_get(struct sk_buff *skb, struct genl_info *info)
struct sw_flow *flow;
struct datapath *dp;
struct sw_flow_match match;
- int err;
+ struct sw_flow_id ufid;
+ u32 ufid_flags = ovs_nla_get_ufid_flags(a[OVS_FLOW_ATTR_UFID_FLAGS]);
+ int err = 0;
bool log = !a[OVS_FLOW_ATTR_PROBE];
+ bool ufid_present;
- if (!a[OVS_FLOW_ATTR_KEY]) {
+ ufid_present = ovs_nla_get_ufid(a[OVS_FLOW_ATTR_UFID], &ufid, log);
+ if (a[OVS_FLOW_ATTR_KEY]) {
+ ovs_match_init(&match, &key, NULL);
+ err = ovs_nla_get_match(&match, a[OVS_FLOW_ATTR_KEY], NULL,
+ log);
+ } else if (!ufid_present) {
OVS_NLERR(log,
"Flow get message rejected, Key attribute missing.");
- return -EINVAL;
+ err = -EINVAL;
}
-
- ovs_match_init(&match, &key, NULL);
- err = ovs_nla_get_match(&match, a[OVS_FLOW_ATTR_KEY], NULL, log);
if (err)
return err;
@@ -1106,14 +1203,17 @@ static int ovs_flow_cmd_get(struct sk_buff *skb, struct genl_info *info)
goto unlock;
}
- flow = ovs_flow_tbl_lookup_exact(&dp->table, &match);
+ if (ufid_present)
+ flow = ovs_flow_tbl_lookup_ufid(&dp->table, &ufid);
+ else
+ flow = ovs_flow_tbl_lookup_exact(&dp->table, &match);
if (!flow) {
err = -ENOENT;
goto unlock;
}
reply = ovs_flow_cmd_build_info(flow, ovs_header->dp_ifindex, info,
- OVS_FLOW_CMD_NEW, true);
+ OVS_FLOW_CMD_NEW, true, ufid_flags);
if (IS_ERR(reply)) {
err = PTR_ERR(reply);
goto unlock;
@@ -1132,13 +1232,17 @@ static int ovs_flow_cmd_del(struct sk_buff *skb, struct genl_info *info)
struct ovs_header *ovs_header = info->userhdr;
struct sw_flow_key key;
struct sk_buff *reply;
- struct sw_flow *flow;
+ struct sw_flow *flow = NULL;
struct datapath *dp;
struct sw_flow_match match;
+ struct sw_flow_id ufid;
+ u32 ufid_flags = ovs_nla_get_ufid_flags(a[OVS_FLOW_ATTR_UFID_FLAGS]);
int err;
bool log = !a[OVS_FLOW_ATTR_PROBE];
+ bool ufid_present;
- if (likely(a[OVS_FLOW_ATTR_KEY])) {
+ ufid_present = ovs_nla_get_ufid(a[OVS_FLOW_ATTR_UFID], &ufid, log);
+ if (a[OVS_FLOW_ATTR_KEY]) {
ovs_match_init(&match, &key, NULL);
err = ovs_nla_get_match(&match, a[OVS_FLOW_ATTR_KEY], NULL,
log);
@@ -1153,12 +1257,15 @@ static int ovs_flow_cmd_del(struct sk_buff *skb, struct genl_info *info)
goto unlock;
}
- if (unlikely(!a[OVS_FLOW_ATTR_KEY])) {
+ if (unlikely(!a[OVS_FLOW_ATTR_KEY] && !ufid_present)) {
err = ovs_flow_tbl_flush(&dp->table);
goto unlock;
}
- flow = ovs_flow_tbl_lookup_exact(&dp->table, &match);
+ if (ufid_present)
+ flow = ovs_flow_tbl_lookup_ufid(&dp->table, &ufid);
+ else
+ flow = ovs_flow_tbl_lookup_exact(&dp->table, &match);
if (unlikely(!flow)) {
err = -ENOENT;
goto unlock;
@@ -1168,14 +1275,15 @@ static int ovs_flow_cmd_del(struct sk_buff *skb, struct genl_info *info)
ovs_unlock();
reply = ovs_flow_cmd_alloc_info((const struct sw_flow_actions __force *) flow->sf_acts,
- info, false);
+ flow->id, info, false, ufid_flags);
if (likely(reply)) {
if (likely(!IS_ERR(reply))) {
rcu_read_lock(); /*To keep RCU checker happy. */
err = ovs_flow_cmd_fill_info(flow, ovs_header->dp_ifindex,
reply, info->snd_portid,
info->snd_seq, 0,
- OVS_FLOW_CMD_DEL);
+ OVS_FLOW_CMD_DEL,
+ ufid_flags);
rcu_read_unlock();
BUG_ON(err < 0);
@@ -1194,9 +1302,18 @@ unlock:
static int ovs_flow_cmd_dump(struct sk_buff *skb, struct netlink_callback *cb)
{
+ struct nlattr *a[__OVS_FLOW_ATTR_MAX];
struct ovs_header *ovs_header = genlmsg_data(nlmsg_data(cb->nlh));
struct table_instance *ti;
struct datapath *dp;
+ u32 ufid_flags;
+ int err;
+
+ err = genlmsg_parse(cb->nlh, &dp_flow_genl_family, a,
+ OVS_FLOW_ATTR_MAX, flow_policy);
+ if (err)
+ return err;
+ ufid_flags = ovs_nla_get_ufid_flags(a[OVS_FLOW_ATTR_UFID_FLAGS]);
rcu_read_lock();
dp = get_dp_rcu(sock_net(skb->sk), ovs_header->dp_ifindex);
@@ -1219,7 +1336,7 @@ static int ovs_flow_cmd_dump(struct sk_buff *skb, struct netlink_callback *cb)
if (ovs_flow_cmd_fill_info(flow, ovs_header->dp_ifindex, skb,
NETLINK_CB(cb->skb).portid,
cb->nlh->nlmsg_seq, NLM_F_MULTI,
- OVS_FLOW_CMD_NEW) < 0)
+ OVS_FLOW_CMD_NEW, ufid_flags) < 0)
break;
cb->args[0] = bucket;
@@ -1235,6 +1352,8 @@ static const struct nla_policy flow_policy[OVS_FLOW_ATTR_MAX + 1] = {
[OVS_FLOW_ATTR_ACTIONS] = { .type = NLA_NESTED },
[OVS_FLOW_ATTR_CLEAR] = { .type = NLA_FLAG },
[OVS_FLOW_ATTR_PROBE] = { .type = NLA_FLAG },
+ [OVS_FLOW_ATTR_UFID] = { .type = NLA_UNSPEC, .len = 1 },
+ [OVS_FLOW_ATTR_UFID_FLAGS] = { .type = NLA_U32 },
};
static const struct genl_ops dp_flow_genl_ops[] = {
diff --git a/net/openvswitch/flow.h b/net/openvswitch/flow.h
index d3d0a40..84f259d 100644
--- a/net/openvswitch/flow.h
+++ b/net/openvswitch/flow.h
@@ -197,6 +197,16 @@ struct sw_flow_match {
struct sw_flow_mask *mask;
};
+#define MAX_UFID_LENGTH 16 /* 128 bits */
+
+struct sw_flow_id {
+ u32 ufid_len;
+ union {
+ u32 ufid[MAX_UFID_LENGTH / 4];
+ struct sw_flow_key flow_key;
+ };
+};
+
struct sw_flow_actions {
struct rcu_head rcu;
u32 actions_len;
@@ -213,13 +223,15 @@ struct flow_stats {
struct sw_flow {
struct rcu_head rcu;
- struct hlist_node hash_node[2];
- u32 hash;
+ struct {
+ struct hlist_node node[2];
+ u32 hash;
+ } flow_table, ufid_table;
int stats_last_writer; /* NUMA-node id of the last writer on
* 'stats[0]'.
*/
struct sw_flow_key key;
- struct sw_flow_key unmasked_key;
+ struct sw_flow_id *id;
struct sw_flow_mask *mask;
struct sw_flow_actions __rcu *sf_acts;
struct flow_stats __rcu *stats[]; /* One for each NUMA node. First one
@@ -243,6 +255,16 @@ struct arp_eth_header {
unsigned char ar_tip[4]; /* target IP address */
} __packed;
+static inline bool ovs_identifier_is_ufid(const struct sw_flow_id *sfid)
+{
+ return sfid->ufid_len;
+}
+
+static inline bool ovs_identifier_is_key(const struct sw_flow_id *sfid)
+{
+ return !ovs_identifier_is_ufid(sfid);
+}
+
void ovs_flow_stats_update(struct sw_flow *, __be16 tcp_flags,
const struct sk_buff *);
void ovs_flow_stats_get(const struct sw_flow *, struct ovs_flow_stats *,
diff --git a/net/openvswitch/flow_netlink.c b/net/openvswitch/flow_netlink.c
index 398f110..cdba8eb 100644
--- a/net/openvswitch/flow_netlink.c
+++ b/net/openvswitch/flow_netlink.c
@@ -1180,6 +1180,58 @@ free_newmask:
return err;
}
+static size_t get_ufid_len(const struct nlattr *attr, bool log)
+{
+ size_t len;
+
+ if (!attr)
+ return 0;
+
+ len = nla_len(attr);
+ if (len < 1 || len > MAX_UFID_LENGTH) {
+ OVS_NLERR(log, "Flow ufid size %u bytes is outside the range "
+ "(1, %d)", nla_len(attr), MAX_UFID_LENGTH);
+ return 0;
+ }
+
+ return len;
+}
+
+/* Initializes 'flow->ufid', returning true if 'attr' contains a valid UFID,
+ * or false otherwise. */
+bool ovs_nla_get_ufid(const struct nlattr *attr, struct sw_flow_id *sfid,
+ bool log)
+{
+ sfid->ufid_len = get_ufid_len(attr, log);
+ if (sfid->ufid_len)
+ memcpy(sfid->ufid, nla_data(attr), sfid->ufid_len);
+
+ return sfid->ufid_len;
+}
+
+struct sw_flow_id *ovs_nla_copy_identifier(const struct nlattr *ufid,
+ const struct sw_flow_key *key,
+ bool log)
+{
+ struct sw_flow_id *sfid;
+
+ sfid = kmalloc(sizeof(*sfid), GFP_KERNEL);
+ if (!sfid)
+ return ERR_PTR(-ENOMEM);
+
+ /* If UFID was not provided, use unmasked key. */
+ if (!ovs_nla_get_ufid(ufid, sfid, log))
+ memcpy(&sfid->flow_key, key, sizeof(*key));
+
+ return sfid;
+}
+
+
+u32 ovs_nla_get_ufid_flags(const struct nlattr *attr)
+{
+ return attr ? nla_get_u32(attr) : 0;
+}
+
/**
* ovs_nla_get_flow_metadata - parses Netlink attributes into a flow key.
* @key: Receives extracted in_port, priority, tun_key and skb_mark.
@@ -1450,9 +1502,20 @@ int ovs_nla_put_key(const struct sw_flow_key *swkey,
}
/* Called with ovs_mutex or RCU read lock. */
-int ovs_nla_put_unmasked_key(const struct sw_flow *flow, struct sk_buff *skb)
+int ovs_nla_put_identifier(const struct sw_flow *flow, struct sk_buff *skb)
+{
+ if (ovs_identifier_is_ufid(flow->id))
+ return nla_put(skb, OVS_FLOW_ATTR_UFID, flow->id->ufid_len,
+ flow->id->ufid);
+
+ return ovs_nla_put_key(&flow->id->flow_key, &flow->id->flow_key,
+ OVS_FLOW_ATTR_KEY, false, skb);
+}
+
+/* Called with ovs_mutex or RCU read lock. */
+int ovs_nla_put_masked_key(const struct sw_flow *flow, struct sk_buff *skb)
{
- return ovs_nla_put_key(&flow->unmasked_key, &flow->unmasked_key,
+ return ovs_nla_put_key(&flow->mask->key, &flow->key,
OVS_FLOW_ATTR_KEY, false, skb);
}
diff --git a/net/openvswitch/flow_netlink.h b/net/openvswitch/flow_netlink.h
index 9ed09e6..07fc9b6 100644
--- a/net/openvswitch/flow_netlink.h
+++ b/net/openvswitch/flow_netlink.h
@@ -48,7 +48,8 @@ int ovs_nla_put_key(const struct sw_flow_key *, const struct sw_flow_key *,
int ovs_nla_get_flow_metadata(const struct nlattr *, struct sw_flow_key *,
bool log);
-int ovs_nla_put_unmasked_key(const struct sw_flow *flow, struct sk_buff *skb);
+int ovs_nla_put_identifier(const struct sw_flow *flow, struct sk_buff *skb);
+int ovs_nla_put_masked_key(const struct sw_flow *flow, struct sk_buff *skb);
int ovs_nla_put_mask(const struct sw_flow *flow, struct sk_buff *skb);
int ovs_nla_get_match(struct sw_flow_match *, const struct nlattr *key,
@@ -56,6 +57,12 @@ int ovs_nla_get_match(struct sw_flow_match *, const struct nlattr *key,
int ovs_nla_put_egress_tunnel_key(struct sk_buff *,
const struct ovs_tunnel_info *);
+bool ovs_nla_get_ufid(const struct nlattr *, struct sw_flow_id *, bool log);
+struct sw_flow_id *ovs_nla_copy_identifier(const struct nlattr *ufid,
+ const struct sw_flow_key *key,
+ bool log);
+u32 ovs_nla_get_ufid_flags(const struct nlattr *attr);
+
int ovs_nla_copy_actions(const struct nlattr *attr,
const struct sw_flow_key *key,
struct sw_flow_actions **sfa, bool log);
diff --git a/net/openvswitch/flow_table.c b/net/openvswitch/flow_table.c
index 9a3f41f..623bbe0 100644
--- a/net/openvswitch/flow_table.c
+++ b/net/openvswitch/flow_table.c
@@ -85,6 +85,7 @@ struct sw_flow *ovs_flow_alloc(void)
flow->sf_acts = NULL;
flow->mask = NULL;
+ flow->id = NULL;
flow->stats_last_writer = NUMA_NO_NODE;
/* Initialize the default stat node. */
@@ -139,6 +140,7 @@ static void flow_free(struct sw_flow *flow)
{
int node;
+ kfree(flow->id);
kfree((struct sw_flow_actions __force *)flow->sf_acts);
for_each_node(node)
if (flow->stats[node])
@@ -200,18 +202,28 @@ static struct table_instance *table_instance_alloc(int new_size)
int ovs_flow_tbl_init(struct flow_table *table)
{
- struct table_instance *ti;
+ struct table_instance *ti, *ufid_ti;
ti = table_instance_alloc(TBL_MIN_BUCKETS);
if (!ti)
return -ENOMEM;
+ ufid_ti = table_instance_alloc(TBL_MIN_BUCKETS);
+ if (!ufid_ti)
+ goto free_ti;
+
rcu_assign_pointer(table->ti, ti);
+ rcu_assign_pointer(table->ufid_ti, ufid_ti);
INIT_LIST_HEAD(&table->mask_list);
table->last_rehash = jiffies;
table->count = 0;
+ table->ufid_count = 0;
return 0;
+
+free_ti:
+ __table_instance_destroy(ti);
+ return -ENOMEM;
}
static void flow_tbl_destroy_rcu_cb(struct rcu_head *rcu)
@@ -221,13 +233,16 @@ static void flow_tbl_destroy_rcu_cb(struct rcu_head *rcu)
__table_instance_destroy(ti);
}
-static void table_instance_destroy(struct table_instance *ti, bool deferred)
+static void table_instance_destroy(struct table_instance *ti,
+ struct table_instance *ufid_ti,
+ bool deferred)
{
int i;
if (!ti)
return;
+ BUG_ON(!ufid_ti);
if (ti->keep_flows)
goto skip_flows;
@@ -236,18 +251,24 @@ static void table_instance_destroy(struct table_instance *ti, bool deferred)
struct hlist_head *head = flex_array_get(ti->buckets, i);
struct hlist_node *n;
int ver = ti->node_ver;
+ int ufid_ver = ufid_ti->node_ver;
- hlist_for_each_entry_safe(flow, n, head, hash_node[ver]) {
- hlist_del_rcu(&flow->hash_node[ver]);
+ hlist_for_each_entry_safe(flow, n, head, flow_table.node[ver]) {
+ hlist_del_rcu(&flow->flow_table.node[ver]);
+ if (ovs_identifier_is_ufid(flow->id))
+ hlist_del_rcu(&flow->ufid_table.node[ufid_ver]);
ovs_flow_free(flow, deferred);
}
}
skip_flows:
- if (deferred)
+ if (deferred) {
call_rcu(&ti->rcu, flow_tbl_destroy_rcu_cb);
- else
+ call_rcu(&ufid_ti->rcu, flow_tbl_destroy_rcu_cb);
+ } else {
__table_instance_destroy(ti);
+ __table_instance_destroy(ufid_ti);
+ }
}
/* No need for locking this function is called from RCU callback or
@@ -256,8 +277,9 @@ skip_flows:
void ovs_flow_tbl_destroy(struct flow_table *table)
{
struct table_instance *ti = rcu_dereference_raw(table->ti);
+ struct table_instance *ufid_ti = rcu_dereference_raw(table->ufid_ti);
- table_instance_destroy(ti, false);
+ table_instance_destroy(ti, ufid_ti, false);
}
struct sw_flow *ovs_flow_tbl_dump_next(struct table_instance *ti,
@@ -272,7 +294,7 @@ struct sw_flow *ovs_flow_tbl_dump_next(struct table_instance *ti,
while (*bucket < ti->n_buckets) {
i = 0;
head = flex_array_get(ti->buckets, *bucket);
- hlist_for_each_entry_rcu(flow, head, hash_node[ver]) {
+ hlist_for_each_entry_rcu(flow, head, flow_table.node[ver]) {
if (i < *last) {
i++;
continue;
@@ -294,16 +316,26 @@ static struct hlist_head *find_bucket(struct table_instance *ti, u32 hash)
(hash & (ti->n_buckets - 1)));
}
-static void table_instance_insert(struct table_instance *ti, struct sw_flow *flow)
+static void table_instance_insert(struct table_instance *ti,
+ struct sw_flow *flow)
{
struct hlist_head *head;
- head = find_bucket(ti, flow->hash);
- hlist_add_head_rcu(&flow->hash_node[ti->node_ver], head);
+ head = find_bucket(ti, flow->flow_table.hash);
+ hlist_add_head_rcu(&flow->flow_table.node[ti->node_ver], head);
+}
+
+static void ufid_table_instance_insert(struct table_instance *ti,
+ struct sw_flow *flow)
+{
+ struct hlist_head *head;
+
+ head = find_bucket(ti, flow->ufid_table.hash);
+ hlist_add_head_rcu(&flow->ufid_table.node[ti->node_ver], head);
}
static void flow_table_copy_flows(struct table_instance *old,
- struct table_instance *new)
+ struct table_instance *new, bool ufid)
{
int old_ver;
int i;
@@ -318,15 +350,21 @@ static void flow_table_copy_flows(struct table_instance *old,
head = flex_array_get(old->buckets, i);
- hlist_for_each_entry(flow, head, hash_node[old_ver])
- table_instance_insert(new, flow);
+ if (ufid)
+ hlist_for_each_entry(flow, head,
+ ufid_table.node[old_ver])
+ ufid_table_instance_insert(new, flow);
+ else
+ hlist_for_each_entry(flow, head,
+ flow_table.node[old_ver])
+ table_instance_insert(new, flow);
}
old->keep_flows = true;
}
static struct table_instance *table_instance_rehash(struct table_instance *ti,
- int n_buckets)
+ int n_buckets, bool ufid)
{
struct table_instance *new_ti;
@@ -334,27 +372,38 @@ static struct table_instance *table_instance_rehash(struct table_instance *ti,
if (!new_ti)
return NULL;
- flow_table_copy_flows(ti, new_ti);
+ flow_table_copy_flows(ti, new_ti, ufid);
return new_ti;
}
int ovs_flow_tbl_flush(struct flow_table *flow_table)
{
- struct table_instance *old_ti;
- struct table_instance *new_ti;
+ struct table_instance *old_ti, *new_ti;
+ struct table_instance *old_ufid_ti, *new_ufid_ti;
- old_ti = ovsl_dereference(flow_table->ti);
new_ti = table_instance_alloc(TBL_MIN_BUCKETS);
if (!new_ti)
return -ENOMEM;
+ new_ufid_ti = table_instance_alloc(TBL_MIN_BUCKETS);
+ if (!new_ufid_ti)
+ goto err_free_ti;
+
+ old_ti = ovsl_dereference(flow_table->ti);
+ old_ufid_ti = ovsl_dereference(flow_table->ufid_ti);
rcu_assign_pointer(flow_table->ti, new_ti);
+ rcu_assign_pointer(flow_table->ufid_ti, new_ufid_ti);
flow_table->last_rehash = jiffies;
flow_table->count = 0;
+ flow_table->ufid_count = 0;
- table_instance_destroy(old_ti, true);
+ table_instance_destroy(old_ti, old_ufid_ti, true);
return 0;
+
+err_free_ti:
+ __table_instance_destroy(new_ti);
+ return -ENOMEM;
}
static u32 flow_hash(const struct sw_flow_key *key,
@@ -402,14 +451,15 @@ static bool flow_cmp_masked_key(const struct sw_flow *flow,
return cmp_key(&flow->key, key, range->start, range->end);
}
-bool ovs_flow_cmp_unmasked_key(const struct sw_flow *flow,
- const struct sw_flow_match *match)
+static bool ovs_flow_cmp_unmasked_key(const struct sw_flow *flow,
+ const struct sw_flow_match *match)
{
struct sw_flow_key *key = match->key;
int key_start = flow_key_start(key);
int key_end = match->range.end;
- return cmp_key(&flow->unmasked_key, key, key_start, key_end);
+ BUG_ON(ovs_identifier_is_ufid(flow->id));
+ return cmp_key(&flow->id->flow_key, key, key_start, key_end);
}
static struct sw_flow *masked_flow_lookup(struct table_instance *ti,
@@ -424,8 +474,8 @@ static struct sw_flow *masked_flow_lookup(struct table_instance *ti,
ovs_flow_mask_key(&masked_key, unmasked, mask);
hash = flow_hash(&masked_key, &mask->range);
head = find_bucket(ti, hash);
- hlist_for_each_entry_rcu(flow, head, hash_node[ti->node_ver]) {
- if (flow->mask == mask && flow->hash == hash &&
+ hlist_for_each_entry_rcu(flow, head, flow_table.node[ti->node_ver]) {
+ if (flow->mask == mask && flow->flow_table.hash == hash &&
flow_cmp_masked_key(flow, &masked_key, &mask->range))
return flow;
}
@@ -468,7 +518,48 @@ struct sw_flow *ovs_flow_tbl_lookup_exact(struct flow_table *tbl,
/* Always called under ovs-mutex. */
list_for_each_entry(mask, &tbl->mask_list, list) {
flow = masked_flow_lookup(ti, match->key, mask);
- if (flow && ovs_flow_cmp_unmasked_key(flow, match)) /* Found */
+ if (flow && ovs_identifier_is_key(flow->id) &&
+ ovs_flow_cmp_unmasked_key(flow, match))
+ return flow;
+ }
+ return NULL;
+}
+
+static u32 ufid_hash(const struct sw_flow_id *sfid)
+{
+ return jhash(sfid->ufid, sfid->ufid_len, 0);
+}
+
+static bool ovs_flow_cmp_ufid(const struct sw_flow *flow,
+ const struct sw_flow_id *sfid)
+{
+ if (flow->id->ufid_len != sfid->ufid_len)
+ return false;
+
+ return !memcmp(flow->id->ufid, sfid->ufid, sfid->ufid_len);
+}
+
+bool ovs_flow_cmp(const struct sw_flow *flow, const struct sw_flow_match *match)
+{
+ if (ovs_identifier_is_ufid(flow->id))
+ return flow_cmp_masked_key(flow, match->key, &match->range);
+
+ return ovs_flow_cmp_unmasked_key(flow, match);
+}
+
+struct sw_flow *ovs_flow_tbl_lookup_ufid(struct flow_table *tbl,
+ const struct sw_flow_id *ufid)
+{
+ struct table_instance *ti = rcu_dereference_ovsl(tbl->ufid_ti);
+ struct sw_flow *flow;
+ struct hlist_head *head;
+ u32 hash;
+
+ hash = ufid_hash(ufid);
+ head = find_bucket(ti, hash);
+ hlist_for_each_entry_rcu(flow, head, ufid_table.node[ti->node_ver]) {
+ if (flow->ufid_table.hash == hash &&
+ ovs_flow_cmp_ufid(flow, ufid))
return flow;
}
return NULL;
@@ -485,9 +576,10 @@ int ovs_flow_tbl_num_masks(const struct flow_table *table)
return num;
}
-static struct table_instance *table_instance_expand(struct table_instance *ti)
+static struct table_instance *table_instance_expand(struct table_instance *ti,
+ bool ufid)
{
- return table_instance_rehash(ti, ti->n_buckets * 2);
+ return table_instance_rehash(ti, ti->n_buckets * 2, ufid);
}
/* Remove 'mask' from the mask list, if it is not needed any more. */
@@ -512,10 +604,15 @@ static void flow_mask_remove(struct flow_table *tbl, struct sw_flow_mask *mask)
void ovs_flow_tbl_remove(struct flow_table *table, struct sw_flow *flow)
{
struct table_instance *ti = ovsl_dereference(table->ti);
+ struct table_instance *ufid_ti = ovsl_dereference(table->ufid_ti);
BUG_ON(table->count == 0);
- hlist_del_rcu(&flow->hash_node[ti->node_ver]);
+ hlist_del_rcu(&flow->flow_table.node[ti->node_ver]);
table->count--;
+ if (ovs_identifier_is_ufid(flow->id)) {
+ hlist_del_rcu(&flow->ufid_table.node[ufid_ti->node_ver]);
+ table->ufid_count--;
+ }
/* RCU delete the mask. 'flow->mask' is not NULLed, as it should be
* accessible as long as the RCU read lock is held.
@@ -589,25 +686,47 @@ static void flow_key_insert(struct flow_table *table, struct sw_flow *flow)
struct table_instance *new_ti = NULL;
struct table_instance *ti;
- flow->hash = flow_hash(&flow->key, &flow->mask->range);
+ flow->flow_table.hash = flow_hash(&flow->key, &flow->mask->range);
ti = ovsl_dereference(table->ti);
table_instance_insert(ti, flow);
table->count++;
/* Expand table, if necessary, to make room. */
if (table->count > ti->n_buckets)
- new_ti = table_instance_expand(ti);
+ new_ti = table_instance_expand(ti, false);
else if (time_after(jiffies, table->last_rehash + REHASH_INTERVAL))
- new_ti = table_instance_rehash(ti, ti->n_buckets);
+ new_ti = table_instance_rehash(ti, ti->n_buckets, false);
if (new_ti) {
rcu_assign_pointer(table->ti, new_ti);
- table_instance_destroy(ti, true);
+ call_rcu(&ti->rcu, flow_tbl_destroy_rcu_cb);
table->last_rehash = jiffies;
}
}
/* Must be called with OVS mutex held. */
+static void flow_ufid_insert(struct flow_table *table, struct sw_flow *flow)
+{
+ struct table_instance *ti;
+
+ flow->ufid_table.hash = ufid_hash(flow->id);
+ ti = ovsl_dereference(table->ufid_ti);
+ ufid_table_instance_insert(ti, flow);
+ table->ufid_count++;
+
+ /* Expand table, if necessary, to make room. */
+ if (table->ufid_count > ti->n_buckets) {
+ struct table_instance *new_ti;
+
+ new_ti = table_instance_expand(ti, true);
+ if (new_ti) {
+ rcu_assign_pointer(table->ufid_ti, new_ti);
+ call_rcu(&ti->rcu, flow_tbl_destroy_rcu_cb);
+ }
+ }
+}
+
+/* Must be called with OVS mutex held. */
int ovs_flow_tbl_insert(struct flow_table *table, struct sw_flow *flow,
const struct sw_flow_mask *mask)
{
@@ -617,6 +736,8 @@ int ovs_flow_tbl_insert(struct flow_table *table, struct sw_flow *flow,
if (err)
return err;
flow_key_insert(table, flow);
+ if (ovs_identifier_is_ufid(flow->id))
+ flow_ufid_insert(table, flow);
return 0;
}
diff --git a/net/openvswitch/flow_table.h b/net/openvswitch/flow_table.h
index 309fa64..616eda1 100644
--- a/net/openvswitch/flow_table.h
+++ b/net/openvswitch/flow_table.h
@@ -47,9 +47,11 @@ struct table_instance {
struct flow_table {
struct table_instance __rcu *ti;
+ struct table_instance __rcu *ufid_ti;
struct list_head mask_list;
unsigned long last_rehash;
unsigned int count;
+ unsigned int ufid_count;
};
extern struct kmem_cache *flow_stats_cache;
@@ -78,8 +80,10 @@ struct sw_flow *ovs_flow_tbl_lookup(struct flow_table *,
const struct sw_flow_key *);
struct sw_flow *ovs_flow_tbl_lookup_exact(struct flow_table *tbl,
const struct sw_flow_match *match);
-bool ovs_flow_cmp_unmasked_key(const struct sw_flow *flow,
- const struct sw_flow_match *match);
+struct sw_flow *ovs_flow_tbl_lookup_ufid(struct flow_table *,
+ const struct sw_flow_id *);
+
+bool ovs_flow_cmp(const struct sw_flow *, const struct sw_flow_match *);
void ovs_flow_mask_key(struct sw_flow_key *dst, const struct sw_flow_key *src,
const struct sw_flow_mask *mask);
--
1.7.10.4
_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev
^ permalink raw reply related
* [PATCH net-next v12 4/5] genetlink: Add genlmsg_parse() helper function.
From: Joe Stringer @ 2015-01-15 21:48 UTC (permalink / raw)
To: netdev-u79uwXL29TY76Z2rM5mHXA
Cc: dev-yBygre7rU0TnMu66kgdUjQ, linux-kernel-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1421358507-5992-1-git-send-email-joestringer-l0M0P4e3n4LQT0dZR+AlfA@public.gmane.org>
The first user will be the next patch.
Signed-off-by: Joe Stringer <joestringer@nicira.com>
---
include/net/genetlink.h | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/include/net/genetlink.h b/include/net/genetlink.h
index 8412508..fb2d2e6 100644
--- a/include/net/genetlink.h
+++ b/include/net/genetlink.h
@@ -206,6 +206,23 @@ static inline struct nlmsghdr *genlmsg_nlhdr(void *user_hdr,
}
/**
+ * genlmsg_parse - parse attributes of a genetlink message
+ * @nlh: netlink message header
+ * @family: genetlink message family
+ * @tb: destination array with maxtype+1 elements
+ * @maxtype: maximum attribute type to be expected
+ * @policy: validation policy
+ * */
+static inline int genlmsg_parse(const struct nlmsghdr *nlh,
+ const struct genl_family *family,
+ struct nlattr *tb[], int maxtype,
+ const struct nla_policy *policy)
+{
+ return nlmsg_parse(nlh, family->hdrsize + GENL_HDRLEN, tb, maxtype,
+ policy);
+}
+
+/**
* genl_dump_check_consistent - check if sequence is consistent and advertise if not
* @cb: netlink callback structure that stores the sequence number
* @user_hdr: user header as returned from genlmsg_put()
--
1.7.10.4
_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox