]> git.baikalelectronics.ru Git - kernel.git/commitdiff
net: devlink: remove region snapshot ID tracking dependency on devlink->lock
authorJiri Pirko <jiri@nvidia.com>
Thu, 28 Jul 2022 15:53:42 +0000 (18:53 +0300)
committerJakub Kicinski <kuba@kernel.org>
Fri, 29 Jul 2022 04:58:46 +0000 (21:58 -0700)
After mlx4 driver is converted to do locked reload, functions to get/put
regions snapshot ID may be called from both locked and unlocked context.

So resolve this by removing dependency on devlink->lock for region
snapshot ID tracking by using internal xa_lock() to maintain
shapshot_ids xa_array consistency.

Signed-off-by: Jiri Pirko <jiri@nvidia.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
net/core/devlink.c

index efeba223b9b869de5551ce7744703b60f0502578..c8e20cafde1d567867ef48b48f23166b48293ed4 100644 (file)
@@ -5894,21 +5894,28 @@ static int __devlink_snapshot_id_increment(struct devlink *devlink, u32 id)
 {
        unsigned long count;
        void *p;
+       int err;
 
-       devl_assert_locked(devlink);
-
+       xa_lock(&devlink->snapshot_ids);
        p = xa_load(&devlink->snapshot_ids, id);
-       if (WARN_ON(!p))
-               return -EINVAL;
+       if (WARN_ON(!p)) {
+               err = -EINVAL;
+               goto unlock;
+       }
 
-       if (WARN_ON(!xa_is_value(p)))
-               return -EINVAL;
+       if (WARN_ON(!xa_is_value(p))) {
+               err = -EINVAL;
+               goto unlock;
+       }
 
        count = xa_to_value(p);
        count++;
 
-       return xa_err(xa_store(&devlink->snapshot_ids, id, xa_mk_value(count),
-                              GFP_KERNEL));
+       err = xa_err(__xa_store(&devlink->snapshot_ids, id, xa_mk_value(count),
+                               GFP_ATOMIC));
+unlock:
+       xa_unlock(&devlink->snapshot_ids);
+       return err;
 }
 
 /**
@@ -5931,25 +5938,26 @@ static void __devlink_snapshot_id_decrement(struct devlink *devlink, u32 id)
        unsigned long count;
        void *p;
 
-       devl_assert_locked(devlink);
-
+       xa_lock(&devlink->snapshot_ids);
        p = xa_load(&devlink->snapshot_ids, id);
        if (WARN_ON(!p))
-               return;
+               goto unlock;
 
        if (WARN_ON(!xa_is_value(p)))
-               return;
+               goto unlock;
 
        count = xa_to_value(p);
 
        if (count > 1) {
                count--;
-               xa_store(&devlink->snapshot_ids, id, xa_mk_value(count),
-                        GFP_KERNEL);
+               __xa_store(&devlink->snapshot_ids, id, xa_mk_value(count),
+                          GFP_ATOMIC);
        } else {
                /* If this was the last user, we can erase this id */
-               xa_erase(&devlink->snapshot_ids, id);
+               __xa_erase(&devlink->snapshot_ids, id);
        }
+unlock:
+       xa_unlock(&devlink->snapshot_ids);
 }
 
 /**
@@ -5970,13 +5978,17 @@ static void __devlink_snapshot_id_decrement(struct devlink *devlink, u32 id)
  */
 static int __devlink_snapshot_id_insert(struct devlink *devlink, u32 id)
 {
-       devl_assert_locked(devlink);
+       int err;
 
-       if (xa_load(&devlink->snapshot_ids, id))
+       xa_lock(&devlink->snapshot_ids);
+       if (xa_load(&devlink->snapshot_ids, id)) {
+               xa_unlock(&devlink->snapshot_ids);
                return -EEXIST;
-
-       return xa_err(xa_store(&devlink->snapshot_ids, id, xa_mk_value(0),
-                              GFP_KERNEL));
+       }
+       err = xa_err(__xa_store(&devlink->snapshot_ids, id, xa_mk_value(0),
+                               GFP_ATOMIC));
+       xa_unlock(&devlink->snapshot_ids);
+       return err;
 }
 
 /**
@@ -5997,8 +6009,6 @@ static int __devlink_snapshot_id_insert(struct devlink *devlink, u32 id)
  */
 static int __devlink_region_snapshot_id_get(struct devlink *devlink, u32 *id)
 {
-       devl_assert_locked(devlink);
-
        return xa_alloc(&devlink->snapshot_ids, id, xa_mk_value(1),
                        xa_limit_32b, GFP_KERNEL);
 }
@@ -11442,13 +11452,7 @@ EXPORT_SYMBOL_GPL(devlink_region_destroy);
  */
 int devlink_region_snapshot_id_get(struct devlink *devlink, u32 *id)
 {
-       int err;
-
-       devl_lock(devlink);
-       err = __devlink_region_snapshot_id_get(devlink, id);
-       devl_unlock(devlink);
-
-       return err;
+       return __devlink_region_snapshot_id_get(devlink, id);
 }
 EXPORT_SYMBOL_GPL(devlink_region_snapshot_id_get);
 
@@ -11464,9 +11468,7 @@ EXPORT_SYMBOL_GPL(devlink_region_snapshot_id_get);
  */
 void devlink_region_snapshot_id_put(struct devlink *devlink, u32 id)
 {
-       devl_lock(devlink);
        __devlink_snapshot_id_decrement(devlink, id);
-       devl_unlock(devlink);
 }
 EXPORT_SYMBOL_GPL(devlink_region_snapshot_id_put);