mei: add optional timeout to internal bus recv

Add optional timeout to internal bus recv function to
enable break out of internal flows in case of no answer from FW.

Signed-off-by: Alexander Usyskin <alexander.usyskin@intel.com>
Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Alexander Usyskin 2018-06-25 00:11:40 +03:00 committed by Greg Kroah-Hartman
parent 3458657f9e
commit 9a7c0b69b6
3 changed files with 28 additions and 12 deletions

View File

@ -266,7 +266,7 @@ static int mei_nfc_if_version(struct mei_cl *cl,
return -ENOMEM;
ret = 0;
bytes_recv = __mei_cl_recv(cl, (u8 *)reply, if_version_length, 0);
bytes_recv = __mei_cl_recv(cl, (u8 *)reply, if_version_length, 0, 0);
if (bytes_recv < if_version_length) {
dev_err(bus->dev, "Could not read IF version\n");
ret = -EIO;

View File

@ -116,11 +116,12 @@ out:
* @buf: buffer to receive
* @length: buffer length
* @mode: io mode
* @timeout: recv timeout, 0 for infinite timeout
*
* Return: read size in bytes of < 0 on error
*/
ssize_t __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length,
unsigned int mode)
unsigned int mode, unsigned long timeout)
{
struct mei_device *bus;
struct mei_cl_cb *cb;
@ -158,13 +159,28 @@ ssize_t __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length,
mutex_unlock(&bus->device_lock);
if (wait_event_interruptible(cl->rx_wait,
(!list_empty(&cl->rd_completed)) ||
(!mei_cl_is_connected(cl)))) {
if (signal_pending(current))
return -EINTR;
return -ERESTARTSYS;
if (timeout) {
rets = wait_event_interruptible_timeout
(cl->rx_wait,
(!list_empty(&cl->rd_completed)) ||
(!mei_cl_is_connected(cl)),
msecs_to_jiffies(timeout));
if (rets == 0)
return -ETIME;
if (rets < 0) {
if (signal_pending(current))
return -EINTR;
return -ERESTARTSYS;
}
} else {
if (wait_event_interruptible
(cl->rx_wait,
(!list_empty(&cl->rd_completed)) ||
(!mei_cl_is_connected(cl)))) {
if (signal_pending(current))
return -EINTR;
return -ERESTARTSYS;
}
}
mutex_lock(&bus->device_lock);
@ -231,7 +247,7 @@ ssize_t mei_cldev_recv_nonblock(struct mei_cl_device *cldev, u8 *buf,
{
struct mei_cl *cl = cldev->cl;
return __mei_cl_recv(cl, buf, length, MEI_CL_IO_RX_NONBLOCK);
return __mei_cl_recv(cl, buf, length, MEI_CL_IO_RX_NONBLOCK, 0);
}
EXPORT_SYMBOL_GPL(mei_cldev_recv_nonblock);
@ -248,7 +264,7 @@ ssize_t mei_cldev_recv(struct mei_cl_device *cldev, u8 *buf, size_t length)
{
struct mei_cl *cl = cldev->cl;
return __mei_cl_recv(cl, buf, length, 0);
return __mei_cl_recv(cl, buf, length, 0, 0);
}
EXPORT_SYMBOL_GPL(mei_cldev_recv);

View File

@ -317,7 +317,7 @@ void mei_cl_bus_dev_fixup(struct mei_cl_device *dev);
ssize_t __mei_cl_send(struct mei_cl *cl, u8 *buf, size_t length,
unsigned int mode);
ssize_t __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length,
unsigned int mode);
unsigned int mode, unsigned long timeout);
bool mei_cl_bus_rx_event(struct mei_cl *cl);
bool mei_cl_bus_notify_event(struct mei_cl *cl);
void mei_cl_bus_remove_devices(struct mei_device *bus);