From 1321ed5e76488cfd7a5d3ee83254be9b7c1cc581 Mon Sep 17 00:00:00 2001 From: Dmytro Linkin Date: Wed, 23 Jun 2021 16:43:13 +0300 Subject: [PATCH 1/3] devlink: Decrease refcnt of parent rate object on leaf destroy Port functions, like SFs, can be deleted by the user when its leaf rate object has parent node. In such case node refcnt won't be decreased which blocks the node from deletion later. Do simple refcnt decrease, since driver in cleanup stage. This: 1) assumes that driver took proper internal parent unset action; 2) allows to avoid nested callbacks call and deadlock. Fixes: d75559845078 ("devlink: Allow setting parent node of rate objects") Signed-off-by: Dmytro Linkin Reviewed-by: Jiri Pirko Signed-off-by: David S. Miller --- net/core/devlink.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/core/devlink.c b/net/core/devlink.c index 566ddd147633..ba27395d8fb3 100644 --- a/net/core/devlink.c +++ b/net/core/devlink.c @@ -9275,6 +9275,8 @@ void devlink_rate_leaf_destroy(struct devlink_port *devlink_port) mutex_lock(&devlink->lock); devlink_rate_notify(devlink_rate, DEVLINK_CMD_RATE_DEL); + if (devlink_rate->parent) + refcount_dec(&devlink_rate->parent->refcnt); list_del(&devlink_rate->list); devlink_port->devlink_rate = NULL; mutex_unlock(&devlink->lock); From ff99324ded0176d28c3d8de7cac44580cf79d52a Mon Sep 17 00:00:00 2001 From: Dmytro Linkin Date: Wed, 23 Jun 2021 16:43:14 +0300 Subject: [PATCH 2/3] devlink: Remove eswitch mode check for mode set call When eswitch is disabled, querying its current mode results in error. Due to this when trying to set the eswitch mode for mlx5 devices, it fails to set the eswitch switchdev mode. Hence remove such check. Fixes: a8ecb93ef03d ("devlink: Introduce rate nodes") Signed-off-by: Dmytro Linkin Reviewed-by: Parav Pandit Reviewed-by: Jiri Pirko Signed-off-by: David S. Miller --- net/core/devlink.c | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/net/core/devlink.c b/net/core/devlink.c index ba27395d8fb3..153d432f6daf 100644 --- a/net/core/devlink.c +++ b/net/core/devlink.c @@ -2709,17 +2709,6 @@ static int devlink_rate_nodes_check(struct devlink *devlink, u16 mode, struct netlink_ext_ack *extack) { struct devlink_rate *devlink_rate; - u16 old_mode; - int err; - - if (!devlink->ops->eswitch_mode_get) - return -EOPNOTSUPP; - err = devlink->ops->eswitch_mode_get(devlink, &old_mode); - if (err) - return err; - - if (old_mode == mode) - return 0; list_for_each_entry(devlink_rate, &devlink->rate_list, list) if (devlink_rate_is_node(devlink_rate)) { From a3e5e5797faad0db319d106afaa31b9020fac44f Mon Sep 17 00:00:00 2001 From: Dmytro Linkin Date: Wed, 23 Jun 2021 16:43:15 +0300 Subject: [PATCH 3/3] devlink: Protect rate list with lock while switching modes Devlink eswitch set command doesn't hold devlink->lock, which makes possible race condition between rate list traversing and others devlink rate KAPI calls, like devlink_rate_nodes_destroy(). Hold devlink lock while traversing the list. Fixes: a8ecb93ef03d ("devlink: Introduce rate nodes") Signed-off-by: Dmytro Linkin Reviewed-by: Parav Pandit Reviewed-by: Jiri Pirko Signed-off-by: David S. Miller --- net/core/devlink.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/net/core/devlink.c b/net/core/devlink.c index 153d432f6daf..8fdd04f00fd7 100644 --- a/net/core/devlink.c +++ b/net/core/devlink.c @@ -2710,11 +2710,15 @@ static int devlink_rate_nodes_check(struct devlink *devlink, u16 mode, { struct devlink_rate *devlink_rate; + /* Take the lock to sync with devlink_rate_nodes_destroy() */ + mutex_lock(&devlink->lock); list_for_each_entry(devlink_rate, &devlink->rate_list, list) if (devlink_rate_is_node(devlink_rate)) { + mutex_unlock(&devlink->lock); NL_SET_ERR_MSG_MOD(extack, "Rate node(s) exists."); return -EBUSY; } + mutex_unlock(&devlink->lock); return 0; }