aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexander Usyskin <alexander.usyskin@intel.com>2016-12-02 17:15:25 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2016-12-06 05:05:46 -0500
commit076802d0061520bc646ee121fe0f34fce6c55a93 (patch)
tree3c17b6372e44c369649691f8c90822bb3f8ea3e0
parenta2eb0fc07f4d4f3b2eb2b1b1b72de738d4b9e003 (diff)
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>
-rw-r--r--drivers/misc/mei/bus-fixup.c4
-rw-r--r--drivers/misc/mei/bus.c31
-rw-r--r--drivers/misc/mei/mei_dev.h7
-rw-r--r--include/linux/mei_cl_bus.h6
4 files changed, 41 insertions, 7 deletions
diff --git a/drivers/misc/mei/bus-fixup.c b/drivers/misc/mei/bus-fixup.c
index 7f2cef9011ae..18e05ca7584f 100644
--- a/drivers/misc/mei/bus-fixup.c
+++ b/drivers/misc/mei/bus-fixup.c
@@ -141,7 +141,7 @@ static int mei_osver(struct mei_cl_device *cldev)
141 if (ret < 0) 141 if (ret < 0)
142 return ret; 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 if (ret < 0) 145 if (ret < 0)
146 return ret; 146 return ret;
147 147
@@ -272,7 +272,7 @@ static int mei_nfc_if_version(struct mei_cl *cl,
272 return -ENOMEM; 272 return -ENOMEM;
273 273
274 ret = 0; 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 if (bytes_recv < if_version_length) { 276 if (bytes_recv < if_version_length) {
277 dev_err(bus->dev, "Could not read IF version\n"); 277 dev_err(bus->dev, "Could not read IF version\n");
278 ret = -EIO; 278 ret = -EIO;
diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c
index 2fd254ecde2f..0037153c80a6 100644
--- a/drivers/misc/mei/bus.c
+++ b/drivers/misc/mei/bus.c
@@ -98,15 +98,18 @@ out:
98 * @cl: host client 98 * @cl: host client
99 * @buf: buffer to receive 99 * @buf: buffer to receive
100 * @length: buffer length 100 * @length: buffer length
101 * @mode: io mode
101 * 102 *
102 * Return: read size in bytes of < 0 on error 103 * Return: read size in bytes of < 0 on error
103 */ 104 */
104ssize_t __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length) 105ssize_t __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length,
106 unsigned int mode)
105{ 107{
106 struct mei_device *bus; 108 struct mei_device *bus;
107 struct mei_cl_cb *cb; 109 struct mei_cl_cb *cb;
108 size_t r_length; 110 size_t r_length;
109 ssize_t rets; 111 ssize_t rets;
112 bool nonblock = !!(mode & MEI_CL_IO_RX_NONBLOCK);
110 113
111 if (WARN_ON(!cl || !cl->dev)) 114 if (WARN_ON(!cl || !cl->dev))
112 return -ENODEV; 115 return -ENODEV;
@@ -127,6 +130,11 @@ ssize_t __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length)
127 if (rets && rets != -EBUSY) 130 if (rets && rets != -EBUSY)
128 goto out; 131 goto out;
129 132
133 if (nonblock) {
134 rets = -EAGAIN;
135 goto out;
136 }
137
130 /* wait on event only if there is no other waiter */ 138 /* wait on event only if there is no other waiter */
131 /* synchronized under device mutex */ 139 /* synchronized under device mutex */
132 if (!waitqueue_active(&cl->rx_wait)) { 140 if (!waitqueue_active(&cl->rx_wait)) {
@@ -192,6 +200,25 @@ ssize_t mei_cldev_send(struct mei_cl_device *cldev, u8 *buf, size_t length)
192EXPORT_SYMBOL_GPL(mei_cldev_send); 200EXPORT_SYMBOL_GPL(mei_cldev_send);
193 201
194/** 202/**
203 * mei_cldev_recv_nonblock - non block client receive (read)
204 *
205 * @cldev: me client device
206 * @buf: buffer to receive
207 * @length: buffer length
208 *
209 * Return: read size in bytes of < 0 on error
210 * -EAGAIN if function will block.
211 */
212ssize_t mei_cldev_recv_nonblock(struct mei_cl_device *cldev, u8 *buf,
213 size_t length)
214{
215 struct mei_cl *cl = cldev->cl;
216
217 return __mei_cl_recv(cl, buf, length, MEI_CL_IO_RX_NONBLOCK);
218}
219EXPORT_SYMBOL_GPL(mei_cldev_recv_nonblock);
220
221/**
195 * mei_cldev_recv - client receive (read) 222 * mei_cldev_recv - client receive (read)
196 * 223 *
197 * @cldev: me client device 224 * @cldev: me client device
@@ -204,7 +231,7 @@ ssize_t mei_cldev_recv(struct mei_cl_device *cldev, u8 *buf, size_t length)
204{ 231{
205 struct mei_cl *cl = cldev->cl; 232 struct mei_cl *cl = cldev->cl;
206 233
207 return __mei_cl_recv(cl, buf, length); 234 return __mei_cl_recv(cl, buf, length, 0);
208} 235}
209EXPORT_SYMBOL_GPL(mei_cldev_recv); 236EXPORT_SYMBOL_GPL(mei_cldev_recv);
210 237
diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h
index 0e94df517410..699693cd8c59 100644
--- a/drivers/misc/mei/mei_dev.h
+++ b/drivers/misc/mei/mei_dev.h
@@ -115,10 +115,14 @@ enum mei_cb_file_ops {
115 * 115 *
116 * @MEI_CL_IO_TX_BLOCKING: send is blocking 116 * @MEI_CL_IO_TX_BLOCKING: send is blocking
117 * @MEI_CL_IO_TX_INTERNAL: internal communication between driver and FW 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 */
119enum mei_cl_io_mode { 121enum mei_cl_io_mode {
120 MEI_CL_IO_TX_BLOCKING = BIT(0), 122 MEI_CL_IO_TX_BLOCKING = BIT(0),
121 MEI_CL_IO_TX_INTERNAL = BIT(1), 123 MEI_CL_IO_TX_INTERNAL = BIT(1),
124
125 MEI_CL_IO_RX_NONBLOCK = BIT(2),
122}; 126};
123 127
124/* 128/*
@@ -319,7 +323,8 @@ void mei_cl_bus_rescan_work(struct work_struct *work);
319void mei_cl_bus_dev_fixup(struct mei_cl_device *dev); 323void mei_cl_bus_dev_fixup(struct mei_cl_device *dev);
320ssize_t __mei_cl_send(struct mei_cl *cl, u8 *buf, size_t length, 324ssize_t __mei_cl_send(struct mei_cl *cl, u8 *buf, size_t length,
321 unsigned int mode); 325 unsigned int mode);
322ssize_t __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length); 326ssize_t __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length,
327 unsigned int mode);
323bool mei_cl_bus_rx_event(struct mei_cl *cl); 328bool mei_cl_bus_rx_event(struct mei_cl *cl);
324bool mei_cl_bus_notify_event(struct mei_cl *cl); 329bool mei_cl_bus_notify_event(struct mei_cl *cl);
325void mei_cl_bus_remove_devices(struct mei_device *bus); 330void mei_cl_bus_remove_devices(struct mei_device *bus);
diff --git a/include/linux/mei_cl_bus.h b/include/linux/mei_cl_bus.h
index 017f5232b3de..a0d274fe08f1 100644
--- a/include/linux/mei_cl_bus.h
+++ b/include/linux/mei_cl_bus.h
@@ -75,7 +75,7 @@ void mei_cldev_driver_unregister(struct mei_cl_driver *cldrv);
75/** 75/**
76 * module_mei_cl_driver - Helper macro for registering mei cl driver 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 * Helper macro for mei cl drivers which do not do anything special in module 80 * Helper macro for mei cl drivers which do not do anything special in module
81 * init/exit, for eliminating a boilerplate code. 81 * init/exit, for eliminating a boilerplate code.
@@ -86,7 +86,9 @@ void mei_cldev_driver_unregister(struct mei_cl_driver *cldrv);
86 mei_cldev_driver_unregister) 86 mei_cldev_driver_unregister)
87 87
88ssize_t mei_cldev_send(struct mei_cl_device *cldev, u8 *buf, size_t length); 88ssize_t mei_cldev_send(struct mei_cl_device *cldev, u8 *buf, size_t length);
89ssize_t mei_cldev_recv(struct mei_cl_device *cldev, u8 *buf, size_t length); 89ssize_t mei_cldev_recv(struct mei_cl_device *cldev, u8 *buf, size_t length);
90ssize_t mei_cldev_recv_nonblock(struct mei_cl_device *cldev, u8 *buf,
91 size_t length);
90 92
91int mei_cldev_register_rx_cb(struct mei_cl_device *cldev, mei_cldev_cb_t rx_cb); 93int mei_cldev_register_rx_cb(struct mei_cl_device *cldev, mei_cldev_cb_t rx_cb);
92int mei_cldev_register_notif_cb(struct mei_cl_device *cldev, 94int mei_cldev_register_notif_cb(struct mei_cl_device *cldev,