PageRenderTime 210ms CodeModel.GetById 66ms app.highlight 30ms RepoModel.GetById 18ms app.codeStats 90ms

/drivers/staging/mei/iorw.c

https://bitbucket.org/cyanogenmod/android_kernel_asus_tf300t
C | 604 lines | 428 code | 77 blank | 99 comment | 98 complexity | ab343b3257cdb394af4b4f36b3b7677c MD5 | raw file
Possible License(s): LGPL-2.0, AGPL-1.0, GPL-2.0
  1/*
  2 *
  3 * Intel Management Engine Interface (Intel MEI) Linux driver
  4 * Copyright (c) 2003-2011, Intel Corporation.
  5 *
  6 * This program is free software; you can redistribute it and/or modify it
  7 * under the terms and conditions of the GNU General Public License,
  8 * version 2, as published by the Free Software Foundation.
  9 *
 10 * This program is distributed in the hope it will be useful, but WITHOUT
 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 12 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 13 * more details.
 14 *
 15 */
 16
 17
 18#include <linux/kernel.h>
 19#include <linux/fs.h>
 20#include <linux/errno.h>
 21#include <linux/types.h>
 22#include <linux/fcntl.h>
 23#include <linux/aio.h>
 24#include <linux/pci.h>
 25#include <linux/init.h>
 26#include <linux/ioctl.h>
 27#include <linux/cdev.h>
 28#include <linux/list.h>
 29#include <linux/delay.h>
 30#include <linux/sched.h>
 31#include <linux/uuid.h>
 32#include <linux/jiffies.h>
 33#include <linux/uaccess.h>
 34
 35
 36#include "mei_dev.h"
 37#include "hw.h"
 38#include "mei.h"
 39#include "interface.h"
 40#include "mei_version.h"
 41
 42
 43
 44/**
 45 * mei_ioctl_connect_client - the connect to fw client IOCTL function
 46 *
 47 * @dev: the device structure
 48 * @data: IOCTL connect data, input and output parameters
 49 * @file: private data of the file object
 50 *
 51 * Locking: called under "dev->device_lock" lock
 52 *
 53 * returns 0 on success, <0 on failure.
 54 */
 55int mei_ioctl_connect_client(struct file *file,
 56			struct mei_connect_client_data *data)
 57{
 58	struct mei_device *dev;
 59	struct mei_cl_cb *cb;
 60	struct mei_client *client;
 61	struct mei_cl *cl;
 62	struct mei_cl *cl_pos = NULL;
 63	struct mei_cl *cl_next = NULL;
 64	long timeout = CONNECT_TIMEOUT;
 65	int i;
 66	int err;
 67	int rets;
 68
 69	cl = file->private_data;
 70	if (WARN_ON(!cl || !cl->dev))
 71		return -ENODEV;
 72
 73	dev = cl->dev;
 74
 75	dev_dbg(&dev->pdev->dev, "mei_ioctl_connect_client() Entry\n");
 76
 77
 78	/* buffered ioctl cb */
 79	cb = kzalloc(sizeof(struct mei_cl_cb), GFP_KERNEL);
 80	if (!cb) {
 81		rets = -ENOMEM;
 82		goto end;
 83	}
 84	INIT_LIST_HEAD(&cb->cb_list);
 85
 86	cb->major_file_operations = MEI_IOCTL;
 87
 88	if (dev->mei_state != MEI_ENABLED) {
 89		rets = -ENODEV;
 90		goto end;
 91	}
 92	if (cl->state != MEI_FILE_INITIALIZING &&
 93	    cl->state != MEI_FILE_DISCONNECTED) {
 94		rets = -EBUSY;
 95		goto end;
 96	}
 97
 98	/* find ME client we're trying to connect to */
 99	i = mei_find_me_client_index(dev, data->in_client_uuid);
100	if (i >= 0 && !dev->me_clients[i].props.fixed_address) {
101		cl->me_client_id = dev->me_clients[i].client_id;
102		cl->state = MEI_FILE_CONNECTING;
103	}
104
105	dev_dbg(&dev->pdev->dev, "Connect to FW Client ID = %d\n",
106			cl->me_client_id);
107	dev_dbg(&dev->pdev->dev, "FW Client - Protocol Version = %d\n",
108			dev->me_clients[i].props.protocol_version);
109	dev_dbg(&dev->pdev->dev, "FW Client - Max Msg Len = %d\n",
110			dev->me_clients[i].props.max_msg_length);
111
112	/* if we're connecting to amthi client so we will use the exist
113	 * connection
114	 */
115	if (uuid_le_cmp(data->in_client_uuid, mei_amthi_guid) == 0) {
116		dev_dbg(&dev->pdev->dev, "FW Client is amthi\n");
117		if (dev->iamthif_cl.state != MEI_FILE_CONNECTED) {
118			rets = -ENODEV;
119			goto end;
120		}
121		clear_bit(cl->host_client_id, dev->host_clients_map);
122		list_for_each_entry_safe(cl_pos, cl_next,
123					 &dev->file_list, link) {
124			if (mei_cl_cmp_id(cl, cl_pos)) {
125				dev_dbg(&dev->pdev->dev,
126					"remove file private data node host"
127				    " client = %d, ME client = %d.\n",
128				    cl_pos->host_client_id,
129				    cl_pos->me_client_id);
130				list_del(&cl_pos->link);
131			}
132
133		}
134		dev_dbg(&dev->pdev->dev, "free file private data memory.\n");
135		kfree(cl);
136
137		cl = NULL;
138		file->private_data = &dev->iamthif_cl;
139
140		client = &data->out_client_properties;
141		client->max_msg_length =
142			dev->me_clients[i].props.max_msg_length;
143		client->protocol_version =
144			dev->me_clients[i].props.protocol_version;
145		rets = dev->iamthif_cl.status;
146
147		goto end;
148	}
149
150	if (cl->state != MEI_FILE_CONNECTING) {
151		rets = -ENODEV;
152		goto end;
153	}
154
155
156	/* prepare the output buffer */
157	client = &data->out_client_properties;
158	client->max_msg_length = dev->me_clients[i].props.max_msg_length;
159	client->protocol_version = dev->me_clients[i].props.protocol_version;
160	dev_dbg(&dev->pdev->dev, "Can connect?\n");
161	if (dev->mei_host_buffer_is_empty
162	    && !mei_other_client_is_connecting(dev, cl)) {
163		dev_dbg(&dev->pdev->dev, "Sending Connect Message\n");
164		dev->mei_host_buffer_is_empty = false;
165		if (!mei_connect(dev, cl)) {
166			dev_dbg(&dev->pdev->dev, "Sending connect message - failed\n");
167			rets = -ENODEV;
168			goto end;
169		} else {
170			dev_dbg(&dev->pdev->dev, "Sending connect message - succeeded\n");
171			cl->timer_count = MEI_CONNECT_TIMEOUT;
172			cb->file_private = cl;
173			list_add_tail(&cb->cb_list,
174				      &dev->ctrl_rd_list.mei_cb.
175				      cb_list);
176		}
177
178
179	} else {
180		dev_dbg(&dev->pdev->dev, "Queuing the connect request due to device busy\n");
181		cb->file_private = cl;
182		dev_dbg(&dev->pdev->dev, "add connect cb to control write list.\n");
183		list_add_tail(&cb->cb_list,
184			      &dev->ctrl_wr_list.mei_cb.cb_list);
185	}
186	mutex_unlock(&dev->device_lock);
187	err = wait_event_timeout(dev->wait_recvd_msg,
188			(MEI_FILE_CONNECTED == cl->state ||
189			 MEI_FILE_DISCONNECTED == cl->state),
190			timeout * HZ);
191
192	mutex_lock(&dev->device_lock);
193	if (MEI_FILE_CONNECTED == cl->state) {
194		dev_dbg(&dev->pdev->dev, "successfully connected to FW client.\n");
195		rets = cl->status;
196		goto end;
197	} else {
198		dev_dbg(&dev->pdev->dev, "failed to connect to FW client.cl->state = %d.\n",
199		    cl->state);
200		if (!err) {
201			dev_dbg(&dev->pdev->dev,
202				"wait_event_interruptible_timeout failed on client"
203				" connect message fw response message.\n");
204		}
205		rets = -EFAULT;
206
207		mei_io_list_flush(&dev->ctrl_rd_list, cl);
208		mei_io_list_flush(&dev->ctrl_wr_list, cl);
209		goto end;
210	}
211	rets = 0;
212end:
213	dev_dbg(&dev->pdev->dev, "free connect cb memory.");
214	kfree(cb);
215	return rets;
216}
217
218/**
219 * find_amthi_read_list_entry - finds a amthilist entry for current file
220 *
221 * @dev: the device structure
222 * @file: pointer to file object
223 *
224 * returns   returned a list entry on success, NULL on failure.
225 */
226struct mei_cl_cb *find_amthi_read_list_entry(
227		struct mei_device *dev,
228		struct file *file)
229{
230	struct mei_cl *cl_temp;
231	struct mei_cl_cb *cb_pos = NULL;
232	struct mei_cl_cb *cb_next = NULL;
233
234	if (!dev->amthi_read_complete_list.status &&
235	    !list_empty(&dev->amthi_read_complete_list.mei_cb.cb_list)) {
236		list_for_each_entry_safe(cb_pos, cb_next,
237		    &dev->amthi_read_complete_list.mei_cb.cb_list, cb_list) {
238			cl_temp = (struct mei_cl *)cb_pos->file_private;
239			if (cl_temp && cl_temp == &dev->iamthif_cl &&
240				cb_pos->file_object == file)
241				return cb_pos;
242		}
243	}
244	return NULL;
245}
246
247/**
248 * amthi_read - read data from AMTHI client
249 *
250 * @dev: the device structure
251 * @if_num:  minor number
252 * @file: pointer to file object
253 * @*ubuf: pointer to user data in user space
254 * @length: data length to read
255 * @offset: data read offset
256 *
257 * Locking: called under "dev->device_lock" lock
258 *
259 * returns
260 *  returned data length on success,
261 *  zero if no data to read,
262 *  negative on failure.
263 */
264int amthi_read(struct mei_device *dev, struct file *file,
265	      char __user *ubuf, size_t length, loff_t *offset)
266{
267	int rets;
268	int wait_ret;
269	struct mei_cl_cb *cb = NULL;
270	struct mei_cl *cl = file->private_data;
271	unsigned long timeout;
272	int i;
273
274	/* Only Posible if we are in timeout */
275	if (!cl || cl != &dev->iamthif_cl) {
276		dev_dbg(&dev->pdev->dev, "bad file ext.\n");
277		return -ETIMEDOUT;
278	}
279
280	for (i = 0; i < dev->me_clients_num; i++) {
281		if (dev->me_clients[i].client_id ==
282		    dev->iamthif_cl.me_client_id)
283			break;
284	}
285
286	if (i == dev->me_clients_num) {
287		dev_dbg(&dev->pdev->dev, "amthi client not found.\n");
288		return -ENODEV;
289	}
290	if (WARN_ON(dev->me_clients[i].client_id != cl->me_client_id))
291		return -ENODEV;
292
293	dev_dbg(&dev->pdev->dev, "checking amthi data\n");
294	cb = find_amthi_read_list_entry(dev, file);
295
296	/* Check for if we can block or not*/
297	if (cb == NULL && file->f_flags & O_NONBLOCK)
298		return -EAGAIN;
299
300
301	dev_dbg(&dev->pdev->dev, "waiting for amthi data\n");
302	while (cb == NULL) {
303		/* unlock the Mutex */
304		mutex_unlock(&dev->device_lock);
305
306		wait_ret = wait_event_interruptible(dev->iamthif_cl.wait,
307			(cb = find_amthi_read_list_entry(dev, file)));
308
309		if (wait_ret)
310			return -ERESTARTSYS;
311
312		dev_dbg(&dev->pdev->dev, "woke up from sleep\n");
313
314		/* Locking again the Mutex */
315		mutex_lock(&dev->device_lock);
316	}
317
318
319	dev_dbg(&dev->pdev->dev, "Got amthi data\n");
320	dev->iamthif_timer = 0;
321
322	if (cb) {
323		timeout = cb->read_time +
324					msecs_to_jiffies(IAMTHIF_READ_TIMER);
325		dev_dbg(&dev->pdev->dev, "amthi timeout = %lud\n",
326				timeout);
327
328		if  (time_after(jiffies, timeout)) {
329			dev_dbg(&dev->pdev->dev, "amthi Time out\n");
330			/* 15 sec for the message has expired */
331			list_del(&cb->cb_list);
332			rets = -ETIMEDOUT;
333			goto free;
334		}
335	}
336	/* if the whole message will fit remove it from the list */
337	if (cb->information >= *offset &&
338	    length >= (cb->information - *offset))
339		list_del(&cb->cb_list);
340	else if (cb->information > 0 && cb->information <= *offset) {
341		/* end of the message has been reached */
342		list_del(&cb->cb_list);
343		rets = 0;
344		goto free;
345	}
346		/* else means that not full buffer will be read and do not
347		 * remove message from deletion list
348		 */
349
350	dev_dbg(&dev->pdev->dev, "amthi cb->response_buffer size - %d\n",
351	    cb->response_buffer.size);
352	dev_dbg(&dev->pdev->dev, "amthi cb->information - %lu\n",
353	    cb->information);
354
355	/* length is being turncated to PAGE_SIZE, however,
356	 * the information may be longer */
357	length = min_t(size_t, length, (cb->information - *offset));
358
359	if (copy_to_user(ubuf,
360			 cb->response_buffer.data + *offset,
361			 length))
362		rets = -EFAULT;
363	else {
364		rets = length;
365		if ((*offset + length) < cb->information) {
366			*offset += length;
367			goto out;
368		}
369	}
370free:
371	dev_dbg(&dev->pdev->dev, "free amthi cb memory.\n");
372	*offset = 0;
373	mei_free_cb_private(cb);
374out:
375	return rets;
376}
377
378/**
379 * mei_start_read - the start read client message function.
380 *
381 * @dev: the device structure
382 * @if_num:  minor number
383 * @cl: private data of the file object
384 *
385 * returns 0 on success, <0 on failure.
386 */
387int mei_start_read(struct mei_device *dev, struct mei_cl *cl)
388{
389	struct mei_cl_cb *cb;
390	int rets = 0;
391	int i;
392
393	if (cl->state != MEI_FILE_CONNECTED)
394		return -ENODEV;
395
396	if (dev->mei_state != MEI_ENABLED)
397		return -ENODEV;
398
399	dev_dbg(&dev->pdev->dev, "check if read is pending.\n");
400	if (cl->read_pending || cl->read_cb) {
401		dev_dbg(&dev->pdev->dev, "read is pending.\n");
402		return -EBUSY;
403	}
404
405	cb = kzalloc(sizeof(struct mei_cl_cb), GFP_KERNEL);
406	if (!cb)
407		return -ENOMEM;
408
409	dev_dbg(&dev->pdev->dev, "allocation call back successful. host client = %d, ME client = %d\n",
410		cl->host_client_id, cl->me_client_id);
411
412	for (i = 0; i < dev->me_clients_num; i++) {
413		if (dev->me_clients[i].client_id == cl->me_client_id)
414			break;
415
416	}
417
418	if (WARN_ON(dev->me_clients[i].client_id != cl->me_client_id)) {
419		rets = -ENODEV;
420		goto unlock;
421	}
422
423	if (i == dev->me_clients_num) {
424		rets = -ENODEV;
425		goto unlock;
426	}
427
428	cb->response_buffer.size = dev->me_clients[i].props.max_msg_length;
429	cb->response_buffer.data =
430	    kmalloc(cb->response_buffer.size, GFP_KERNEL);
431	if (!cb->response_buffer.data) {
432		rets = -ENOMEM;
433		goto unlock;
434	}
435	dev_dbg(&dev->pdev->dev, "allocation call back data success.\n");
436	cb->major_file_operations = MEI_READ;
437	/* make sure information is zero before we start */
438	cb->information = 0;
439	cb->file_private = (void *) cl;
440	cl->read_cb = cb;
441	if (dev->mei_host_buffer_is_empty) {
442		dev->mei_host_buffer_is_empty = false;
443		if (!mei_send_flow_control(dev, cl)) {
444			rets = -ENODEV;
445			goto unlock;
446		} else {
447			list_add_tail(&cb->cb_list,
448				      &dev->read_list.mei_cb.cb_list);
449		}
450	} else {
451		list_add_tail(&cb->cb_list,
452			      &dev->ctrl_wr_list.mei_cb.cb_list);
453	}
454	return rets;
455unlock:
456	mei_free_cb_private(cb);
457	return rets;
458}
459
460/**
461 * amthi_write - write iamthif data to amthi client
462 *
463 * @dev: the device structure
464 * @cb: mei call back struct
465 *
466 * returns 0 on success, <0 on failure.
467 */
468int amthi_write(struct mei_device *dev, struct mei_cl_cb *cb)
469{
470	struct mei_msg_hdr mei_hdr;
471	int ret;
472
473	if (!dev || !cb)
474		return -ENODEV;
475
476	dev_dbg(&dev->pdev->dev, "write data to amthi client.\n");
477
478	dev->iamthif_state = MEI_IAMTHIF_WRITING;
479	dev->iamthif_current_cb = cb;
480	dev->iamthif_file_object = cb->file_object;
481	dev->iamthif_canceled = false;
482	dev->iamthif_ioctl = true;
483	dev->iamthif_msg_buf_size = cb->request_buffer.size;
484	memcpy(dev->iamthif_msg_buf, cb->request_buffer.data,
485	    cb->request_buffer.size);
486
487	ret = mei_flow_ctrl_creds(dev, &dev->iamthif_cl);
488	if (ret < 0)
489		return ret;
490
491	if (ret && dev->mei_host_buffer_is_empty) {
492		ret = 0;
493		dev->mei_host_buffer_is_empty = false;
494		if (cb->request_buffer.size >
495			(((dev->host_hw_state & H_CBD) >> 24) * sizeof(u32))
496				-sizeof(struct mei_msg_hdr)) {
497			mei_hdr.length =
498			    (((dev->host_hw_state & H_CBD) >> 24) *
499			    sizeof(u32)) - sizeof(struct mei_msg_hdr);
500			mei_hdr.msg_complete = 0;
501		} else {
502			mei_hdr.length = cb->request_buffer.size;
503			mei_hdr.msg_complete = 1;
504		}
505
506		mei_hdr.host_addr = dev->iamthif_cl.host_client_id;
507		mei_hdr.me_addr = dev->iamthif_cl.me_client_id;
508		mei_hdr.reserved = 0;
509		dev->iamthif_msg_buf_index += mei_hdr.length;
510		if (!mei_write_message(dev, &mei_hdr,
511					(unsigned char *)(dev->iamthif_msg_buf),
512					mei_hdr.length))
513			return -ENODEV;
514
515		if (mei_hdr.msg_complete) {
516			if (mei_flow_ctrl_reduce(dev, &dev->iamthif_cl))
517				return -ENODEV;
518			dev->iamthif_flow_control_pending = true;
519			dev->iamthif_state = MEI_IAMTHIF_FLOW_CONTROL;
520			dev_dbg(&dev->pdev->dev, "add amthi cb to write waiting list\n");
521			dev->iamthif_current_cb = cb;
522			dev->iamthif_file_object = cb->file_object;
523			list_add_tail(&cb->cb_list,
524				      &dev->write_waiting_list.mei_cb.cb_list);
525		} else {
526			dev_dbg(&dev->pdev->dev, "message does not complete, "
527					"so add amthi cb to write list.\n");
528			list_add_tail(&cb->cb_list,
529				      &dev->write_list.mei_cb.cb_list);
530		}
531	} else {
532		if (!(dev->mei_host_buffer_is_empty))
533			dev_dbg(&dev->pdev->dev, "host buffer is not empty");
534
535		dev_dbg(&dev->pdev->dev, "No flow control credentials, "
536				"so add iamthif cb to write list.\n");
537		list_add_tail(&cb->cb_list,
538			      &dev->write_list.mei_cb.cb_list);
539	}
540	return 0;
541}
542
543/**
544 * iamthif_ioctl_send_msg - send cmd data to amthi client
545 *
546 * @dev: the device structure
547 *
548 * returns 0 on success, <0 on failure.
549 */
550void mei_run_next_iamthif_cmd(struct mei_device *dev)
551{
552	struct mei_cl *cl_tmp;
553	struct mei_cl_cb *cb_pos = NULL;
554	struct mei_cl_cb *cb_next = NULL;
555	int status;
556
557	if (!dev)
558		return;
559
560	dev->iamthif_msg_buf_size = 0;
561	dev->iamthif_msg_buf_index = 0;
562	dev->iamthif_canceled = false;
563	dev->iamthif_ioctl = true;
564	dev->iamthif_state = MEI_IAMTHIF_IDLE;
565	dev->iamthif_timer = 0;
566	dev->iamthif_file_object = NULL;
567
568	if (dev->amthi_cmd_list.status == 0 &&
569	    !list_empty(&dev->amthi_cmd_list.mei_cb.cb_list)) {
570		dev_dbg(&dev->pdev->dev, "complete amthi cmd_list cb.\n");
571
572		list_for_each_entry_safe(cb_pos, cb_next,
573		    &dev->amthi_cmd_list.mei_cb.cb_list, cb_list) {
574			list_del(&cb_pos->cb_list);
575			cl_tmp = (struct mei_cl *)cb_pos->file_private;
576
577			if (cl_tmp && cl_tmp == &dev->iamthif_cl) {
578				status = amthi_write(dev, cb_pos);
579				if (status) {
580					dev_dbg(&dev->pdev->dev,
581						"amthi write failed status = %d\n",
582							status);
583					return;
584				}
585				break;
586			}
587		}
588	}
589}
590
591/**
592 * mei_free_cb_private - free mei_cb_private related memory
593 *
594 * @cb: mei callback struct
595 */
596void mei_free_cb_private(struct mei_cl_cb *cb)
597{
598	if (cb == NULL)
599		return;
600
601	kfree(cb->request_buffer.data);
602	kfree(cb->response_buffer.data);
603	kfree(cb);
604}