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