mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-26 21:54:11 +08:00
mei: add a spin lock to protect rd_completed queue
In order to support vtags we need to access read completed queue out of driver big lock. Add a spin lock to protect rd_completed queue. Signed-off-by: Alexander Usyskin <alexander.usyskin@intel.com> Signed-off-by: Tomas Winkler <tomas.winkler@intel.com> Link: https://lore.kernel.org/r/20200818115147.2567012-7-tomas.winkler@intel.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
74a9c967aa
commit
d1376f3d89
@ -152,7 +152,7 @@ ssize_t __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length,
|
||||
if (timeout) {
|
||||
rets = wait_event_interruptible_timeout
|
||||
(cl->rx_wait,
|
||||
(!list_empty(&cl->rd_completed)) ||
|
||||
mei_cl_read_cb(cl, NULL) ||
|
||||
(!mei_cl_is_connected(cl)),
|
||||
msecs_to_jiffies(timeout));
|
||||
if (rets == 0)
|
||||
@ -165,7 +165,7 @@ ssize_t __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length,
|
||||
} else {
|
||||
if (wait_event_interruptible
|
||||
(cl->rx_wait,
|
||||
(!list_empty(&cl->rd_completed)) ||
|
||||
mei_cl_read_cb(cl, NULL) ||
|
||||
(!mei_cl_is_connected(cl)))) {
|
||||
if (signal_pending(current))
|
||||
return -EINTR;
|
||||
@ -198,7 +198,7 @@ copy:
|
||||
rets = r_length;
|
||||
|
||||
free:
|
||||
mei_io_cb_free(cb);
|
||||
mei_cl_del_rd_completed(cl, cb);
|
||||
out:
|
||||
mutex_unlock(&bus->device_lock);
|
||||
|
||||
|
@ -507,15 +507,19 @@ struct mei_cl_cb *mei_cl_enqueue_ctrl_wr_cb(struct mei_cl *cl, size_t length,
|
||||
*
|
||||
* Return: cb on success, NULL if cb is not found
|
||||
*/
|
||||
struct mei_cl_cb *mei_cl_read_cb(const struct mei_cl *cl, const struct file *fp)
|
||||
struct mei_cl_cb *mei_cl_read_cb(struct mei_cl *cl, const struct file *fp)
|
||||
{
|
||||
struct mei_cl_cb *cb;
|
||||
struct mei_cl_cb *ret_cb = NULL;
|
||||
|
||||
spin_lock(&cl->rd_completed_lock);
|
||||
list_for_each_entry(cb, &cl->rd_completed, list)
|
||||
if (!fp || fp == cb->fp)
|
||||
return cb;
|
||||
|
||||
return NULL;
|
||||
if (!fp || fp == cb->fp) {
|
||||
ret_cb = cb;
|
||||
break;
|
||||
}
|
||||
spin_unlock(&cl->rd_completed_lock);
|
||||
return ret_cb;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -541,7 +545,9 @@ int mei_cl_flush_queues(struct mei_cl *cl, const struct file *fp)
|
||||
mei_io_list_flush_cl(&cl->dev->ctrl_wr_list, cl);
|
||||
mei_io_list_flush_cl(&cl->dev->ctrl_rd_list, cl);
|
||||
mei_io_list_free_fp(&cl->rd_pending, fp);
|
||||
spin_lock(&cl->rd_completed_lock);
|
||||
mei_io_list_free_fp(&cl->rd_completed, fp);
|
||||
spin_unlock(&cl->rd_completed_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -559,6 +565,7 @@ static void mei_cl_init(struct mei_cl *cl, struct mei_device *dev)
|
||||
init_waitqueue_head(&cl->rx_wait);
|
||||
init_waitqueue_head(&cl->tx_wait);
|
||||
init_waitqueue_head(&cl->ev_wait);
|
||||
spin_lock_init(&cl->rd_completed_lock);
|
||||
INIT_LIST_HEAD(&cl->rd_completed);
|
||||
INIT_LIST_HEAD(&cl->rd_pending);
|
||||
INIT_LIST_HEAD(&cl->link);
|
||||
@ -1230,6 +1237,34 @@ static int mei_cl_tx_flow_ctrl_creds_reduce(struct mei_cl *cl)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* mei_cl_add_rd_completed - add read completed callback to list with lock
|
||||
*
|
||||
* @cl: host client
|
||||
* @cb: callback block
|
||||
*
|
||||
*/
|
||||
void mei_cl_add_rd_completed(struct mei_cl *cl, struct mei_cl_cb *cb)
|
||||
{
|
||||
spin_lock(&cl->rd_completed_lock);
|
||||
list_add_tail(&cb->list, &cl->rd_completed);
|
||||
spin_unlock(&cl->rd_completed_lock);
|
||||
}
|
||||
|
||||
/**
|
||||
* mei_cl_del_rd_completed - free read completed callback with lock
|
||||
*
|
||||
* @cl: host client
|
||||
* @cb: callback block
|
||||
*
|
||||
*/
|
||||
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);
|
||||
spin_unlock(&cl->rd_completed_lock);
|
||||
}
|
||||
|
||||
/**
|
||||
* mei_cl_notify_fop2req - convert fop to proper request
|
||||
*
|
||||
@ -1897,7 +1932,7 @@ void mei_cl_complete(struct mei_cl *cl, struct mei_cl_cb *cb)
|
||||
break;
|
||||
|
||||
case MEI_FOP_READ:
|
||||
list_add_tail(&cb->list, &cl->rd_completed);
|
||||
mei_cl_add_rd_completed(cl, cb);
|
||||
if (!mei_cl_is_fixed_address(cl) &&
|
||||
!WARN_ON(!cl->rx_flow_ctrl_creds))
|
||||
cl->rx_flow_ctrl_creds--;
|
||||
|
@ -133,8 +133,11 @@ int mei_cl_unlink(struct mei_cl *cl);
|
||||
|
||||
struct mei_cl *mei_cl_alloc_linked(struct mei_device *dev);
|
||||
|
||||
struct mei_cl_cb *mei_cl_read_cb(const struct mei_cl *cl,
|
||||
const struct file *fp);
|
||||
struct mei_cl_cb *mei_cl_read_cb(struct mei_cl *cl, const struct file *fp);
|
||||
|
||||
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);
|
||||
|
||||
struct mei_cl_cb *mei_cl_alloc_cb(struct mei_cl *cl, size_t length,
|
||||
enum mei_cb_file_ops type,
|
||||
const struct file *fp);
|
||||
|
@ -178,7 +178,7 @@ static ssize_t mei_read(struct file *file, char __user *ubuf,
|
||||
|
||||
mutex_unlock(&dev->device_lock);
|
||||
if (wait_event_interruptible(cl->rx_wait,
|
||||
!list_empty(&cl->rd_completed) ||
|
||||
mei_cl_read_cb(cl, file) ||
|
||||
!mei_cl_is_connected(cl))) {
|
||||
if (signal_pending(current))
|
||||
return -EINTR;
|
||||
@ -229,7 +229,7 @@ copy_buffer:
|
||||
goto out;
|
||||
|
||||
free:
|
||||
mei_io_cb_free(cb);
|
||||
mei_cl_del_rd_completed(cl, cb);
|
||||
*offset = 0;
|
||||
|
||||
out:
|
||||
@ -572,7 +572,7 @@ static __poll_t mei_poll(struct file *file, poll_table *wait)
|
||||
if (req_events & (EPOLLIN | EPOLLRDNORM)) {
|
||||
poll_wait(file, &cl->rx_wait, wait);
|
||||
|
||||
if (!list_empty(&cl->rd_completed))
|
||||
if (mei_cl_read_cb(cl, file))
|
||||
mask |= EPOLLIN | EPOLLRDNORM;
|
||||
else
|
||||
mei_cl_read_start(cl, mei_cl_mtu(cl), file);
|
||||
|
@ -217,6 +217,7 @@ struct mei_cl_cb {
|
||||
* @tx_cb_queued: number of tx callbacks in queue
|
||||
* @writing_state: state of the tx
|
||||
* @rd_pending: pending read credits
|
||||
* @rd_completed_lock: protects rd_completed queue
|
||||
* @rd_completed: completed read
|
||||
*
|
||||
* @cldev: device on the mei client bus
|
||||
@ -242,6 +243,7 @@ struct mei_cl {
|
||||
u8 tx_cb_queued;
|
||||
enum mei_file_transaction_states writing_state;
|
||||
struct list_head rd_pending;
|
||||
spinlock_t rd_completed_lock; /* protects rd_completed queue */
|
||||
struct list_head rd_completed;
|
||||
|
||||
struct mei_cl_device *cldev;
|
||||
|
Loading…
Reference in New Issue
Block a user