[PATCH net-next 01/12] switchdev: SWITCHDEV_OBJ_PORT_{VLAN, MDB}(): Sanitize

2018-11-22 Thread Petr Machata
The two macros SWITCHDEV_OBJ_PORT_VLAN() and SWITCHDEV_OBJ_PORT_MDB()
expand to a container_of() call, yielding an appropriate container of
their sole argument. However, due to a name collision, the first
argument, i.e. the contained object pointer, is not the only one to get
expanded. The third argument, which is a structure member name, and
should be kept literal, gets expanded as well. The only safe way to use
these two macros is therefore to name the local variable passed to them
"obj".

To fix this, rename the sole argument of the two macros from
"obj" (which collides with the member name) to "OBJ". Additionally,
instead of passing "OBJ" to container_of() verbatim, parenthesize it, so
that a comma in the passed-in expression doesn't pollute the
container_of() invocation.

Signed-off-by: Petr Machata 
Acked-by: Jiri Pirko 
Reviewed-by: Ido Schimmel 
---
 include/net/switchdev.h | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/include/net/switchdev.h b/include/net/switchdev.h
index 7b371e7c4bc6..dd969224a9b9 100644
--- a/include/net/switchdev.h
+++ b/include/net/switchdev.h
@@ -95,8 +95,8 @@ struct switchdev_obj_port_vlan {
u16 vid_end;
 };
 
-#define SWITCHDEV_OBJ_PORT_VLAN(obj) \
-   container_of(obj, struct switchdev_obj_port_vlan, obj)
+#define SWITCHDEV_OBJ_PORT_VLAN(OBJ) \
+   container_of((OBJ), struct switchdev_obj_port_vlan, obj)
 
 /* SWITCHDEV_OBJ_ID_PORT_MDB */
 struct switchdev_obj_port_mdb {
@@ -105,8 +105,8 @@ struct switchdev_obj_port_mdb {
u16 vid;
 };
 
-#define SWITCHDEV_OBJ_PORT_MDB(obj) \
-   container_of(obj, struct switchdev_obj_port_mdb, obj)
+#define SWITCHDEV_OBJ_PORT_MDB(OBJ) \
+   container_of((OBJ), struct switchdev_obj_port_mdb, obj)
 
 void switchdev_trans_item_enqueue(struct switchdev_trans *trans,
  void *data, void (*destructor)(void const *),
-- 
2.4.11

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH net-next 00/12] switchdev: Convert switchdev_port_obj_{add,del}() to notifiers

2018-11-22 Thread Petr Machata
An offloading driver may need to have access to switchdev events on
ports that aren't directly under its control. An example is a VXLAN port
attached to a bridge offloaded by a driver. The driver needs to know
about VLANs configured on the VXLAN device. However the VXLAN device
isn't stashed between the bridge and a front-panel-port device (such as
is the case e.g. for LAG devices), so the usual switchdev ops don't
reach the driver.

VXLAN is likely not the only device type like this: in theory any L2
tunnel device that needs offloading will prompt requirement of this
sort.

A way to fix this is to give up the notion of port object addition /
deletion as a switchdev operation, which assumes somewhat tight coupling
between the message producer and consumer. And instead send the message
over a notifier chain.

The series starts with a clean-up patch #1, where
SWITCHDEV_OBJ_PORT_{VLAN, MDB}() are fixed up to lift the constraint
that the passed-in argument be a simple variable named "obj".

switchdev_port_obj_add and _del are invoked in a context that permits
blocking. Not only that, at least for the VLAN notification, being able
to signal failure is actually important. Therefore introduce a new
blocking notifier chain that the new events will be sent on. That's done
in patch #2. Retain the current (atomic) notifier chain for the
preexisting notifications.

In patch #3, introduce two new switchdev notifier types,
SWITCHDEV_PORT_OBJ_ADD and SWITCHDEV_PORT_OBJ_DEL. These notifier types
communicate the same event as the corresponding switchdev op, except in
a form of a notification. struct switchdev_notifier_port_obj_info was
added to carry the fields that correspond to the switchdev op arguments.
An additional field, handled, will be used to communicate back to
switchdev that the event has reached an interested party, which will be
important for the two-phase commit.

In patches #4, #5, and #7, rocker, DSA resp. ethsw are updated to
subscribe to the switchdev blocking notifier chain, and handle the new
notifier types. #6 introduces a helper to determine whether a
netdevice corresponds to a front panel port.

What these three drivers have in common is that their ports don't
support any uppers besides bridge. That makes it possible to ignore any
notifiers that don't reference a front-panel port device, because they
are certainly out of scope.

Unlike the previous three, mlxsw and ocelot drivers admit stacked
devices as uppers. While the current switchdev code recursively descends
through layers of lower devices, eventually calling the op on a
front-panel port device, the notifier would reference a stacking device
that's one of front-panel ports uppers. The filtering is thus more
complex.

For ocelot, such iteration is currently pretty much required, because
there's no bookkeeping of LAG devices. mlxsw does keep the list of LAGs,
however it iterates the lower devices anyway when deciding whether an
event on a tunnel device pertains to the driver or not.

Therefore this patch set instead introduces, in patch #8, a helper to
iterate through lowers, much like the current switchdev code does,
looking for devices that match a given predicate.

Then in patches #9 and #10, first mlxsw and then ocelot are updated to
dispatch the newly-added notifier types to the preexisting
port_obj_add/_del handlers. The dispatch is done via the new helper, to
recursively descend through lower devices.

Finally in patch #11, the actual switch is made, retiring the current
SDO-based code in favor of a notifier.

Now that the event is distributed through a notifier, the explicit
netdevice check in rocker, DSA and ethsw doesn't let through any events
except those done on a front-panel port itself. It is therefore
unnecessary to check in VLAN-handling code whether a VLAN was added to
the bridge itself: such events will simply be ignored much sooner.
Therefore remove it in patch #12.

Petr Machata (12):
  switchdev: SWITCHDEV_OBJ_PORT_{VLAN, MDB}(): Sanitize
  switchdev: Add a blocking notifier chain
  switchdev: Add SWITCHDEV_PORT_OBJ_ADD, SWITCHDEV_PORT_OBJ_DEL
  rocker: Handle SWITCHDEV_PORT_OBJ_ADD/_DEL
  net: dsa: slave: Handle SWITCHDEV_PORT_OBJ_ADD/_DEL
  staging: fsl-dpaa2: ethsw: Introduce ethsw_port_dev_check()
  staging: fsl-dpaa2: ethsw: Handle SWITCHDEV_PORT_OBJ_ADD/_DEL
  switchdev: Add helpers to aid traversal through lower devices
  mlxsw: spectrum_switchdev: Handle SWITCHDEV_PORT_OBJ_ADD/_DEL
  ocelot: Handle SWITCHDEV_PORT_OBJ_ADD/_DEL
  switchdev: Replace port obj add/del SDO with a notification
  rocker, dsa, ethsw: Don't filter VLAN events on bridge itself

 .../ethernet/mellanox/mlxsw/spectrum_switchdev.c   |  47 -
 drivers/net/ethernet/mscc/ocelot.c |  30 +++-
 drivers/net/ethernet/mscc/ocelot.h |   1 +
 drivers/net/ethernet/mscc/ocelot_board.c   |   3 +
 drivers/net/ethernet/rocker/rocker_main.c  |  60 +

[PATCH net-next 04/12] rocker: Handle SWITCHDEV_PORT_OBJ_ADD/_DEL

2018-11-22 Thread Petr Machata
Following patches will change the way of distributing port object
changes from a switchdev operation to a switchdev notifier. The
switchdev code currently recursively descends through layers of lower
devices, eventually calling the op on a front-panel port device. The
notifier will instead be sent referencing the bridge port device, which
may be a stacking device that's one of front-panel ports uppers, or a
completely unrelated device.

rocker currently doesn't support any uppers other than bridge. Thus the
only case that a stacked device could be validly referenced by port
object notifications are bridge notifications for VLAN objects added to
the bridge itself. But the driver explicitly rejects such notifications
in rocker_world_port_obj_vlan_add(). It is therefore safe to assume that
the only interesting case is that the notification is on a front-panel
port netdevice.

Subscribe to the blocking notifier chain. In the handler, filter out
notifications on any foreign netdevices. Dispatch the new notifiers to
rocker_port_obj_add() resp. _del() to maintain the behavior that the
switchdev operation based code currently has.

Signed-off-by: Petr Machata 
Acked-by: Jiri Pirko 
---
 drivers/net/ethernet/rocker/rocker_main.c | 55 +++
 1 file changed, 55 insertions(+)

diff --git a/drivers/net/ethernet/rocker/rocker_main.c 
b/drivers/net/ethernet/rocker/rocker_main.c
index beb06628f22d..806ffe1d906e 100644
--- a/drivers/net/ethernet/rocker/rocker_main.c
+++ b/drivers/net/ethernet/rocker/rocker_main.c
@@ -2812,12 +2812,54 @@ static int rocker_switchdev_event(struct notifier_block 
*unused,
return NOTIFY_DONE;
 }
 
+static int
+rocker_switchdev_port_obj_event(unsigned long event, struct net_device *netdev,
+   struct switchdev_notifier_port_obj_info *port_obj_info)
+{
+   int err = -EOPNOTSUPP;
+
+   switch (event) {
+   case SWITCHDEV_PORT_OBJ_ADD:
+   err = rocker_port_obj_add(netdev, port_obj_info->obj,
+ port_obj_info->trans);
+   break;
+   case SWITCHDEV_PORT_OBJ_DEL:
+   err = rocker_port_obj_del(netdev, port_obj_info->obj);
+   break;
+   }
+
+   port_obj_info->handled = true;
+   return notifier_from_errno(err);
+}
+
+static int rocker_switchdev_blocking_event(struct notifier_block *unused,
+  unsigned long event, void *ptr)
+{
+   struct net_device *dev = switchdev_notifier_info_to_dev(ptr);
+
+   if (!rocker_port_dev_check(dev))
+   return NOTIFY_DONE;
+
+   switch (event) {
+   case SWITCHDEV_PORT_OBJ_ADD:
+   case SWITCHDEV_PORT_OBJ_DEL:
+   return rocker_switchdev_port_obj_event(event, dev, ptr);
+   }
+
+   return NOTIFY_DONE;
+}
+
 static struct notifier_block rocker_switchdev_notifier = {
.notifier_call = rocker_switchdev_event,
 };
 
+static struct notifier_block rocker_switchdev_blocking_notifier = {
+   .notifier_call = rocker_switchdev_blocking_event,
+};
+
 static int rocker_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
+   struct notifier_block *nb;
struct rocker *rocker;
int err;
 
@@ -2933,6 +2975,13 @@ static int rocker_probe(struct pci_dev *pdev, const 
struct pci_device_id *id)
goto err_register_switchdev_notifier;
}
 
+   nb = &rocker_switchdev_blocking_notifier;
+   err = register_switchdev_blocking_notifier(nb);
+   if (err) {
+   dev_err(&pdev->dev, "Failed to register switchdev blocking 
notifier\n");
+   goto err_register_switchdev_blocking_notifier;
+   }
+
rocker->hw.id = rocker_read64(rocker, SWITCH_ID);
 
dev_info(&pdev->dev, "Rocker switch with id %*phN\n",
@@ -2940,6 +2989,8 @@ static int rocker_probe(struct pci_dev *pdev, const 
struct pci_device_id *id)
 
return 0;
 
+err_register_switchdev_blocking_notifier:
+   unregister_switchdev_notifier(&rocker_switchdev_notifier);
 err_register_switchdev_notifier:
unregister_fib_notifier(&rocker->fib_nb);
 err_register_fib_notifier:
@@ -2971,6 +3022,10 @@ static int rocker_probe(struct pci_dev *pdev, const 
struct pci_device_id *id)
 static void rocker_remove(struct pci_dev *pdev)
 {
struct rocker *rocker = pci_get_drvdata(pdev);
+   struct notifier_block *nb;
+
+   nb = &rocker_switchdev_blocking_notifier;
+   unregister_switchdev_blocking_notifier(nb);
 
unregister_switchdev_notifier(&rocker_switchdev_notifier);
unregister_fib_notifier(&rocker->fib_nb);
-- 
2.4.11

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH net-next 02/12] switchdev: Add a blocking notifier chain

2018-11-22 Thread Petr Machata
In general one can't assume that a switchdev notifier is called in a
non-atomic context, and correspondingly, the switchdev notifier chain is
an atomic one.

However, port object addition and deletion messages are delivered from a
process context. Even the MDB addition messages, whose delivery is
scheduled from atomic context, are queued and the delivery itself takes
place in blocking context. For VLAN messages in particular, keeping the
blocking nature is important for error reporting.

Therefore introduce a blocking notifier chain and related service
functions to distribute the notifications for which a blocking context
can be assumed.

Signed-off-by: Petr Machata 
Reviewed-by: Jiri Pirko 
Reviewed-by: Ido Schimmel 
---
 include/net/switchdev.h   | 27 +++
 net/switchdev/switchdev.c | 26 ++
 2 files changed, 53 insertions(+)

diff --git a/include/net/switchdev.h b/include/net/switchdev.h
index dd969224a9b9..e021b67b9b32 100644
--- a/include/net/switchdev.h
+++ b/include/net/switchdev.h
@@ -182,10 +182,17 @@ int switchdev_port_obj_add(struct net_device *dev,
   const struct switchdev_obj *obj);
 int switchdev_port_obj_del(struct net_device *dev,
   const struct switchdev_obj *obj);
+
 int register_switchdev_notifier(struct notifier_block *nb);
 int unregister_switchdev_notifier(struct notifier_block *nb);
 int call_switchdev_notifiers(unsigned long val, struct net_device *dev,
 struct switchdev_notifier_info *info);
+
+int register_switchdev_blocking_notifier(struct notifier_block *nb);
+int unregister_switchdev_blocking_notifier(struct notifier_block *nb);
+int call_switchdev_blocking_notifiers(unsigned long val, struct net_device 
*dev,
+ struct switchdev_notifier_info *info);
+
 void switchdev_port_fwd_mark_set(struct net_device *dev,
 struct net_device *group_dev,
 bool joining);
@@ -241,6 +248,26 @@ static inline int call_switchdev_notifiers(unsigned long 
val,
return NOTIFY_DONE;
 }
 
+static inline int
+register_switchdev_blocking_notifier(struct notifier_block *nb)
+{
+   return 0;
+}
+
+static inline int
+unregister_switchdev_blocking_notifier(struct notifier_block *nb)
+{
+   return 0;
+}
+
+static inline int
+call_switchdev_blocking_notifiers(unsigned long val,
+ struct net_device *dev,
+ struct switchdev_notifier_info *info)
+{
+   return NOTIFY_DONE;
+}
+
 static inline bool switchdev_port_same_parent_id(struct net_device *a,
 struct net_device *b)
 {
diff --git a/net/switchdev/switchdev.c b/net/switchdev/switchdev.c
index 74b9d916a58b..e109bb97ce3f 100644
--- a/net/switchdev/switchdev.c
+++ b/net/switchdev/switchdev.c
@@ -535,6 +535,7 @@ int switchdev_port_obj_del(struct net_device *dev,
 EXPORT_SYMBOL_GPL(switchdev_port_obj_del);
 
 static ATOMIC_NOTIFIER_HEAD(switchdev_notif_chain);
+static BLOCKING_NOTIFIER_HEAD(switchdev_blocking_notif_chain);
 
 /**
  * register_switchdev_notifier - Register notifier
@@ -576,6 +577,31 @@ int call_switchdev_notifiers(unsigned long val, struct 
net_device *dev,
 }
 EXPORT_SYMBOL_GPL(call_switchdev_notifiers);
 
+int register_switchdev_blocking_notifier(struct notifier_block *nb)
+{
+   struct blocking_notifier_head *chain = &switchdev_blocking_notif_chain;
+
+   return blocking_notifier_chain_register(chain, nb);
+}
+EXPORT_SYMBOL_GPL(register_switchdev_blocking_notifier);
+
+int unregister_switchdev_blocking_notifier(struct notifier_block *nb)
+{
+   struct blocking_notifier_head *chain = &switchdev_blocking_notif_chain;
+
+   return blocking_notifier_chain_unregister(chain, nb);
+}
+EXPORT_SYMBOL_GPL(unregister_switchdev_blocking_notifier);
+
+int call_switchdev_blocking_notifiers(unsigned long val, struct net_device 
*dev,
+ struct switchdev_notifier_info *info)
+{
+   info->dev = dev;
+   return blocking_notifier_call_chain(&switchdev_blocking_notif_chain,
+   val, info);
+}
+EXPORT_SYMBOL_GPL(call_switchdev_blocking_notifiers);
+
 bool switchdev_port_same_parent_id(struct net_device *a,
   struct net_device *b)
 {
-- 
2.4.11

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH net-next 03/12] switchdev: Add SWITCHDEV_PORT_OBJ_ADD, SWITCHDEV_PORT_OBJ_DEL

2018-11-22 Thread Petr Machata
An offloading driver may need to have access to switchdev events on
ports that aren't directly under its control. An example is a VXLAN port
attached to a bridge offloaded by a driver. The driver needs to know
about VLANs configured on the VXLAN device. However the VXLAN device
isn't stashed between the bridge and a front-panel-port device (such as
is the case e.g. for LAG devices), so the usual switchdev ops don't
reach the driver.

VXLAN is likely not the only device type like this: in theory any L2
tunnel device that needs offloading will prompt requirement of this
sort. This falsifies the assumption that only the lower devices of a
front panel port need to be notified to achieve flawless offloading.

A way to fix this is to give up the notion of port object addition /
deletion as a switchdev operation, which assumes somewhat tight coupling
between the message producer and consumer. And instead send the message
over a notifier chain.

To that end, introduce two new switchdev notifier types,
SWITCHDEV_PORT_OBJ_ADD and SWITCHDEV_PORT_OBJ_DEL. These notifier types
communicate the same event as the corresponding switchdev op, except in
a form of a notification. struct switchdev_notifier_port_obj_info was
added to carry the fields that the switchdev op carries. An additional
field, handled, will be used to communicate back to switchdev that the
event has reached an interested party, which will be important for the
two-phase commit.

The two switchdev operations themselves are kept in place. Following
patches first convert individual clients to the notifier protocol, and
only then are the operations removed.

Signed-off-by: Petr Machata 
Acked-by: Jiri Pirko 
Reviewed-by: Ido Schimmel 
---
 include/net/switchdev.h | 10 ++
 1 file changed, 10 insertions(+)

diff --git a/include/net/switchdev.h b/include/net/switchdev.h
index e021b67b9b32..a2f3ebf39301 100644
--- a/include/net/switchdev.h
+++ b/include/net/switchdev.h
@@ -146,6 +146,9 @@ enum switchdev_notifier_type {
SWITCHDEV_FDB_DEL_TO_DEVICE,
SWITCHDEV_FDB_OFFLOADED,
 
+   SWITCHDEV_PORT_OBJ_ADD, /* Blocking. */
+   SWITCHDEV_PORT_OBJ_DEL, /* Blocking. */
+
SWITCHDEV_VXLAN_FDB_ADD_TO_BRIDGE,
SWITCHDEV_VXLAN_FDB_DEL_TO_BRIDGE,
SWITCHDEV_VXLAN_FDB_ADD_TO_DEVICE,
@@ -165,6 +168,13 @@ struct switchdev_notifier_fdb_info {
   offloaded:1;
 };
 
+struct switchdev_notifier_port_obj_info {
+   struct switchdev_notifier_info info; /* must be first */
+   const struct switchdev_obj *obj;
+   struct switchdev_trans *trans;
+   bool handled;
+};
+
 static inline struct net_device *
 switchdev_notifier_info_to_dev(const struct switchdev_notifier_info *info)
 {
-- 
2.4.11

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH net-next 05/12] net: dsa: slave: Handle SWITCHDEV_PORT_OBJ_ADD/_DEL

2018-11-22 Thread Petr Machata
Following patches will change the way of distributing port object
changes from a switchdev operation to a switchdev notifier. The
switchdev code currently recursively descends through layers of lower
devices, eventually calling the op on a front-panel port device. The
notifier will instead be sent referencing the bridge port device, which
may be a stacking device that's one of front-panel ports uppers, or a
completely unrelated device.

DSA currently doesn't support any other uppers than bridge.
SWITCHDEV_OBJ_ID_HOST_MDB and _PORT_MDB objects are always notified on
the bridge port device. Thus the only case that a stacked device could
be validly referenced by port object notifications are bridge
notifications for VLAN objects added to the bridge itself. But the
driver explicitly rejects such notifications in dsa_port_vlan_add(). It
is therefore safe to assume that the only interesting case is that the
notification is on a front-panel port netdevice. Therefore keep the
filtering by dsa_slave_dev_check() in place.

To handle SWITCHDEV_PORT_OBJ_ADD and _DEL, subscribe to the blocking
notifier chain. Dispatch to rocker_port_obj_add() resp. _del() to
maintain the behavior that the switchdev operation based code currently
has.

Signed-off-by: Petr Machata 
Acked-by: Jiri Pirko 
---
 net/dsa/slave.c | 56 
 1 file changed, 56 insertions(+)

diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index 7d0c19e7edcf..d00a0b6d4ce0 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -1557,6 +1557,44 @@ static int dsa_slave_switchdev_event(struct 
notifier_block *unused,
return NOTIFY_BAD;
 }
 
+static int
+dsa_slave_switchdev_port_obj_event(unsigned long event,
+   struct net_device *netdev,
+   struct switchdev_notifier_port_obj_info *port_obj_info)
+{
+   int err = -EOPNOTSUPP;
+
+   switch (event) {
+   case SWITCHDEV_PORT_OBJ_ADD:
+   err = dsa_slave_port_obj_add(netdev, port_obj_info->obj,
+port_obj_info->trans);
+   break;
+   case SWITCHDEV_PORT_OBJ_DEL:
+   err = dsa_slave_port_obj_del(netdev, port_obj_info->obj);
+   break;
+   }
+
+   port_obj_info->handled = true;
+   return notifier_from_errno(err);
+}
+
+static int dsa_slave_switchdev_blocking_event(struct notifier_block *unused,
+ unsigned long event, void *ptr)
+{
+   struct net_device *dev = switchdev_notifier_info_to_dev(ptr);
+
+   if (!dsa_slave_dev_check(dev))
+   return NOTIFY_DONE;
+
+   switch (event) {
+   case SWITCHDEV_PORT_OBJ_ADD: /* fall through */
+   case SWITCHDEV_PORT_OBJ_DEL:
+   return dsa_slave_switchdev_port_obj_event(event, dev, ptr);
+   }
+
+   return NOTIFY_DONE;
+}
+
 static struct notifier_block dsa_slave_nb __read_mostly = {
.notifier_call  = dsa_slave_netdevice_event,
 };
@@ -1565,8 +1603,13 @@ static struct notifier_block 
dsa_slave_switchdev_notifier = {
.notifier_call = dsa_slave_switchdev_event,
 };
 
+static struct notifier_block dsa_slave_switchdev_blocking_notifier = {
+   .notifier_call = dsa_slave_switchdev_blocking_event,
+};
+
 int dsa_slave_register_notifier(void)
 {
+   struct notifier_block *nb;
int err;
 
err = register_netdevice_notifier(&dsa_slave_nb);
@@ -1577,8 +1620,15 @@ int dsa_slave_register_notifier(void)
if (err)
goto err_switchdev_nb;
 
+   nb = &dsa_slave_switchdev_blocking_notifier;
+   err = register_switchdev_blocking_notifier(nb);
+   if (err)
+   goto err_switchdev_blocking_nb;
+
return 0;
 
+err_switchdev_blocking_nb:
+   unregister_switchdev_notifier(&dsa_slave_switchdev_notifier);
 err_switchdev_nb:
unregister_netdevice_notifier(&dsa_slave_nb);
return err;
@@ -1586,8 +1636,14 @@ int dsa_slave_register_notifier(void)
 
 void dsa_slave_unregister_notifier(void)
 {
+   struct notifier_block *nb;
int err;
 
+   nb = &dsa_slave_switchdev_blocking_notifier;
+   err = unregister_switchdev_blocking_notifier(nb);
+   if (err)
+   pr_err("DSA: failed to unregister switchdev blocking notifier 
(%d)\n", err);
+
err = unregister_switchdev_notifier(&dsa_slave_switchdev_notifier);
if (err)
pr_err("DSA: failed to unregister switchdev notifier (%d)\n", 
err);
-- 
2.4.11

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH net-next 08/12] switchdev: Add helpers to aid traversal through lower devices

2018-11-22 Thread Petr Machata
After the transition from switchdev operations to notifier chain (which
will take place in following patches), the onus is on the driver to find
its own devices below possible layer of LAG or other uppers.

The logic to do so is fairly repetitive: each driver is looking for its
own devices among the lowers of the notified device. For those that it
finds, it calls a handler. To indicate that the event was handled,
struct switchdev_notifier_port_obj_info.handled is set. The differences
lie only in what constitutes an "own" device and what handler to call.

Therefore abstract this logic into two helpers,
switchdev_handle_port_obj_add() and switchdev_handle_port_obj_del(). If
a driver only supports physical ports under a bridge device, it will
simply avoid this layer of indirection.

One area where this helper diverges from the current switchdev behavior
is the case of mixed lowers, some of which are switchdev ports and some
of which are not. Previously, such scenario would fail with -EOPNOTSUPP.
The helper could do that for lowers for which the passed-in predicate
doesn't hold. That would however break the case that switchdev ports
from several different drivers are stashed under one master, a scenario
that switchdev currently happily supports. Therefore tolerate any and
all unknown netdevices, whether they are backed by a switchdev driver
or not.

Signed-off-by: Petr Machata 
Reviewed-by: Ido Schimmel 
---
 include/net/switchdev.h   |  33 +++
 net/switchdev/switchdev.c | 100 ++
 2 files changed, 133 insertions(+)

diff --git a/include/net/switchdev.h b/include/net/switchdev.h
index a2f3ebf39301..6dc7de576167 100644
--- a/include/net/switchdev.h
+++ b/include/net/switchdev.h
@@ -210,6 +210,18 @@ void switchdev_port_fwd_mark_set(struct net_device *dev,
 bool switchdev_port_same_parent_id(struct net_device *a,
   struct net_device *b);
 
+int switchdev_handle_port_obj_add(struct net_device *dev,
+   struct switchdev_notifier_port_obj_info *port_obj_info,
+   bool (*check_cb)(const struct net_device *dev),
+   int (*add_cb)(struct net_device *dev,
+ const struct switchdev_obj *obj,
+ struct switchdev_trans *trans));
+int switchdev_handle_port_obj_del(struct net_device *dev,
+   struct switchdev_notifier_port_obj_info *port_obj_info,
+   bool (*check_cb)(const struct net_device *dev),
+   int (*del_cb)(struct net_device *dev,
+ const struct switchdev_obj *obj));
+
 #define SWITCHDEV_SET_OPS(netdev, ops) ((netdev)->switchdev_ops = (ops))
 #else
 
@@ -284,6 +296,27 @@ static inline bool switchdev_port_same_parent_id(struct 
net_device *a,
return false;
 }
 
+static inline int
+switchdev_handle_port_obj_add(struct net_device *dev,
+   struct switchdev_notifier_port_obj_info *port_obj_info,
+   bool (*check_cb)(const struct net_device *dev),
+   int (*add_cb)(struct net_device *dev,
+ const struct switchdev_obj *obj,
+ struct switchdev_trans *trans))
+{
+   return 0;
+}
+
+static inline int
+switchdev_handle_port_obj_del(struct net_device *dev,
+   struct switchdev_notifier_port_obj_info *port_obj_info,
+   bool (*check_cb)(const struct net_device *dev),
+   int (*del_cb)(struct net_device *dev,
+ const struct switchdev_obj *obj))
+{
+   return 0;
+}
+
 #define SWITCHDEV_SET_OPS(netdev, ops) do {} while (0)
 
 #endif
diff --git a/net/switchdev/switchdev.c b/net/switchdev/switchdev.c
index e109bb97ce3f..099434ec7996 100644
--- a/net/switchdev/switchdev.c
+++ b/net/switchdev/switchdev.c
@@ -621,3 +621,103 @@ bool switchdev_port_same_parent_id(struct net_device *a,
return netdev_phys_item_id_same(&a_attr.u.ppid, &b_attr.u.ppid);
 }
 EXPORT_SYMBOL_GPL(switchdev_port_same_parent_id);
+
+static int __switchdev_handle_port_obj_add(struct net_device *dev,
+   struct switchdev_notifier_port_obj_info *port_obj_info,
+   bool (*check_cb)(const struct net_device *dev),
+   int (*add_cb)(struct net_device *dev,
+ const struct switchdev_obj *obj,
+ struct switchdev_trans *trans))
+{
+   struct net_device *lower_dev;
+   struct list_head *iter;
+   int err = -EOPNOTSUPP;
+
+   if (check_cb(dev)) {
+   /* This flag is only checked if the return value is success. */
+   port_obj_info->handled = true;
+   return add_cb(dev, port_obj_info->obj, port_obj_info->tr

[PATCH net-next 06/12] staging: fsl-dpaa2: ethsw: Introduce ethsw_port_dev_check()

2018-11-22 Thread Petr Machata
ethsw currently uses an open-coded comparison of netdev_ops to determine
whether whether a device represents a front panel port. Wrap this into a
named function to simplify reuse.

Signed-off-by: Petr Machata 
Acked-by: Jiri Pirko 
---
 drivers/staging/fsl-dpaa2/ethsw/ethsw.c | 7 ++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c 
b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c
index 7a7ca67822c5..e379b0fa936f 100644
--- a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c
+++ b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c
@@ -972,6 +972,11 @@ static int port_bridge_leave(struct net_device *netdev)
return err;
 }
 
+static bool ethsw_port_dev_check(const struct net_device *netdev)
+{
+   return netdev->netdev_ops == ðsw_port_ops;
+}
+
 static int port_netdevice_event(struct notifier_block *unused,
unsigned long event, void *ptr)
 {
@@ -980,7 +985,7 @@ static int port_netdevice_event(struct notifier_block 
*unused,
struct net_device *upper_dev;
int err = 0;
 
-   if (netdev->netdev_ops != ðsw_port_ops)
+   if (!ethsw_port_dev_check(netdev))
return NOTIFY_DONE;
 
/* Handle just upper dev link/unlink for the moment */
-- 
2.4.11

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH net-next 10/12] ocelot: Handle SWITCHDEV_PORT_OBJ_ADD/_DEL

2018-11-22 Thread Petr Machata
Following patches will change the way of distributing port object
changes from a switchdev operation to a switchdev notifier. The
switchdev code currently recursively descends through layers of lower
devices, eventually calling the op on a front-panel port device. The
notifier will instead be sent referencing the bridge port device, which
may be a stacking device that's one of front-panel ports uppers, or a
completely unrelated device.

Dispatch the new events to ocelot_port_obj_add() resp. _del() to
maintain the same behavior that the switchdev operation based code
currently has. Pass through switchdev_handle_port_obj_add() / _del() to
handle the recursive descend, because Ocelot supports LAG uppers.

Register to the new switchdev blocking notifier chain to get the new
events when they start getting distributed.

Signed-off-by: Petr Machata 
Acked-by: Jiri Pirko 
---
 drivers/net/ethernet/mscc/ocelot.c   | 28 
 drivers/net/ethernet/mscc/ocelot.h   |  1 +
 drivers/net/ethernet/mscc/ocelot_board.c |  3 +++
 3 files changed, 32 insertions(+)

diff --git a/drivers/net/ethernet/mscc/ocelot.c 
b/drivers/net/ethernet/mscc/ocelot.c
index 3238b9ee42f3..01403b530522 100644
--- a/drivers/net/ethernet/mscc/ocelot.c
+++ b/drivers/net/ethernet/mscc/ocelot.c
@@ -1595,6 +1595,34 @@ struct notifier_block ocelot_netdevice_nb __read_mostly 
= {
 };
 EXPORT_SYMBOL(ocelot_netdevice_nb);
 
+static int ocelot_switchdev_blocking_event(struct notifier_block *unused,
+  unsigned long event, void *ptr)
+{
+   struct net_device *dev = switchdev_notifier_info_to_dev(ptr);
+   int err;
+
+   switch (event) {
+   /* Blocking events. */
+   case SWITCHDEV_PORT_OBJ_ADD:
+   err = switchdev_handle_port_obj_add(dev, ptr,
+   ocelot_netdevice_dev_check,
+   ocelot_port_obj_add);
+   return notifier_from_errno(err);
+   case SWITCHDEV_PORT_OBJ_DEL:
+   err = switchdev_handle_port_obj_del(dev, ptr,
+   ocelot_netdevice_dev_check,
+   ocelot_port_obj_del);
+   return notifier_from_errno(err);
+   }
+
+   return NOTIFY_DONE;
+}
+
+struct notifier_block ocelot_switchdev_blocking_nb __read_mostly = {
+   .notifier_call = ocelot_switchdev_blocking_event,
+};
+EXPORT_SYMBOL(ocelot_switchdev_blocking_nb);
+
 int ocelot_probe_port(struct ocelot *ocelot, u8 port,
  void __iomem *regs,
  struct phy_device *phy)
diff --git a/drivers/net/ethernet/mscc/ocelot.h 
b/drivers/net/ethernet/mscc/ocelot.h
index 62c7c8eb00d9..086775f7b52f 100644
--- a/drivers/net/ethernet/mscc/ocelot.h
+++ b/drivers/net/ethernet/mscc/ocelot.h
@@ -499,5 +499,6 @@ int ocelot_probe_port(struct ocelot *ocelot, u8 port,
  struct phy_device *phy);
 
 extern struct notifier_block ocelot_netdevice_nb;
+extern struct notifier_block ocelot_switchdev_blocking_nb;
 
 #endif
diff --git a/drivers/net/ethernet/mscc/ocelot_board.c 
b/drivers/net/ethernet/mscc/ocelot_board.c
index 4c23d18bbf44..ca3ea2fbfcd0 100644
--- a/drivers/net/ethernet/mscc/ocelot_board.c
+++ b/drivers/net/ethernet/mscc/ocelot_board.c
@@ -12,6 +12,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "ocelot.h"
 
@@ -328,6 +329,7 @@ static int mscc_ocelot_probe(struct platform_device *pdev)
}
 
register_netdevice_notifier(&ocelot_netdevice_nb);
+   register_switchdev_blocking_notifier(&ocelot_switchdev_blocking_nb);
 
dev_info(&pdev->dev, "Ocelot switch probed\n");
 
@@ -342,6 +344,7 @@ static int mscc_ocelot_remove(struct platform_device *pdev)
struct ocelot *ocelot = platform_get_drvdata(pdev);
 
ocelot_deinit(ocelot);
+   unregister_switchdev_blocking_notifier(&ocelot_switchdev_blocking_nb);
unregister_netdevice_notifier(&ocelot_netdevice_nb);
 
return 0;
-- 
2.4.11

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH net-next 09/12] mlxsw: spectrum_switchdev: Handle SWITCHDEV_PORT_OBJ_ADD/_DEL

2018-11-22 Thread Petr Machata
Following patches will change the way of distributing port object
changes from a switchdev operation to a switchdev notifier. The
switchdev code currently recursively descends through layers of lower
devices, eventually calling the op on a front-panel port device. The
notifier will instead be sent referencing the bridge port device, which
may be a stacking device that's one of front-panel ports uppers, or a
completely unrelated device.

To handle SWITCHDEV_PORT_OBJ_ADD and _DEL, subscribe to the blocking
notifier chain. Dispatch to mlxsw_sp_port_obj_add() resp. _del() to
maintain the behavior that the switchdev operation based code currently
has. Defer to switchdev_handle_port_obj_add() / _del() to handle the
recursive descend, because mlxsw supports a number of upper types.

Signed-off-by: Petr Machata 
Reviewed-by: Ido Schimmel 
---
 .../ethernet/mellanox/mlxsw/spectrum_switchdev.c   | 45 +-
 1 file changed, 44 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c 
b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
index b32a5ee57fb9..3756aaecd39c 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
@@ -3118,6 +3118,32 @@ static struct notifier_block mlxsw_sp_switchdev_notifier 
= {
.notifier_call = mlxsw_sp_switchdev_event,
 };
 
+static int mlxsw_sp_switchdev_blocking_event(struct notifier_block *unused,
+unsigned long event, void *ptr)
+{
+   struct net_device *dev = switchdev_notifier_info_to_dev(ptr);
+   int err;
+
+   switch (event) {
+   case SWITCHDEV_PORT_OBJ_ADD:
+   err = switchdev_handle_port_obj_add(dev, ptr,
+   mlxsw_sp_port_dev_check,
+   mlxsw_sp_port_obj_add);
+   return notifier_from_errno(err);
+   case SWITCHDEV_PORT_OBJ_DEL:
+   err = switchdev_handle_port_obj_del(dev, ptr,
+   mlxsw_sp_port_dev_check,
+   mlxsw_sp_port_obj_del);
+   return notifier_from_errno(err);
+   }
+
+   return NOTIFY_DONE;
+}
+
+static struct notifier_block mlxsw_sp_switchdev_blocking_notifier = {
+   .notifier_call = mlxsw_sp_switchdev_blocking_event,
+};
+
 u8
 mlxsw_sp_bridge_port_stp_state(struct mlxsw_sp_bridge_port *bridge_port)
 {
@@ -3127,6 +3153,7 @@ mlxsw_sp_bridge_port_stp_state(struct 
mlxsw_sp_bridge_port *bridge_port)
 static int mlxsw_sp_fdb_init(struct mlxsw_sp *mlxsw_sp)
 {
struct mlxsw_sp_bridge *bridge = mlxsw_sp->bridge;
+   struct notifier_block *nb;
int err;
 
err = mlxsw_sp_ageing_set(mlxsw_sp, MLXSW_SP_DEFAULT_AGEING_TIME);
@@ -3141,17 +3168,33 @@ static int mlxsw_sp_fdb_init(struct mlxsw_sp *mlxsw_sp)
return err;
}
 
+   nb = &mlxsw_sp_switchdev_blocking_notifier;
+   err = register_switchdev_blocking_notifier(nb);
+   if (err) {
+   dev_err(mlxsw_sp->bus_info->dev, "Failed to register switchdev 
blocking notifier\n");
+   goto err_register_switchdev_blocking_notifier;
+   }
+
INIT_DELAYED_WORK(&bridge->fdb_notify.dw, mlxsw_sp_fdb_notify_work);
bridge->fdb_notify.interval = MLXSW_SP_DEFAULT_LEARNING_INTERVAL;
mlxsw_sp_fdb_notify_work_schedule(mlxsw_sp);
return 0;
+
+err_register_switchdev_blocking_notifier:
+   unregister_switchdev_notifier(&mlxsw_sp_switchdev_notifier);
+   return err;
 }
 
 static void mlxsw_sp_fdb_fini(struct mlxsw_sp *mlxsw_sp)
 {
+   struct notifier_block *nb;
+
cancel_delayed_work_sync(&mlxsw_sp->bridge->fdb_notify.dw);
-   unregister_switchdev_notifier(&mlxsw_sp_switchdev_notifier);
 
+   nb = &mlxsw_sp_switchdev_blocking_notifier;
+   unregister_switchdev_blocking_notifier(nb);
+
+   unregister_switchdev_notifier(&mlxsw_sp_switchdev_notifier);
 }
 
 int mlxsw_sp_switchdev_init(struct mlxsw_sp *mlxsw_sp)
-- 
2.4.11

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH net-next 07/12] staging: fsl-dpaa2: ethsw: Handle SWITCHDEV_PORT_OBJ_ADD/_DEL

2018-11-22 Thread Petr Machata
Following patches will change the way of distributing port object
changes from a switchdev operation to a switchdev notifier. The
switchdev code currently recursively descends through layers of lower
devices, eventually calling the op on a front-panel port device. The
notifier will instead be sent referencing the bridge port device, which
may be a stacking device that's one of front-panel ports uppers, or a
completely unrelated device.

ethsw currently doesn't support any uppers other than bridge.
SWITCHDEV_OBJ_ID_HOST_MDB and _PORT_MDB objects are always notified on
the bridge port device. Thus the only case that a stacked device could
be validly referenced by port object notifications are bridge
notifications for VLAN objects added to the bridge itself. But the
driver explicitly rejects such notifications in port_vlans_add(). It is
therefore safe to assume that the only interesting case is that the
notification is on a front-panel port netdevice.

To handle SWITCHDEV_PORT_OBJ_ADD and _DEL, subscribe to the blocking
notifier chain. Dispatch to swdev_port_obj_add() resp. _del() to
maintain the behavior that the switchdev operation based code currently
has.

Signed-off-by: Petr Machata 
Acked-by: Jiri Pirko 
---
 drivers/staging/fsl-dpaa2/ethsw/ethsw.c | 56 +
 1 file changed, 56 insertions(+)

diff --git a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c 
b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c
index e379b0fa936f..83e1d92dc7f3 100644
--- a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c
+++ b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c
@@ -1088,10 +1088,51 @@ static int port_switchdev_event(struct notifier_block 
*unused,
return NOTIFY_BAD;
 }
 
+static int
+ethsw_switchdev_port_obj_event(unsigned long event, struct net_device *netdev,
+   struct switchdev_notifier_port_obj_info *port_obj_info)
+{
+   int err = -EOPNOTSUPP;
+
+   switch (event) {
+   case SWITCHDEV_PORT_OBJ_ADD:
+   err = swdev_port_obj_add(netdev, port_obj_info->obj,
+port_obj_info->trans);
+   break;
+   case SWITCHDEV_PORT_OBJ_DEL:
+   err = swdev_port_obj_del(netdev, port_obj_info->obj);
+   break;
+   }
+
+   port_obj_info->handled = true;
+   return notifier_from_errno(err);
+}
+
+static int port_switchdev_blocking_event(struct notifier_block *unused,
+unsigned long event, void *ptr)
+{
+   struct net_device *dev = switchdev_notifier_info_to_dev(ptr);
+
+   if (!ethsw_port_dev_check(dev))
+   return NOTIFY_DONE;
+
+   switch (event) {
+   case SWITCHDEV_PORT_OBJ_ADD: /* fall through */
+   case SWITCHDEV_PORT_OBJ_DEL:
+   return ethsw_switchdev_port_obj_event(event, dev, ptr);
+   }
+
+   return NOTIFY_DONE;
+}
+
 static struct notifier_block port_switchdev_nb = {
.notifier_call = port_switchdev_event,
 };
 
+static struct notifier_block port_switchdev_blocking_nb = {
+   .notifier_call = port_switchdev_blocking_event,
+};
+
 static int ethsw_register_notifier(struct device *dev)
 {
int err;
@@ -1108,8 +1149,16 @@ static int ethsw_register_notifier(struct device *dev)
goto err_switchdev_nb;
}
 
+   err = register_switchdev_blocking_notifier(&port_switchdev_blocking_nb);
+   if (err) {
+   dev_err(dev, "Failed to register switchdev blocking 
notifier\n");
+   goto err_switchdev_blocking_nb;
+   }
+
return 0;
 
+err_switchdev_blocking_nb:
+   unregister_switchdev_notifier(&port_switchdev_nb);
 err_switchdev_nb:
unregister_netdevice_notifier(&port_nb);
return err;
@@ -1296,8 +1345,15 @@ static int ethsw_port_init(struct ethsw_port_priv 
*port_priv, u16 port)
 
 static void ethsw_unregister_notifier(struct device *dev)
 {
+   struct notifier_block *nb;
int err;
 
+   nb = &port_switchdev_blocking_nb;
+   err = unregister_switchdev_blocking_notifier(nb);
+   if (err)
+   dev_err(dev,
+   "Failed to unregister switchdev blocking notifier 
(%d)\n", err);
+
err = unregister_switchdev_notifier(&port_switchdev_nb);
if (err)
dev_err(dev,
-- 
2.4.11

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH net-next 11/12] switchdev: Replace port obj add/del SDO with a notification

2018-11-22 Thread Petr Machata
Drop switchdev_ops.switchdev_port_obj_add and _del. Drop the uses of
this field from all clients, which were migrated to use switchdev
notification in the previous patches.

Add a new function switchdev_port_obj_notify() that sends the switchdev
notifications SWITCHDEV_PORT_OBJ_ADD and _DEL.

Update switchdev_port_obj_del_now() to dispatch to this new function.
Drop __switchdev_port_obj_add() and update switchdev_port_obj_add()
likewise.

Signed-off-by: Petr Machata 
Reviewed-by: Ido Schimmel 
---
 .../ethernet/mellanox/mlxsw/spectrum_switchdev.c   |  2 -
 drivers/net/ethernet/mscc/ocelot.c |  2 -
 drivers/net/ethernet/rocker/rocker_main.c  |  2 -
 drivers/staging/fsl-dpaa2/ethsw/ethsw.c|  2 -
 include/net/switchdev.h|  9 ---
 net/dsa/slave.c|  2 -
 net/switchdev/switchdev.c  | 67 --
 7 files changed, 25 insertions(+), 61 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c 
b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
index 3756aaecd39c..73e5db176d7e 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
@@ -1968,8 +1968,6 @@ static struct mlxsw_sp_port *mlxsw_sp_lag_rep_port(struct 
mlxsw_sp *mlxsw_sp,
 static const struct switchdev_ops mlxsw_sp_port_switchdev_ops = {
.switchdev_port_attr_get= mlxsw_sp_port_attr_get,
.switchdev_port_attr_set= mlxsw_sp_port_attr_set,
-   .switchdev_port_obj_add = mlxsw_sp_port_obj_add,
-   .switchdev_port_obj_del = mlxsw_sp_port_obj_del,
 };
 
 static int
diff --git a/drivers/net/ethernet/mscc/ocelot.c 
b/drivers/net/ethernet/mscc/ocelot.c
index 01403b530522..7f8da8873a96 100644
--- a/drivers/net/ethernet/mscc/ocelot.c
+++ b/drivers/net/ethernet/mscc/ocelot.c
@@ -1337,8 +1337,6 @@ static int ocelot_port_obj_del(struct net_device *dev,
 static const struct switchdev_ops ocelot_port_switchdev_ops = {
.switchdev_port_attr_get= ocelot_port_attr_get,
.switchdev_port_attr_set= ocelot_port_attr_set,
-   .switchdev_port_obj_add = ocelot_port_obj_add,
-   .switchdev_port_obj_del = ocelot_port_obj_del,
 };
 
 static int ocelot_port_bridge_join(struct ocelot_port *ocelot_port,
diff --git a/drivers/net/ethernet/rocker/rocker_main.c 
b/drivers/net/ethernet/rocker/rocker_main.c
index 806ffe1d906e..f05d5c1341b6 100644
--- a/drivers/net/ethernet/rocker/rocker_main.c
+++ b/drivers/net/ethernet/rocker/rocker_main.c
@@ -2145,8 +2145,6 @@ static int rocker_port_obj_del(struct net_device *dev,
 static const struct switchdev_ops rocker_port_switchdev_ops = {
.switchdev_port_attr_get= rocker_port_attr_get,
.switchdev_port_attr_set= rocker_port_attr_set,
-   .switchdev_port_obj_add = rocker_port_obj_add,
-   .switchdev_port_obj_del = rocker_port_obj_del,
 };
 
 struct rocker_fib_event_work {
diff --git a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c 
b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c
index 83e1d92dc7f3..06a233c7cdd3 100644
--- a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c
+++ b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c
@@ -930,8 +930,6 @@ static int swdev_port_obj_del(struct net_device *netdev,
 static const struct switchdev_ops ethsw_port_switchdev_ops = {
.switchdev_port_attr_get= swdev_port_attr_get,
.switchdev_port_attr_set= swdev_port_attr_set,
-   .switchdev_port_obj_add = swdev_port_obj_add,
-   .switchdev_port_obj_del = swdev_port_obj_del,
 };
 
 /* For the moment, only flood setting needs to be updated */
diff --git a/include/net/switchdev.h b/include/net/switchdev.h
index 6dc7de576167..866b6d148b77 100644
--- a/include/net/switchdev.h
+++ b/include/net/switchdev.h
@@ -121,10 +121,6 @@ typedef int switchdev_obj_dump_cb_t(struct switchdev_obj 
*obj);
  * @switchdev_port_attr_get: Get a port attribute (see switchdev_attr).
  *
  * @switchdev_port_attr_set: Set a port attribute (see switchdev_attr).
- *
- * @switchdev_port_obj_add: Add an object to port (see switchdev_obj_*).
- *
- * @switchdev_port_obj_del: Delete an object from port (see switchdev_obj_*).
  */
 struct switchdev_ops {
int (*switchdev_port_attr_get)(struct net_device *dev,
@@ -132,11 +128,6 @@ struct switchdev_ops {
int (*switchdev_port_attr_set)(struct net_device *dev,
   const struct switchdev_attr *attr,
   struct switchdev_trans *trans);
-   int (*switchdev_port_obj_add)(struct net_device *dev,
- const struct switchdev_obj *obj,
- struct switchdev_trans *trans);
-   int (*switchdev_port_obj_del)(struct net_device *dev

Re: [PATCH net-next 00/12] switchdev: Convert switchdev_port_obj_{add,del}() to notifiers

2018-11-22 Thread Petr Machata
Petr Machata  writes:

> An offloading driver may need to have access to switchdev events on
> ports that aren't directly under its control. An example is a VXLAN port
> attached to a bridge offloaded by a driver. The driver needs to know
> about VLANs configured on the VXLAN device. However the VXLAN device
> isn't stashed between the bridge and a front-panel-port device (such as
> is the case e.g. for LAG devices), so the usual switchdev ops don't
> reach the driver.

mlxsw will use these notifications to offload VXLAN devices attached to
a VLAN-aware bridge. The patches are available here should anyone wish
to take a look:

https://github.com/idosch/linux/commits/vxlan

Thanks,
Petr
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH net-next 12/12] rocker, dsa, ethsw: Don't filter VLAN events on bridge itself

2018-11-22 Thread Petr Machata
Due to an explicit check in rocker_world_port_obj_vlan_add(),
dsa_slave_switchdev_event() resp. port_switchdev_event(), VLAN objects
that are added to a device that is not a front-panel port device are
ignored. Therefore this check is immaterial.

Signed-off-by: Petr Machata 
Acked-by: Jiri Pirko 
---
 drivers/net/ethernet/rocker/rocker_main.c | 3 ---
 drivers/staging/fsl-dpaa2/ethsw/ethsw.c   | 3 ---
 net/dsa/port.c| 3 ---
 3 files changed, 9 deletions(-)

diff --git a/drivers/net/ethernet/rocker/rocker_main.c 
b/drivers/net/ethernet/rocker/rocker_main.c
index f05d5c1341b6..6213827e3956 100644
--- a/drivers/net/ethernet/rocker/rocker_main.c
+++ b/drivers/net/ethernet/rocker/rocker_main.c
@@ -1632,9 +1632,6 @@ rocker_world_port_obj_vlan_add(struct rocker_port 
*rocker_port,
 {
struct rocker_world_ops *wops = rocker_port->rocker->wops;
 
-   if (netif_is_bridge_master(vlan->obj.orig_dev))
-   return -EOPNOTSUPP;
-
if (!wops->port_obj_vlan_add)
return -EOPNOTSUPP;
 
diff --git a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c 
b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c
index 06a233c7cdd3..4fa37d6e598b 100644
--- a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c
+++ b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c
@@ -719,9 +719,6 @@ static int port_vlans_add(struct net_device *netdev,
struct ethsw_port_priv *port_priv = netdev_priv(netdev);
int vid, err = 0;
 
-   if (netif_is_bridge_master(vlan->obj.orig_dev))
-   return -EOPNOTSUPP;
-
if (switchdev_trans_ph_prepare(trans))
return 0;
 
diff --git a/net/dsa/port.c b/net/dsa/port.c
index ed0595459df1..2d7e01b23572 100644
--- a/net/dsa/port.c
+++ b/net/dsa/port.c
@@ -252,9 +252,6 @@ int dsa_port_vlan_add(struct dsa_port *dp,
.vlan = vlan,
};
 
-   if (netif_is_bridge_master(vlan->obj.orig_dev))
-   return -EOPNOTSUPP;
-
if (br_vlan_enabled(dp->bridge_dev))
return dsa_port_notify(dp, DSA_NOTIFIER_VLAN_ADD, &info);
 
-- 
2.4.11

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH net-next 5/8] net: core: dev: Add extack argument to __dev_change_flags()

2018-12-05 Thread Petr Machata
In order to pass extack together with NETDEV_PRE_UP notifications, it's
necessary to route the extack to __dev_open() from diverse (possibly
indirect) callers. The last missing API is __dev_change_flags().

Therefore extend __dev_change_flags() with and extra extack argument and
update the two existing users.

Since the function declaration line is changed anyway, name the struct
net_device argument to placate checkpatch.

Signed-off-by: Petr Machata 
Acked-by: Jiri Pirko 
Reviewed-by: Ido Schimmel 
---
 include/linux/netdevice.h | 3 ++-
 net/core/dev.c| 5 +++--
 net/core/rtnetlink.c  | 3 ++-
 3 files changed, 7 insertions(+), 4 deletions(-)

diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 18cf464450ee..fc6ba71513be 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -3611,7 +3611,8 @@ int dev_ioctl(struct net *net, unsigned int cmd, struct 
ifreq *ifr,
 int dev_ifconf(struct net *net, struct ifconf *, int);
 int dev_ethtool(struct net *net, struct ifreq *);
 unsigned int dev_get_flags(const struct net_device *);
-int __dev_change_flags(struct net_device *, unsigned int flags);
+int __dev_change_flags(struct net_device *dev, unsigned int flags,
+  struct netlink_ext_ack *extack);
 int dev_change_flags(struct net_device *dev, unsigned int flags,
 struct netlink_ext_ack *extack);
 void __dev_notify_flags(struct net_device *, unsigned int old_flags,
diff --git a/net/core/dev.c b/net/core/dev.c
index 8bba6f98b545..b37e320def13 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -7498,7 +7498,8 @@ unsigned int dev_get_flags(const struct net_device *dev)
 }
 EXPORT_SYMBOL(dev_get_flags);
 
-int __dev_change_flags(struct net_device *dev, unsigned int flags)
+int __dev_change_flags(struct net_device *dev, unsigned int flags,
+  struct netlink_ext_ack *extack)
 {
unsigned int old_flags = dev->flags;
int ret;
@@ -7606,7 +7607,7 @@ int dev_change_flags(struct net_device *dev, unsigned int 
flags,
int ret;
unsigned int changes, old_flags = dev->flags, old_gflags = dev->gflags;
 
-   ret = __dev_change_flags(dev, flags);
+   ret = __dev_change_flags(dev, flags, extack);
if (ret < 0)
return ret;
 
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 4c9e4e187600..91a0f7477f8e 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -2871,7 +2871,8 @@ int rtnl_configure_link(struct net_device *dev, const 
struct ifinfomsg *ifm)
 
old_flags = dev->flags;
if (ifm && (ifm->ifi_flags || ifm->ifi_change)) {
-   err = __dev_change_flags(dev, rtnl_dev_combine_flags(dev, ifm));
+   err = __dev_change_flags(dev, rtnl_dev_combine_flags(dev, ifm),
+NULL);
if (err < 0)
return err;
}
-- 
2.4.11

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH net-next 3/8] net: ipvlan: ipvlan_set_port_mode(): Add an extack argument

2018-12-05 Thread Petr Machata
A follow-up patch will extend dev_change_flags() with an extack
argument. Extend ipvlan_set_port_mode() to have that argument available
for the conversion.

Signed-off-by: Petr Machata 
Acked-by: Jiri Pirko 
Reviewed-by: Ido Schimmel 
---
 drivers/net/ipvlan/ipvlan_main.c | 7 ---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ipvlan/ipvlan_main.c b/drivers/net/ipvlan/ipvlan_main.c
index 4a949569ec4c..14f1cbd3b96f 100644
--- a/drivers/net/ipvlan/ipvlan_main.c
+++ b/drivers/net/ipvlan/ipvlan_main.c
@@ -71,7 +71,8 @@ static void ipvlan_unregister_nf_hook(struct net *net)
ARRAY_SIZE(ipvl_nfops));
 }
 
-static int ipvlan_set_port_mode(struct ipvl_port *port, u16 nval)
+static int ipvlan_set_port_mode(struct ipvl_port *port, u16 nval,
+   struct netlink_ext_ack *extack)
 {
struct ipvl_dev *ipvlan;
struct net_device *mdev = port->dev;
@@ -498,7 +499,7 @@ static int ipvlan_nl_changelink(struct net_device *dev,
if (data[IFLA_IPVLAN_MODE]) {
u16 nmode = nla_get_u16(data[IFLA_IPVLAN_MODE]);
 
-   err = ipvlan_set_port_mode(port, nmode);
+   err = ipvlan_set_port_mode(port, nmode, extack);
}
 
if (!err && data[IFLA_IPVLAN_FLAGS]) {
@@ -672,7 +673,7 @@ int ipvlan_link_new(struct net *src_net, struct net_device 
*dev,
if (data && data[IFLA_IPVLAN_MODE])
mode = nla_get_u16(data[IFLA_IPVLAN_MODE]);
 
-   err = ipvlan_set_port_mode(port, mode);
+   err = ipvlan_set_port_mode(port, mode, extack);
if (err)
goto unlink_netdev;
 
-- 
2.4.11

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH net-next 4/8] net: core: dev: Add extack argument to dev_change_flags()

2018-12-05 Thread Petr Machata
In order to pass extack together with NETDEV_PRE_UP notifications, it's
necessary to route the extack to __dev_open() from diverse (possibly
indirect) callers. One prominent API through which the notification is
invoked is dev_change_flags().

Therefore extend dev_change_flags() with and extra extack argument and
update all users. Most of the calls end up just encoding NULL, but
several sites (VLAN, ipvlan, VRF, rtnetlink) do have extack available.

Since the function declaration line is changed anyway, name the other
function arguments to placate checkpatch.

Signed-off-by: Petr Machata 
Acked-by: Jiri Pirko 
Reviewed-by: Ido Schimmel 
---
 drivers/infiniband/ulp/ipoib/ipoib_main.c |  6 +++---
 drivers/net/hyperv/netvsc_drv.c   |  2 +-
 drivers/net/ipvlan/ipvlan_main.c  | 12 
 drivers/net/vrf.c |  4 ++--
 include/linux/netdevice.h |  3 ++-
 net/8021q/vlan.c  |  4 +++-
 net/core/dev.c|  4 +++-
 net/core/dev_ioctl.c  |  2 +-
 net/core/net-sysfs.c  |  2 +-
 net/core/rtnetlink.c  |  3 ++-
 net/ipv4/devinet.c|  2 +-
 net/ipv4/ipconfig.c   |  6 +++---
 net/openvswitch/vport-geneve.c|  2 +-
 net/openvswitch/vport-gre.c   |  2 +-
 net/openvswitch/vport-vxlan.c |  2 +-
 15 files changed, 33 insertions(+), 23 deletions(-)

diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c 
b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index 8710214594d8..6214d8c0d546 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -167,7 +167,7 @@ int ipoib_open(struct net_device *dev)
if (flags & IFF_UP)
continue;
 
-   dev_change_flags(cpriv->dev, flags | IFF_UP);
+   dev_change_flags(cpriv->dev, flags | IFF_UP, NULL);
}
up_read(&priv->vlan_rwsem);
}
@@ -207,7 +207,7 @@ static int ipoib_stop(struct net_device *dev)
if (!(flags & IFF_UP))
continue;
 
-   dev_change_flags(cpriv->dev, flags & ~IFF_UP);
+   dev_change_flags(cpriv->dev, flags & ~IFF_UP, NULL);
}
up_read(&priv->vlan_rwsem);
}
@@ -1823,7 +1823,7 @@ static void ipoib_parent_unregister_pre(struct net_device 
*ndev)
 * running ensures the it will not add more work.
 */
rtnl_lock();
-   dev_change_flags(priv->dev, priv->dev->flags & ~IFF_UP);
+   dev_change_flags(priv->dev, priv->dev->flags & ~IFF_UP, NULL);
rtnl_unlock();
 
/* ipoib_event() cannot be running once this returns */
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
index c65620adab52..18b5584d6377 100644
--- a/drivers/net/hyperv/netvsc_drv.c
+++ b/drivers/net/hyperv/netvsc_drv.c
@@ -1993,7 +1993,7 @@ static void __netvsc_vf_setup(struct net_device *ndev,
"unable to change mtu to %u\n", ndev->mtu);
 
/* set multicast etc flags on VF */
-   dev_change_flags(vf_netdev, ndev->flags | IFF_SLAVE);
+   dev_change_flags(vf_netdev, ndev->flags | IFF_SLAVE, NULL);
 
/* sync address list from ndev to VF */
netif_addr_lock_bh(ndev);
diff --git a/drivers/net/ipvlan/ipvlan_main.c b/drivers/net/ipvlan/ipvlan_main.c
index 14f1cbd3b96f..c3d3e458f541 100644
--- a/drivers/net/ipvlan/ipvlan_main.c
+++ b/drivers/net/ipvlan/ipvlan_main.c
@@ -85,10 +85,12 @@ static int ipvlan_set_port_mode(struct ipvl_port *port, u16 
nval,
flags = ipvlan->dev->flags;
if (nval == IPVLAN_MODE_L3 || nval == IPVLAN_MODE_L3S) {
err = dev_change_flags(ipvlan->dev,
-  flags | IFF_NOARP);
+  flags | IFF_NOARP,
+  extack);
} else {
err = dev_change_flags(ipvlan->dev,
-  flags & ~IFF_NOARP);
+  flags & ~IFF_NOARP,
+  extack);
}
if (unlikely(err))
goto fail;
@@ -117,9 +119,11 @@ static int ipvlan_set_port_mode(struct ipvl_port *port, 
u16 nval,
flags = ipvlan->dev->flags;
if (port->mode == IPVLAN_MODE_L3 ||
port->mode == IPVLAN_MODE_L3S)
-

[PATCH net-next 8/8] selftests: mlxsw: Add a new test extack.sh

2018-12-05 Thread Petr Machata
Add a testsuite dedicated to testing extack propagation and related
functionality.

Signed-off-by: Petr Machata 
Acked-by: Jiri Pirko 
Reviewed-by: Ido Schimmel 
---
 .../testing/selftests/drivers/net/mlxsw/extack.sh  | 84 ++
 1 file changed, 84 insertions(+)
 create mode 100755 tools/testing/selftests/drivers/net/mlxsw/extack.sh

diff --git a/tools/testing/selftests/drivers/net/mlxsw/extack.sh 
b/tools/testing/selftests/drivers/net/mlxsw/extack.sh
new file mode 100755
index ..101a5508bdfd
--- /dev/null
+++ b/tools/testing/selftests/drivers/net/mlxsw/extack.sh
@@ -0,0 +1,84 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+#
+# Test operations that we expect to report extended ack.
+
+lib_dir=$(dirname $0)/../../../net/forwarding
+
+ALL_TESTS="
+   netdev_pre_up_test
+"
+NUM_NETIFS=2
+source $lib_dir/lib.sh
+
+setup_prepare()
+{
+   swp1=${NETIFS[p1]}
+   swp2=${NETIFS[p2]}
+
+   ip link set dev $swp1 up
+   ip link set dev $swp2 up
+}
+
+cleanup()
+{
+   pre_cleanup
+
+   ip link set dev $swp2 down
+   ip link set dev $swp1 down
+}
+
+netdev_pre_up_test()
+{
+   RET=0
+
+   ip link add name br1 up type bridge vlan_filtering 0 mcast_snooping 0
+   ip link add name vx1 up type vxlan id 1000 \
+   local 192.0.2.17 remote 192.0.2.18 \
+   dstport 4789 nolearning noudpcsum tos inherit ttl 100
+
+   ip link set dev vx1 master br1
+   check_err $?
+
+   ip link set dev $swp1 master br1
+   check_err $?
+
+   ip link add name br2 up type bridge vlan_filtering 0 mcast_snooping 0
+   ip link add name vx2 up type vxlan id 2000 \
+   local 192.0.2.17 remote 192.0.2.18 \
+   dstport 4789 nolearning noudpcsum tos inherit ttl 100
+
+   ip link set dev vx2 master br2
+   check_err $?
+
+   ip link set dev $swp2 master br2
+   check_err $?
+
+   # Unsupported configuration: mlxsw demands that all offloaded VXLAN
+   # devices have the same TTL.
+   ip link set dev vx2 down
+   ip link set dev vx2 type vxlan ttl 200
+
+   ip link set dev vx2 up &>/dev/null
+   check_fail $?
+
+   ip link set dev vx2 up 2>&1 >/dev/null | grep -q mlxsw_spectrum
+   check_err $?
+
+   log_test "extack - NETDEV_PRE_UP"
+
+   ip link del dev vx2
+   ip link del dev br2
+
+   ip link del dev vx1
+   ip link del dev br1
+}
+
+trap cleanup EXIT
+
+setup_prepare
+setup_wait
+
+tests_run
+
+exit $EXIT_STATUS
-- 
2.4.11

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH net-next 2/8] net: vrf: cycle_netdev(): Add an extack argument

2018-12-05 Thread Petr Machata
A follow-up patch will extend dev_change_flags() with an extack
argument. Extend cycle_netdev() to have that argument available for the
conversion.

Signed-off-by: Petr Machata 
Acked-by: Jiri Pirko 
Reviewed-by: Ido Schimmel 
---
 drivers/net/vrf.c | 7 ---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c
index 21ad4b1d7f03..1e9f2dc0de07 100644
--- a/drivers/net/vrf.c
+++ b/drivers/net/vrf.c
@@ -747,7 +747,8 @@ static int vrf_rtable_create(struct net_device *dev)
 / device handling /
 
 /* cycle interface to flush neighbor cache and move routes across tables */
-static void cycle_netdev(struct net_device *dev)
+static void cycle_netdev(struct net_device *dev,
+struct netlink_ext_ack *extack)
 {
unsigned int flags = dev->flags;
int ret;
@@ -785,7 +786,7 @@ static int do_vrf_add_slave(struct net_device *dev, struct 
net_device *port_dev,
if (ret < 0)
goto err;
 
-   cycle_netdev(port_dev);
+   cycle_netdev(port_dev, extack);
 
return 0;
 
@@ -815,7 +816,7 @@ static int do_vrf_del_slave(struct net_device *dev, struct 
net_device *port_dev)
netdev_upper_dev_unlink(port_dev, dev);
port_dev->priv_flags &= ~IFF_L3MDEV_SLAVE;
 
-   cycle_netdev(port_dev);
+   cycle_netdev(port_dev, NULL);
 
return 0;
 }
-- 
2.4.11

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH net-next 7/8] net: core: dev: Attach extack to NETDEV_PRE_UP

2018-12-05 Thread Petr Machata
Drivers may need to validate configuration of a device that's about to
be upped. Should the validation fail, there's currently no way to
communicate details of the failure to the user, beyond an error number.

To mend that, change __dev_open() to take an extack argument and pass it
from __dev_change_flags() and dev_open(), where it was propagated in the
previous patches.

Change __dev_open() to call call_netdevice_notifiers_extack() so that
the passed-in extack is attached to the NETDEV_PRE_UP notifier.

Signed-off-by: Petr Machata 
Acked-by: Jiri Pirko 
Reviewed-by: Ido Schimmel 
---
 net/core/dev.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/net/core/dev.c b/net/core/dev.c
index 4b033af8e6cd..068b60db35ae 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1364,7 +1364,7 @@ void netdev_notify_peers(struct net_device *dev)
 }
 EXPORT_SYMBOL(netdev_notify_peers);
 
-static int __dev_open(struct net_device *dev)
+static int __dev_open(struct net_device *dev, struct netlink_ext_ack *extack)
 {
const struct net_device_ops *ops = dev->netdev_ops;
int ret;
@@ -1380,7 +1380,7 @@ static int __dev_open(struct net_device *dev)
 */
netpoll_poll_disable(dev);
 
-   ret = call_netdevice_notifiers(NETDEV_PRE_UP, dev);
+   ret = call_netdevice_notifiers_extack(NETDEV_PRE_UP, dev, extack);
ret = notifier_to_errno(ret);
if (ret)
return ret;
@@ -1427,7 +1427,7 @@ int dev_open(struct net_device *dev, struct 
netlink_ext_ack *extack)
if (dev->flags & IFF_UP)
return 0;
 
-   ret = __dev_open(dev);
+   ret = __dev_open(dev, extack);
if (ret < 0)
return ret;
 
@@ -7547,7 +7547,7 @@ int __dev_change_flags(struct net_device *dev, unsigned 
int flags,
if (old_flags & IFF_UP)
__dev_close(dev);
else
-   ret = __dev_open(dev);
+   ret = __dev_open(dev, extack);
}
 
if ((flags ^ dev->gflags) & IFF_PROMISC) {
-- 
2.4.11

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH net-next 1/8] net: core: dev: Add extack argument to dev_open()

2018-12-05 Thread Petr Machata
In order to pass extack together with NETDEV_PRE_UP notifications, it's
necessary to route the extack to __dev_open() from diverse (possibly
indirect) callers. One prominent API through which the notification is
invoked is dev_open().

Therefore extend dev_open() with and extra extack argument and update
all users. Most of the calls end up just encoding NULL, but bond and
team drivers have the extack readily available.

Signed-off-by: Petr Machata 
Acked-by: Jiri Pirko 
Reviewed-by: Ido Schimmel 
---
 drivers/net/bonding/bond_main.c | 2 +-
 drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c | 2 +-
 drivers/net/ethernet/cisco/enic/enic_ethtool.c  | 2 +-
 drivers/net/ethernet/hisilicon/hns/hns_ethtool.c| 2 +-
 drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c  | 2 +-
 drivers/net/ethernet/sfc/ethtool.c  | 2 +-
 drivers/net/ethernet/sfc/falcon/ethtool.c   | 2 +-
 drivers/net/ethernet/stmicro/stmmac/stmmac_main.c   | 2 +-
 drivers/net/hyperv/netvsc_drv.c | 4 ++--
 drivers/net/net_failover.c  | 8 
 drivers/net/team/team.c | 2 +-
 drivers/net/wireless/intersil/hostap/hostap_main.c  | 2 +-
 drivers/s390/net/qeth_l2_main.c | 2 +-
 drivers/s390/net/qeth_l3_main.c | 2 +-
 drivers/staging/fsl-dpaa2/ethsw/ethsw.c | 2 +-
 drivers/staging/unisys/visornic/visornic_main.c | 2 +-
 include/linux/netdevice.h   | 2 +-
 net/bluetooth/6lowpan.c | 2 +-
 net/core/dev.c  | 5 +++--
 net/core/netpoll.c  | 2 +-
 net/ipv4/ipmr.c | 4 ++--
 net/ipv6/addrconf.c | 2 +-
 net/ipv6/ip6mr.c| 2 +-
 23 files changed, 30 insertions(+), 29 deletions(-)

diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 87f1f1fe..6b34dbefa7dd 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -1538,7 +1538,7 @@ int bond_enslave(struct net_device *bond_dev, struct 
net_device *slave_dev,
slave_dev->flags |= IFF_SLAVE;
 
/* open the slave since the application closed it */
-   res = dev_open(slave_dev);
+   res = dev_open(slave_dev, extack);
if (res) {
netdev_dbg(bond_dev, "Opening slave %s failed\n", 
slave_dev->name);
goto err_restore_mac;
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c 
b/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c
index a5fd71692c8b..43b42615ad84 100644
--- a/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c
@@ -525,7 +525,7 @@ static int aq_set_ringparam(struct net_device *ndev,
}
}
if (ndev_running)
-   err = dev_open(ndev);
+   err = dev_open(ndev, NULL);
 
 err_exit:
return err;
diff --git a/drivers/net/ethernet/cisco/enic/enic_ethtool.c 
b/drivers/net/ethernet/cisco/enic/enic_ethtool.c
index f42f7a6e1559..ebd5c2cf1efe 100644
--- a/drivers/net/ethernet/cisco/enic/enic_ethtool.c
+++ b/drivers/net/ethernet/cisco/enic/enic_ethtool.c
@@ -241,7 +241,7 @@ static int enic_set_ringparam(struct net_device *netdev,
}
enic_init_vnic_resources(enic);
if (running) {
-   err = dev_open(netdev);
+   err = dev_open(netdev, NULL);
if (err)
goto err_out;
}
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c 
b/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c
index 774beda040a1..8e9b95871d30 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c
@@ -624,7 +624,7 @@ static void hns_nic_self_test(struct net_device *ndev,
clear_bit(NIC_STATE_TESTING, &priv->state);
 
if (if_running)
-   (void)dev_open(ndev);
+   (void)dev_open(ndev, NULL);
}
/* Online tests aren't run; pass by default */
 
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c 
b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c
index 4563638367ac..e678b6939da3 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c
@@ -821,7 +821,7 @@ static int hns3_set_ringparam(struct net_device *ndev,
}
 
if (if_running)
-   ret = dev_open(ndev);
+   ret = dev_open(ndev, NULL);
 
return ret;
 }
diff --git a/drivers/net/ethernet/sfc/ethtool.c 
b/drivers/net/ethernet/sfc/ethtool.c
index 3143588ffd77..600d7b895cf2 100644
--- a/drivers/net/ethernet/sfc/ethtool.c
+++ b/drivers/net/ethernet/sfc/ethtool.

[PATCH net-next 6/8] net: core: dev: Add call_netdevice_notifiers_extack()

2018-12-05 Thread Petr Machata
In order to propagate extack through NETDEV_PRE_UP, add a new function
call_netdevice_notifiers_extack() that primes the extack field of the
notifier info. Convert call_netdevice_notifiers() to a simple wrapper
around the new function that passes NULL for extack.

Signed-off-by: Petr Machata 
Acked-by: Jiri Pirko 
Reviewed-by: Ido Schimmel 
---
 net/core/dev.c | 21 -
 1 file changed, 16 insertions(+), 5 deletions(-)

diff --git a/net/core/dev.c b/net/core/dev.c
index b37e320def13..4b033af8e6cd 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -162,6 +162,9 @@ static struct list_head offload_base __read_mostly;
 static int netif_rx_internal(struct sk_buff *skb);
 static int call_netdevice_notifiers_info(unsigned long val,
 struct netdev_notifier_info *info);
+static int call_netdevice_notifiers_extack(unsigned long val,
+  struct net_device *dev,
+  struct netlink_ext_ack *extack);
 static struct napi_struct *napi_by_id(unsigned int napi_id);
 
 /*
@@ -1734,6 +1737,18 @@ static int call_netdevice_notifiers_info(unsigned long 
val,
return raw_notifier_call_chain(&netdev_chain, val, info);
 }
 
+static int call_netdevice_notifiers_extack(unsigned long val,
+  struct net_device *dev,
+  struct netlink_ext_ack *extack)
+{
+   struct netdev_notifier_info info = {
+   .dev = dev,
+   .extack = extack,
+   };
+
+   return call_netdevice_notifiers_info(val, &info);
+}
+
 /**
  * call_netdevice_notifiers - call all network notifier blocks
  *  @val: value passed unmodified to notifier function
@@ -1745,11 +1760,7 @@ static int call_netdevice_notifiers_info(unsigned long 
val,
 
 int call_netdevice_notifiers(unsigned long val, struct net_device *dev)
 {
-   struct netdev_notifier_info info = {
-   .dev = dev,
-   };
-
-   return call_netdevice_notifiers_info(val, &info);
+   return call_netdevice_notifiers_extack(val, dev, NULL);
 }
 EXPORT_SYMBOL(call_netdevice_notifiers);
 
-- 
2.4.11

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH net-next 0/8] Pass extack to NETDEV_PRE_UP

2018-12-05 Thread Petr Machata
Drivers may need to validate configuration of a device that's about to
be upped. An example is mlxsw, which needs to check the configuration of
a VXLAN device attached to an offloaded bridge. Should the validation
fail, there's currently no way to communicate details of the failure to
the user, beyond an error number.

Therefore this patch set extends the NETDEV_PRE_UP event to include
extack, if available.

There are three vectors through which NETDEV_PRE_UP invocation can be
reached. The two major ones are dev_open() and dev_change_flags(), the
last is then __dev_change_flags().

In patch #1, the first access vector, dev_open() is addressed. An extack
parameter is added and all users converted to use it.

Before addressing the second vector, two preparatory patches propagate
extack argument to the proximity of the dev_change_flags() call in VRF
and IPVLAN drivers. That happens in patches #2 and #3. Then in patch #4,
dev_change_flags() is treated similarly to dev_open().

Likewise in patch #5, __dev_change_flags() is extended.

Then in patches #6 and #7, the extack is finally propagated all the way
to the point where the notification is emitted.

This change allows particularly mlxsw (which already has code to
leverage extack if available) to communicate to the user error messages
regarding VXLAN configuration. In patch #8, add a test case that
exercises this code and checks that an error message is propagated.

For example:

# ip link add name br1 up type bridge vlan_filtering 0 mcast_snooping 0
# ip link add name vx1 up type vxlan id 1000 \
local 192.0.2.17 remote 192.0.2.18 \
dstport 4789 nolearning noudpcsum tos inherit ttl 100
# ip link set dev vx1 master br1
# ip link set dev sw1p1 master br1
# ip link add name br2 up type bridge vlan_filtering 0 mcast_snooping 0
# ip link add name vx2 up type vxlan id 2000 \
local 192.0.2.17 remote 192.0.2.18 \
dstport 4789 nolearning noudpcsum tos inherit ttl 100
# ip link set dev vx2 master br2
# ip link set dev sw1p2 master br2
# ip link set dev vx2 down
# ip link set dev vx2 type vxlan ttl 200
# ip link set dev vx2 up
Error: mlxsw_spectrum: Conflicting NVE tunnels configuration.

Petr Machata (8):
  net: core: dev: Add extack argument to dev_open()
  net: vrf: cycle_netdev(): Add an extack argument
  net: ipvlan: ipvlan_set_port_mode(): Add an extack argument
  net: core: dev: Add extack argument to dev_change_flags()
  net: core: dev: Add extack argument to __dev_change_flags()
  net: core: dev: Add call_netdevice_notifiers_extack()
  net: core: dev: Attach extack to NETDEV_PRE_UP
  selftests: mlxsw: Add a new test extack.sh

 drivers/infiniband/ulp/ipoib/ipoib_main.c  |  6 +-
 drivers/net/bonding/bond_main.c|  2 +-
 .../net/ethernet/aquantia/atlantic/aq_ethtool.c|  2 +-
 drivers/net/ethernet/cisco/enic/enic_ethtool.c |  2 +-
 drivers/net/ethernet/hisilicon/hns/hns_ethtool.c   |  2 +-
 drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c |  2 +-
 drivers/net/ethernet/sfc/ethtool.c |  2 +-
 drivers/net/ethernet/sfc/falcon/ethtool.c  |  2 +-
 drivers/net/ethernet/stmicro/stmmac/stmmac_main.c  |  2 +-
 drivers/net/hyperv/netvsc_drv.c|  6 +-
 drivers/net/ipvlan/ipvlan_main.c   | 19 +++--
 drivers/net/net_failover.c |  8 +--
 drivers/net/team/team.c|  2 +-
 drivers/net/vrf.c  | 11 +--
 drivers/net/wireless/intersil/hostap/hostap_main.c |  2 +-
 drivers/s390/net/qeth_l2_main.c|  2 +-
 drivers/s390/net/qeth_l3_main.c|  2 +-
 drivers/staging/fsl-dpaa2/ethsw/ethsw.c|  2 +-
 drivers/staging/unisys/visornic/visornic_main.c|  2 +-
 include/linux/netdevice.h  |  8 ++-
 net/8021q/vlan.c   |  4 +-
 net/bluetooth/6lowpan.c|  2 +-
 net/core/dev.c | 43 +++
 net/core/dev_ioctl.c   |  2 +-
 net/core/net-sysfs.c   |  2 +-
 net/core/netpoll.c |  2 +-
 net/core/rtnetlink.c   |  6 +-
 net/ipv4/devinet.c |  2 +-
 net/ipv4/ipconfig.c|  6 +-
 net/ipv4/ipmr.c|  4 +-
 net/ipv6/addrconf.c|  2 +-
 net/ipv6/ip6mr.c   |  2 +-
 net/openvswitch/vport-geneve.c |  2 +-
 net/openvswitch/vport-gre.c|  2 +-
 net/openvswitch/vport-vxlan.c  |  2 +-
 .../testing/selftests/drivers/net/mlxsw/extack.sh  | 84 ++
 36 files changed, 182 insertions(+), 71 deletions(-)
 create mode 100755 tools/testing/selftests/drivers/net/mlxsw/extack.sh


[PATCH net-next 1/7] net: bridge: Extract boilerplate around switchdev_port_obj_*()

2018-05-24 Thread Petr Machata
A call to switchdev_port_obj_add() or switchdev_port_obj_del() involves
initializing a struct switchdev_obj_port_vlan, a piece of code that
repeats on each call site almost verbatim. While in the current codebase
there is just one duplicated add call, the follow-up patches add more of
both add and del calls.

Thus to remove the duplication, extract the repetition into named
functions and reuse.

Signed-off-by: Petr Machata 
---
 net/bridge/br_vlan.c | 44 +++-
 1 file changed, 23 insertions(+), 21 deletions(-)

diff --git a/net/bridge/br_vlan.c b/net/bridge/br_vlan.c
index dc832c09..a75fe930 100644
--- a/net/bridge/br_vlan.c
+++ b/net/bridge/br_vlan.c
@@ -79,8 +79,7 @@ static bool __vlan_add_flags(struct net_bridge_vlan *v, u16 
flags)
return ret || !!(old_flags ^ v->flags);
 }
 
-static int __vlan_vid_add(struct net_device *dev, struct net_bridge *br,
- u16 vid, u16 flags)
+static int br_switchdev_port_obj_add(struct net_device *dev, u16 vid, u16 
flags)
 {
struct switchdev_obj_port_vlan v = {
.obj.orig_dev = dev,
@@ -89,12 +88,29 @@ static int __vlan_vid_add(struct net_device *dev, struct 
net_bridge *br,
.vid_begin = vid,
.vid_end = vid,
};
-   int err;
 
+   return switchdev_port_obj_add(dev, &v.obj);
+}
+
+static int br_switchdev_port_obj_del(struct net_device *dev, u16 vid)
+{
+   struct switchdev_obj_port_vlan v = {
+   .obj.orig_dev = dev,
+   .obj.id = SWITCHDEV_OBJ_ID_PORT_VLAN,
+   .vid_begin = vid,
+   .vid_end = vid,
+   };
+
+   return switchdev_port_obj_del(dev, &v.obj);
+}
+
+static int __vlan_vid_add(struct net_device *dev, struct net_bridge *br,
+ u16 vid, u16 flags)
+{
/* Try switchdev op first. In case it is not supported, fallback to
 * 8021q add.
 */
-   err = switchdev_port_obj_add(dev, &v.obj);
+   int err = br_switchdev_port_obj_add(dev, vid, flags);
if (err == -EOPNOTSUPP)
return vlan_vid_add(dev, br->vlan_proto, vid);
return err;
@@ -130,18 +146,11 @@ static void __vlan_del_list(struct net_bridge_vlan *v)
 static int __vlan_vid_del(struct net_device *dev, struct net_bridge *br,
  u16 vid)
 {
-   struct switchdev_obj_port_vlan v = {
-   .obj.orig_dev = dev,
-   .obj.id = SWITCHDEV_OBJ_ID_PORT_VLAN,
-   .vid_begin = vid,
-   .vid_end = vid,
-   };
-   int err;
-
/* Try switchdev op first. In case it is not supported, fallback to
 * 8021q del.
 */
-   err = switchdev_port_obj_del(dev, &v.obj);
+   int err = br_switchdev_port_obj_del(dev, vid);
+
if (err == -EOPNOTSUPP) {
vlan_vid_del(dev, br->vlan_proto, vid);
return 0;
@@ -1053,13 +1062,6 @@ int nbp_vlan_init(struct net_bridge_port *p)
 int nbp_vlan_add(struct net_bridge_port *port, u16 vid, u16 flags,
 bool *changed)
 {
-   struct switchdev_obj_port_vlan v = {
-   .obj.orig_dev = port->dev,
-   .obj.id = SWITCHDEV_OBJ_ID_PORT_VLAN,
-   .flags = flags,
-   .vid_begin = vid,
-   .vid_end = vid,
-   };
struct net_bridge_vlan *vlan;
int ret;
 
@@ -1069,7 +1071,7 @@ int nbp_vlan_add(struct net_bridge_port *port, u16 vid, 
u16 flags,
vlan = br_vlan_find(nbp_vlan_group(port), vid);
if (vlan) {
/* Pass the flags to the hardware bridge */
-   ret = switchdev_port_obj_add(port->dev, &v.obj);
+   ret = br_switchdev_port_obj_add(port->dev, vid, flags);
if (ret && ret != -EOPNOTSUPP)
return ret;
*changed = __vlan_add_flags(vlan, flags);
-- 
2.4.11

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH net-next 5/7] staging: fsl-dpaa2: ethsw: Ignore bridge VLAN events

2018-05-24 Thread Petr Machata
Ignore VLAN events where the orig_dev is the bridge device itself.

Signed-off-by: Petr Machata 
---
 drivers/staging/fsl-dpaa2/ethsw/ethsw.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c 
b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c
index c723a04..a17dd29 100644
--- a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c
+++ b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c
@@ -719,6 +719,9 @@ static int port_vlans_add(struct net_device *netdev,
struct ethsw_port_priv *port_priv = netdev_priv(netdev);
int vid, err;
 
+   if (netif_is_bridge_master(vlan->obj.orig_dev))
+   return -EOPNOTSUPP;
+
if (switchdev_trans_ph_prepare(trans))
return 0;
 
@@ -873,6 +876,9 @@ static int port_vlans_del(struct net_device *netdev,
struct ethsw_port_priv *port_priv = netdev_priv(netdev);
int vid, err;
 
+   if (netif_is_bridge_master(vlan->obj.orig_dev))
+   return -EOPNOTSUPP;
+
for (vid = vlan->vid_begin; vid <= vlan->vid_end; vid++) {
err = ethsw_port_del_vlan(port_priv, vid);
if (err)
-- 
2.4.11

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH net-next 7/7] mlxsw: spectrum_switchdev: Schedule respin during trans prepare

2018-05-24 Thread Petr Machata
Since there's no special support for the bridge events, the driver
returns -EOPNOTSUPP, and thus the commit never happens. Therefore
schedule respin during the prepare stage: there's no real difference one
way or another.

This fixes the problem that mirror-to-gretap offload wouldn't adapt to
changes in bridge vlan configuration right away and another notification
would have to arrive for mlxsw to catch up.

Signed-off-by: Petr Machata 
Reviewed-by: Ido Schimmel 
---
 drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c 
b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
index cbc8fab..8a15ac4 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
@@ -1697,7 +1697,7 @@ static int mlxsw_sp_port_obj_add(struct net_device *dev,
vlan = SWITCHDEV_OBJ_PORT_VLAN(obj);
err = mlxsw_sp_port_vlans_add(mlxsw_sp_port, vlan, trans);
 
-   if (switchdev_trans_ph_commit(trans)) {
+   if (switchdev_trans_ph_prepare(trans)) {
/* The event is emitted before the changes are actually
 * applied to the bridge. Therefore schedule the respin
 * call for later, so that the respin logic sees the
-- 
2.4.11

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH net-next 2/7] mlxsw: spectrum_switchdev: Ignore bridge VLAN events

2018-05-24 Thread Petr Machata
Ignore VLAN events where the orig_dev is the bridge device itself.

Signed-off-by: Petr Machata 
Reviewed-by: Ido Schimmel 
---
 drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c 
b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
index 8c9cf8e..cbc8fab 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
@@ -1144,6 +1144,9 @@ static int mlxsw_sp_port_vlans_add(struct mlxsw_sp_port 
*mlxsw_sp_port,
struct mlxsw_sp_bridge_port *bridge_port;
u16 vid;
 
+   if (netif_is_bridge_master(orig_dev))
+   return -EOPNOTSUPP;
+
if (switchdev_trans_ph_prepare(trans))
return 0;
 
@@ -1741,6 +1744,9 @@ static int mlxsw_sp_port_vlans_del(struct mlxsw_sp_port 
*mlxsw_sp_port,
struct mlxsw_sp_bridge_port *bridge_port;
u16 vid;
 
+   if (netif_is_bridge_master(orig_dev))
+   return -EOPNOTSUPP;
+
bridge_port = mlxsw_sp_bridge_port_find(mlxsw_sp->bridge, orig_dev);
if (WARN_ON(!bridge_port))
return -EINVAL;
-- 
2.4.11

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH net-next 6/7] net: bridge: Notify about bridge VLANs

2018-05-24 Thread Petr Machata
A driver might need to react to changes in settings of brentry VLANs.
Therefore send switchdev port notifications for these as well. Reuse
SWITCHDEV_OBJ_ID_PORT_VLAN for this purpose. Listeners should use
netif_is_bridge_master() on orig_dev to determine whether the
notification is about a bridge port or a bridge.

Signed-off-by: Petr Machata 
---
 net/bridge/br_vlan.c | 14 ++
 1 file changed, 14 insertions(+)

diff --git a/net/bridge/br_vlan.c b/net/bridge/br_vlan.c
index a75fe930..14c1b6c 100644
--- a/net/bridge/br_vlan.c
+++ b/net/bridge/br_vlan.c
@@ -268,6 +268,10 @@ static int __vlan_add(struct net_bridge_vlan *v, u16 flags)
goto out_filt;
v->brvlan = masterv;
v->stats = masterv->stats;
+   } else {
+   err = br_switchdev_port_obj_add(dev, v->vid, flags);
+   if (err && err != -EOPNOTSUPP)
+   goto out;
}
 
/* Add the dev mac and count the vlan only if it's usable */
@@ -303,6 +307,8 @@ static int __vlan_add(struct net_bridge_vlan *v, u16 flags)
br_vlan_put_master(masterv);
v->brvlan = NULL;
}
+   } else {
+   br_switchdev_port_obj_del(dev, v->vid);
}
 
goto out;
@@ -328,6 +334,11 @@ static int __vlan_del(struct net_bridge_vlan *v)
err = __vlan_vid_del(p->dev, p->br, v->vid);
if (err)
goto out;
+   } else {
+   err = br_switchdev_port_obj_del(v->br->dev, v->vid);
+   if (err && err != -EOPNOTSUPP)
+   goto out;
+   err = 0;
}
 
if (br_vlan_should_use(v)) {
@@ -605,6 +616,9 @@ int br_vlan_add(struct net_bridge *br, u16 vid, u16 flags, 
bool *changed)
vg->num_vlans++;
*changed = true;
}
+   ret = br_switchdev_port_obj_add(br->dev, vid, flags);
+   if (ret && ret != -EOPNOTSUPP)
+   return ret;
if (__vlan_add_flags(vlan, flags))
*changed = true;
 
-- 
2.4.11

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH net-next 4/7] dsa: port: Ignore bridge VLAN events

2018-05-24 Thread Petr Machata
Ignore VLAN events where the orig_dev is the bridge device itself.

Signed-off-by: Petr Machata 
---
 net/dsa/port.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/net/dsa/port.c b/net/dsa/port.c
index 2413beb..ed05954 100644
--- a/net/dsa/port.c
+++ b/net/dsa/port.c
@@ -252,6 +252,9 @@ int dsa_port_vlan_add(struct dsa_port *dp,
.vlan = vlan,
};
 
+   if (netif_is_bridge_master(vlan->obj.orig_dev))
+   return -EOPNOTSUPP;
+
if (br_vlan_enabled(dp->bridge_dev))
return dsa_port_notify(dp, DSA_NOTIFIER_VLAN_ADD, &info);
 
@@ -267,6 +270,9 @@ int dsa_port_vlan_del(struct dsa_port *dp,
.vlan = vlan,
};
 
+   if (netif_is_bridge_master(vlan->obj.orig_dev))
+   return -EOPNOTSUPP;
+
if (br_vlan_enabled(dp->bridge_dev))
return dsa_port_notify(dp, DSA_NOTIFIER_VLAN_DEL, &info);
 
-- 
2.4.11

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH net-next 3/7] rocker: rocker_main: Ignore bridge VLAN events

2018-05-24 Thread Petr Machata
Ignore VLAN events where the orig_dev is the bridge device itself.

Signed-off-by: Petr Machata 
---
 drivers/net/ethernet/rocker/rocker_main.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/drivers/net/ethernet/rocker/rocker_main.c 
b/drivers/net/ethernet/rocker/rocker_main.c
index e73e4fe..aeafdb9 100644
--- a/drivers/net/ethernet/rocker/rocker_main.c
+++ b/drivers/net/ethernet/rocker/rocker_main.c
@@ -1632,6 +1632,9 @@ rocker_world_port_obj_vlan_add(struct rocker_port 
*rocker_port,
 {
struct rocker_world_ops *wops = rocker_port->rocker->wops;
 
+   if (netif_is_bridge_master(vlan->obj.orig_dev))
+   return -EOPNOTSUPP;
+
if (!wops->port_obj_vlan_add)
return -EOPNOTSUPP;
 
@@ -1647,6 +1650,9 @@ rocker_world_port_obj_vlan_del(struct rocker_port 
*rocker_port,
 {
struct rocker_world_ops *wops = rocker_port->rocker->wops;
 
+   if (netif_is_bridge_master(vlan->obj.orig_dev))
+   return -EOPNOTSUPP;
+
if (!wops->port_obj_vlan_del)
return -EOPNOTSUPP;
return wops->port_obj_vlan_del(rocker_port, vlan);
-- 
2.4.11

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH net-next 0/7] net: bridge: Notify about bridge VLANs

2018-05-24 Thread Petr Machata
In commit 946a11e7408e ("mlxsw: spectrum_span: Allow bridge for gretap
mirror"), mlxsw got support for offloading mirror-to-gretap such that
the underlay packet path involves a bridge. In that case, the offload is
also influenced by PVID setting of said bridge. However, changes to VLAN
configuration of the bridge itself do not generate switchdev
notifications, so there's no mechanism to prod mlxsw to update the
offload when these settings change.

In this patchset, the problem is resolved by distributing the switchdev
notification SWITCHDEV_OBJ_ID_PORT_VLAN also for configuration changes
on bridge VLANs. Since stacked devices distribute the notification to
lower devices, such event eventually reaches the driver, which can
determine whether it's a bridge or port VLAN by inspecting orig_dev.

To keep things consistent, the newly-distributed notifications observe
the same protocol as the existing ones: dual prepare/commit, with
-EOPNOTSUPP indicating lack of support, even though there's currently
nothing to prepare for and nothing to support. Correspondingly, all
switchdev drivers have been updated to return -EOPNOTSUPP for bridge
VLAN notifications.

In patch #1, the code to send notifications for adding and deleting is
factored out into two named functions.

In patches #2-#5, respectively for mlxsw, rocker, DSA and DPAA2 ethsw,
the new notifications (which are not enabled yet) are ignored to
maintain the current behavior.

In patch #6, the notification is actually enabled.

In patch #7, mlxsw is changed to update offloads of mirror-to-gre also
for bridge-related notifications.

Petr Machata (7):
  net: bridge: Extract boilerplate around switchdev_port_obj_*()
  mlxsw: spectrum_switchdev: Ignore bridge VLAN events
  rocker: rocker_main: Ignore bridge VLAN events
  dsa: port: Ignore bridge VLAN events
  staging: fsl-dpaa2: ethsw: Ignore bridge VLAN events
  net: bridge: Notify about bridge VLANs
  mlxsw: spectrum_switchdev: Schedule respin during trans prepare

 .../ethernet/mellanox/mlxsw/spectrum_switchdev.c   |  8 ++-
 drivers/net/ethernet/rocker/rocker_main.c  |  6 +++
 drivers/staging/fsl-dpaa2/ethsw/ethsw.c|  6 +++
 net/bridge/br_vlan.c   | 58 ++
 net/dsa/port.c |  6 +++
 5 files changed, 62 insertions(+), 22 deletions(-)

-- 
2.4.11

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


Re: [PATCH net-next 0/7] net: bridge: Notify about bridge VLANs

2018-05-25 Thread Petr Machata
Florian Fainelli  writes:

> You seem to have approached the bridge changes a little differently from
> this series:
>
> https://lists.linux-foundation.org/pipermail/bridge/2016-November/010112.html

It pretty much extends the patchset to also send the notifications for
the CPU port.

I missed this e-mail yesterday and now I see you already found out for
yourself how it behaves.

> Both have the same intent that by targeting the bridge device itself,
> you can propagate that through switchdev to the switch drivers, and in
> turn create configurations where for instance, you have:
>
> - CPU/management port present in specific VLANs that is a subset or
> superset of the VLANs configured on front-panel ports
> - CPU/management port tagged/untagged in specific VLANs which can be a
> different setting from the front-panel ports
>
> One problem we have in DSA at the moment is that we always add the CPU
> port to the VLANs configured to the front-panel port but we do this with
> the same attributes as the front panel ports! For instance, if you add
> Port 0 to VLAN1 untagged, the the CPU port also gets added to that
> VLAN1, also untagged. As long as there is just one VLAN untagged, this
> is not much of a problem. Now do this with another VLAN or another port,
> and the CPU can no longer differentiate the traffic from which VLAN it
> is coming from, no bueno.

Yep, with this patchset you should be able to use the CPU port
notifications to configure things exactly.

> bridge vlan add vid 2 dev port0 pvid untagged
>   -> port0 (e.g: switch port 0) gets programmed
>   -> CPU port gets programmed
> bridge vlan add vid 2 dev br0 self
>   -> CPU port gets programmed
> bridge vlan add vid 2 dev port0
>   -> port0 (switch port 0) gets programmed
>
> Are these use cases possible with your series? It seems to me like it is
> if we drop the netif_is_bridge_master() checks and resolve orig_dev as
> being a hint for the CPU/management port.

Yeah, that's how it behaves. If you accept the events where
netif_is_bridge_master(orig_dev), you can tell the CPU port-related
events from the rest by BRIDGE_VLAN_INFO_BRENTRY.

Thanks,
Petr
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


Re: [PATCH net-next 1/7] net: bridge: Extract boilerplate around switchdev_port_obj_*()

2018-05-25 Thread Petr Machata
Vivien Didelot  writes:

> Hi Petr,
>
> Petr Machata  writes:
>
>> -static int __vlan_vid_add(struct net_device *dev, struct net_bridge *br,
>> -  u16 vid, u16 flags)
>> +static int br_switchdev_port_obj_add(struct net_device *dev, u16 vid, u16 
>> flags)
>>  {
>>  struct switchdev_obj_port_vlan v = {
>>  .obj.orig_dev = dev,
>> @@ -89,12 +88,29 @@ static int __vlan_vid_add(struct net_device *dev, struct 
>> net_bridge *br,
>>  .vid_begin = vid,
>>  .vid_end = vid,
>>  };
>> -int err;
>>  
>> +return switchdev_port_obj_add(dev, &v.obj);
>> +}
>> +
>> +static int br_switchdev_port_obj_del(struct net_device *dev, u16 vid)
>> +{
>> +struct switchdev_obj_port_vlan v = {
>> +.obj.orig_dev = dev,
>> +.obj.id = SWITCHDEV_OBJ_ID_PORT_VLAN,
>> +.vid_begin = vid,
>> +.vid_end = vid,
>> +};
>> +
>> +return switchdev_port_obj_del(dev, &v.obj);
>> +}
>
> Shouldn't they be br_switchdev_port_vlan_add (or similar) implemented in
> net/bridge/br_switchdev.c instead, since they are VLAN specific?

(You mean switchdev-specific?)

This logic was in br_vlan.c before as well, so it's natural to think
about the functions as helpers of VLAN module. I can move to
br_switchdev.c if you think that's the better place.

Thanks,
Petr
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


Re: [PATCH net-next 6/7] net: bridge: Notify about bridge VLANs

2018-05-25 Thread Petr Machata
Vivien Didelot  writes:

>> +} else {
>> +err = br_switchdev_port_obj_add(dev, v->vid, flags);
>> +if (err && err != -EOPNOTSUPP)
>> +goto out;
>>  }
>
> Except that br_switchdev_port_obj_add taking vid and flags arguments
> seems confusing to me, the change looks good:

I'm not sure what you're aiming at. Both VID and flags are sent with the
notification, so they need to be passed on to the function somehow. Do
you have a counterproposal for the API?

Thanks,
Petr
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


Re: [PATCH net-next 6/7] net: bridge: Notify about bridge VLANs

2018-05-28 Thread Petr Machata
Vivien Didelot  writes:

> Hi Petr,
>
> Petr Machata  writes:
>
>> Vivien Didelot  writes:
>>
>>>> +  } else {
>>>> +  err = br_switchdev_port_obj_add(dev, v->vid, flags);
>>>> +  if (err && err != -EOPNOTSUPP)
>>>> +  goto out;
>>>>}
>>>
>>> Except that br_switchdev_port_obj_add taking vid and flags arguments
>>> seems confusing to me, the change looks good:
>>
>> I'm not sure what you're aiming at. Both VID and flags are sent with the
>> notification, so they need to be passed on to the function somehow. Do
>> you have a counterproposal for the API?
>
> I'm only questioning the code organization here, not the functional
> aspect which I do agree with. What I'm saying is that you name a new
> switchdev helper br_switchdev_port_OBJ_add, which takes VLAN arguments
> (vid and flags.) How would you call another eventual helper taking MDB
> arguments, br_switchdev_port_OBJ_add again? So something like
> br_switchdev_port_VLAN_add would be more intuitive.
>
> At the same time there's an effort to centralize all switchdev helpers
> of the bridge layer (i.e. the software -> hardware bridge calls) into
> net/bridge/br_switchdev.c, so that file would be more adequate.
>
> You may discard my comments but I think it'd be beneficial to us all to
> finally keep a bit of consistency in that bridge layer code.

Nope, those are reasonable points. I'll post a v2 along those lines.

Thanks,
Petr
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH net-next v2 2/7] mlxsw: spectrum_switchdev: Ignore bridge VLAN events

2018-05-28 Thread Petr Machata
Ignore VLAN events where the orig_dev is the bridge device itself.

Signed-off-by: Petr Machata 
Reviewed-by: Ido Schimmel 
---
 drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c 
b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
index 8c9cf8e..cbc8fab 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
@@ -1144,6 +1144,9 @@ static int mlxsw_sp_port_vlans_add(struct mlxsw_sp_port 
*mlxsw_sp_port,
struct mlxsw_sp_bridge_port *bridge_port;
u16 vid;
 
+   if (netif_is_bridge_master(orig_dev))
+   return -EOPNOTSUPP;
+
if (switchdev_trans_ph_prepare(trans))
return 0;
 
@@ -1741,6 +1744,9 @@ static int mlxsw_sp_port_vlans_del(struct mlxsw_sp_port 
*mlxsw_sp_port,
struct mlxsw_sp_bridge_port *bridge_port;
u16 vid;
 
+   if (netif_is_bridge_master(orig_dev))
+   return -EOPNOTSUPP;
+
bridge_port = mlxsw_sp_bridge_port_find(mlxsw_sp->bridge, orig_dev);
if (WARN_ON(!bridge_port))
return -EINVAL;
-- 
2.4.11

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH net-next v2 0/7] net: bridge: Notify about bridge VLANs

2018-05-28 Thread Petr Machata
In commit 946a11e7408e ("mlxsw: spectrum_span: Allow bridge for gretap
mirror"), mlxsw got support for offloading mirror-to-gretap such that
the underlay packet path involves a bridge. In that case, the offload is
also influenced by PVID setting of said bridge. However, changes to VLAN
configuration of the bridge itself do not generate switchdev
notifications, so there's no mechanism to prod mlxsw to update the
offload when these settings change.

In this patchset, the problem is resolved by distributing the switchdev
notification SWITCHDEV_OBJ_ID_PORT_VLAN also for configuration changes
on bridge VLANs. Since stacked devices distribute the notification to
lower devices, such event eventually reaches the driver, which can
determine whether it's a bridge or port VLAN by inspecting orig_dev.

To keep things consistent, the newly-distributed notifications observe
the same protocol as the existing ones: dual prepare/commit, with
-EOPNOTSUPP indicating lack of support, even though there's currently
nothing to prepare for and nothing to support. Correspondingly, all
switchdev drivers have been updated to return -EOPNOTSUPP for bridge
VLAN notifications.

In patch #1, the code to send notifications for adding and deleting is
factored out into two named functions.

In patches #2-#5, respectively for mlxsw, rocker, DSA and DPAA2 ethsw,
the new notifications (which are not enabled yet) are ignored to
maintain the current behavior.

In patch #6, the notification is actually enabled.

In patch #7, mlxsw is changed to update offloads of mirror-to-gre also
for bridge-related notifications.

Changes from v1 to v2:

- Rename br_switchdev_port_obj_add() and br_switchdev_port_obj_del() to
  br_switchdev_port_vlan_add() and br_switchdev_port_vlan_del(), and
  move from br_vlan.c to br_switchdev.c.

Petr Machata (7):
  net: bridge: Extract boilerplate around switchdev_port_obj_*()
  mlxsw: spectrum_switchdev: Ignore bridge VLAN events
  rocker: rocker_main: Ignore bridge VLAN events
  dsa: port: Ignore bridge VLAN events
  staging: fsl-dpaa2: ethsw: Ignore bridge VLAN events
  net: bridge: Notify about bridge VLANs
  mlxsw: spectrum_switchdev: Schedule respin during trans prepare

 .../ethernet/mellanox/mlxsw/spectrum_switchdev.c   |  8 +++-
 drivers/net/ethernet/rocker/rocker_main.c  |  6 +++
 drivers/staging/fsl-dpaa2/ethsw/ethsw.c|  6 +++
 net/bridge/br_private.h|  3 ++
 net/bridge/br_switchdev.c  | 25 
 net/bridge/br_vlan.c   | 45 +-
 net/dsa/port.c |  6 +++
 7 files changed, 71 insertions(+), 28 deletions(-)

-- 
2.4.11

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH net-next v2 5/7] staging: fsl-dpaa2: ethsw: Ignore bridge VLAN events

2018-05-28 Thread Petr Machata
Ignore VLAN events where the orig_dev is the bridge device itself.

Signed-off-by: Petr Machata 
---
 drivers/staging/fsl-dpaa2/ethsw/ethsw.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c 
b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c
index c723a04..a17dd29 100644
--- a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c
+++ b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c
@@ -719,6 +719,9 @@ static int port_vlans_add(struct net_device *netdev,
struct ethsw_port_priv *port_priv = netdev_priv(netdev);
int vid, err;
 
+   if (netif_is_bridge_master(vlan->obj.orig_dev))
+   return -EOPNOTSUPP;
+
if (switchdev_trans_ph_prepare(trans))
return 0;
 
@@ -873,6 +876,9 @@ static int port_vlans_del(struct net_device *netdev,
struct ethsw_port_priv *port_priv = netdev_priv(netdev);
int vid, err;
 
+   if (netif_is_bridge_master(vlan->obj.orig_dev))
+   return -EOPNOTSUPP;
+
for (vid = vlan->vid_begin; vid <= vlan->vid_end; vid++) {
err = ethsw_port_del_vlan(port_priv, vid);
if (err)
-- 
2.4.11

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH net-next v2 1/7] net: bridge: Extract boilerplate around switchdev_port_obj_*()

2018-05-28 Thread Petr Machata
A call to switchdev_port_obj_add() or switchdev_port_obj_del() involves
initializing a struct switchdev_obj_port_vlan, a piece of code that
repeats on each call site almost verbatim. While in the current codebase
there is just one duplicated add call, the follow-up patches add more of
both add and del calls.

Thus to remove the duplication, extract the repetition into named
functions and reuse.

Signed-off-by: Petr Machata 
---
 net/bridge/br_private.h   |  3 +++
 net/bridge/br_switchdev.c | 25 +
 net/bridge/br_vlan.c  | 31 ---
 3 files changed, 32 insertions(+), 27 deletions(-)

diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index 11520ed..33bd914 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -1178,6 +1178,9 @@ static inline void br_switchdev_frame_unmark(struct 
sk_buff *skb)
 }
 #endif /* CONFIG_NET_SWITCHDEV */
 
+int br_switchdev_port_vlan_add(struct net_device *dev, u16 vid, u16 flags);
+int br_switchdev_port_vlan_del(struct net_device *dev, u16 vid);
+
 /* br_arp_nd_proxy.c */
 void br_recalculate_neigh_suppress_enabled(struct net_bridge *br);
 void br_do_proxy_suppress_arp(struct sk_buff *skb, struct net_bridge *br,
diff --git a/net/bridge/br_switchdev.c b/net/bridge/br_switchdev.c
index 35474d4..d77f807 100644
--- a/net/bridge/br_switchdev.c
+++ b/net/bridge/br_switchdev.c
@@ -136,3 +136,28 @@ br_switchdev_fdb_notify(const struct net_bridge_fdb_entry 
*fdb, int type)
break;
}
 }
+
+int br_switchdev_port_vlan_add(struct net_device *dev, u16 vid, u16 flags)
+{
+   struct switchdev_obj_port_vlan v = {
+   .obj.orig_dev = dev,
+   .obj.id = SWITCHDEV_OBJ_ID_PORT_VLAN,
+   .flags = flags,
+   .vid_begin = vid,
+   .vid_end = vid,
+   };
+
+   return switchdev_port_obj_add(dev, &v.obj);
+}
+
+int br_switchdev_port_vlan_del(struct net_device *dev, u16 vid)
+{
+   struct switchdev_obj_port_vlan v = {
+   .obj.orig_dev = dev,
+   .obj.id = SWITCHDEV_OBJ_ID_PORT_VLAN,
+   .vid_begin = vid,
+   .vid_end = vid,
+   };
+
+   return switchdev_port_obj_del(dev, &v.obj);
+}
diff --git a/net/bridge/br_vlan.c b/net/bridge/br_vlan.c
index dc832c09..8ad5756 100644
--- a/net/bridge/br_vlan.c
+++ b/net/bridge/br_vlan.c
@@ -82,19 +82,10 @@ static bool __vlan_add_flags(struct net_bridge_vlan *v, u16 
flags)
 static int __vlan_vid_add(struct net_device *dev, struct net_bridge *br,
  u16 vid, u16 flags)
 {
-   struct switchdev_obj_port_vlan v = {
-   .obj.orig_dev = dev,
-   .obj.id = SWITCHDEV_OBJ_ID_PORT_VLAN,
-   .flags = flags,
-   .vid_begin = vid,
-   .vid_end = vid,
-   };
-   int err;
-
/* Try switchdev op first. In case it is not supported, fallback to
 * 8021q add.
 */
-   err = switchdev_port_obj_add(dev, &v.obj);
+   int err = br_switchdev_port_vlan_add(dev, vid, flags);
if (err == -EOPNOTSUPP)
return vlan_vid_add(dev, br->vlan_proto, vid);
return err;
@@ -130,18 +121,11 @@ static void __vlan_del_list(struct net_bridge_vlan *v)
 static int __vlan_vid_del(struct net_device *dev, struct net_bridge *br,
  u16 vid)
 {
-   struct switchdev_obj_port_vlan v = {
-   .obj.orig_dev = dev,
-   .obj.id = SWITCHDEV_OBJ_ID_PORT_VLAN,
-   .vid_begin = vid,
-   .vid_end = vid,
-   };
-   int err;
-
/* Try switchdev op first. In case it is not supported, fallback to
 * 8021q del.
 */
-   err = switchdev_port_obj_del(dev, &v.obj);
+   int err = br_switchdev_port_vlan_del(dev, vid);
+
if (err == -EOPNOTSUPP) {
vlan_vid_del(dev, br->vlan_proto, vid);
return 0;
@@ -1053,13 +1037,6 @@ int nbp_vlan_init(struct net_bridge_port *p)
 int nbp_vlan_add(struct net_bridge_port *port, u16 vid, u16 flags,
 bool *changed)
 {
-   struct switchdev_obj_port_vlan v = {
-   .obj.orig_dev = port->dev,
-   .obj.id = SWITCHDEV_OBJ_ID_PORT_VLAN,
-   .flags = flags,
-   .vid_begin = vid,
-   .vid_end = vid,
-   };
struct net_bridge_vlan *vlan;
int ret;
 
@@ -1069,7 +1046,7 @@ int nbp_vlan_add(struct net_bridge_port *port, u16 vid, 
u16 flags,
vlan = br_vlan_find(nbp_vlan_group(port), vid);
if (vlan) {
/* Pass the flags to the hardware bridge */
-   ret = switchdev_port_obj_add(port->dev, &v.obj);
+   ret = br_switchdev_port_vlan_add(port->dev, vid, flags);
if (ret && ret != -EOPNOTSUPP)
return ret;
*changed 

[PATCH net-next v2 4/7] dsa: port: Ignore bridge VLAN events

2018-05-28 Thread Petr Machata
Ignore VLAN events where the orig_dev is the bridge device itself.

Signed-off-by: Petr Machata 
Reviewed-by: Vivien Didelot 
---
 net/dsa/port.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/net/dsa/port.c b/net/dsa/port.c
index 2413beb..ed05954 100644
--- a/net/dsa/port.c
+++ b/net/dsa/port.c
@@ -252,6 +252,9 @@ int dsa_port_vlan_add(struct dsa_port *dp,
.vlan = vlan,
};
 
+   if (netif_is_bridge_master(vlan->obj.orig_dev))
+   return -EOPNOTSUPP;
+
if (br_vlan_enabled(dp->bridge_dev))
return dsa_port_notify(dp, DSA_NOTIFIER_VLAN_ADD, &info);
 
@@ -267,6 +270,9 @@ int dsa_port_vlan_del(struct dsa_port *dp,
.vlan = vlan,
};
 
+   if (netif_is_bridge_master(vlan->obj.orig_dev))
+   return -EOPNOTSUPP;
+
if (br_vlan_enabled(dp->bridge_dev))
return dsa_port_notify(dp, DSA_NOTIFIER_VLAN_DEL, &info);
 
-- 
2.4.11

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH net-next v2 3/7] rocker: rocker_main: Ignore bridge VLAN events

2018-05-28 Thread Petr Machata
Ignore VLAN events where the orig_dev is the bridge device itself.

Signed-off-by: Petr Machata 
---
 drivers/net/ethernet/rocker/rocker_main.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/drivers/net/ethernet/rocker/rocker_main.c 
b/drivers/net/ethernet/rocker/rocker_main.c
index e73e4fe..aeafdb9 100644
--- a/drivers/net/ethernet/rocker/rocker_main.c
+++ b/drivers/net/ethernet/rocker/rocker_main.c
@@ -1632,6 +1632,9 @@ rocker_world_port_obj_vlan_add(struct rocker_port 
*rocker_port,
 {
struct rocker_world_ops *wops = rocker_port->rocker->wops;
 
+   if (netif_is_bridge_master(vlan->obj.orig_dev))
+   return -EOPNOTSUPP;
+
if (!wops->port_obj_vlan_add)
return -EOPNOTSUPP;
 
@@ -1647,6 +1650,9 @@ rocker_world_port_obj_vlan_del(struct rocker_port 
*rocker_port,
 {
struct rocker_world_ops *wops = rocker_port->rocker->wops;
 
+   if (netif_is_bridge_master(vlan->obj.orig_dev))
+   return -EOPNOTSUPP;
+
if (!wops->port_obj_vlan_del)
return -EOPNOTSUPP;
return wops->port_obj_vlan_del(rocker_port, vlan);
-- 
2.4.11

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH net-next v2 7/7] mlxsw: spectrum_switchdev: Schedule respin during trans prepare

2018-05-28 Thread Petr Machata
Since there's no special support for the bridge events, the driver
returns -EOPNOTSUPP, and thus the commit never happens. Therefore
schedule respin during the prepare stage: there's no real difference one
way or another.

This fixes the problem that mirror-to-gretap offload wouldn't adapt to
changes in bridge vlan configuration right away and another notification
would have to arrive for mlxsw to catch up.

Signed-off-by: Petr Machata 
Reviewed-by: Ido Schimmel 
---
 drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c 
b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
index cbc8fab..8a15ac4 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
@@ -1697,7 +1697,7 @@ static int mlxsw_sp_port_obj_add(struct net_device *dev,
vlan = SWITCHDEV_OBJ_PORT_VLAN(obj);
err = mlxsw_sp_port_vlans_add(mlxsw_sp_port, vlan, trans);
 
-   if (switchdev_trans_ph_commit(trans)) {
+   if (switchdev_trans_ph_prepare(trans)) {
/* The event is emitted before the changes are actually
 * applied to the bridge. Therefore schedule the respin
 * call for later, so that the respin logic sees the
-- 
2.4.11

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH net-next v2 6/7] net: bridge: Notify about bridge VLANs

2018-05-28 Thread Petr Machata
A driver might need to react to changes in settings of brentry VLANs.
Therefore send switchdev port notifications for these as well. Reuse
SWITCHDEV_OBJ_ID_PORT_VLAN for this purpose. Listeners should use
netif_is_bridge_master() on orig_dev to determine whether the
notification is about a bridge port or a bridge.

Signed-off-by: Petr Machata 
Reviewed-by: Florian Fainelli 
Reviewed-by: Vivien Didelot 
Reviewed-by: Nikolay Aleksandrov 
Tested-by: Florian Fainelli 
---
 net/bridge/br_vlan.c | 14 ++
 1 file changed, 14 insertions(+)

diff --git a/net/bridge/br_vlan.c b/net/bridge/br_vlan.c
index 8ad5756..b15ef3f 100644
--- a/net/bridge/br_vlan.c
+++ b/net/bridge/br_vlan.c
@@ -243,6 +243,10 @@ static int __vlan_add(struct net_bridge_vlan *v, u16 flags)
goto out_filt;
v->brvlan = masterv;
v->stats = masterv->stats;
+   } else {
+   err = br_switchdev_port_vlan_add(dev, v->vid, flags);
+   if (err && err != -EOPNOTSUPP)
+   goto out;
}
 
/* Add the dev mac and count the vlan only if it's usable */
@@ -278,6 +282,8 @@ static int __vlan_add(struct net_bridge_vlan *v, u16 flags)
br_vlan_put_master(masterv);
v->brvlan = NULL;
}
+   } else {
+   br_switchdev_port_vlan_del(dev, v->vid);
}
 
goto out;
@@ -303,6 +309,11 @@ static int __vlan_del(struct net_bridge_vlan *v)
err = __vlan_vid_del(p->dev, p->br, v->vid);
if (err)
goto out;
+   } else {
+   err = br_switchdev_port_vlan_del(v->br->dev, v->vid);
+   if (err && err != -EOPNOTSUPP)
+   goto out;
+   err = 0;
}
 
if (br_vlan_should_use(v)) {
@@ -580,6 +591,9 @@ int br_vlan_add(struct net_bridge *br, u16 vid, u16 flags, 
bool *changed)
vg->num_vlans++;
*changed = true;
}
+   ret = br_switchdev_port_vlan_add(br->dev, vid, flags);
+   if (ret && ret != -EOPNOTSUPP)
+   return ret;
if (__vlan_add_flags(vlan, flags))
*changed = true;
 
-- 
2.4.11

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


Re: [PATCH net-next v2 1/7] net: bridge: Extract boilerplate around switchdev_port_obj_*()

2018-05-28 Thread Petr Machata
Petr Machata  writes:

> diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
> index 11520ed..33bd914 100644
> --- a/net/bridge/br_private.h
> +++ b/net/bridge/br_private.h
> @@ -1178,6 +1178,9 @@ static inline void br_switchdev_frame_unmark(struct 
> sk_buff *skb)
>  }
>  #endif /* CONFIG_NET_SWITCHDEV */
>  
> +int br_switchdev_port_vlan_add(struct net_device *dev, u16 vid, u16 flags);
> +int br_switchdev_port_vlan_del(struct net_device *dev, u16 vid);
> +

Nope, this actually does need to be in the ifdef block. The whole
br_switchdev.c is built conditionally.

I'll send v3.

Petr
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH net-next v3 0/7] net: bridge: Notify about bridge VLANs

2018-05-28 Thread Petr Machata
In commit 946a11e7408e ("mlxsw: spectrum_span: Allow bridge for gretap
mirror"), mlxsw got support for offloading mirror-to-gretap such that
the underlay packet path involves a bridge. In that case, the offload is
also influenced by PVID setting of said bridge. However, changes to VLAN
configuration of the bridge itself do not generate switchdev
notifications, so there's no mechanism to prod mlxsw to update the
offload when these settings change.

In this patchset, the problem is resolved by distributing the switchdev
notification SWITCHDEV_OBJ_ID_PORT_VLAN also for configuration changes
on bridge VLANs. Since stacked devices distribute the notification to
lower devices, such event eventually reaches the driver, which can
determine whether it's a bridge or port VLAN by inspecting orig_dev.

To keep things consistent, the newly-distributed notifications observe
the same protocol as the existing ones: dual prepare/commit, with
-EOPNOTSUPP indicating lack of support, even though there's currently
nothing to prepare for and nothing to support. Correspondingly, all
switchdev drivers have been updated to return -EOPNOTSUPP for bridge
VLAN notifications.

In patch #1, the code to send notifications for adding and deleting is
factored out into two named functions.

In patches #2-#5, respectively for mlxsw, rocker, DSA and DPAA2 ethsw,
the new notifications (which are not enabled yet) are ignored to
maintain the current behavior.

In patch #6, the notification is actually enabled.

In patch #7, mlxsw is changed to update offloads of mirror-to-gre also
for bridge-related notifications.

Changes from v2 to v3:

- Add a fallback definition for br_switchdev_port_obj_add() and
  br_switchdev_port_obj_del() when !CONFIG_NET_SWITCHDEV.

Changes from v1 to v2:

- Rename br_switchdev_port_obj_add() and br_switchdev_port_obj_del() to
  br_switchdev_port_vlan_add() and br_switchdev_port_vlan_del(), and
  move from br_vlan.c to br_switchdev.c.

Petr Machata (7):
  net: bridge: Extract boilerplate around switchdev_port_obj_*()
  mlxsw: spectrum_switchdev: Ignore bridge VLAN events
  rocker: rocker_main: Ignore bridge VLAN events
  dsa: port: Ignore bridge VLAN events
  staging: fsl-dpaa2: ethsw: Ignore bridge VLAN events
  net: bridge: Notify about bridge VLANs
  mlxsw: spectrum_switchdev: Schedule respin during trans prepare

 .../ethernet/mellanox/mlxsw/spectrum_switchdev.c   |  8 +++-
 drivers/net/ethernet/rocker/rocker_main.c  |  6 +++
 drivers/staging/fsl-dpaa2/ethsw/ethsw.c|  6 +++
 net/bridge/br_private.h| 13 +++
 net/bridge/br_switchdev.c  | 25 
 net/bridge/br_vlan.c   | 45 +-
 net/dsa/port.c |  6 +++
 7 files changed, 81 insertions(+), 28 deletions(-)

-- 
2.4.11

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH net-next v3 2/7] mlxsw: spectrum_switchdev: Ignore bridge VLAN events

2018-05-28 Thread Petr Machata
Ignore VLAN events where the orig_dev is the bridge device itself.

Signed-off-by: Petr Machata 
Reviewed-by: Ido Schimmel 
---
 drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c 
b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
index 8c9cf8e..cbc8fab 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
@@ -1144,6 +1144,9 @@ static int mlxsw_sp_port_vlans_add(struct mlxsw_sp_port 
*mlxsw_sp_port,
struct mlxsw_sp_bridge_port *bridge_port;
u16 vid;
 
+   if (netif_is_bridge_master(orig_dev))
+   return -EOPNOTSUPP;
+
if (switchdev_trans_ph_prepare(trans))
return 0;
 
@@ -1741,6 +1744,9 @@ static int mlxsw_sp_port_vlans_del(struct mlxsw_sp_port 
*mlxsw_sp_port,
struct mlxsw_sp_bridge_port *bridge_port;
u16 vid;
 
+   if (netif_is_bridge_master(orig_dev))
+   return -EOPNOTSUPP;
+
bridge_port = mlxsw_sp_bridge_port_find(mlxsw_sp->bridge, orig_dev);
if (WARN_ON(!bridge_port))
return -EINVAL;
-- 
2.4.11

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH net-next v3 1/7] net: bridge: Extract boilerplate around switchdev_port_obj_*()

2018-05-28 Thread Petr Machata
A call to switchdev_port_obj_add() or switchdev_port_obj_del() involves
initializing a struct switchdev_obj_port_vlan, a piece of code that
repeats on each call site almost verbatim. While in the current codebase
there is just one duplicated add call, the follow-up patches add more of
both add and del calls.

Thus to remove the duplication, extract the repetition into named
functions and reuse.

Signed-off-by: Petr Machata 
---
 net/bridge/br_private.h   | 13 +
 net/bridge/br_switchdev.c | 25 +
 net/bridge/br_vlan.c  | 31 ---
 3 files changed, 42 insertions(+), 27 deletions(-)

diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index 11520ed..5216a52 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -1139,6 +1139,8 @@ int br_switchdev_set_port_flag(struct net_bridge_port *p,
   unsigned long mask);
 void br_switchdev_fdb_notify(const struct net_bridge_fdb_entry *fdb,
 int type);
+int br_switchdev_port_vlan_add(struct net_device *dev, u16 vid, u16 flags);
+int br_switchdev_port_vlan_del(struct net_device *dev, u16 vid);
 
 static inline void br_switchdev_frame_unmark(struct sk_buff *skb)
 {
@@ -1168,6 +1170,17 @@ static inline int br_switchdev_set_port_flag(struct 
net_bridge_port *p,
return 0;
 }
 
+static inline int br_switchdev_port_vlan_add(struct net_device *dev,
+u16 vid, u16 flags)
+{
+   return -EOPNOTSUPP;
+}
+
+static inline int br_switchdev_port_vlan_del(struct net_device *dev, u16 vid)
+{
+   return -EOPNOTSUPP;
+}
+
 static inline void
 br_switchdev_fdb_notify(const struct net_bridge_fdb_entry *fdb, int type)
 {
diff --git a/net/bridge/br_switchdev.c b/net/bridge/br_switchdev.c
index 35474d4..d77f807 100644
--- a/net/bridge/br_switchdev.c
+++ b/net/bridge/br_switchdev.c
@@ -136,3 +136,28 @@ br_switchdev_fdb_notify(const struct net_bridge_fdb_entry 
*fdb, int type)
break;
}
 }
+
+int br_switchdev_port_vlan_add(struct net_device *dev, u16 vid, u16 flags)
+{
+   struct switchdev_obj_port_vlan v = {
+   .obj.orig_dev = dev,
+   .obj.id = SWITCHDEV_OBJ_ID_PORT_VLAN,
+   .flags = flags,
+   .vid_begin = vid,
+   .vid_end = vid,
+   };
+
+   return switchdev_port_obj_add(dev, &v.obj);
+}
+
+int br_switchdev_port_vlan_del(struct net_device *dev, u16 vid)
+{
+   struct switchdev_obj_port_vlan v = {
+   .obj.orig_dev = dev,
+   .obj.id = SWITCHDEV_OBJ_ID_PORT_VLAN,
+   .vid_begin = vid,
+   .vid_end = vid,
+   };
+
+   return switchdev_port_obj_del(dev, &v.obj);
+}
diff --git a/net/bridge/br_vlan.c b/net/bridge/br_vlan.c
index dc832c09..8ad5756 100644
--- a/net/bridge/br_vlan.c
+++ b/net/bridge/br_vlan.c
@@ -82,19 +82,10 @@ static bool __vlan_add_flags(struct net_bridge_vlan *v, u16 
flags)
 static int __vlan_vid_add(struct net_device *dev, struct net_bridge *br,
  u16 vid, u16 flags)
 {
-   struct switchdev_obj_port_vlan v = {
-   .obj.orig_dev = dev,
-   .obj.id = SWITCHDEV_OBJ_ID_PORT_VLAN,
-   .flags = flags,
-   .vid_begin = vid,
-   .vid_end = vid,
-   };
-   int err;
-
/* Try switchdev op first. In case it is not supported, fallback to
 * 8021q add.
 */
-   err = switchdev_port_obj_add(dev, &v.obj);
+   int err = br_switchdev_port_vlan_add(dev, vid, flags);
if (err == -EOPNOTSUPP)
return vlan_vid_add(dev, br->vlan_proto, vid);
return err;
@@ -130,18 +121,11 @@ static void __vlan_del_list(struct net_bridge_vlan *v)
 static int __vlan_vid_del(struct net_device *dev, struct net_bridge *br,
  u16 vid)
 {
-   struct switchdev_obj_port_vlan v = {
-   .obj.orig_dev = dev,
-   .obj.id = SWITCHDEV_OBJ_ID_PORT_VLAN,
-   .vid_begin = vid,
-   .vid_end = vid,
-   };
-   int err;
-
/* Try switchdev op first. In case it is not supported, fallback to
 * 8021q del.
 */
-   err = switchdev_port_obj_del(dev, &v.obj);
+   int err = br_switchdev_port_vlan_del(dev, vid);
+
if (err == -EOPNOTSUPP) {
vlan_vid_del(dev, br->vlan_proto, vid);
return 0;
@@ -1053,13 +1037,6 @@ int nbp_vlan_init(struct net_bridge_port *p)
 int nbp_vlan_add(struct net_bridge_port *port, u16 vid, u16 flags,
 bool *changed)
 {
-   struct switchdev_obj_port_vlan v = {
-   .obj.orig_dev = port->dev,
-   .obj.id = SWITCHDEV_OBJ_ID_PORT_VLAN,
-   .flags = flags,
-   .vid_begin = vid,
-   .vid_end = vid,
-   };
struct net_bridge_vlan *vlan;
int ret;
 

[PATCH net-next v3 7/7] mlxsw: spectrum_switchdev: Schedule respin during trans prepare

2018-05-28 Thread Petr Machata
Since there's no special support for the bridge events, the driver
returns -EOPNOTSUPP, and thus the commit never happens. Therefore
schedule respin during the prepare stage: there's no real difference one
way or another.

This fixes the problem that mirror-to-gretap offload wouldn't adapt to
changes in bridge vlan configuration right away and another notification
would have to arrive for mlxsw to catch up.

Signed-off-by: Petr Machata 
Reviewed-by: Ido Schimmel 
---
 drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c 
b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
index cbc8fab..8a15ac4 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
@@ -1697,7 +1697,7 @@ static int mlxsw_sp_port_obj_add(struct net_device *dev,
vlan = SWITCHDEV_OBJ_PORT_VLAN(obj);
err = mlxsw_sp_port_vlans_add(mlxsw_sp_port, vlan, trans);
 
-   if (switchdev_trans_ph_commit(trans)) {
+   if (switchdev_trans_ph_prepare(trans)) {
/* The event is emitted before the changes are actually
 * applied to the bridge. Therefore schedule the respin
 * call for later, so that the respin logic sees the
-- 
2.4.11

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH net-next v3 6/7] net: bridge: Notify about bridge VLANs

2018-05-28 Thread Petr Machata
A driver might need to react to changes in settings of brentry VLANs.
Therefore send switchdev port notifications for these as well. Reuse
SWITCHDEV_OBJ_ID_PORT_VLAN for this purpose. Listeners should use
netif_is_bridge_master() on orig_dev to determine whether the
notification is about a bridge port or a bridge.

Signed-off-by: Petr Machata 
Reviewed-by: Florian Fainelli 
Reviewed-by: Vivien Didelot 
Reviewed-by: Nikolay Aleksandrov 
Tested-by: Florian Fainelli 
---
 net/bridge/br_vlan.c | 14 ++
 1 file changed, 14 insertions(+)

diff --git a/net/bridge/br_vlan.c b/net/bridge/br_vlan.c
index 8ad5756..b15ef3f 100644
--- a/net/bridge/br_vlan.c
+++ b/net/bridge/br_vlan.c
@@ -243,6 +243,10 @@ static int __vlan_add(struct net_bridge_vlan *v, u16 flags)
goto out_filt;
v->brvlan = masterv;
v->stats = masterv->stats;
+   } else {
+   err = br_switchdev_port_vlan_add(dev, v->vid, flags);
+   if (err && err != -EOPNOTSUPP)
+   goto out;
}
 
/* Add the dev mac and count the vlan only if it's usable */
@@ -278,6 +282,8 @@ static int __vlan_add(struct net_bridge_vlan *v, u16 flags)
br_vlan_put_master(masterv);
v->brvlan = NULL;
}
+   } else {
+   br_switchdev_port_vlan_del(dev, v->vid);
}
 
goto out;
@@ -303,6 +309,11 @@ static int __vlan_del(struct net_bridge_vlan *v)
err = __vlan_vid_del(p->dev, p->br, v->vid);
if (err)
goto out;
+   } else {
+   err = br_switchdev_port_vlan_del(v->br->dev, v->vid);
+   if (err && err != -EOPNOTSUPP)
+   goto out;
+   err = 0;
}
 
if (br_vlan_should_use(v)) {
@@ -580,6 +591,9 @@ int br_vlan_add(struct net_bridge *br, u16 vid, u16 flags, 
bool *changed)
vg->num_vlans++;
*changed = true;
}
+   ret = br_switchdev_port_vlan_add(br->dev, vid, flags);
+   if (ret && ret != -EOPNOTSUPP)
+   return ret;
if (__vlan_add_flags(vlan, flags))
*changed = true;
 
-- 
2.4.11

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH net-next v3 5/7] staging: fsl-dpaa2: ethsw: Ignore bridge VLAN events

2018-05-28 Thread Petr Machata
Ignore VLAN events where the orig_dev is the bridge device itself.

Signed-off-by: Petr Machata 
---
 drivers/staging/fsl-dpaa2/ethsw/ethsw.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c 
b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c
index c723a04..a17dd29 100644
--- a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c
+++ b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c
@@ -719,6 +719,9 @@ static int port_vlans_add(struct net_device *netdev,
struct ethsw_port_priv *port_priv = netdev_priv(netdev);
int vid, err;
 
+   if (netif_is_bridge_master(vlan->obj.orig_dev))
+   return -EOPNOTSUPP;
+
if (switchdev_trans_ph_prepare(trans))
return 0;
 
@@ -873,6 +876,9 @@ static int port_vlans_del(struct net_device *netdev,
struct ethsw_port_priv *port_priv = netdev_priv(netdev);
int vid, err;
 
+   if (netif_is_bridge_master(vlan->obj.orig_dev))
+   return -EOPNOTSUPP;
+
for (vid = vlan->vid_begin; vid <= vlan->vid_end; vid++) {
err = ethsw_port_del_vlan(port_priv, vid);
if (err)
-- 
2.4.11

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH net-next v3 3/7] rocker: rocker_main: Ignore bridge VLAN events

2018-05-28 Thread Petr Machata
Ignore VLAN events where the orig_dev is the bridge device itself.

Signed-off-by: Petr Machata 
---
 drivers/net/ethernet/rocker/rocker_main.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/drivers/net/ethernet/rocker/rocker_main.c 
b/drivers/net/ethernet/rocker/rocker_main.c
index e73e4fe..aeafdb9 100644
--- a/drivers/net/ethernet/rocker/rocker_main.c
+++ b/drivers/net/ethernet/rocker/rocker_main.c
@@ -1632,6 +1632,9 @@ rocker_world_port_obj_vlan_add(struct rocker_port 
*rocker_port,
 {
struct rocker_world_ops *wops = rocker_port->rocker->wops;
 
+   if (netif_is_bridge_master(vlan->obj.orig_dev))
+   return -EOPNOTSUPP;
+
if (!wops->port_obj_vlan_add)
return -EOPNOTSUPP;
 
@@ -1647,6 +1650,9 @@ rocker_world_port_obj_vlan_del(struct rocker_port 
*rocker_port,
 {
struct rocker_world_ops *wops = rocker_port->rocker->wops;
 
+   if (netif_is_bridge_master(vlan->obj.orig_dev))
+   return -EOPNOTSUPP;
+
if (!wops->port_obj_vlan_del)
return -EOPNOTSUPP;
return wops->port_obj_vlan_del(rocker_port, vlan);
-- 
2.4.11

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH net-next v3 4/7] dsa: port: Ignore bridge VLAN events

2018-05-28 Thread Petr Machata
Ignore VLAN events where the orig_dev is the bridge device itself.

Signed-off-by: Petr Machata 
Reviewed-by: Vivien Didelot 
---
 net/dsa/port.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/net/dsa/port.c b/net/dsa/port.c
index 2413beb..ed05954 100644
--- a/net/dsa/port.c
+++ b/net/dsa/port.c
@@ -252,6 +252,9 @@ int dsa_port_vlan_add(struct dsa_port *dp,
.vlan = vlan,
};
 
+   if (netif_is_bridge_master(vlan->obj.orig_dev))
+   return -EOPNOTSUPP;
+
if (br_vlan_enabled(dp->bridge_dev))
return dsa_port_notify(dp, DSA_NOTIFIER_VLAN_ADD, &info);
 
@@ -267,6 +270,9 @@ int dsa_port_vlan_del(struct dsa_port *dp,
.vlan = vlan,
};
 
+   if (netif_is_bridge_master(vlan->obj.orig_dev))
+   return -EOPNOTSUPP;
+
if (br_vlan_enabled(dp->bridge_dev))
return dsa_port_notify(dp, DSA_NOTIFIER_VLAN_DEL, &info);
 
-- 
2.4.11

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


Re: [PATCH net-next v3 6/7] net: bridge: Notify about bridge VLANs

2018-05-29 Thread Petr Machata
Dan Carpenter  writes:

> On Mon, May 28, 2018 at 05:11:04PM +0200, Petr Machata wrote:
>> @@ -580,6 +591,9 @@ int br_vlan_add(struct net_bridge *br, u16 vid, u16 
>> flags, bool *changed)
>>  vg->num_vlans++;
>>  *changed = true;
>>  }
>> +ret = br_switchdev_port_vlan_add(br->dev, vid, flags);
>> +if (ret && ret != -EOPNOTSUPP)
>> +return ret;
>
> We should probably do some error handling instead of returning directly?

I missed that, you are right. There's a bunch of mutations in the block
above.

Thanks,
Petr
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


Re: [PATCH net-next v2 3/7] rocker: rocker_main: Ignore bridge VLAN events

2018-05-29 Thread Petr Machata
Ilias Apalodimas  writes:

>> diff --git a/drivers/net/ethernet/rocker/rocker_main.c 
>> b/drivers/net/ethernet/rocker/rocker_main.c
>> index e73e4fe..aeafdb9 100644
>> --- a/drivers/net/ethernet/rocker/rocker_main.c
>> +++ b/drivers/net/ethernet/rocker/rocker_main.c
>> @@ -1632,6 +1632,9 @@ rocker_world_port_obj_vlan_add(struct rocker_port 
>> *rocker_port,
>>  {
>>  struct rocker_world_ops *wops = rocker_port->rocker->wops;
>>  
>> +if (netif_is_bridge_master(vlan->obj.orig_dev))
>> +return -EOPNOTSUPP;
>> +
> What will happen to the "bridge vlan add dev br0 vid X pvid untagged self" 
> when
> the lower level (the driver) returns -EOPNOTSUPP? Will it avoid adding a vlan 
> on
> the bridge ?

No, it will still do it. The reasons are:

- that's what currently happens anyway: none of the drivers has any
  support, yet the bridge logic is done

- -EOPNOTSUPP is what switchdev_port_obj_*() return if switchdev is not
  compiled in

In order to suppress the setting, return e.g. -EINVAL:

# bridge vlan add dev br vid 111 self
RTNETLINK answers: Invalid argument
# bridge vlan show dev br
portvlan ids
br   1 PVID Egress Untagged

Thanks,
Petr
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH net-next v4 0/8] net: bridge: Notify about bridge VLANs

2018-05-29 Thread Petr Machata
In commit 946a11e7408e ("mlxsw: spectrum_span: Allow bridge for gretap
mirror"), mlxsw got support for offloading mirror-to-gretap such that
the underlay packet path involves a bridge. In that case, the offload is
also influenced by PVID setting of said bridge. However, changes to VLAN
configuration of the bridge itself do not generate switchdev
notifications, so there's no mechanism to prod mlxsw to update the
offload when these settings change.

In this patchset, the problem is resolved by distributing the switchdev
notification SWITCHDEV_OBJ_ID_PORT_VLAN also for configuration changes
on bridge VLANs. Since stacked devices distribute the notification to
lower devices, such event eventually reaches the driver, which can
determine whether it's a bridge or port VLAN by inspecting orig_dev.

To keep things consistent, the newly-distributed notifications observe
the same protocol as the existing ones: dual prepare/commit, with
-EOPNOTSUPP indicating lack of support, even though there's currently
nothing to prepare for and nothing to support. Correspondingly, all
switchdev drivers have been updated to return -EOPNOTSUPP for bridge
VLAN notifications.

In patches #1 and #2, the code base is changed to support the following
additions: functions br_switchdev_port_vlan_add() and
br_switchdev_port_vlan_del() are introduced to simplify sending
notifications; and br_vlan_add_existing() is introduced to later make it
simpler to add error-handling code for the case of configuring a
preexisting VLAN on bridge CPU port.

In patches #3-#6, respectively for mlxsw, rocker, DSA and DPAA2 ethsw,
the new notifications (which are not enabled yet) are ignored to
maintain the current behavior.

In patch #7, the notification is actually enabled.

In patch #8, mlxsw is changed to update offloads of mirror-to-gre also
for bridge-related notifications.

Changes from v3 to v4:

- In patch #1, separate variable declarations from program logic.
- Add patch #2.
- In patch #7, add error handling around a newly-introduced call to
  br_switchdev_port_vlan_add().
- Rephrase commit messages of patches #3-#6 to explain motivation for
  the change.

Changes from v2 to v3:

- Add a fallback definition for br_switchdev_port_obj_add() and
  br_switchdev_port_obj_del() when !CONFIG_NET_SWITCHDEV.

Changes from v1 to v2:

- Rename br_switchdev_port_obj_add() and br_switchdev_port_obj_del() to
  br_switchdev_port_vlan_add() and br_switchdev_port_vlan_del(), and
  move from br_vlan.c to br_switchdev.c.

Petr Machata (8):
  net: bridge: Extract boilerplate around switchdev_port_obj_*()
  net: bridge: Extract br_vlan_add_existing()
  mlxsw: spectrum_switchdev: Ignore bridge VLAN events
  rocker: rocker_main: Ignore bridge VLAN events
  dsa: port: Ignore bridge VLAN events
  staging: fsl-dpaa2: ethsw: Ignore bridge VLAN events
  net: bridge: Notify about bridge VLANs
  mlxsw: spectrum_switchdev: Schedule respin during trans prepare

 .../ethernet/mellanox/mlxsw/spectrum_switchdev.c   |   8 +-
 drivers/net/ethernet/rocker/rocker_main.c  |   6 ++
 drivers/staging/fsl-dpaa2/ethsw/ethsw.c|   6 ++
 net/bridge/br_private.h|  13 +++
 net/bridge/br_switchdev.c  |  25 +
 net/bridge/br_vlan.c   | 103 -
 net/dsa/port.c |   6 ++
 7 files changed, 121 insertions(+), 46 deletions(-)

-- 
2.4.11

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH net-next v4 1/8] net: bridge: Extract boilerplate around switchdev_port_obj_*()

2018-05-29 Thread Petr Machata
A call to switchdev_port_obj_add() or switchdev_port_obj_del() involves
initializing a struct switchdev_obj_port_vlan, a piece of code that
repeats on each call site almost verbatim. While in the current codebase
there is just one duplicated add call, the follow-up patches add more of
both add and del calls.

Thus to remove the duplication, extract the repetition into named
functions and reuse.

Signed-off-by: Petr Machata 
Reviewed-by: Vivien Didelot 
---
 net/bridge/br_private.h   | 13 +
 net/bridge/br_switchdev.c | 25 +
 net/bridge/br_vlan.c  | 26 +++---
 3 files changed, 41 insertions(+), 23 deletions(-)

diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index 11520ed..5216a52 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -1139,6 +1139,8 @@ int br_switchdev_set_port_flag(struct net_bridge_port *p,
   unsigned long mask);
 void br_switchdev_fdb_notify(const struct net_bridge_fdb_entry *fdb,
 int type);
+int br_switchdev_port_vlan_add(struct net_device *dev, u16 vid, u16 flags);
+int br_switchdev_port_vlan_del(struct net_device *dev, u16 vid);
 
 static inline void br_switchdev_frame_unmark(struct sk_buff *skb)
 {
@@ -1168,6 +1170,17 @@ static inline int br_switchdev_set_port_flag(struct 
net_bridge_port *p,
return 0;
 }
 
+static inline int br_switchdev_port_vlan_add(struct net_device *dev,
+u16 vid, u16 flags)
+{
+   return -EOPNOTSUPP;
+}
+
+static inline int br_switchdev_port_vlan_del(struct net_device *dev, u16 vid)
+{
+   return -EOPNOTSUPP;
+}
+
 static inline void
 br_switchdev_fdb_notify(const struct net_bridge_fdb_entry *fdb, int type)
 {
diff --git a/net/bridge/br_switchdev.c b/net/bridge/br_switchdev.c
index 35474d4..d77f807 100644
--- a/net/bridge/br_switchdev.c
+++ b/net/bridge/br_switchdev.c
@@ -136,3 +136,28 @@ br_switchdev_fdb_notify(const struct net_bridge_fdb_entry 
*fdb, int type)
break;
}
 }
+
+int br_switchdev_port_vlan_add(struct net_device *dev, u16 vid, u16 flags)
+{
+   struct switchdev_obj_port_vlan v = {
+   .obj.orig_dev = dev,
+   .obj.id = SWITCHDEV_OBJ_ID_PORT_VLAN,
+   .flags = flags,
+   .vid_begin = vid,
+   .vid_end = vid,
+   };
+
+   return switchdev_port_obj_add(dev, &v.obj);
+}
+
+int br_switchdev_port_vlan_del(struct net_device *dev, u16 vid)
+{
+   struct switchdev_obj_port_vlan v = {
+   .obj.orig_dev = dev,
+   .obj.id = SWITCHDEV_OBJ_ID_PORT_VLAN,
+   .vid_begin = vid,
+   .vid_end = vid,
+   };
+
+   return switchdev_port_obj_del(dev, &v.obj);
+}
diff --git a/net/bridge/br_vlan.c b/net/bridge/br_vlan.c
index dc832c09..e3b14c0 100644
--- a/net/bridge/br_vlan.c
+++ b/net/bridge/br_vlan.c
@@ -82,19 +82,12 @@ static bool __vlan_add_flags(struct net_bridge_vlan *v, u16 
flags)
 static int __vlan_vid_add(struct net_device *dev, struct net_bridge *br,
  u16 vid, u16 flags)
 {
-   struct switchdev_obj_port_vlan v = {
-   .obj.orig_dev = dev,
-   .obj.id = SWITCHDEV_OBJ_ID_PORT_VLAN,
-   .flags = flags,
-   .vid_begin = vid,
-   .vid_end = vid,
-   };
int err;
 
/* Try switchdev op first. In case it is not supported, fallback to
 * 8021q add.
 */
-   err = switchdev_port_obj_add(dev, &v.obj);
+   err = br_switchdev_port_vlan_add(dev, vid, flags);
if (err == -EOPNOTSUPP)
return vlan_vid_add(dev, br->vlan_proto, vid);
return err;
@@ -130,18 +123,12 @@ static void __vlan_del_list(struct net_bridge_vlan *v)
 static int __vlan_vid_del(struct net_device *dev, struct net_bridge *br,
  u16 vid)
 {
-   struct switchdev_obj_port_vlan v = {
-   .obj.orig_dev = dev,
-   .obj.id = SWITCHDEV_OBJ_ID_PORT_VLAN,
-   .vid_begin = vid,
-   .vid_end = vid,
-   };
int err;
 
/* Try switchdev op first. In case it is not supported, fallback to
 * 8021q del.
 */
-   err = switchdev_port_obj_del(dev, &v.obj);
+   err = br_switchdev_port_vlan_del(dev, vid);
if (err == -EOPNOTSUPP) {
vlan_vid_del(dev, br->vlan_proto, vid);
return 0;
@@ -1053,13 +1040,6 @@ int nbp_vlan_init(struct net_bridge_port *p)
 int nbp_vlan_add(struct net_bridge_port *port, u16 vid, u16 flags,
 bool *changed)
 {
-   struct switchdev_obj_port_vlan v = {
-   .obj.orig_dev = port->dev,
-   .obj.id = SWITCHDEV_OBJ_ID_PORT_VLAN,
-   .flags = flags,
-   .vid_begin = vid,
-   .vid_end = vid,
-   };
struct net_bridge_vlan *vlan;

[PATCH net-next v4 2/8] net: bridge: Extract br_vlan_add_existing()

2018-05-29 Thread Petr Machata
Extract the code that deals with adding a preexisting VLAN to bridge CPU
port to a separate function. A follow-up patch introduces a need to roll
back operations in this block due to an error, and this split will make
the error-handling code clearer.

Signed-off-by: Petr Machata 
---
 net/bridge/br_vlan.c | 55 +++-
 1 file changed, 33 insertions(+), 22 deletions(-)

diff --git a/net/bridge/br_vlan.c b/net/bridge/br_vlan.c
index e3b14c0..602c869 100644
--- a/net/bridge/br_vlan.c
+++ b/net/bridge/br_vlan.c
@@ -551,6 +551,37 @@ bool br_should_learn(struct net_bridge_port *p, struct 
sk_buff *skb, u16 *vid)
return false;
 }
 
+static int br_vlan_add_existing(struct net_bridge *br,
+   struct net_bridge_vlan_group *vg,
+   struct net_bridge_vlan *vlan,
+   u16 flags, bool *changed)
+{
+   int err;
+
+   if (!br_vlan_is_brentry(vlan)) {
+   /* Trying to change flags of non-existent bridge vlan */
+   if (!(flags & BRIDGE_VLAN_INFO_BRENTRY))
+   return -EINVAL;
+   /* It was only kept for port vlans, now make it real */
+   err = br_fdb_insert(br, NULL, br->dev->dev_addr,
+   vlan->vid);
+   if (err) {
+   br_err(br, "failed to insert local address into bridge 
forwarding table\n");
+   return err;
+   }
+
+   refcount_inc(&vlan->refcnt);
+   vlan->flags |= BRIDGE_VLAN_INFO_BRENTRY;
+   vg->num_vlans++;
+   *changed = true;
+   }
+
+   if (__vlan_add_flags(vlan, flags))
+   *changed = true;
+
+   return 0;
+}
+
 /* Must be protected by RTNL.
  * Must be called with vid in range from 1 to 4094 inclusive.
  * changed must be true only if the vlan was created or updated
@@ -566,28 +597,8 @@ int br_vlan_add(struct net_bridge *br, u16 vid, u16 flags, 
bool *changed)
*changed = false;
vg = br_vlan_group(br);
vlan = br_vlan_find(vg, vid);
-   if (vlan) {
-   if (!br_vlan_is_brentry(vlan)) {
-   /* Trying to change flags of non-existent bridge vlan */
-   if (!(flags & BRIDGE_VLAN_INFO_BRENTRY))
-   return -EINVAL;
-   /* It was only kept for port vlans, now make it real */
-   ret = br_fdb_insert(br, NULL, br->dev->dev_addr,
-   vlan->vid);
-   if (ret) {
-   br_err(br, "failed insert local address into 
bridge forwarding table\n");
-   return ret;
-   }
-   refcount_inc(&vlan->refcnt);
-   vlan->flags |= BRIDGE_VLAN_INFO_BRENTRY;
-   vg->num_vlans++;
-   *changed = true;
-   }
-   if (__vlan_add_flags(vlan, flags))
-   *changed = true;
-
-   return 0;
-   }
+   if (vlan)
+   return br_vlan_add_existing(br, vg, vlan, flags, changed);
 
vlan = kzalloc(sizeof(*vlan), GFP_KERNEL);
if (!vlan)
-- 
2.4.11

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH net-next v4 3/8] mlxsw: spectrum_switchdev: Ignore bridge VLAN events

2018-05-29 Thread Petr Machata
A follow-up patch enables emitting VLAN notifications for the bridge CPU
port in addition to the existing slave port notifications. These
notifications have orig_dev set to the bridge in question.

Because there's no specific support for these VLANs, just ignore the
notifications to maintain the current behavior.

Signed-off-by: Petr Machata 
Reviewed-by: Ido Schimmel 
---
 drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c 
b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
index 8c9cf8e..cbc8fab 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
@@ -1144,6 +1144,9 @@ static int mlxsw_sp_port_vlans_add(struct mlxsw_sp_port 
*mlxsw_sp_port,
struct mlxsw_sp_bridge_port *bridge_port;
u16 vid;
 
+   if (netif_is_bridge_master(orig_dev))
+   return -EOPNOTSUPP;
+
if (switchdev_trans_ph_prepare(trans))
return 0;
 
@@ -1741,6 +1744,9 @@ static int mlxsw_sp_port_vlans_del(struct mlxsw_sp_port 
*mlxsw_sp_port,
struct mlxsw_sp_bridge_port *bridge_port;
u16 vid;
 
+   if (netif_is_bridge_master(orig_dev))
+   return -EOPNOTSUPP;
+
bridge_port = mlxsw_sp_bridge_port_find(mlxsw_sp->bridge, orig_dev);
if (WARN_ON(!bridge_port))
return -EINVAL;
-- 
2.4.11

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH net-next v4 4/8] rocker: rocker_main: Ignore bridge VLAN events

2018-05-29 Thread Petr Machata
A follow-up patch enables emitting VLAN notifications for the bridge CPU
port in addition to the existing slave port notifications. These
notifications have orig_dev set to the bridge in question.

Because there's no specific support for these VLANs, just ignore the
notifications to maintain the current behavior.

Signed-off-by: Petr Machata 
---
 drivers/net/ethernet/rocker/rocker_main.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/drivers/net/ethernet/rocker/rocker_main.c 
b/drivers/net/ethernet/rocker/rocker_main.c
index e73e4fe..aeafdb9 100644
--- a/drivers/net/ethernet/rocker/rocker_main.c
+++ b/drivers/net/ethernet/rocker/rocker_main.c
@@ -1632,6 +1632,9 @@ rocker_world_port_obj_vlan_add(struct rocker_port 
*rocker_port,
 {
struct rocker_world_ops *wops = rocker_port->rocker->wops;
 
+   if (netif_is_bridge_master(vlan->obj.orig_dev))
+   return -EOPNOTSUPP;
+
if (!wops->port_obj_vlan_add)
return -EOPNOTSUPP;
 
@@ -1647,6 +1650,9 @@ rocker_world_port_obj_vlan_del(struct rocker_port 
*rocker_port,
 {
struct rocker_world_ops *wops = rocker_port->rocker->wops;
 
+   if (netif_is_bridge_master(vlan->obj.orig_dev))
+   return -EOPNOTSUPP;
+
if (!wops->port_obj_vlan_del)
return -EOPNOTSUPP;
return wops->port_obj_vlan_del(rocker_port, vlan);
-- 
2.4.11

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH net-next v4 5/8] dsa: port: Ignore bridge VLAN events

2018-05-29 Thread Petr Machata
A follow-up patch enables emitting VLAN notifications for the bridge CPU
port in addition to the existing slave port notifications. These
notifications have orig_dev set to the bridge in question.

Because there's no specific support for these VLANs, just ignore the
notifications to maintain the current behavior.

Signed-off-by: Petr Machata 
Reviewed-by: Vivien Didelot 
---
 net/dsa/port.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/net/dsa/port.c b/net/dsa/port.c
index 2413beb..ed05954 100644
--- a/net/dsa/port.c
+++ b/net/dsa/port.c
@@ -252,6 +252,9 @@ int dsa_port_vlan_add(struct dsa_port *dp,
.vlan = vlan,
};
 
+   if (netif_is_bridge_master(vlan->obj.orig_dev))
+   return -EOPNOTSUPP;
+
if (br_vlan_enabled(dp->bridge_dev))
return dsa_port_notify(dp, DSA_NOTIFIER_VLAN_ADD, &info);
 
@@ -267,6 +270,9 @@ int dsa_port_vlan_del(struct dsa_port *dp,
.vlan = vlan,
};
 
+   if (netif_is_bridge_master(vlan->obj.orig_dev))
+   return -EOPNOTSUPP;
+
if (br_vlan_enabled(dp->bridge_dev))
return dsa_port_notify(dp, DSA_NOTIFIER_VLAN_DEL, &info);
 
-- 
2.4.11

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH net-next v4 7/8] net: bridge: Notify about bridge VLANs

2018-05-29 Thread Petr Machata
A driver might need to react to changes in settings of brentry VLANs.
Therefore send switchdev port notifications for these as well. Reuse
SWITCHDEV_OBJ_ID_PORT_VLAN for this purpose. Listeners should use
netif_is_bridge_master() on orig_dev to determine whether the
notification is about a bridge port or a bridge.

Signed-off-by: Petr Machata 
---
 net/bridge/br_vlan.c | 28 +---
 1 file changed, 25 insertions(+), 3 deletions(-)

diff --git a/net/bridge/br_vlan.c b/net/bridge/br_vlan.c
index 602c869..7df2690 100644
--- a/net/bridge/br_vlan.c
+++ b/net/bridge/br_vlan.c
@@ -246,6 +246,10 @@ static int __vlan_add(struct net_bridge_vlan *v, u16 flags)
goto out_filt;
v->brvlan = masterv;
v->stats = masterv->stats;
+   } else {
+   err = br_switchdev_port_vlan_add(dev, v->vid, flags);
+   if (err && err != -EOPNOTSUPP)
+   goto out;
}
 
/* Add the dev mac and count the vlan only if it's usable */
@@ -281,6 +285,8 @@ static int __vlan_add(struct net_bridge_vlan *v, u16 flags)
br_vlan_put_master(masterv);
v->brvlan = NULL;
}
+   } else {
+   br_switchdev_port_vlan_del(dev, v->vid);
}
 
goto out;
@@ -306,6 +312,11 @@ static int __vlan_del(struct net_bridge_vlan *v)
err = __vlan_vid_del(p->dev, p->br, v->vid);
if (err)
goto out;
+   } else {
+   err = br_switchdev_port_vlan_del(v->br->dev, v->vid);
+   if (err && err != -EOPNOTSUPP)
+   goto out;
+   err = 0;
}
 
if (br_vlan_should_use(v)) {
@@ -558,16 +569,22 @@ static int br_vlan_add_existing(struct net_bridge *br,
 {
int err;
 
+   err = br_switchdev_port_vlan_add(br->dev, vlan->vid, flags);
+   if (err && err != -EOPNOTSUPP)
+   return err;
+
if (!br_vlan_is_brentry(vlan)) {
/* Trying to change flags of non-existent bridge vlan */
-   if (!(flags & BRIDGE_VLAN_INFO_BRENTRY))
-   return -EINVAL;
+   if (!(flags & BRIDGE_VLAN_INFO_BRENTRY)) {
+   err = -EINVAL;
+   goto err_flags;
+   }
/* It was only kept for port vlans, now make it real */
err = br_fdb_insert(br, NULL, br->dev->dev_addr,
vlan->vid);
if (err) {
br_err(br, "failed to insert local address into bridge 
forwarding table\n");
-   return err;
+   goto err_fdb_insert;
}
 
refcount_inc(&vlan->refcnt);
@@ -580,6 +597,11 @@ static int br_vlan_add_existing(struct net_bridge *br,
*changed = true;
 
return 0;
+
+err_fdb_insert:
+err_flags:
+   br_switchdev_port_vlan_del(br->dev, vlan->vid);
+   return err;
 }
 
 /* Must be protected by RTNL.
-- 
2.4.11

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH net-next v4 6/8] staging: fsl-dpaa2: ethsw: Ignore bridge VLAN events

2018-05-29 Thread Petr Machata
A follow-up patch enables emitting VLAN notifications for the bridge CPU
port in addition to the existing slave port notifications. These
notifications have orig_dev set to the bridge in question.

Because there's no specific support for these VLANs, just ignore the
notifications to maintain the current behavior.

Signed-off-by: Petr Machata 
---
 drivers/staging/fsl-dpaa2/ethsw/ethsw.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c 
b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c
index c723a04..a17dd29 100644
--- a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c
+++ b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c
@@ -719,6 +719,9 @@ static int port_vlans_add(struct net_device *netdev,
struct ethsw_port_priv *port_priv = netdev_priv(netdev);
int vid, err;
 
+   if (netif_is_bridge_master(vlan->obj.orig_dev))
+   return -EOPNOTSUPP;
+
if (switchdev_trans_ph_prepare(trans))
return 0;
 
@@ -873,6 +876,9 @@ static int port_vlans_del(struct net_device *netdev,
struct ethsw_port_priv *port_priv = netdev_priv(netdev);
int vid, err;
 
+   if (netif_is_bridge_master(vlan->obj.orig_dev))
+   return -EOPNOTSUPP;
+
for (vid = vlan->vid_begin; vid <= vlan->vid_end; vid++) {
err = ethsw_port_del_vlan(port_priv, vid);
if (err)
-- 
2.4.11

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH net-next v4 8/8] mlxsw: spectrum_switchdev: Schedule respin during trans prepare

2018-05-29 Thread Petr Machata
Since there's no special support for the bridge events, the driver
returns -EOPNOTSUPP, and thus the commit never happens. Therefore
schedule respin during the prepare stage: there's no real difference one
way or another.

This fixes the problem that mirror-to-gretap offload wouldn't adapt to
changes in bridge vlan configuration right away and another notification
would have to arrive for mlxsw to catch up.

Signed-off-by: Petr Machata 
Reviewed-by: Ido Schimmel 
---
 drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c 
b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
index cbc8fab..8a15ac4 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
@@ -1697,7 +1697,7 @@ static int mlxsw_sp_port_obj_add(struct net_device *dev,
vlan = SWITCHDEV_OBJ_PORT_VLAN(obj);
err = mlxsw_sp_port_vlans_add(mlxsw_sp_port, vlan, trans);
 
-   if (switchdev_trans_ph_commit(trans)) {
+   if (switchdev_trans_ph_prepare(trans)) {
/* The event is emitted before the changes are actually
 * applied to the bridge. Therefore schedule the respin
 * call for later, so that the respin logic sees the
-- 
2.4.11

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel