diff options
| author | David S. Miller <davem@davemloft.net> | 2015-10-15 16:09:58 +0300 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2015-10-15 16:09:58 +0300 |
| commit | 74661bee1f524ca970086748291b3ca1b4c21ffe (patch) | |
| tree | 7d6671c6e2f27c0b04ce775d913f09384b89e07f /include | |
| parent | adc9048c607a08320e87befc940955d6ffe51fac (diff) | |
| parent | 771acac2ffa5957b91e881908cd4c9657978a209 (diff) | |
| download | linux-74661bee1f524ca970086748291b3ca1b4c21ffe.tar.xz | |
Merge branch 'switchdev-locking'
Jiri Pirko says:
====================
switchdev: change locking
This is something which I'm currently struggling with.
Callers of attr_set and obj_add/del often hold not only RTNL, but also
spinlock (bridge). So in that case, the driver implementing the op cannot sleep.
The way rocker is dealing with this now is just to invoke driver operation
and go out, without any checking or reporting of the operation status.
Since it would be nice to at least put a warning in case the operation fails,
it makes sense to do this in delayed work directly in switchdev core
instead of implementing this in separate drivers. And that is what this patchset
is introducing.
So from now on, the locking of switchdev mod ops is consistent. Caller either
holds rtnl mutex or in case it does not, caller sets defer flag, telling
switchdev core to process the op later, in deferred queue.
Function to force to process switchdev deferred ops can be called by op
caller in appropriate location, for example after it releases
spin lock, to force switchdev core to process pending ops.
v1->v2:
- rebased on current net-next head (including Scott's ageing patchset)
v2->v3:
- fixed comment s/of/or/ typo suggested by Nik
v3->v4:
- the actual patchset is sent instead of different branch I send in v3 :/
v4->v5:
- added patch to "const" attr param
- reworked deferred ops infrastructure (mainly patch number 1 and
internal users (patch 3 and 5)) - resolves the issue pointed out
by John
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'include')
| -rw-r--r-- | include/net/switchdev.h | 20 |
1 files changed, 13 insertions, 7 deletions
diff --git a/include/net/switchdev.h b/include/net/switchdev.h index 1ce70830357d..bc865e244efe 100644 --- a/include/net/switchdev.h +++ b/include/net/switchdev.h @@ -14,9 +14,11 @@ #include <linux/netdevice.h> #include <linux/notifier.h> #include <linux/list.h> +#include <net/ip_fib.h> #define SWITCHDEV_F_NO_RECURSE BIT(0) #define SWITCHDEV_F_SKIP_EOPNOTSUPP BIT(1) +#define SWITCHDEV_F_DEFER BIT(2) struct switchdev_trans_item { struct list_head list; @@ -58,8 +60,6 @@ struct switchdev_attr { } u; }; -struct fib_info; - enum switchdev_obj_id { SWITCHDEV_OBJ_ID_UNDEFINED, SWITCHDEV_OBJ_ID_PORT_VLAN, @@ -69,6 +69,7 @@ enum switchdev_obj_id { struct switchdev_obj { enum switchdev_obj_id id; + u32 flags; }; /* SWITCHDEV_OBJ_ID_PORT_VLAN */ @@ -87,7 +88,7 @@ struct switchdev_obj_ipv4_fib { struct switchdev_obj obj; u32 dst; int dst_len; - struct fib_info *fi; + struct fib_info fi; u8 tos; u8 type; u32 nlflags; @@ -100,7 +101,7 @@ struct switchdev_obj_ipv4_fib { /* SWITCHDEV_OBJ_ID_PORT_FDB */ struct switchdev_obj_port_fdb { struct switchdev_obj obj; - const unsigned char *addr; + unsigned char addr[ETH_ALEN]; u16 vid; u16 ndm_state; }; @@ -132,7 +133,7 @@ struct switchdev_ops { int (*switchdev_port_attr_get)(struct net_device *dev, struct switchdev_attr *attr); int (*switchdev_port_attr_set)(struct net_device *dev, - struct switchdev_attr *attr, + const struct switchdev_attr *attr, struct switchdev_trans *trans); int (*switchdev_port_obj_add)(struct net_device *dev, const struct switchdev_obj *obj, @@ -167,10 +168,11 @@ switchdev_notifier_info_to_dev(const struct switchdev_notifier_info *info) #ifdef CONFIG_NET_SWITCHDEV +void switchdev_deferred_process(void); int switchdev_port_attr_get(struct net_device *dev, struct switchdev_attr *attr); int switchdev_port_attr_set(struct net_device *dev, - struct switchdev_attr *attr); + const struct switchdev_attr *attr); int switchdev_port_obj_add(struct net_device *dev, const struct switchdev_obj *obj); int switchdev_port_obj_del(struct net_device *dev, @@ -208,6 +210,10 @@ void switchdev_port_fwd_mark_set(struct net_device *dev, #else +static inline void switchdev_deferred_process(void) +{ +} + static inline int switchdev_port_attr_get(struct net_device *dev, struct switchdev_attr *attr) { @@ -215,7 +221,7 @@ static inline int switchdev_port_attr_get(struct net_device *dev, } static inline int switchdev_port_attr_set(struct net_device *dev, - struct switchdev_attr *attr) + const struct switchdev_attr *attr) { return -EOPNOTSUPP; } |
