Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+52 −0
Original line number Diff line number Diff line
@@ -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 @@ int mei_cl_notify_request(struct mei_cl *cl, struct file *file, u8 request)
	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);
		}
	}
}

+1 −0
Original line number Diff line number Diff line
@@ -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);
+3 −1
Original line number Diff line number Diff line
@@ -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);
	}
}

/**
+2 −0
Original line number Diff line number Diff line
@@ -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;