diff options
author | Tomas Winkler <tomas.winkler@intel.com> | 2013-04-08 14:56:37 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2013-04-08 19:55:57 -0400 |
commit | 4234a6deb5ab04e50cfd6d72761345727bd2de21 (patch) | |
tree | 6da543ec16e78959e5a05055d4b6cee393d2ad47 /drivers/misc/mei/bus.c | |
parent | 606f34ad124faeeb77830d7fdfc513084566d2ba (diff) |
mei: add mei_cl_write function
consolidate write code to a specific me client in mei_cl_write function
the function is called from mei device write handler and from
mei_cl bus send function
Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/misc/mei/bus.c')
-rw-r--r-- | drivers/misc/mei/bus.c | 103 |
1 files changed, 19 insertions, 84 deletions
diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c index 8dbcb1516dc6..6badfa1110e9 100644 --- a/drivers/misc/mei/bus.c +++ b/drivers/misc/mei/bus.c | |||
@@ -226,112 +226,47 @@ static int ___mei_cl_send(struct mei_cl *cl, u8 *buf, size_t length, | |||
226 | bool blocking) | 226 | bool blocking) |
227 | { | 227 | { |
228 | struct mei_device *dev; | 228 | struct mei_device *dev; |
229 | struct mei_msg_hdr mei_hdr; | ||
230 | struct mei_cl_cb *cb; | 229 | struct mei_cl_cb *cb; |
231 | int me_cl_id, err; | 230 | int id; |
231 | int rets; | ||
232 | 232 | ||
233 | if (WARN_ON(!cl || !cl->dev)) | 233 | if (WARN_ON(!cl || !cl->dev)) |
234 | return -ENODEV; | 234 | return -ENODEV; |
235 | 235 | ||
236 | dev = cl->dev; | ||
237 | |||
236 | if (cl->state != MEI_FILE_CONNECTED) | 238 | if (cl->state != MEI_FILE_CONNECTED) |
237 | return -ENODEV; | 239 | return -ENODEV; |
238 | 240 | ||
241 | /* Check if we have an ME client device */ | ||
242 | id = mei_me_cl_by_id(dev, cl->me_client_id); | ||
243 | if (id < 0) | ||
244 | return -ENODEV; | ||
245 | |||
246 | if (length > dev->me_clients[id].props.max_msg_length) | ||
247 | return -EINVAL; | ||
248 | |||
239 | cb = mei_io_cb_init(cl, NULL); | 249 | cb = mei_io_cb_init(cl, NULL); |
240 | if (!cb) | 250 | if (!cb) |
241 | return -ENOMEM; | 251 | return -ENOMEM; |
242 | 252 | ||
243 | err = mei_io_cb_alloc_req_buf(cb, length); | 253 | rets = mei_io_cb_alloc_req_buf(cb, length); |
244 | if (err < 0) { | 254 | if (rets < 0) { |
245 | mei_io_cb_free(cb); | 255 | mei_io_cb_free(cb); |
246 | return err; | 256 | return rets; |
247 | } | 257 | } |
248 | 258 | ||
249 | memcpy(cb->request_buffer.data, buf, length); | 259 | memcpy(cb->request_buffer.data, buf, length); |
250 | cb->fop_type = MEI_FOP_WRITE; | ||
251 | |||
252 | dev = cl->dev; | ||
253 | 260 | ||
254 | mutex_lock(&dev->device_lock); | 261 | mutex_lock(&dev->device_lock); |
255 | 262 | ||
256 | /* Check if we have an ME client device */ | 263 | rets = mei_cl_write(cl, cb, blocking); |
257 | me_cl_id = mei_me_cl_by_id(dev, cl->me_client_id); | ||
258 | if (me_cl_id == dev->me_clients_num) { | ||
259 | err = -ENODEV; | ||
260 | goto out_err; | ||
261 | } | ||
262 | |||
263 | if (length > dev->me_clients[me_cl_id].props.max_msg_length) { | ||
264 | err = -EINVAL; | ||
265 | goto out_err; | ||
266 | } | ||
267 | |||
268 | err = mei_cl_flow_ctrl_creds(cl); | ||
269 | if (err < 0) | ||
270 | goto out_err; | ||
271 | |||
272 | /* Host buffer is not ready, we queue the request */ | ||
273 | if (err == 0 || !dev->hbuf_is_ready) { | ||
274 | cb->buf_idx = 0; | ||
275 | mei_hdr.msg_complete = 0; | ||
276 | cl->writing_state = MEI_WRITING; | ||
277 | |||
278 | goto out; | ||
279 | } | ||
280 | |||
281 | dev->hbuf_is_ready = false; | ||
282 | |||
283 | /* Check for a maximum length */ | ||
284 | if (length > mei_hbuf_max_len(dev)) { | ||
285 | mei_hdr.length = mei_hbuf_max_len(dev); | ||
286 | mei_hdr.msg_complete = 0; | ||
287 | } else { | ||
288 | mei_hdr.length = length; | ||
289 | mei_hdr.msg_complete = 1; | ||
290 | } | ||
291 | |||
292 | mei_hdr.host_addr = cl->host_client_id; | ||
293 | mei_hdr.me_addr = cl->me_client_id; | ||
294 | mei_hdr.reserved = 0; | ||
295 | |||
296 | if (mei_write_message(dev, &mei_hdr, buf)) { | ||
297 | err = -EIO; | ||
298 | goto out_err; | ||
299 | } | ||
300 | |||
301 | cl->writing_state = MEI_WRITING; | ||
302 | cb->buf_idx = mei_hdr.length; | ||
303 | |||
304 | out: | ||
305 | if (mei_hdr.msg_complete) { | ||
306 | if (mei_cl_flow_ctrl_reduce(cl)) { | ||
307 | err = -ENODEV; | ||
308 | goto out_err; | ||
309 | } | ||
310 | list_add_tail(&cb->list, &dev->write_waiting_list.list); | ||
311 | } else { | ||
312 | list_add_tail(&cb->list, &dev->write_list.list); | ||
313 | } | ||
314 | 264 | ||
315 | mutex_unlock(&dev->device_lock); | 265 | mutex_unlock(&dev->device_lock); |
266 | if (rets < 0) | ||
267 | mei_io_cb_free(cb); | ||
316 | 268 | ||
317 | if (blocking && cl->writing_state != MEI_WRITE_COMPLETE) { | 269 | return rets; |
318 | if (wait_event_interruptible(cl->tx_wait, | ||
319 | cl->writing_state == MEI_WRITE_COMPLETE)) { | ||
320 | if (signal_pending(current)) | ||
321 | err = -EINTR; | ||
322 | err = -ERESTARTSYS; | ||
323 | mutex_lock(&dev->device_lock); | ||
324 | goto out_err; | ||
325 | } | ||
326 | } | ||
327 | |||
328 | return mei_hdr.length; | ||
329 | |||
330 | out_err: | ||
331 | mutex_unlock(&dev->device_lock); | ||
332 | mei_io_cb_free(cb); | ||
333 | |||
334 | return err; | ||
335 | } | 270 | } |
336 | 271 | ||
337 | int __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length) | 272 | int __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length) |