mei: add a handler that waits for notification on event
mei_cl_notify_get is to be called by a host client to wait, receive, and ack the event notification. Signed-off-by: Tomas Winkler <tomas.winkler@intel.com> Signed-off-by: Alexander Usyskin <alexander.usyskin@intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Родитель
51678ccb7b
Коммит
b38a362fad
|
@ -555,6 +555,7 @@ void mei_cl_init(struct mei_cl *cl, struct mei_device *dev)
|
|||
init_waitqueue_head(&cl->wait);
|
||||
init_waitqueue_head(&cl->rx_wait);
|
||||
init_waitqueue_head(&cl->tx_wait);
|
||||
init_waitqueue_head(&cl->ev_wait);
|
||||
INIT_LIST_HEAD(&cl->rd_completed);
|
||||
INIT_LIST_HEAD(&cl->rd_pending);
|
||||
INIT_LIST_HEAD(&cl->link);
|
||||
|
@ -1349,6 +1350,51 @@ out:
|
|||
return rets;
|
||||
}
|
||||
|
||||
/**
|
||||
* mei_cl_notify_get - get or wait for notification event
|
||||
*
|
||||
* @cl: host client
|
||||
* @block: this request is blocking
|
||||
* @notify_ev: true if notification event was received
|
||||
*
|
||||
* Locking: called under "dev->device_lock" lock
|
||||
*
|
||||
* Return: 0 on such and error otherwise.
|
||||
*/
|
||||
int mei_cl_notify_get(struct mei_cl *cl, bool block, bool *notify_ev)
|
||||
{
|
||||
struct mei_device *dev;
|
||||
int rets;
|
||||
|
||||
*notify_ev = false;
|
||||
|
||||
if (WARN_ON(!cl || !cl->dev))
|
||||
return -ENODEV;
|
||||
|
||||
dev = cl->dev;
|
||||
|
||||
if (!mei_cl_is_connected(cl))
|
||||
return -ENODEV;
|
||||
|
||||
if (cl->notify_ev)
|
||||
goto out;
|
||||
|
||||
if (!block)
|
||||
return -EAGAIN;
|
||||
|
||||
mutex_unlock(&dev->device_lock);
|
||||
rets = wait_event_interruptible(cl->ev_wait, cl->notify_ev);
|
||||
mutex_lock(&dev->device_lock);
|
||||
|
||||
if (rets < 0)
|
||||
return rets;
|
||||
|
||||
out:
|
||||
*notify_ev = cl->notify_ev;
|
||||
cl->notify_ev = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* mei_cl_read_start - the start read client message function.
|
||||
*
|
||||
|
@ -1701,6 +1747,12 @@ void mei_cl_all_wakeup(struct mei_device *dev)
|
|||
cl_dbg(dev, cl, "Waking up writing client!\n");
|
||||
wake_up_interruptible(&cl->tx_wait);
|
||||
}
|
||||
|
||||
/* synchronized under device mutex */
|
||||
if (waitqueue_active(&cl->ev_wait)) {
|
||||
cl_dbg(dev, cl, "Waking up waiting for event clients!\n");
|
||||
wake_up_interruptible(&cl->ev_wait);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -224,6 +224,7 @@ enum mei_cb_file_ops mei_cl_notify_req2fop(u8 request);
|
|||
int mei_cl_notify_request(struct mei_cl *cl, struct file *file, u8 request);
|
||||
int mei_cl_irq_notify(struct mei_cl *cl, struct mei_cl_cb *cb,
|
||||
struct mei_cl_cb *cmpl_list);
|
||||
int mei_cl_notify_get(struct mei_cl *cl, bool block, bool *notify_ev);
|
||||
|
||||
void mei_cl_all_disconnect(struct mei_device *dev);
|
||||
void mei_cl_all_wakeup(struct mei_device *dev);
|
||||
|
|
|
@ -514,8 +514,10 @@ static void mei_hbm_cl_notify(struct mei_device *dev,
|
|||
struct mei_cl *cl;
|
||||
|
||||
cl = mei_hbm_cl_find_by_cmd(dev, cmd);
|
||||
if (cl && cl->notify_en)
|
||||
if (cl && cl->notify_en) {
|
||||
cl->notify_ev = true;
|
||||
wake_up_interruptible(&cl->ev_wait);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -235,6 +235,7 @@ struct mei_cl_cb {
|
|||
* @tx_wait: wait queue for tx completion
|
||||
* @rx_wait: wait queue for rx completion
|
||||
* @wait: wait queue for management operation
|
||||
* @ev_wait: notification wait queue
|
||||
* @status: connection status
|
||||
* @me_cl: fw client connected
|
||||
* @host_client_id: host id
|
||||
|
@ -256,6 +257,7 @@ struct mei_cl {
|
|||
wait_queue_head_t tx_wait;
|
||||
wait_queue_head_t rx_wait;
|
||||
wait_queue_head_t wait;
|
||||
wait_queue_head_t ev_wait;
|
||||
int status;
|
||||
struct mei_me_client *me_cl;
|
||||
u8 host_client_id;
|
||||
|
|
Загрузка…
Ссылка в новой задаче