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  */
mei_ioctl_connect_client(struct file * file,struct mei_connect_client_data * data)55 int 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;
212 end:
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  */
find_amthi_read_list_entry(struct mei_device * dev,struct file * file)226 struct 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 *pos = NULL;
232 	struct mei_cl_cb *next = NULL;
233 
234 	list_for_each_entry_safe(pos, next,
235 	    &dev->amthi_read_complete_list.mei_cb.cb_list, cb_list) {
236 		cl_temp = (struct mei_cl *)pos->file_private;
237 		if (cl_temp && cl_temp == &dev->iamthif_cl &&
238 			pos->file_object == file)
239 			return pos;
240 	}
241 	return NULL;
242 }
243 
244 /**
245  * amthi_read - read data from AMTHI client
246  *
247  * @dev: the device structure
248  * @if_num:  minor number
249  * @file: pointer to file object
250  * @*ubuf: pointer to user data in user space
251  * @length: data length to read
252  * @offset: data read offset
253  *
254  * Locking: called under "dev->device_lock" lock
255  *
256  * returns
257  *  returned data length on success,
258  *  zero if no data to read,
259  *  negative on failure.
260  */
amthi_read(struct mei_device * dev,struct file * file,char __user * ubuf,size_t length,loff_t * offset)261 int amthi_read(struct mei_device *dev, struct file *file,
262 	       char __user *ubuf, size_t length, loff_t *offset)
263 {
264 	int rets;
265 	int wait_ret;
266 	struct mei_cl_cb *cb = NULL;
267 	struct mei_cl *cl = file->private_data;
268 	unsigned long timeout;
269 	int i;
270 
271 	/* Only Posible if we are in timeout */
272 	if (!cl || cl != &dev->iamthif_cl) {
273 		dev_dbg(&dev->pdev->dev, "bad file ext.\n");
274 		return -ETIMEDOUT;
275 	}
276 
277 	for (i = 0; i < dev->me_clients_num; i++) {
278 		if (dev->me_clients[i].client_id ==
279 		    dev->iamthif_cl.me_client_id)
280 			break;
281 	}
282 
283 	if (i == dev->me_clients_num) {
284 		dev_dbg(&dev->pdev->dev, "amthi client not found.\n");
285 		return -ENODEV;
286 	}
287 	if (WARN_ON(dev->me_clients[i].client_id != cl->me_client_id))
288 		return -ENODEV;
289 
290 	dev_dbg(&dev->pdev->dev, "checking amthi data\n");
291 	cb = find_amthi_read_list_entry(dev, file);
292 
293 	/* Check for if we can block or not*/
294 	if (cb == NULL && file->f_flags & O_NONBLOCK)
295 		return -EAGAIN;
296 
297 
298 	dev_dbg(&dev->pdev->dev, "waiting for amthi data\n");
299 	while (cb == NULL) {
300 		/* unlock the Mutex */
301 		mutex_unlock(&dev->device_lock);
302 
303 		wait_ret = wait_event_interruptible(dev->iamthif_cl.wait,
304 			(cb = find_amthi_read_list_entry(dev, file)));
305 
306 		if (wait_ret)
307 			return -ERESTARTSYS;
308 
309 		dev_dbg(&dev->pdev->dev, "woke up from sleep\n");
310 
311 		/* Locking again the Mutex */
312 		mutex_lock(&dev->device_lock);
313 	}
314 
315 
316 	dev_dbg(&dev->pdev->dev, "Got amthi data\n");
317 	dev->iamthif_timer = 0;
318 
319 	if (cb) {
320 		timeout = cb->read_time +
321 					msecs_to_jiffies(IAMTHIF_READ_TIMER);
322 		dev_dbg(&dev->pdev->dev, "amthi timeout = %lud\n",
323 				timeout);
324 
325 		if  (time_after(jiffies, timeout)) {
326 			dev_dbg(&dev->pdev->dev, "amthi Time out\n");
327 			/* 15 sec for the message has expired */
328 			list_del(&cb->cb_list);
329 			rets = -ETIMEDOUT;
330 			goto free;
331 		}
332 	}
333 	/* if the whole message will fit remove it from the list */
334 	if (cb->information >= *offset && length >= (cb->information - *offset))
335 		list_del(&cb->cb_list);
336 	else if (cb->information > 0 && cb->information <= *offset) {
337 		/* end of the message has been reached */
338 		list_del(&cb->cb_list);
339 		rets = 0;
340 		goto free;
341 	}
342 		/* else means that not full buffer will be read and do not
343 		 * remove message from deletion list
344 		 */
345 
346 	dev_dbg(&dev->pdev->dev, "amthi cb->response_buffer size - %d\n",
347 	    cb->response_buffer.size);
348 	dev_dbg(&dev->pdev->dev, "amthi cb->information - %lu\n",
349 	    cb->information);
350 
351 	/* length is being turncated to PAGE_SIZE, however,
352 	 * the information may be longer */
353 	length = min_t(size_t, length, (cb->information - *offset));
354 
355 	if (copy_to_user(ubuf, cb->response_buffer.data + *offset, length))
356 		rets = -EFAULT;
357 	else {
358 		rets = length;
359 		if ((*offset + length) < cb->information) {
360 			*offset += length;
361 			goto out;
362 		}
363 	}
364 free:
365 	dev_dbg(&dev->pdev->dev, "free amthi cb memory.\n");
366 	*offset = 0;
367 	mei_free_cb_private(cb);
368 out:
369 	return rets;
370 }
371 
372 /**
373  * mei_start_read - the start read client message function.
374  *
375  * @dev: the device structure
376  * @if_num:  minor number
377  * @cl: private data of the file object
378  *
379  * returns 0 on success, <0 on failure.
380  */
mei_start_read(struct mei_device * dev,struct mei_cl * cl)381 int mei_start_read(struct mei_device *dev, struct mei_cl *cl)
382 {
383 	struct mei_cl_cb *cb;
384 	int rets = 0;
385 	int i;
386 
387 	if (cl->state != MEI_FILE_CONNECTED)
388 		return -ENODEV;
389 
390 	if (dev->mei_state != MEI_ENABLED)
391 		return -ENODEV;
392 
393 	dev_dbg(&dev->pdev->dev, "check if read is pending.\n");
394 	if (cl->read_pending || cl->read_cb) {
395 		dev_dbg(&dev->pdev->dev, "read is pending.\n");
396 		return -EBUSY;
397 	}
398 
399 	cb = kzalloc(sizeof(struct mei_cl_cb), GFP_KERNEL);
400 	if (!cb)
401 		return -ENOMEM;
402 
403 	dev_dbg(&dev->pdev->dev, "allocation call back successful. host client = %d, ME client = %d\n",
404 		cl->host_client_id, cl->me_client_id);
405 
406 	for (i = 0; i < dev->me_clients_num; i++) {
407 		if (dev->me_clients[i].client_id == cl->me_client_id)
408 			break;
409 
410 	}
411 
412 	if (WARN_ON(dev->me_clients[i].client_id != cl->me_client_id)) {
413 		rets = -ENODEV;
414 		goto unlock;
415 	}
416 
417 	if (i == dev->me_clients_num) {
418 		rets = -ENODEV;
419 		goto unlock;
420 	}
421 
422 	cb->response_buffer.size = dev->me_clients[i].props.max_msg_length;
423 	cb->response_buffer.data =
424 			kmalloc(cb->response_buffer.size, GFP_KERNEL);
425 	if (!cb->response_buffer.data) {
426 		rets = -ENOMEM;
427 		goto unlock;
428 	}
429 	dev_dbg(&dev->pdev->dev, "allocation call back data success.\n");
430 	cb->major_file_operations = MEI_READ;
431 	/* make sure information is zero before we start */
432 	cb->information = 0;
433 	cb->file_private = (void *) cl;
434 	cl->read_cb = cb;
435 	if (dev->mei_host_buffer_is_empty) {
436 		dev->mei_host_buffer_is_empty = false;
437 		if (!mei_send_flow_control(dev, cl)) {
438 			rets = -ENODEV;
439 			goto unlock;
440 		} else {
441 			list_add_tail(&cb->cb_list,
442 				      &dev->read_list.mei_cb.cb_list);
443 		}
444 	} else {
445 		list_add_tail(&cb->cb_list, &dev->ctrl_wr_list.mei_cb.cb_list);
446 	}
447 	return rets;
448 unlock:
449 	mei_free_cb_private(cb);
450 	return rets;
451 }
452 
453 /**
454  * amthi_write - write iamthif data to amthi client
455  *
456  * @dev: the device structure
457  * @cb: mei call back struct
458  *
459  * returns 0 on success, <0 on failure.
460  */
amthi_write(struct mei_device * dev,struct mei_cl_cb * cb)461 int amthi_write(struct mei_device *dev, struct mei_cl_cb *cb)
462 {
463 	struct mei_msg_hdr mei_hdr;
464 	int ret;
465 
466 	if (!dev || !cb)
467 		return -ENODEV;
468 
469 	dev_dbg(&dev->pdev->dev, "write data to amthi client.\n");
470 
471 	dev->iamthif_state = MEI_IAMTHIF_WRITING;
472 	dev->iamthif_current_cb = cb;
473 	dev->iamthif_file_object = cb->file_object;
474 	dev->iamthif_canceled = false;
475 	dev->iamthif_ioctl = true;
476 	dev->iamthif_msg_buf_size = cb->request_buffer.size;
477 	memcpy(dev->iamthif_msg_buf, cb->request_buffer.data,
478 	       cb->request_buffer.size);
479 
480 	ret = mei_flow_ctrl_creds(dev, &dev->iamthif_cl);
481 	if (ret < 0)
482 		return ret;
483 
484 	if (ret && dev->mei_host_buffer_is_empty) {
485 		ret = 0;
486 		dev->mei_host_buffer_is_empty = false;
487 		if (cb->request_buffer.size >
488 			(((dev->host_hw_state & H_CBD) >> 24) * sizeof(u32))
489 				-sizeof(struct mei_msg_hdr)) {
490 			mei_hdr.length =
491 			    (((dev->host_hw_state & H_CBD) >> 24) *
492 			    sizeof(u32)) - sizeof(struct mei_msg_hdr);
493 			mei_hdr.msg_complete = 0;
494 		} else {
495 			mei_hdr.length = cb->request_buffer.size;
496 			mei_hdr.msg_complete = 1;
497 		}
498 
499 		mei_hdr.host_addr = dev->iamthif_cl.host_client_id;
500 		mei_hdr.me_addr = dev->iamthif_cl.me_client_id;
501 		mei_hdr.reserved = 0;
502 		dev->iamthif_msg_buf_index += mei_hdr.length;
503 		if (!mei_write_message(dev, &mei_hdr,
504 					(unsigned char *)(dev->iamthif_msg_buf),
505 					mei_hdr.length))
506 			return -ENODEV;
507 
508 		if (mei_hdr.msg_complete) {
509 			if (mei_flow_ctrl_reduce(dev, &dev->iamthif_cl))
510 				return -ENODEV;
511 			dev->iamthif_flow_control_pending = true;
512 			dev->iamthif_state = MEI_IAMTHIF_FLOW_CONTROL;
513 			dev_dbg(&dev->pdev->dev, "add amthi cb to write waiting list\n");
514 			dev->iamthif_current_cb = cb;
515 			dev->iamthif_file_object = cb->file_object;
516 			list_add_tail(&cb->cb_list,
517 				      &dev->write_waiting_list.mei_cb.cb_list);
518 		} else {
519 			dev_dbg(&dev->pdev->dev, "message does not complete, "
520 					"so add amthi cb to write list.\n");
521 			list_add_tail(&cb->cb_list,
522 				      &dev->write_list.mei_cb.cb_list);
523 		}
524 	} else {
525 		if (!(dev->mei_host_buffer_is_empty))
526 			dev_dbg(&dev->pdev->dev, "host buffer is not empty");
527 
528 		dev_dbg(&dev->pdev->dev, "No flow control credentials, "
529 				"so add iamthif cb to write list.\n");
530 		list_add_tail(&cb->cb_list, &dev->write_list.mei_cb.cb_list);
531 	}
532 	return 0;
533 }
534 
535 /**
536  * iamthif_ioctl_send_msg - send cmd data to amthi client
537  *
538  * @dev: the device structure
539  *
540  * returns 0 on success, <0 on failure.
541  */
mei_run_next_iamthif_cmd(struct mei_device * dev)542 void mei_run_next_iamthif_cmd(struct mei_device *dev)
543 {
544 	struct mei_cl *cl_tmp;
545 	struct mei_cl_cb *pos = NULL;
546 	struct mei_cl_cb *next = NULL;
547 	int status;
548 
549 	if (!dev)
550 		return;
551 
552 	dev->iamthif_msg_buf_size = 0;
553 	dev->iamthif_msg_buf_index = 0;
554 	dev->iamthif_canceled = false;
555 	dev->iamthif_ioctl = true;
556 	dev->iamthif_state = MEI_IAMTHIF_IDLE;
557 	dev->iamthif_timer = 0;
558 	dev->iamthif_file_object = NULL;
559 
560 	dev_dbg(&dev->pdev->dev, "complete amthi cmd_list cb.\n");
561 
562 	list_for_each_entry_safe(pos, next,
563 			&dev->amthi_cmd_list.mei_cb.cb_list, cb_list) {
564 		list_del(&pos->cb_list);
565 		cl_tmp = (struct mei_cl *)pos->file_private;
566 
567 		if (cl_tmp && cl_tmp == &dev->iamthif_cl) {
568 			status = amthi_write(dev, pos);
569 			if (status) {
570 				dev_dbg(&dev->pdev->dev,
571 					"amthi write failed status = %d\n",
572 						status);
573 				return;
574 			}
575 			break;
576 		}
577 	}
578 }
579 
580 /**
581  * mei_free_cb_private - free mei_cb_private related memory
582  *
583  * @cb: mei callback struct
584  */
mei_free_cb_private(struct mei_cl_cb * cb)585 void mei_free_cb_private(struct mei_cl_cb *cb)
586 {
587 	if (cb == NULL)
588 		return;
589 
590 	kfree(cb->request_buffer.data);
591 	kfree(cb->response_buffer.data);
592 	kfree(cb);
593 }
594