Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mei: bus: enable non-blocking RX

Enable non-blocking receive for drivers on mei bus, this allows checking
for data availability by mei client drivers. This is most effective for
fixed address clients, that lacks flow control.

This function adds new API function mei_cldev_recv_nonblock(), it
retuns -EGAIN if function will block.

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>

authored by

Alexander Usyskin and committed by
Greg Kroah-Hartman
076802d0 a2eb0fc0

+41 -7
+2 -2
drivers/misc/mei/bus-fixup.c
··· 141 141 if (ret < 0) 142 142 return ret; 143 143 144 - ret = __mei_cl_recv(cldev->cl, buf, length); 144 + ret = __mei_cl_recv(cldev->cl, buf, length, 0); 145 145 if (ret < 0) 146 146 return ret; 147 147 ··· 272 272 return -ENOMEM; 273 273 274 274 ret = 0; 275 - bytes_recv = __mei_cl_recv(cl, (u8 *)reply, if_version_length); 275 + bytes_recv = __mei_cl_recv(cl, (u8 *)reply, if_version_length, 0); 276 276 if (bytes_recv < if_version_length) { 277 277 dev_err(bus->dev, "Could not read IF version\n"); 278 278 ret = -EIO;
+29 -2
drivers/misc/mei/bus.c
··· 98 98 * @cl: host client 99 99 * @buf: buffer to receive 100 100 * @length: buffer length 101 + * @mode: io mode 101 102 * 102 103 * Return: read size in bytes of < 0 on error 103 104 */ 104 - ssize_t __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length) 105 + ssize_t __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length, 106 + unsigned int mode) 105 107 { 106 108 struct mei_device *bus; 107 109 struct mei_cl_cb *cb; 108 110 size_t r_length; 109 111 ssize_t rets; 112 + bool nonblock = !!(mode & MEI_CL_IO_RX_NONBLOCK); 110 113 111 114 if (WARN_ON(!cl || !cl->dev)) 112 115 return -ENODEV; ··· 129 126 rets = mei_cl_read_start(cl, length, NULL); 130 127 if (rets && rets != -EBUSY) 131 128 goto out; 129 + 130 + if (nonblock) { 131 + rets = -EAGAIN; 132 + goto out; 133 + } 132 134 133 135 /* wait on event only if there is no other waiter */ 134 136 /* synchronized under device mutex */ ··· 200 192 EXPORT_SYMBOL_GPL(mei_cldev_send); 201 193 202 194 /** 195 + * mei_cldev_recv_nonblock - non block client receive (read) 196 + * 197 + * @cldev: me client device 198 + * @buf: buffer to receive 199 + * @length: buffer length 200 + * 201 + * Return: read size in bytes of < 0 on error 202 + * -EAGAIN if function will block. 203 + */ 204 + ssize_t mei_cldev_recv_nonblock(struct mei_cl_device *cldev, u8 *buf, 205 + size_t length) 206 + { 207 + struct mei_cl *cl = cldev->cl; 208 + 209 + return __mei_cl_recv(cl, buf, length, MEI_CL_IO_RX_NONBLOCK); 210 + } 211 + EXPORT_SYMBOL_GPL(mei_cldev_recv_nonblock); 212 + 213 + /** 203 214 * mei_cldev_recv - client receive (read) 204 215 * 205 216 * @cldev: me client device ··· 231 204 { 232 205 struct mei_cl *cl = cldev->cl; 233 206 234 - return __mei_cl_recv(cl, buf, length); 207 + return __mei_cl_recv(cl, buf, length, 0); 235 208 } 236 209 EXPORT_SYMBOL_GPL(mei_cldev_recv); 237 210
+6 -1
drivers/misc/mei/mei_dev.h
··· 115 115 * 116 116 * @MEI_CL_IO_TX_BLOCKING: send is blocking 117 117 * @MEI_CL_IO_TX_INTERNAL: internal communication between driver and FW 118 + * 119 + * @MEI_CL_IO_RX_NONBLOCK: recv is non-blocking 118 120 */ 119 121 enum mei_cl_io_mode { 120 122 MEI_CL_IO_TX_BLOCKING = BIT(0), 121 123 MEI_CL_IO_TX_INTERNAL = BIT(1), 124 + 125 + MEI_CL_IO_RX_NONBLOCK = BIT(2), 122 126 }; 123 127 124 128 /* ··· 323 319 void mei_cl_bus_dev_fixup(struct mei_cl_device *dev); 324 320 ssize_t __mei_cl_send(struct mei_cl *cl, u8 *buf, size_t length, 325 321 unsigned int mode); 326 - ssize_t __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length); 322 + ssize_t __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length, 323 + unsigned int mode); 327 324 bool mei_cl_bus_rx_event(struct mei_cl *cl); 328 325 bool mei_cl_bus_notify_event(struct mei_cl *cl); 329 326 void mei_cl_bus_remove_devices(struct mei_device *bus);
+4 -2
include/linux/mei_cl_bus.h
··· 75 75 /** 76 76 * module_mei_cl_driver - Helper macro for registering mei cl driver 77 77 * 78 - * @__mei_cldrv mei_cl_driver structure 78 + * @__mei_cldrv: mei_cl_driver structure 79 79 * 80 80 * Helper macro for mei cl drivers which do not do anything special in module 81 81 * init/exit, for eliminating a boilerplate code. ··· 86 86 mei_cldev_driver_unregister) 87 87 88 88 ssize_t mei_cldev_send(struct mei_cl_device *cldev, u8 *buf, size_t length); 89 - ssize_t mei_cldev_recv(struct mei_cl_device *cldev, u8 *buf, size_t length); 89 + ssize_t mei_cldev_recv(struct mei_cl_device *cldev, u8 *buf, size_t length); 90 + ssize_t mei_cldev_recv_nonblock(struct mei_cl_device *cldev, u8 *buf, 91 + size_t length); 90 92 91 93 int mei_cldev_register_rx_cb(struct mei_cl_device *cldev, mei_cldev_cb_t rx_cb); 92 94 int mei_cldev_register_notif_cb(struct mei_cl_device *cldev,