xref: /openbmc/linux/drivers/misc/mei/client.c (revision 9ca9050b)
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 #include <linux/pci.h>
18 #include <linux/sched.h>
19 #include <linux/wait.h>
20 #include <linux/delay.h>
21 
22 #include <linux/mei.h>
23 
24 #include "mei_dev.h"
25 #include "hbm.h"
26 #include "interface.h"
27 
28 
29 /**
30  * mei_io_list_flush - removes list entry belonging to cl.
31  *
32  * @list:  An instance of our list structure
33  * @cl: host client
34  */
35 void mei_io_list_flush(struct mei_cl_cb *list, struct mei_cl *cl)
36 {
37 	struct mei_cl_cb *cb;
38 	struct mei_cl_cb *next;
39 
40 	list_for_each_entry_safe(cb, next, &list->list, list) {
41 		if (cb->cl && mei_cl_cmp_id(cl, cb->cl))
42 			list_del(&cb->list);
43 	}
44 }
45 
46 /**
47  * mei_io_cb_free - free mei_cb_private related memory
48  *
49  * @cb: mei callback struct
50  */
51 void mei_io_cb_free(struct mei_cl_cb *cb)
52 {
53 	if (cb == NULL)
54 		return;
55 
56 	kfree(cb->request_buffer.data);
57 	kfree(cb->response_buffer.data);
58 	kfree(cb);
59 }
60 
61 /**
62  * mei_io_cb_init - allocate and initialize io callback
63  *
64  * @cl - mei client
65  * @file: pointer to file structure
66  *
67  * returns mei_cl_cb pointer or NULL;
68  */
69 struct mei_cl_cb *mei_io_cb_init(struct mei_cl *cl, struct file *fp)
70 {
71 	struct mei_cl_cb *cb;
72 
73 	cb = kzalloc(sizeof(struct mei_cl_cb), GFP_KERNEL);
74 	if (!cb)
75 		return NULL;
76 
77 	mei_io_list_init(cb);
78 
79 	cb->file_object = fp;
80 	cb->cl = cl;
81 	cb->buf_idx = 0;
82 	return cb;
83 }
84 
85 /**
86  * mei_io_cb_alloc_req_buf - allocate request buffer
87  *
88  * @cb -  io callback structure
89  * @size: size of the buffer
90  *
91  * returns 0 on success
92  *         -EINVAL if cb is NULL
93  *         -ENOMEM if allocation failed
94  */
95 int mei_io_cb_alloc_req_buf(struct mei_cl_cb *cb, size_t length)
96 {
97 	if (!cb)
98 		return -EINVAL;
99 
100 	if (length == 0)
101 		return 0;
102 
103 	cb->request_buffer.data = kmalloc(length, GFP_KERNEL);
104 	if (!cb->request_buffer.data)
105 		return -ENOMEM;
106 	cb->request_buffer.size = length;
107 	return 0;
108 }
109 /**
110  * mei_io_cb_alloc_req_buf - allocate respose buffer
111  *
112  * @cb -  io callback structure
113  * @size: size of the buffer
114  *
115  * returns 0 on success
116  *         -EINVAL if cb is NULL
117  *         -ENOMEM if allocation failed
118  */
119 int mei_io_cb_alloc_resp_buf(struct mei_cl_cb *cb, size_t length)
120 {
121 	if (!cb)
122 		return -EINVAL;
123 
124 	if (length == 0)
125 		return 0;
126 
127 	cb->response_buffer.data = kmalloc(length, GFP_KERNEL);
128 	if (!cb->response_buffer.data)
129 		return -ENOMEM;
130 	cb->response_buffer.size = length;
131 	return 0;
132 }
133 
134 
135 
136 /**
137  * mei_cl_flush_queues - flushes queue lists belonging to cl.
138  *
139  * @dev: the device structure
140  * @cl: host client
141  */
142 int mei_cl_flush_queues(struct mei_cl *cl)
143 {
144 	if (!cl || !cl->dev)
145 		return -EINVAL;
146 
147 	dev_dbg(&cl->dev->pdev->dev, "remove list entry belonging to cl\n");
148 	mei_io_list_flush(&cl->dev->read_list, cl);
149 	mei_io_list_flush(&cl->dev->write_list, cl);
150 	mei_io_list_flush(&cl->dev->write_waiting_list, cl);
151 	mei_io_list_flush(&cl->dev->ctrl_wr_list, cl);
152 	mei_io_list_flush(&cl->dev->ctrl_rd_list, cl);
153 	mei_io_list_flush(&cl->dev->amthif_cmd_list, cl);
154 	mei_io_list_flush(&cl->dev->amthif_rd_complete_list, cl);
155 	return 0;
156 }
157 
158 /**
159  * mei_me_cl_by_uuid - locate index of me client
160  *
161  * @dev: mei device
162  * returns me client index or -ENOENT if not found
163  */
164 int mei_me_cl_by_uuid(const struct mei_device *dev, const uuid_le *uuid)
165 {
166 	int i, res = -ENOENT;
167 
168 	for (i = 0; i < dev->me_clients_num; ++i)
169 		if (uuid_le_cmp(*uuid,
170 				dev->me_clients[i].props.protocol_name) == 0) {
171 			res = i;
172 			break;
173 		}
174 
175 	return res;
176 }
177 
178 
179 /**
180  * mei_me_cl_by_id return index to me_clients for client_id
181  *
182  * @dev: the device structure
183  * @client_id: me client id
184  *
185  * Locking: called under "dev->device_lock" lock
186  *
187  * returns index on success, -ENOENT on failure.
188  */
189 
190 int mei_me_cl_by_id(struct mei_device *dev, u8 client_id)
191 {
192 	int i;
193 	for (i = 0; i < dev->me_clients_num; i++)
194 		if (dev->me_clients[i].client_id == client_id)
195 			break;
196 	if (WARN_ON(dev->me_clients[i].client_id != client_id))
197 		return -ENOENT;
198 
199 	if (i == dev->me_clients_num)
200 		return -ENOENT;
201 
202 	return i;
203 }
204 
205 /**
206  * mei_cl_init - initializes intialize cl.
207  *
208  * @cl: host client to be initialized
209  * @dev: mei device
210  */
211 void mei_cl_init(struct mei_cl *cl, struct mei_device *dev)
212 {
213 	memset(cl, 0, sizeof(struct mei_cl));
214 	init_waitqueue_head(&cl->wait);
215 	init_waitqueue_head(&cl->rx_wait);
216 	init_waitqueue_head(&cl->tx_wait);
217 	INIT_LIST_HEAD(&cl->link);
218 	cl->reading_state = MEI_IDLE;
219 	cl->writing_state = MEI_IDLE;
220 	cl->dev = dev;
221 }
222 
223 /**
224  * mei_cl_allocate - allocates cl  structure and sets it up.
225  *
226  * @dev: mei device
227  * returns  The allocated file or NULL on failure
228  */
229 struct mei_cl *mei_cl_allocate(struct mei_device *dev)
230 {
231 	struct mei_cl *cl;
232 
233 	cl = kmalloc(sizeof(struct mei_cl), GFP_KERNEL);
234 	if (!cl)
235 		return NULL;
236 
237 	mei_cl_init(cl, dev);
238 
239 	return cl;
240 }
241 
242 
243 /**
244  * mei_me_cl_link - create link between host and me clinet and add
245  *   me_cl to the list
246  *
247  * @dev: the device structure
248  * @cl: link between me and host client assocated with opened file descriptor
249  * @uuid: uuid of ME client
250  * @client_id: id of the host client
251  *
252  * returns ME client index if ME client
253  *	-EINVAL on incorrect values
254  *	-ENONET if client not found
255  */
256 int mei_me_cl_link(struct mei_device *dev, struct mei_cl *cl,
257 			const uuid_le *uuid, u8 host_cl_id)
258 {
259 	int i;
260 
261 	if (!dev || !cl || !uuid)
262 		return -EINVAL;
263 
264 	/* check for valid client id */
265 	i = mei_me_cl_by_uuid(dev, uuid);
266 	if (i >= 0) {
267 		cl->me_client_id = dev->me_clients[i].client_id;
268 		cl->state = MEI_FILE_CONNECTING;
269 		cl->host_client_id = host_cl_id;
270 
271 		list_add_tail(&cl->link, &dev->file_list);
272 		return (u8)i;
273 	}
274 
275 	return -ENOENT;
276 }
277 /**
278  * mei_me_cl_unlink - remove me_cl from the list
279  *
280  * @dev: the device structure
281  * @host_client_id: host client id to be removed
282  */
283 void mei_me_cl_unlink(struct mei_device *dev, struct mei_cl *cl)
284 {
285 	struct mei_cl *pos, *next;
286 	list_for_each_entry_safe(pos, next, &dev->file_list, link) {
287 		if (cl->host_client_id == pos->host_client_id) {
288 			dev_dbg(&dev->pdev->dev, "remove host client = %d, ME client = %d\n",
289 					pos->host_client_id, pos->me_client_id);
290 			list_del_init(&pos->link);
291 			break;
292 		}
293 	}
294 }
295 
296 
297 void mei_host_client_init(struct work_struct *work)
298 {
299 	struct mei_device *dev = container_of(work,
300 					      struct mei_device, init_work);
301 	struct mei_client_properties *client_props;
302 	int i;
303 
304 	mutex_lock(&dev->device_lock);
305 
306 	bitmap_zero(dev->host_clients_map, MEI_CLIENTS_MAX);
307 	dev->open_handle_count = 0;
308 
309 	/*
310 	 * Reserving the first three client IDs
311 	 * 0: Reserved for MEI Bus Message communications
312 	 * 1: Reserved for Watchdog
313 	 * 2: Reserved for AMTHI
314 	 */
315 	bitmap_set(dev->host_clients_map, 0, 3);
316 
317 	for (i = 0; i < dev->me_clients_num; i++) {
318 		client_props = &dev->me_clients[i].props;
319 
320 		if (!uuid_le_cmp(client_props->protocol_name, mei_amthi_guid))
321 			mei_amthif_host_init(dev);
322 		else if (!uuid_le_cmp(client_props->protocol_name, mei_wd_guid))
323 			mei_wd_host_init(dev);
324 	}
325 
326 	dev->dev_state = MEI_DEV_ENABLED;
327 
328 	mutex_unlock(&dev->device_lock);
329 }
330 
331 
332 /**
333  * mei_disconnect_host_client - sends disconnect message to fw from host client.
334  *
335  * @dev: the device structure
336  * @cl: private data of the file object
337  *
338  * Locking: called under "dev->device_lock" lock
339  *
340  * returns 0 on success, <0 on failure.
341  */
342 int mei_disconnect_host_client(struct mei_device *dev, struct mei_cl *cl)
343 {
344 	struct mei_cl_cb *cb;
345 	int rets, err;
346 
347 	if (!dev || !cl)
348 		return -ENODEV;
349 
350 	if (cl->state != MEI_FILE_DISCONNECTING)
351 		return 0;
352 
353 	cb = mei_io_cb_init(cl, NULL);
354 	if (!cb)
355 		return -ENOMEM;
356 
357 	cb->fop_type = MEI_FOP_CLOSE;
358 	if (dev->mei_host_buffer_is_empty) {
359 		dev->mei_host_buffer_is_empty = false;
360 		if (mei_hbm_cl_disconnect_req(dev, cl)) {
361 			rets = -ENODEV;
362 			dev_err(&dev->pdev->dev, "failed to disconnect.\n");
363 			goto free;
364 		}
365 		mdelay(10); /* Wait for hardware disconnection ready */
366 		list_add_tail(&cb->list, &dev->ctrl_rd_list.list);
367 	} else {
368 		dev_dbg(&dev->pdev->dev, "add disconnect cb to control write list\n");
369 		list_add_tail(&cb->list, &dev->ctrl_wr_list.list);
370 
371 	}
372 	mutex_unlock(&dev->device_lock);
373 
374 	err = wait_event_timeout(dev->wait_recvd_msg,
375 			MEI_FILE_DISCONNECTED == cl->state,
376 			mei_secs_to_jiffies(MEI_CL_CONNECT_TIMEOUT));
377 
378 	mutex_lock(&dev->device_lock);
379 	if (MEI_FILE_DISCONNECTED == cl->state) {
380 		rets = 0;
381 		dev_dbg(&dev->pdev->dev, "successfully disconnected from FW client.\n");
382 	} else {
383 		rets = -ENODEV;
384 		if (MEI_FILE_DISCONNECTED != cl->state)
385 			dev_dbg(&dev->pdev->dev, "wrong status client disconnect.\n");
386 
387 		if (err)
388 			dev_dbg(&dev->pdev->dev,
389 					"wait failed disconnect err=%08x\n",
390 					err);
391 
392 		dev_dbg(&dev->pdev->dev, "failed to disconnect from FW client.\n");
393 	}
394 
395 	mei_io_list_flush(&dev->ctrl_rd_list, cl);
396 	mei_io_list_flush(&dev->ctrl_wr_list, cl);
397 free:
398 	mei_io_cb_free(cb);
399 	return rets;
400 }
401 
402 
403 /**
404  * mei_other_client_is_connecting - checks if other
405  *    client with the same client id is connected.
406  *
407  * @dev: the device structure
408  * @cl: private data of the file object
409  *
410  * returns 1 if other client is connected, 0 - otherwise.
411  */
412 int mei_other_client_is_connecting(struct mei_device *dev,
413 				struct mei_cl *cl)
414 {
415 	struct mei_cl *cl_pos = NULL;
416 	struct mei_cl *cl_next = NULL;
417 
418 	list_for_each_entry_safe(cl_pos, cl_next, &dev->file_list, link) {
419 		if ((cl_pos->state == MEI_FILE_CONNECTING) &&
420 			(cl_pos != cl) &&
421 			cl->me_client_id == cl_pos->me_client_id)
422 			return 1;
423 
424 	}
425 	return 0;
426 }
427 
428 /**
429  * mei_flow_ctrl_creds - checks flow_control credentials.
430  *
431  * @dev: the device structure
432  * @cl: private data of the file object
433  *
434  * returns 1 if mei_flow_ctrl_creds >0, 0 - otherwise.
435  *	-ENOENT if mei_cl is not present
436  *	-EINVAL if single_recv_buf == 0
437  */
438 int mei_flow_ctrl_creds(struct mei_device *dev, struct mei_cl *cl)
439 {
440 	int i;
441 
442 	if (!dev->me_clients_num)
443 		return 0;
444 
445 	if (cl->mei_flow_ctrl_creds > 0)
446 		return 1;
447 
448 	for (i = 0; i < dev->me_clients_num; i++) {
449 		struct mei_me_client  *me_cl = &dev->me_clients[i];
450 		if (me_cl->client_id == cl->me_client_id) {
451 			if (me_cl->mei_flow_ctrl_creds) {
452 				if (WARN_ON(me_cl->props.single_recv_buf == 0))
453 					return -EINVAL;
454 				return 1;
455 			} else {
456 				return 0;
457 			}
458 		}
459 	}
460 	return -ENOENT;
461 }
462 
463 /**
464  * mei_flow_ctrl_reduce - reduces flow_control.
465  *
466  * @dev: the device structure
467  * @cl: private data of the file object
468  * @returns
469  *	0 on success
470  *	-ENOENT when me client is not found
471  *	-EINVAL when ctrl credits are <= 0
472  */
473 int mei_flow_ctrl_reduce(struct mei_device *dev, struct mei_cl *cl)
474 {
475 	int i;
476 
477 	if (!dev->me_clients_num)
478 		return -ENOENT;
479 
480 	for (i = 0; i < dev->me_clients_num; i++) {
481 		struct mei_me_client  *me_cl = &dev->me_clients[i];
482 		if (me_cl->client_id == cl->me_client_id) {
483 			if (me_cl->props.single_recv_buf != 0) {
484 				if (WARN_ON(me_cl->mei_flow_ctrl_creds <= 0))
485 					return -EINVAL;
486 				dev->me_clients[i].mei_flow_ctrl_creds--;
487 			} else {
488 				if (WARN_ON(cl->mei_flow_ctrl_creds <= 0))
489 					return -EINVAL;
490 				cl->mei_flow_ctrl_creds--;
491 			}
492 			return 0;
493 		}
494 	}
495 	return -ENOENT;
496 }
497 
498 
499 
500 /**
501  * mei_ioctl_connect_client - the connect to fw client IOCTL function
502  *
503  * @dev: the device structure
504  * @data: IOCTL connect data, input and output parameters
505  * @file: private data of the file object
506  *
507  * Locking: called under "dev->device_lock" lock
508  *
509  * returns 0 on success, <0 on failure.
510  */
511 int mei_ioctl_connect_client(struct file *file,
512 			struct mei_connect_client_data *data)
513 {
514 	struct mei_device *dev;
515 	struct mei_cl_cb *cb;
516 	struct mei_client *client;
517 	struct mei_cl *cl;
518 	long timeout = mei_secs_to_jiffies(MEI_CL_CONNECT_TIMEOUT);
519 	int i;
520 	int err;
521 	int rets;
522 
523 	cl = file->private_data;
524 	if (WARN_ON(!cl || !cl->dev))
525 		return -ENODEV;
526 
527 	dev = cl->dev;
528 
529 	dev_dbg(&dev->pdev->dev, "mei_ioctl_connect_client() Entry\n");
530 
531 	/* buffered ioctl cb */
532 	cb = mei_io_cb_init(cl, file);
533 	if (!cb) {
534 		rets = -ENOMEM;
535 		goto end;
536 	}
537 
538 	cb->fop_type = MEI_FOP_IOCTL;
539 
540 	if (dev->dev_state != MEI_DEV_ENABLED) {
541 		rets = -ENODEV;
542 		goto end;
543 	}
544 	if (cl->state != MEI_FILE_INITIALIZING &&
545 	    cl->state != MEI_FILE_DISCONNECTED) {
546 		rets = -EBUSY;
547 		goto end;
548 	}
549 
550 	/* find ME client we're trying to connect to */
551 	i = mei_me_cl_by_uuid(dev, &data->in_client_uuid);
552 	if (i >= 0 && !dev->me_clients[i].props.fixed_address) {
553 		cl->me_client_id = dev->me_clients[i].client_id;
554 		cl->state = MEI_FILE_CONNECTING;
555 	}
556 
557 	dev_dbg(&dev->pdev->dev, "Connect to FW Client ID = %d\n",
558 			cl->me_client_id);
559 	dev_dbg(&dev->pdev->dev, "FW Client - Protocol Version = %d\n",
560 			dev->me_clients[i].props.protocol_version);
561 	dev_dbg(&dev->pdev->dev, "FW Client - Max Msg Len = %d\n",
562 			dev->me_clients[i].props.max_msg_length);
563 
564 	/* if we're connecting to amthi client then we will use the
565 	 * existing connection
566 	 */
567 	if (uuid_le_cmp(data->in_client_uuid, mei_amthi_guid) == 0) {
568 		dev_dbg(&dev->pdev->dev, "FW Client is amthi\n");
569 		if (dev->iamthif_cl.state != MEI_FILE_CONNECTED) {
570 			rets = -ENODEV;
571 			goto end;
572 		}
573 		clear_bit(cl->host_client_id, dev->host_clients_map);
574 		mei_me_cl_unlink(dev, cl);
575 
576 		kfree(cl);
577 		cl = NULL;
578 		file->private_data = &dev->iamthif_cl;
579 
580 		client = &data->out_client_properties;
581 		client->max_msg_length =
582 			dev->me_clients[i].props.max_msg_length;
583 		client->protocol_version =
584 			dev->me_clients[i].props.protocol_version;
585 		rets = dev->iamthif_cl.status;
586 
587 		goto end;
588 	}
589 
590 	if (cl->state != MEI_FILE_CONNECTING) {
591 		rets = -ENODEV;
592 		goto end;
593 	}
594 
595 
596 	/* prepare the output buffer */
597 	client = &data->out_client_properties;
598 	client->max_msg_length = dev->me_clients[i].props.max_msg_length;
599 	client->protocol_version = dev->me_clients[i].props.protocol_version;
600 	dev_dbg(&dev->pdev->dev, "Can connect?\n");
601 	if (dev->mei_host_buffer_is_empty
602 	    && !mei_other_client_is_connecting(dev, cl)) {
603 		dev_dbg(&dev->pdev->dev, "Sending Connect Message\n");
604 		dev->mei_host_buffer_is_empty = false;
605 		if (mei_hbm_cl_connect_req(dev, cl)) {
606 			dev_dbg(&dev->pdev->dev, "Sending connect message - failed\n");
607 			rets = -ENODEV;
608 			goto end;
609 		} else {
610 			dev_dbg(&dev->pdev->dev, "Sending connect message - succeeded\n");
611 			cl->timer_count = MEI_CONNECT_TIMEOUT;
612 			list_add_tail(&cb->list, &dev->ctrl_rd_list.list);
613 		}
614 
615 
616 	} else {
617 		dev_dbg(&dev->pdev->dev, "Queuing the connect request due to device busy\n");
618 		dev_dbg(&dev->pdev->dev, "add connect cb to control write list.\n");
619 		list_add_tail(&cb->list, &dev->ctrl_wr_list.list);
620 	}
621 	mutex_unlock(&dev->device_lock);
622 	err = wait_event_timeout(dev->wait_recvd_msg,
623 			(MEI_FILE_CONNECTED == cl->state ||
624 			 MEI_FILE_DISCONNECTED == cl->state), timeout);
625 
626 	mutex_lock(&dev->device_lock);
627 	if (MEI_FILE_CONNECTED == cl->state) {
628 		dev_dbg(&dev->pdev->dev, "successfully connected to FW client.\n");
629 		rets = cl->status;
630 		goto end;
631 	} else {
632 		dev_dbg(&dev->pdev->dev, "failed to connect to FW client.cl->state = %d.\n",
633 		    cl->state);
634 		if (!err) {
635 			dev_dbg(&dev->pdev->dev,
636 				"wait_event_interruptible_timeout failed on client"
637 				" connect message fw response message.\n");
638 		}
639 		rets = -EFAULT;
640 
641 		mei_io_list_flush(&dev->ctrl_rd_list, cl);
642 		mei_io_list_flush(&dev->ctrl_wr_list, cl);
643 		goto end;
644 	}
645 	rets = 0;
646 end:
647 	dev_dbg(&dev->pdev->dev, "free connect cb memory.");
648 	mei_io_cb_free(cb);
649 	return rets;
650 }
651 
652 /**
653  * mei_start_read - the start read client message function.
654  *
655  * @dev: the device structure
656  * @if_num:  minor number
657  * @cl: private data of the file object
658  *
659  * returns 0 on success, <0 on failure.
660  */
661 int mei_start_read(struct mei_device *dev, struct mei_cl *cl)
662 {
663 	struct mei_cl_cb *cb;
664 	int rets;
665 	int i;
666 
667 	if (cl->state != MEI_FILE_CONNECTED)
668 		return -ENODEV;
669 
670 	if (dev->dev_state != MEI_DEV_ENABLED)
671 		return -ENODEV;
672 
673 	if (cl->read_pending || cl->read_cb) {
674 		dev_dbg(&dev->pdev->dev, "read is pending.\n");
675 		return -EBUSY;
676 	}
677 	i = mei_me_cl_by_id(dev, cl->me_client_id);
678 	if (i < 0) {
679 		dev_err(&dev->pdev->dev, "no such me client %d\n",
680 			cl->me_client_id);
681 		return  -ENODEV;
682 	}
683 
684 	cb = mei_io_cb_init(cl, NULL);
685 	if (!cb)
686 		return -ENOMEM;
687 
688 	rets = mei_io_cb_alloc_resp_buf(cb,
689 			dev->me_clients[i].props.max_msg_length);
690 	if (rets)
691 		goto err;
692 
693 	cb->fop_type = MEI_FOP_READ;
694 	cl->read_cb = cb;
695 	if (dev->mei_host_buffer_is_empty) {
696 		dev->mei_host_buffer_is_empty = false;
697 		if (mei_hbm_cl_flow_control_req(dev, cl)) {
698 			rets = -ENODEV;
699 			goto err;
700 		}
701 		list_add_tail(&cb->list, &dev->read_list.list);
702 	} else {
703 		list_add_tail(&cb->list, &dev->ctrl_wr_list.list);
704 	}
705 	return rets;
706 err:
707 	mei_io_cb_free(cb);
708 	return rets;
709 }
710 
711