mirror of
https://github.com/torvalds/linux.git
synced 2026-09-22 12:44:03 +02:00
mei: pull kvfree out of spinlock
The read buffer allocation was changed from kmalloc() to kvmalloc().
This buffer is part of mei_cl_cb structure that can be queued in
rd_complete queue protected by spinlock.
Releasing the structure leads to errors like below when freeing buffer
that allocated non-contiguous:
BUG: sleeping function called from invalid context at mm/vmalloc.c:3448
Separate mei_cl_cb structure dequeue and release to
perform only dequeue under spinlock and push release out of spinlock.
Cc: stable <stable@kernel.org>
Fixes: 4adf613e01 ("mei: use kvmalloc for read buffer")
Closes: https://gitlab.freedesktop.org/drm/i915/kernel/-/work_items/16359
Reviewed-by: Menachem Adin <menachem.adin@intel.com>
Signed-off-by: Alexander Usyskin <alexander.usyskin@intel.com>
Link: https://patch.msgid.link/20260719-kvfree_out_of_spinlock-v1-1-e07d6333bea7@intel.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
dd7aea9ee2
commit
b0495bb58a
|
|
@ -425,18 +425,24 @@ static void mei_io_tx_list_free_cl(struct list_head *head,
|
|||
}
|
||||
|
||||
/**
|
||||
* mei_io_list_free_fp - free cb from a list that matches file pointer
|
||||
* mei_io_rd_list_free_fp - free cb from a rd_completed list that matches file pointer
|
||||
*
|
||||
* @head: io list
|
||||
* @cl: host client
|
||||
* @fp: file pointer (matching cb file object), may be NULL
|
||||
*/
|
||||
static void mei_io_list_free_fp(struct list_head *head, const struct file *fp)
|
||||
static void mei_io_rd_list_free_fp(struct mei_cl *cl, const struct file *fp)
|
||||
{
|
||||
struct mei_cl_cb *cb, *next;
|
||||
LIST_HEAD(cmpl_list);
|
||||
|
||||
list_for_each_entry_safe(cb, next, head, list)
|
||||
spin_lock(&cl->rd_completed_lock);
|
||||
list_for_each_entry_safe(cb, next, &cl->rd_completed, list)
|
||||
if (!fp || fp == cb->fp)
|
||||
mei_io_cb_free(cb);
|
||||
list_move(&cb->list, &cmpl_list);
|
||||
spin_unlock(&cl->rd_completed_lock);
|
||||
|
||||
list_for_each_entry_safe(cb, next, &cmpl_list, list)
|
||||
mei_io_cb_free(cb);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -565,9 +571,7 @@ int mei_cl_flush_queues(struct mei_cl *cl, const struct file *fp)
|
|||
mei_io_list_flush_cl(&cl->dev->ctrl_rd_list, cl);
|
||||
mei_cl_free_pending(cl);
|
||||
}
|
||||
spin_lock(&cl->rd_completed_lock);
|
||||
mei_io_list_free_fp(&cl->rd_completed, fp);
|
||||
spin_unlock(&cl->rd_completed_lock);
|
||||
mei_io_rd_list_free_fp(cl, fp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1401,7 +1405,7 @@ void mei_cl_add_rd_completed(struct mei_cl *cl, struct mei_cl_cb *cb)
|
|||
}
|
||||
|
||||
/**
|
||||
* mei_cl_del_rd_completed - free read completed callback with lock
|
||||
* mei_cl_del_rd_completed - unlink read completed callback with lock and free it
|
||||
*
|
||||
* @cl: host client
|
||||
* @cb: callback block
|
||||
|
|
@ -1410,8 +1414,9 @@ void mei_cl_add_rd_completed(struct mei_cl *cl, struct mei_cl_cb *cb)
|
|||
void mei_cl_del_rd_completed(struct mei_cl *cl, struct mei_cl_cb *cb)
|
||||
{
|
||||
spin_lock(&cl->rd_completed_lock);
|
||||
mei_io_cb_free(cb);
|
||||
list_del_init(&cb->list);
|
||||
spin_unlock(&cl->rd_completed_lock);
|
||||
mei_io_cb_free(cb);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user