mirror of
https://github.com/torvalds/linux.git
synced 2026-07-28 01:55:51 +02:00
IB/mlx5: Reduce spinlock contention by moving free operations outside
The functions kfree() and kvfree() can occasionally trigger a long chain of calls or face contention in the slab allocator. Executing these inside a spinlock increases the risk of CPU stalls and increases lock contention under heavy event load. Move the memory freeing logic out of the critical sections in devx.c by using temporary lists and local flags. This narrows the lock's scope to only protect the list integrity and state transitions. Signed-off-by: Li RongQing <lirongqing@baidu.com> Link: https://patch.msgid.link/20260503023349.1959-1-lirongqing@baidu.com Signed-off-by: Leon Romanovsky <leon@kernel.org>
This commit is contained in:
parent
43f8f79468
commit
d38e69adc2
|
|
@ -2528,7 +2528,7 @@ static int deliver_event(struct devx_event_subscription *event_sub,
|
|||
const void *data)
|
||||
{
|
||||
struct devx_async_event_file *ev_file;
|
||||
struct devx_async_event_data *event_data;
|
||||
struct devx_async_event_data *event_data, *to_free;
|
||||
unsigned long flags;
|
||||
|
||||
ev_file = event_sub->ev_file;
|
||||
|
|
@ -2559,12 +2559,17 @@ static int deliver_event(struct devx_event_subscription *event_sub,
|
|||
event_data->hdr.cookie = event_sub->cookie;
|
||||
memcpy(event_data->hdr.out_data, data, sizeof(struct mlx5_eqe));
|
||||
|
||||
to_free = NULL;
|
||||
|
||||
spin_lock_irqsave(&ev_file->lock, flags);
|
||||
if (!ev_file->is_destroyed)
|
||||
list_add_tail(&event_data->list, &ev_file->event_list);
|
||||
else
|
||||
kfree(event_data);
|
||||
to_free = event_data;
|
||||
spin_unlock_irqrestore(&ev_file->lock, flags);
|
||||
|
||||
kfree(to_free);
|
||||
|
||||
wake_up_interruptible(&ev_file->poll_wait);
|
||||
|
||||
return 0;
|
||||
|
|
@ -2958,6 +2963,7 @@ static void devx_async_cmd_event_destroy_uobj(struct ib_uobject *uobj,
|
|||
uobj);
|
||||
struct devx_async_event_queue *ev_queue = &comp_ev_file->ev_queue;
|
||||
struct devx_async_data *entry, *tmp;
|
||||
LIST_HEAD(tmp_list);
|
||||
|
||||
spin_lock_irq(&ev_queue->lock);
|
||||
ev_queue->is_destroyed = 1;
|
||||
|
|
@ -2967,12 +2973,15 @@ static void devx_async_cmd_event_destroy_uobj(struct ib_uobject *uobj,
|
|||
mlx5_cmd_cleanup_async_ctx(&comp_ev_file->async_ctx);
|
||||
|
||||
spin_lock_irq(&comp_ev_file->ev_queue.lock);
|
||||
list_for_each_entry_safe(entry, tmp,
|
||||
&comp_ev_file->ev_queue.event_list, list) {
|
||||
/* Move all entries to a temporary list and free them outside lock */
|
||||
list_splice_init(&comp_ev_file->ev_queue.event_list, &tmp_list);
|
||||
spin_unlock_irq(&comp_ev_file->ev_queue.lock);
|
||||
|
||||
/* Free memory outside of critical section */
|
||||
list_for_each_entry_safe(entry, tmp, &tmp_list, list) {
|
||||
list_del(&entry->list);
|
||||
kvfree(entry);
|
||||
}
|
||||
spin_unlock_irq(&comp_ev_file->ev_queue.lock);
|
||||
};
|
||||
|
||||
static void devx_async_event_destroy_uobj(struct ib_uobject *uobj,
|
||||
|
|
@ -2982,7 +2991,9 @@ static void devx_async_event_destroy_uobj(struct ib_uobject *uobj,
|
|||
container_of(uobj, struct devx_async_event_file,
|
||||
uobj);
|
||||
struct devx_event_subscription *event_sub, *event_sub_tmp;
|
||||
struct devx_async_event_data *entry, *tmp;
|
||||
struct mlx5_ib_dev *dev = ev_file->dev;
|
||||
LIST_HEAD(tmp_list);
|
||||
|
||||
spin_lock_irq(&ev_file->lock);
|
||||
ev_file->is_destroyed = 1;
|
||||
|
|
@ -2996,18 +3007,19 @@ static void devx_async_event_destroy_uobj(struct ib_uobject *uobj,
|
|||
list_del_init(&event_sub->event_list);
|
||||
|
||||
} else {
|
||||
struct devx_async_event_data *entry, *tmp;
|
||||
|
||||
list_for_each_entry_safe(entry, tmp, &ev_file->event_list,
|
||||
list) {
|
||||
list_del(&entry->list);
|
||||
kfree(entry);
|
||||
}
|
||||
/* Move all entries to a temporary list */
|
||||
list_splice_init(&ev_file->event_list, &tmp_list);
|
||||
}
|
||||
|
||||
spin_unlock_irq(&ev_file->lock);
|
||||
wake_up_interruptible(&ev_file->poll_wait);
|
||||
|
||||
/* Free event data outside of critical section */
|
||||
list_for_each_entry_safe(entry, tmp, &tmp_list, list) {
|
||||
list_del(&entry->list);
|
||||
kfree(entry);
|
||||
}
|
||||
|
||||
mutex_lock(&dev->devx_event_table.event_xa_lock);
|
||||
/* delete the subscriptions which are related to this FD */
|
||||
list_for_each_entry_safe(event_sub, event_sub_tmp,
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user