Commit b38a362f authored by Tomas Winkler's avatar Tomas Winkler Committed by Greg Kroah-Hartman

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: default avatarTomas Winkler <tomas.winkler@intel.com>
Signed-off-by: default avatarAlexander Usyskin <alexander.usyskin@intel.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 51678ccb
...@@ -555,6 +555,7 @@ void mei_cl_init(struct mei_cl *cl, struct mei_device *dev) ...@@ -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->wait);
init_waitqueue_head(&cl->rx_wait); init_waitqueue_head(&cl->rx_wait);
init_waitqueue_head(&cl->tx_wait); init_waitqueue_head(&cl->tx_wait);
init_waitqueue_head(&cl->ev_wait);
INIT_LIST_HEAD(&cl->rd_completed); INIT_LIST_HEAD(&cl->rd_completed);
INIT_LIST_HEAD(&cl->rd_pending); INIT_LIST_HEAD(&cl->rd_pending);
INIT_LIST_HEAD(&cl->link); INIT_LIST_HEAD(&cl->link);
...@@ -1349,6 +1350,51 @@ int mei_cl_notify_request(struct mei_cl *cl, struct file *file, u8 request) ...@@ -1349,6 +1350,51 @@ int mei_cl_notify_request(struct mei_cl *cl, struct file *file, u8 request)
return rets; 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. * mei_cl_read_start - the start read client message function.
* *
...@@ -1701,6 +1747,12 @@ void mei_cl_all_wakeup(struct mei_device *dev) ...@@ -1701,6 +1747,12 @@ void mei_cl_all_wakeup(struct mei_device *dev)
cl_dbg(dev, cl, "Waking up writing client!\n"); cl_dbg(dev, cl, "Waking up writing client!\n");
wake_up_interruptible(&cl->tx_wait); 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); ...@@ -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_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, int mei_cl_irq_notify(struct mei_cl *cl, struct mei_cl_cb *cb,
struct mei_cl_cb *cmpl_list); 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_disconnect(struct mei_device *dev);
void mei_cl_all_wakeup(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, ...@@ -514,8 +514,10 @@ static void mei_hbm_cl_notify(struct mei_device *dev,
struct mei_cl *cl; struct mei_cl *cl;
cl = mei_hbm_cl_find_by_cmd(dev, cmd); cl = mei_hbm_cl_find_by_cmd(dev, cmd);
if (cl && cl->notify_en) if (cl && cl->notify_en) {
cl->notify_ev = true; cl->notify_ev = true;
wake_up_interruptible(&cl->ev_wait);
}
} }
/** /**
......
...@@ -235,6 +235,7 @@ struct mei_cl_cb { ...@@ -235,6 +235,7 @@ struct mei_cl_cb {
* @tx_wait: wait queue for tx completion * @tx_wait: wait queue for tx completion
* @rx_wait: wait queue for rx completion * @rx_wait: wait queue for rx completion
* @wait: wait queue for management operation * @wait: wait queue for management operation
* @ev_wait: notification wait queue
* @status: connection status * @status: connection status
* @me_cl: fw client connected * @me_cl: fw client connected
* @host_client_id: host id * @host_client_id: host id
...@@ -256,6 +257,7 @@ struct mei_cl { ...@@ -256,6 +257,7 @@ struct mei_cl {
wait_queue_head_t tx_wait; wait_queue_head_t tx_wait;
wait_queue_head_t rx_wait; wait_queue_head_t rx_wait;
wait_queue_head_t wait; wait_queue_head_t wait;
wait_queue_head_t ev_wait;
int status; int status;
struct mei_me_client *me_cl; struct mei_me_client *me_cl;
u8 host_client_id; u8 host_client_id;
......
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