Commit 5502e871 authored by Jiri Pirko's avatar Jiri Pirko Committed by Jakub Kicinski

net: devlink: remove region snapshot ID tracking dependency on devlink->lock

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: default avatarJiri Pirko <jiri@nvidia.com>
Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent 1515a1b8
...@@ -5894,21 +5894,28 @@ static int __devlink_snapshot_id_increment(struct devlink *devlink, u32 id) ...@@ -5894,21 +5894,28 @@ static int __devlink_snapshot_id_increment(struct devlink *devlink, u32 id)
{ {
unsigned long count; unsigned long count;
void *p; void *p;
int err;
devl_assert_locked(devlink); xa_lock(&devlink->snapshot_ids);
p = xa_load(&devlink->snapshot_ids, id); p = xa_load(&devlink->snapshot_ids, id);
if (WARN_ON(!p)) if (WARN_ON(!p)) {
return -EINVAL; err = -EINVAL;
goto unlock;
}
if (WARN_ON(!xa_is_value(p))) if (WARN_ON(!xa_is_value(p))) {
return -EINVAL; err = -EINVAL;
goto unlock;
}
count = xa_to_value(p); count = xa_to_value(p);
count++; count++;
return xa_err(xa_store(&devlink->snapshot_ids, id, xa_mk_value(count), err = xa_err(__xa_store(&devlink->snapshot_ids, id, xa_mk_value(count),
GFP_KERNEL)); 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) ...@@ -5931,25 +5938,26 @@ static void __devlink_snapshot_id_decrement(struct devlink *devlink, u32 id)
unsigned long count; unsigned long count;
void *p; void *p;
devl_assert_locked(devlink); xa_lock(&devlink->snapshot_ids);
p = xa_load(&devlink->snapshot_ids, id); p = xa_load(&devlink->snapshot_ids, id);
if (WARN_ON(!p)) if (WARN_ON(!p))
return; goto unlock;
if (WARN_ON(!xa_is_value(p))) if (WARN_ON(!xa_is_value(p)))
return; goto unlock;
count = xa_to_value(p); count = xa_to_value(p);
if (count > 1) { if (count > 1) {
count--; count--;
xa_store(&devlink->snapshot_ids, id, xa_mk_value(count), __xa_store(&devlink->snapshot_ids, id, xa_mk_value(count),
GFP_KERNEL); GFP_ATOMIC);
} else { } else {
/* If this was the last user, we can erase this id */ /* 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) ...@@ -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) 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 -EEXIST;
}
return xa_err(xa_store(&devlink->snapshot_ids, id, xa_mk_value(0), err = xa_err(__xa_store(&devlink->snapshot_ids, id, xa_mk_value(0),
GFP_KERNEL)); GFP_ATOMIC));
xa_unlock(&devlink->snapshot_ids);
return err;
} }
/** /**
...@@ -5997,8 +6009,6 @@ static int __devlink_snapshot_id_insert(struct devlink *devlink, u32 id) ...@@ -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) 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), return xa_alloc(&devlink->snapshot_ids, id, xa_mk_value(1),
xa_limit_32b, GFP_KERNEL); xa_limit_32b, GFP_KERNEL);
} }
...@@ -11442,13 +11452,7 @@ EXPORT_SYMBOL_GPL(devlink_region_destroy); ...@@ -11442,13 +11452,7 @@ EXPORT_SYMBOL_GPL(devlink_region_destroy);
*/ */
int devlink_region_snapshot_id_get(struct devlink *devlink, u32 *id) int devlink_region_snapshot_id_get(struct devlink *devlink, u32 *id)
{ {
int err; return __devlink_region_snapshot_id_get(devlink, id);
devl_lock(devlink);
err = __devlink_region_snapshot_id_get(devlink, id);
devl_unlock(devlink);
return err;
} }
EXPORT_SYMBOL_GPL(devlink_region_snapshot_id_get); EXPORT_SYMBOL_GPL(devlink_region_snapshot_id_get);
...@@ -11464,9 +11468,7 @@ 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) void devlink_region_snapshot_id_put(struct devlink *devlink, u32 id)
{ {
devl_lock(devlink);
__devlink_snapshot_id_decrement(devlink, id); __devlink_snapshot_id_decrement(devlink, id);
devl_unlock(devlink);
} }
EXPORT_SYMBOL_GPL(devlink_region_snapshot_id_put); EXPORT_SYMBOL_GPL(devlink_region_snapshot_id_put);
......
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