if (ret < 0)
return ret;
- ret = __mei_cl_recv(cldev->cl, buf, length);
+ ret = __mei_cl_recv(cldev->cl, buf, length, 0);
if (ret < 0)
return ret;
return -ENOMEM;
ret = 0;
- bytes_recv = __mei_cl_recv(cl, (u8 *)reply, if_version_length);
+ bytes_recv = __mei_cl_recv(cl, (u8 *)reply, if_version_length, 0);
if (bytes_recv < if_version_length) {
dev_err(bus->dev, "Could not read IF version\n");
ret = -EIO;
* @cl: host client
* @buf: buffer to receive
* @length: buffer length
+ * @mode: io mode
*
* Return: read size in bytes of < 0 on error
*/
-ssize_t __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length)
+ssize_t __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length,
+ unsigned int mode)
{
struct mei_device *bus;
struct mei_cl_cb *cb;
size_t r_length;
ssize_t rets;
+ bool nonblock = !!(mode & MEI_CL_IO_RX_NONBLOCK);
if (WARN_ON(!cl || !cl->dev))
return -ENODEV;
if (rets && rets != -EBUSY)
goto out;
+ if (nonblock) {
+ rets = -EAGAIN;
+ goto out;
+ }
+
/* wait on event only if there is no other waiter */
/* synchronized under device mutex */
if (!waitqueue_active(&cl->rx_wait)) {
EXPORT_SYMBOL_GPL(mei_cldev_send);
/**
+ * mei_cldev_recv_nonblock - non block client receive (read)
+ *
+ * @cldev: me client device
+ * @buf: buffer to receive
+ * @length: buffer length
+ *
+ * Return: read size in bytes of < 0 on error
+ * -EAGAIN if function will block.
+ */
+ssize_t mei_cldev_recv_nonblock(struct mei_cl_device *cldev, u8 *buf,
+ size_t length)
+{
+ struct mei_cl *cl = cldev->cl;
+
+ return __mei_cl_recv(cl, buf, length, MEI_CL_IO_RX_NONBLOCK);
+}
+EXPORT_SYMBOL_GPL(mei_cldev_recv_nonblock);
+
+/**
* mei_cldev_recv - client receive (read)
*
* @cldev: me client device
{
struct mei_cl *cl = cldev->cl;
- return __mei_cl_recv(cl, buf, length);
+ return __mei_cl_recv(cl, buf, length, 0);
}
EXPORT_SYMBOL_GPL(mei_cldev_recv);
*
* @MEI_CL_IO_TX_BLOCKING: send is blocking
* @MEI_CL_IO_TX_INTERNAL: internal communication between driver and FW
+ *
+ * @MEI_CL_IO_RX_NONBLOCK: recv is non-blocking
*/
enum mei_cl_io_mode {
MEI_CL_IO_TX_BLOCKING = BIT(0),
MEI_CL_IO_TX_INTERNAL = BIT(1),
+
+ MEI_CL_IO_RX_NONBLOCK = BIT(2),
};
/*
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);
+ssize_t __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length,
+ unsigned int mode);
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);
/**
* module_mei_cl_driver - Helper macro for registering mei cl driver
*
- * @__mei_cldrv mei_cl_driver structure
+ * @__mei_cldrv: mei_cl_driver structure
*
* Helper macro for mei cl drivers which do not do anything special in module
* init/exit, for eliminating a boilerplate code.
mei_cldev_driver_unregister)
ssize_t mei_cldev_send(struct mei_cl_device *cldev, u8 *buf, size_t length);
-ssize_t mei_cldev_recv(struct mei_cl_device *cldev, u8 *buf, size_t length);
+ssize_t mei_cldev_recv(struct mei_cl_device *cldev, u8 *buf, size_t length);
+ssize_t mei_cldev_recv_nonblock(struct mei_cl_device *cldev, u8 *buf,
+ size_t length);
int mei_cldev_register_rx_cb(struct mei_cl_device *cldev, mei_cldev_cb_t rx_cb);
int mei_cldev_register_notif_cb(struct mei_cl_device *cldev,