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 {
struct dsa_switch *ds;
unsigned int index;
const char *name;
const struct dsa_port *cpu_dp;
struct dsa_port *cpu_dp;
const char *mac;
struct device_node *dn;
unsigned int ageing_time;
......
......@@ -336,9 +336,6 @@ int dsa_port_vlan_add(struct dsa_port *dp,
.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))
return dsa_port_notify(dp, DSA_NOTIFIER_VLAN_ADD, &info);
......@@ -354,12 +351,6 @@ int dsa_port_vlan_del(struct dsa_port *dp,
.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))
return dsa_port_notify(dp, DSA_NOTIFIER_VLAN_DEL, &info);
......
......@@ -22,7 +22,7 @@
#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 ***************************************************/
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,
static int dsa_slave_port_obj_add(struct net_device *dev,
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);
int err;
......@@ -323,6 +324,8 @@ static int dsa_slave_port_obj_add(struct net_device *dev,
switch (obj->id) {
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);
break;
case SWITCHDEV_OBJ_ID_HOST_MDB:
......@@ -333,6 +336,8 @@ static int dsa_slave_port_obj_add(struct net_device *dev,
trans);
break;
case SWITCHDEV_OBJ_ID_PORT_VLAN:
if (obj->orig_dev != dev)
return -EOPNOTSUPP;
err = dsa_port_vlan_add(dp, SWITCHDEV_OBJ_PORT_VLAN(obj),
trans);
break;
......@@ -352,6 +357,8 @@ static int dsa_slave_port_obj_del(struct net_device *dev,
switch (obj->id) {
case SWITCHDEV_OBJ_ID_PORT_MDB:
if (obj->orig_dev != dev)
return -EOPNOTSUPP;
err = dsa_port_mdb_del(dp, SWITCHDEV_OBJ_PORT_MDB(obj));
break;
case SWITCHDEV_OBJ_ID_HOST_MDB:
......@@ -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));
break;
case SWITCHDEV_OBJ_ID_PORT_VLAN:
if (obj->orig_dev != dev)
return -EOPNOTSUPP;
err = dsa_port_vlan_del(dp, SWITCHDEV_OBJ_PORT_VLAN(obj));
break;
default:
......@@ -1408,7 +1417,7 @@ void dsa_slave_destroy(struct net_device *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;
}
......@@ -1479,19 +1488,6 @@ static int dsa_slave_netdevice_event(struct notifier_block *nb,
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 work_struct work;
struct switchdev_notifier_fdb_info fdb_info;
......@@ -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 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))
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);
if (!switchdev_work)
return NOTIFY_BAD;
......@@ -1602,41 +1603,28 @@ 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;
int err;
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:
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:
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;
......
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