Commit 877cd9ff authored by David S. Miller's avatar David S. Miller

Merge branch 'net-dsa-use-switchdev-attr-and-obj-handlers'

Vivien Didelot says:

====================
net: dsa: use switchdev attr and obj handlers

This series reduces boilerplate in the handling of switchdev attribute and
object operations by using the switchdev_handle_* helpers, which check the
targeted devices and recurse into their lower devices.

This also brings back the ability to inspect operations targeting the bridge
device itself (where .orig_dev and .dev were originally the bridge device),
even though that is of no use yet and skipped by this series.

Changes in v2: Only VLAN and (non-host) MDB objects not directly targeting
the slave device are unsupported at the moment, so only skip these cases.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 5a1c492b 79b139f4
...@@ -181,7 +181,7 @@ struct dsa_port { ...@@ -181,7 +181,7 @@ struct dsa_port {
struct dsa_switch *ds; struct dsa_switch *ds;
unsigned int index; unsigned int index;
const char *name; const char *name;
const struct dsa_port *cpu_dp; struct dsa_port *cpu_dp;
const char *mac; const char *mac;
struct device_node *dn; struct device_node *dn;
unsigned int ageing_time; unsigned int ageing_time;
......
...@@ -336,9 +336,6 @@ int dsa_port_vlan_add(struct dsa_port *dp, ...@@ -336,9 +336,6 @@ int dsa_port_vlan_add(struct dsa_port *dp,
.vlan = vlan, .vlan = vlan,
}; };
/* Can be called from dsa_slave_port_obj_add() or
* dsa_slave_vlan_rx_add_vid()
*/
if (!dp->bridge_dev || br_vlan_enabled(dp->bridge_dev)) if (!dp->bridge_dev || br_vlan_enabled(dp->bridge_dev))
return dsa_port_notify(dp, DSA_NOTIFIER_VLAN_ADD, &info); return dsa_port_notify(dp, DSA_NOTIFIER_VLAN_ADD, &info);
...@@ -354,12 +351,6 @@ int dsa_port_vlan_del(struct dsa_port *dp, ...@@ -354,12 +351,6 @@ int dsa_port_vlan_del(struct dsa_port *dp,
.vlan = vlan, .vlan = vlan,
}; };
if (vlan->obj.orig_dev && netif_is_bridge_master(vlan->obj.orig_dev))
return -EOPNOTSUPP;
/* Can be called from dsa_slave_port_obj_del() or
* dsa_slave_vlan_rx_kill_vid()
*/
if (!dp->bridge_dev || br_vlan_enabled(dp->bridge_dev)) if (!dp->bridge_dev || br_vlan_enabled(dp->bridge_dev))
return dsa_port_notify(dp, DSA_NOTIFIER_VLAN_DEL, &info); return dsa_port_notify(dp, DSA_NOTIFIER_VLAN_DEL, &info);
......
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
#include "dsa_priv.h" #include "dsa_priv.h"
static bool dsa_slave_dev_check(struct net_device *dev); static bool dsa_slave_dev_check(const struct net_device *dev);
/* slave mii_bus handling ***************************************************/ /* slave mii_bus handling ***************************************************/
static int dsa_slave_phy_read(struct mii_bus *bus, int addr, int reg) static int dsa_slave_phy_read(struct mii_bus *bus, int addr, int reg)
...@@ -311,7 +311,8 @@ static int dsa_slave_port_attr_set(struct net_device *dev, ...@@ -311,7 +311,8 @@ static int dsa_slave_port_attr_set(struct net_device *dev,
static int dsa_slave_port_obj_add(struct net_device *dev, static int dsa_slave_port_obj_add(struct net_device *dev,
const struct switchdev_obj *obj, const struct switchdev_obj *obj,
struct switchdev_trans *trans) struct switchdev_trans *trans,
struct netlink_ext_ack *extack)
{ {
struct dsa_port *dp = dsa_slave_to_port(dev); struct dsa_port *dp = dsa_slave_to_port(dev);
int err; int err;
...@@ -323,6 +324,8 @@ static int dsa_slave_port_obj_add(struct net_device *dev, ...@@ -323,6 +324,8 @@ static int dsa_slave_port_obj_add(struct net_device *dev,
switch (obj->id) { switch (obj->id) {
case SWITCHDEV_OBJ_ID_PORT_MDB: case SWITCHDEV_OBJ_ID_PORT_MDB:
if (obj->orig_dev != dev)
return -EOPNOTSUPP;
err = dsa_port_mdb_add(dp, SWITCHDEV_OBJ_PORT_MDB(obj), trans); err = dsa_port_mdb_add(dp, SWITCHDEV_OBJ_PORT_MDB(obj), trans);
break; break;
case SWITCHDEV_OBJ_ID_HOST_MDB: case SWITCHDEV_OBJ_ID_HOST_MDB:
...@@ -333,6 +336,8 @@ static int dsa_slave_port_obj_add(struct net_device *dev, ...@@ -333,6 +336,8 @@ static int dsa_slave_port_obj_add(struct net_device *dev,
trans); trans);
break; break;
case SWITCHDEV_OBJ_ID_PORT_VLAN: case SWITCHDEV_OBJ_ID_PORT_VLAN:
if (obj->orig_dev != dev)
return -EOPNOTSUPP;
err = dsa_port_vlan_add(dp, SWITCHDEV_OBJ_PORT_VLAN(obj), err = dsa_port_vlan_add(dp, SWITCHDEV_OBJ_PORT_VLAN(obj),
trans); trans);
break; break;
...@@ -352,6 +357,8 @@ static int dsa_slave_port_obj_del(struct net_device *dev, ...@@ -352,6 +357,8 @@ static int dsa_slave_port_obj_del(struct net_device *dev,
switch (obj->id) { switch (obj->id) {
case SWITCHDEV_OBJ_ID_PORT_MDB: case SWITCHDEV_OBJ_ID_PORT_MDB:
if (obj->orig_dev != dev)
return -EOPNOTSUPP;
err = dsa_port_mdb_del(dp, SWITCHDEV_OBJ_PORT_MDB(obj)); err = dsa_port_mdb_del(dp, SWITCHDEV_OBJ_PORT_MDB(obj));
break; break;
case SWITCHDEV_OBJ_ID_HOST_MDB: case SWITCHDEV_OBJ_ID_HOST_MDB:
...@@ -361,6 +368,8 @@ static int dsa_slave_port_obj_del(struct net_device *dev, ...@@ -361,6 +368,8 @@ static int dsa_slave_port_obj_del(struct net_device *dev,
err = dsa_port_mdb_del(dp->cpu_dp, SWITCHDEV_OBJ_PORT_MDB(obj)); err = dsa_port_mdb_del(dp->cpu_dp, SWITCHDEV_OBJ_PORT_MDB(obj));
break; break;
case SWITCHDEV_OBJ_ID_PORT_VLAN: case SWITCHDEV_OBJ_ID_PORT_VLAN:
if (obj->orig_dev != dev)
return -EOPNOTSUPP;
err = dsa_port_vlan_del(dp, SWITCHDEV_OBJ_PORT_VLAN(obj)); err = dsa_port_vlan_del(dp, SWITCHDEV_OBJ_PORT_VLAN(obj));
break; break;
default: default:
...@@ -1408,7 +1417,7 @@ void dsa_slave_destroy(struct net_device *slave_dev) ...@@ -1408,7 +1417,7 @@ void dsa_slave_destroy(struct net_device *slave_dev)
free_netdev(slave_dev); free_netdev(slave_dev);
} }
static bool dsa_slave_dev_check(struct net_device *dev) static bool dsa_slave_dev_check(const struct net_device *dev)
{ {
return dev->netdev_ops == &dsa_slave_netdev_ops; return dev->netdev_ops == &dsa_slave_netdev_ops;
} }
...@@ -1479,19 +1488,6 @@ static int dsa_slave_netdevice_event(struct notifier_block *nb, ...@@ -1479,19 +1488,6 @@ static int dsa_slave_netdevice_event(struct notifier_block *nb,
return NOTIFY_DONE; return NOTIFY_DONE;
} }
static int
dsa_slave_switchdev_port_attr_set_event(struct net_device *netdev,
struct switchdev_notifier_port_attr_info *port_attr_info)
{
int err;
err = dsa_slave_port_attr_set(netdev, port_attr_info->attr,
port_attr_info->trans);
port_attr_info->handled = true;
return notifier_from_errno(err);
}
struct dsa_switchdev_event_work { struct dsa_switchdev_event_work {
struct work_struct work; struct work_struct work;
struct switchdev_notifier_fdb_info fdb_info; struct switchdev_notifier_fdb_info fdb_info;
...@@ -1566,13 +1562,18 @@ static int dsa_slave_switchdev_event(struct notifier_block *unused, ...@@ -1566,13 +1562,18 @@ static int dsa_slave_switchdev_event(struct notifier_block *unused,
{ {
struct net_device *dev = switchdev_notifier_info_to_dev(ptr); struct net_device *dev = switchdev_notifier_info_to_dev(ptr);
struct dsa_switchdev_event_work *switchdev_work; struct dsa_switchdev_event_work *switchdev_work;
int err;
if (event == SWITCHDEV_PORT_ATTR_SET) {
err = switchdev_handle_port_attr_set(dev, ptr,
dsa_slave_dev_check,
dsa_slave_port_attr_set);
return notifier_from_errno(err);
}
if (!dsa_slave_dev_check(dev)) if (!dsa_slave_dev_check(dev))
return NOTIFY_DONE; return NOTIFY_DONE;
if (event == SWITCHDEV_PORT_ATTR_SET)
return dsa_slave_switchdev_port_attr_set_event(dev, ptr);
switchdev_work = kzalloc(sizeof(*switchdev_work), GFP_ATOMIC); switchdev_work = kzalloc(sizeof(*switchdev_work), GFP_ATOMIC);
if (!switchdev_work) if (!switchdev_work)
return NOTIFY_BAD; return NOTIFY_BAD;
...@@ -1602,41 +1603,28 @@ static int dsa_slave_switchdev_event(struct notifier_block *unused, ...@@ -1602,41 +1603,28 @@ static int dsa_slave_switchdev_event(struct notifier_block *unused,
return NOTIFY_BAD; 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, static int dsa_slave_switchdev_blocking_event(struct notifier_block *unused,
unsigned long event, void *ptr) unsigned long event, void *ptr)
{ {
struct net_device *dev = switchdev_notifier_info_to_dev(ptr); struct net_device *dev = switchdev_notifier_info_to_dev(ptr);
int err;
if (!dsa_slave_dev_check(dev))
return NOTIFY_DONE;
switch (event) { switch (event) {
case SWITCHDEV_PORT_OBJ_ADD: /* fall through */ case SWITCHDEV_PORT_OBJ_ADD:
err = switchdev_handle_port_obj_add(dev, ptr,
dsa_slave_dev_check,
dsa_slave_port_obj_add);
return notifier_from_errno(err);
case SWITCHDEV_PORT_OBJ_DEL: case SWITCHDEV_PORT_OBJ_DEL:
return dsa_slave_switchdev_port_obj_event(event, dev, ptr); err = switchdev_handle_port_obj_del(dev, ptr,
dsa_slave_dev_check,
dsa_slave_port_obj_del);
return notifier_from_errno(err);
case SWITCHDEV_PORT_ATTR_SET: case SWITCHDEV_PORT_ATTR_SET:
return dsa_slave_switchdev_port_attr_set_event(dev, ptr); err = switchdev_handle_port_attr_set(dev, ptr,
dsa_slave_dev_check,
dsa_slave_port_attr_set);
return notifier_from_errno(err);
} }
return NOTIFY_DONE; return NOTIFY_DONE;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment