xref: /openbmc/linux/drivers/misc/mei/interrupt.c (revision 483eb062)
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/export.h>
19 #include <linux/pci.h>
20 #include <linux/kthread.h>
21 #include <linux/interrupt.h>
22 #include <linux/fs.h>
23 #include <linux/jiffies.h>
24 
25 #include <linux/mei.h>
26 
27 #include "mei_dev.h"
28 #include "hbm.h"
29 #include "hw-me.h"
30 #include "client.h"
31 
32 
33 /**
34  * mei_irq_compl_handler - dispatch complete handlers
35  *	for the completed callbacks
36  *
37  * @dev - mei device
38  * @compl_list - list of completed cbs
39  */
40 void mei_irq_compl_handler(struct mei_device *dev, struct mei_cl_cb *compl_list)
41 {
42 	struct mei_cl_cb *cb, *next;
43 	struct mei_cl *cl;
44 
45 	list_for_each_entry_safe(cb, next, &compl_list->list, list) {
46 		cl = cb->cl;
47 		list_del(&cb->list);
48 		if (!cl)
49 			continue;
50 
51 		dev_dbg(&dev->pdev->dev, "completing call back.\n");
52 		if (cl == &dev->iamthif_cl)
53 			mei_amthif_complete(dev, cb);
54 		else
55 			mei_cl_complete(cl, cb);
56 	}
57 }
58 EXPORT_SYMBOL_GPL(mei_irq_compl_handler);
59 
60 /**
61  * mei_cl_hbm_equal - check if hbm is addressed to the client
62  *
63  * @cl: host client
64  * @mei_hdr: header of mei client message
65  *
66  * returns true if matches, false otherwise
67  */
68 static inline int mei_cl_hbm_equal(struct mei_cl *cl,
69 			struct mei_msg_hdr *mei_hdr)
70 {
71 	return cl->host_client_id == mei_hdr->host_addr &&
72 		cl->me_client_id == mei_hdr->me_addr;
73 }
74 /**
75  * mei_cl_is_reading - checks if the client
76 		is the one to read this message
77  *
78  * @cl: mei client
79  * @mei_hdr: header of mei message
80  *
81  * returns true on match and false otherwise
82  */
83 static bool mei_cl_is_reading(struct mei_cl *cl, struct mei_msg_hdr *mei_hdr)
84 {
85 	return mei_cl_hbm_equal(cl, mei_hdr) &&
86 		cl->state == MEI_FILE_CONNECTED &&
87 		cl->reading_state != MEI_READ_COMPLETE;
88 }
89 
90 /**
91  * mei_irq_read_client_message - process client message
92  *
93  * @dev: the device structure
94  * @mei_hdr: header of mei client message
95  * @complete_list: An instance of our list structure
96  *
97  * returns 0 on success, <0 on failure.
98  */
99 static int mei_cl_irq_read_msg(struct mei_device *dev,
100 			       struct mei_msg_hdr *mei_hdr,
101 			       struct mei_cl_cb *complete_list)
102 {
103 	struct mei_cl *cl;
104 	struct mei_cl_cb *cb, *next;
105 	unsigned char *buffer = NULL;
106 
107 	list_for_each_entry_safe(cb, next, &dev->read_list.list, list) {
108 		cl = cb->cl;
109 		if (!cl || !mei_cl_is_reading(cl, mei_hdr))
110 			continue;
111 
112 		cl->reading_state = MEI_READING;
113 
114 		if (cb->response_buffer.size == 0 ||
115 		    cb->response_buffer.data == NULL) {
116 			cl_err(dev, cl, "response buffer is not allocated.\n");
117 			list_del(&cb->list);
118 			return -ENOMEM;
119 		}
120 
121 		if (cb->response_buffer.size < mei_hdr->length + cb->buf_idx) {
122 			cl_dbg(dev, cl, "message overflow. size %d len %d idx %ld\n",
123 				cb->response_buffer.size,
124 				mei_hdr->length, cb->buf_idx);
125 			buffer = krealloc(cb->response_buffer.data,
126 					  mei_hdr->length + cb->buf_idx,
127 					  GFP_KERNEL);
128 
129 			if (!buffer) {
130 				cl_err(dev, cl, "allocation failed.\n");
131 				list_del(&cb->list);
132 				return -ENOMEM;
133 			}
134 			cb->response_buffer.data = buffer;
135 			cb->response_buffer.size =
136 				mei_hdr->length + cb->buf_idx;
137 		}
138 
139 		buffer = cb->response_buffer.data + cb->buf_idx;
140 		mei_read_slots(dev, buffer, mei_hdr->length);
141 
142 		cb->buf_idx += mei_hdr->length;
143 		if (mei_hdr->msg_complete) {
144 			cl->status = 0;
145 			list_del(&cb->list);
146 			cl_dbg(dev, cl, "completed read length = %lu\n",
147 				cb->buf_idx);
148 			list_add_tail(&cb->list, &complete_list->list);
149 		}
150 		break;
151 	}
152 
153 	dev_dbg(&dev->pdev->dev, "message read\n");
154 	if (!buffer) {
155 		mei_read_slots(dev, dev->rd_msg_buf, mei_hdr->length);
156 		dev_dbg(&dev->pdev->dev, "discarding message " MEI_HDR_FMT "\n",
157 				MEI_HDR_PRM(mei_hdr));
158 	}
159 
160 	return 0;
161 }
162 
163 /**
164  * mei_cl_irq_close - processes close related operation from
165  *	interrupt thread context - send disconnect request
166  *
167  * @cl: client
168  * @cb: callback block.
169  * @slots: free slots.
170  * @cmpl_list: complete list.
171  *
172  * returns 0, OK; otherwise, error.
173  */
174 static int mei_cl_irq_close(struct mei_cl *cl, struct mei_cl_cb *cb,
175 			s32 *slots, struct mei_cl_cb *cmpl_list)
176 {
177 	struct mei_device *dev = cl->dev;
178 
179 	u32 msg_slots =
180 		mei_data2slots(sizeof(struct hbm_client_connect_request));
181 
182 	if (*slots < msg_slots)
183 		return -EMSGSIZE;
184 
185 	*slots -= msg_slots;
186 
187 	if (mei_hbm_cl_disconnect_req(dev, cl)) {
188 		cl->status = 0;
189 		cb->buf_idx = 0;
190 		list_move_tail(&cb->list, &cmpl_list->list);
191 		return -EIO;
192 	}
193 
194 	cl->state = MEI_FILE_DISCONNECTING;
195 	cl->status = 0;
196 	cb->buf_idx = 0;
197 	list_move_tail(&cb->list, &dev->ctrl_rd_list.list);
198 	cl->timer_count = MEI_CONNECT_TIMEOUT;
199 
200 	return 0;
201 }
202 
203 
204 /**
205  * mei_cl_irq_close - processes client read related operation from the
206  *	interrupt thread context - request for flow control credits
207  *
208  * @cl: client
209  * @cb: callback block.
210  * @slots: free slots.
211  * @cmpl_list: complete list.
212  *
213  * returns 0, OK; otherwise, error.
214  */
215 static int mei_cl_irq_read(struct mei_cl *cl, struct mei_cl_cb *cb,
216 			   s32 *slots, struct mei_cl_cb *cmpl_list)
217 {
218 	struct mei_device *dev = cl->dev;
219 	u32 msg_slots = mei_data2slots(sizeof(struct hbm_flow_control));
220 
221 	int ret;
222 
223 
224 	if (*slots < msg_slots) {
225 		/* return the cancel routine */
226 		list_del(&cb->list);
227 		return -EMSGSIZE;
228 	}
229 
230 	*slots -= msg_slots;
231 
232 	ret = mei_hbm_cl_flow_control_req(dev, cl);
233 	if (ret) {
234 		cl->status = ret;
235 		cb->buf_idx = 0;
236 		list_move_tail(&cb->list, &cmpl_list->list);
237 		return ret;
238 	}
239 
240 	list_move_tail(&cb->list, &dev->read_list.list);
241 
242 	return 0;
243 }
244 
245 
246 /**
247  * mei_cl_irq_ioctl - processes client ioctl related operation from the
248  *	interrupt thread context -   send connection request
249  *
250  * @cl: client
251  * @cb: callback block.
252  * @slots: free slots.
253  * @cmpl_list: complete list.
254  *
255  * returns 0, OK; otherwise, error.
256  */
257 static int mei_cl_irq_ioctl(struct mei_cl *cl, struct mei_cl_cb *cb,
258 			   s32 *slots, struct mei_cl_cb *cmpl_list)
259 {
260 	struct mei_device *dev = cl->dev;
261 	int ret;
262 
263 	u32 msg_slots =
264 		mei_data2slots(sizeof(struct hbm_client_connect_request));
265 
266 	if (*slots < msg_slots) {
267 		/* return the cancel routine */
268 		list_del(&cb->list);
269 		return -EMSGSIZE;
270 	}
271 
272 	*slots -=  msg_slots;
273 
274 	cl->state = MEI_FILE_CONNECTING;
275 
276 	ret = mei_hbm_cl_connect_req(dev, cl);
277 	if (ret) {
278 		cl->status = ret;
279 		cb->buf_idx = 0;
280 		list_del(&cb->list);
281 		return ret;
282 	}
283 
284 	list_move_tail(&cb->list, &dev->ctrl_rd_list.list);
285 	cl->timer_count = MEI_CONNECT_TIMEOUT;
286 	return 0;
287 }
288 
289 
290 /**
291  * mei_irq_read_handler - bottom half read routine after ISR to
292  * handle the read processing.
293  *
294  * @dev: the device structure
295  * @cmpl_list: An instance of our list structure
296  * @slots: slots to read.
297  *
298  * returns 0 on success, <0 on failure.
299  */
300 int mei_irq_read_handler(struct mei_device *dev,
301 		struct mei_cl_cb *cmpl_list, s32 *slots)
302 {
303 	struct mei_msg_hdr *mei_hdr;
304 	struct mei_cl *cl;
305 	int ret;
306 
307 	if (!dev->rd_msg_hdr) {
308 		dev->rd_msg_hdr = mei_read_hdr(dev);
309 		(*slots)--;
310 		dev_dbg(&dev->pdev->dev, "slots =%08x.\n", *slots);
311 	}
312 	mei_hdr = (struct mei_msg_hdr *) &dev->rd_msg_hdr;
313 	dev_dbg(&dev->pdev->dev, MEI_HDR_FMT, MEI_HDR_PRM(mei_hdr));
314 
315 	if (mei_hdr->reserved || !dev->rd_msg_hdr) {
316 		dev_err(&dev->pdev->dev, "corrupted message header 0x%08X\n",
317 				dev->rd_msg_hdr);
318 		ret = -EBADMSG;
319 		goto end;
320 	}
321 
322 	if (mei_slots2data(*slots) < mei_hdr->length) {
323 		dev_err(&dev->pdev->dev, "less data available than length=%08x.\n",
324 				*slots);
325 		/* we can't read the message */
326 		ret = -ERANGE;
327 		goto end;
328 	}
329 
330 	/*  HBM message */
331 	if (mei_hdr->host_addr == 0 && mei_hdr->me_addr == 0) {
332 		ret = mei_hbm_dispatch(dev, mei_hdr);
333 		if (ret) {
334 			dev_dbg(&dev->pdev->dev, "mei_hbm_dispatch failed ret = %d\n",
335 					ret);
336 			goto end;
337 		}
338 		goto reset_slots;
339 	}
340 
341 	/* find recipient cl */
342 	list_for_each_entry(cl, &dev->file_list, link) {
343 		if (mei_cl_hbm_equal(cl, mei_hdr)) {
344 			cl_dbg(dev, cl, "got a message\n");
345 			break;
346 		}
347 	}
348 
349 	/* if no recipient cl was found we assume corrupted header */
350 	if (&cl->link == &dev->file_list) {
351 		dev_err(&dev->pdev->dev, "no destination client found 0x%08X\n",
352 				dev->rd_msg_hdr);
353 		ret = -EBADMSG;
354 		goto end;
355 	}
356 
357 	if (mei_hdr->host_addr == dev->iamthif_cl.host_client_id &&
358 	    MEI_FILE_CONNECTED == dev->iamthif_cl.state &&
359 	    dev->iamthif_state == MEI_IAMTHIF_READING) {
360 
361 		ret = mei_amthif_irq_read_msg(dev, mei_hdr, cmpl_list);
362 		if (ret) {
363 			dev_err(&dev->pdev->dev, "mei_amthif_irq_read_msg failed = %d\n",
364 					ret);
365 			goto end;
366 		}
367 	} else {
368 		ret = mei_cl_irq_read_msg(dev, mei_hdr, cmpl_list);
369 		if (ret) {
370 			dev_err(&dev->pdev->dev, "mei_cl_irq_read_msg failed = %d\n",
371 					ret);
372 			goto end;
373 		}
374 	}
375 
376 reset_slots:
377 	/* reset the number of slots and header */
378 	*slots = mei_count_full_read_slots(dev);
379 	dev->rd_msg_hdr = 0;
380 
381 	if (*slots == -EOVERFLOW) {
382 		/* overflow - reset */
383 		dev_err(&dev->pdev->dev, "resetting due to slots overflow.\n");
384 		/* set the event since message has been read */
385 		ret = -ERANGE;
386 		goto end;
387 	}
388 end:
389 	return ret;
390 }
391 EXPORT_SYMBOL_GPL(mei_irq_read_handler);
392 
393 
394 /**
395  * mei_irq_write_handler -  dispatch write requests
396  *  after irq received
397  *
398  * @dev: the device structure
399  * @cmpl_list: An instance of our list structure
400  *
401  * returns 0 on success, <0 on failure.
402  */
403 int mei_irq_write_handler(struct mei_device *dev, struct mei_cl_cb *cmpl_list)
404 {
405 
406 	struct mei_cl *cl;
407 	struct mei_cl_cb *cb, *next;
408 	struct mei_cl_cb *list;
409 	s32 slots;
410 	int ret;
411 
412 	if (!mei_hbuf_is_ready(dev)) {
413 		dev_dbg(&dev->pdev->dev, "host buffer is not empty.\n");
414 		return 0;
415 	}
416 	slots = mei_hbuf_empty_slots(dev);
417 	if (slots <= 0)
418 		return -EMSGSIZE;
419 
420 	/* complete all waiting for write CB */
421 	dev_dbg(&dev->pdev->dev, "complete all waiting for write cb.\n");
422 
423 	list = &dev->write_waiting_list;
424 	list_for_each_entry_safe(cb, next, &list->list, list) {
425 		cl = cb->cl;
426 		if (cl == NULL)
427 			continue;
428 
429 		cl->status = 0;
430 		list_del(&cb->list);
431 		if (MEI_WRITING == cl->writing_state &&
432 		    cb->fop_type == MEI_FOP_WRITE &&
433 		    cl != &dev->iamthif_cl) {
434 			cl_dbg(dev, cl, "MEI WRITE COMPLETE\n");
435 			cl->writing_state = MEI_WRITE_COMPLETE;
436 			list_add_tail(&cb->list, &cmpl_list->list);
437 		}
438 		if (cl == &dev->iamthif_cl) {
439 			cl_dbg(dev, cl, "check iamthif flow control.\n");
440 			if (dev->iamthif_flow_control_pending) {
441 				ret = mei_amthif_irq_read(dev, &slots);
442 				if (ret)
443 					return ret;
444 			}
445 		}
446 	}
447 
448 	if (dev->wd_state == MEI_WD_STOPPING) {
449 		dev->wd_state = MEI_WD_IDLE;
450 		wake_up_interruptible(&dev->wait_stop_wd);
451 	}
452 
453 	if (dev->wr_ext_msg.hdr.length) {
454 		mei_write_message(dev, &dev->wr_ext_msg.hdr,
455 				dev->wr_ext_msg.data);
456 		slots -= mei_data2slots(dev->wr_ext_msg.hdr.length);
457 		dev->wr_ext_msg.hdr.length = 0;
458 	}
459 	if (dev->dev_state == MEI_DEV_ENABLED) {
460 		if (dev->wd_pending &&
461 		    mei_cl_flow_ctrl_creds(&dev->wd_cl) > 0) {
462 			if (mei_wd_send(dev))
463 				dev_dbg(&dev->pdev->dev, "wd send failed.\n");
464 			else if (mei_cl_flow_ctrl_reduce(&dev->wd_cl))
465 				return -ENODEV;
466 
467 			dev->wd_pending = false;
468 
469 			if (dev->wd_state == MEI_WD_RUNNING)
470 				slots -= mei_data2slots(MEI_WD_START_MSG_SIZE);
471 			else
472 				slots -= mei_data2slots(MEI_WD_STOP_MSG_SIZE);
473 		}
474 	}
475 
476 	/* complete control write list CB */
477 	dev_dbg(&dev->pdev->dev, "complete control write list cb.\n");
478 	list_for_each_entry_safe(cb, next, &dev->ctrl_wr_list.list, list) {
479 		cl = cb->cl;
480 		if (!cl) {
481 			list_del(&cb->list);
482 			return -ENODEV;
483 		}
484 		switch (cb->fop_type) {
485 		case MEI_FOP_CLOSE:
486 			/* send disconnect message */
487 			ret = mei_cl_irq_close(cl, cb, &slots, cmpl_list);
488 			if (ret)
489 				return ret;
490 
491 			break;
492 		case MEI_FOP_READ:
493 			/* send flow control message */
494 			ret = mei_cl_irq_read(cl, cb, &slots, cmpl_list);
495 			if (ret)
496 				return ret;
497 
498 			break;
499 		case MEI_FOP_IOCTL:
500 			/* connect message */
501 			if (mei_cl_is_other_connecting(cl))
502 				continue;
503 			ret = mei_cl_irq_ioctl(cl, cb, &slots, cmpl_list);
504 			if (ret)
505 				return ret;
506 
507 			break;
508 
509 		default:
510 			BUG();
511 		}
512 
513 	}
514 	/* complete  write list CB */
515 	dev_dbg(&dev->pdev->dev, "complete write list cb.\n");
516 	list_for_each_entry_safe(cb, next, &dev->write_list.list, list) {
517 		cl = cb->cl;
518 		if (cl == NULL)
519 			continue;
520 		if (cl == &dev->iamthif_cl)
521 			ret = mei_amthif_irq_write_complete(cl, cb,
522 						&slots, cmpl_list);
523 		else
524 			ret = mei_cl_irq_write_complete(cl, cb,
525 						&slots, cmpl_list);
526 		if (ret)
527 			return ret;
528 	}
529 	return 0;
530 }
531 EXPORT_SYMBOL_GPL(mei_irq_write_handler);
532 
533 
534 
535 /**
536  * mei_timer - timer function.
537  *
538  * @work: pointer to the work_struct structure
539  *
540  */
541 void mei_timer(struct work_struct *work)
542 {
543 	unsigned long timeout;
544 	struct mei_cl *cl_pos = NULL;
545 	struct mei_cl *cl_next = NULL;
546 	struct mei_cl_cb  *cb_pos = NULL;
547 	struct mei_cl_cb  *cb_next = NULL;
548 
549 	struct mei_device *dev = container_of(work,
550 					struct mei_device, timer_work.work);
551 
552 
553 	mutex_lock(&dev->device_lock);
554 
555 	/* Catch interrupt stalls during HBM init handshake */
556 	if (dev->dev_state == MEI_DEV_INIT_CLIENTS &&
557 	    dev->hbm_state != MEI_HBM_IDLE) {
558 
559 		if (dev->init_clients_timer) {
560 			if (--dev->init_clients_timer == 0) {
561 				dev_err(&dev->pdev->dev, "timer: init clients timeout hbm_state = %d.\n",
562 					dev->hbm_state);
563 				mei_reset(dev);
564 				goto out;
565 			}
566 		}
567 	}
568 
569 	if (dev->dev_state != MEI_DEV_ENABLED)
570 		goto out;
571 
572 	/*** connect/disconnect timeouts ***/
573 	list_for_each_entry_safe(cl_pos, cl_next, &dev->file_list, link) {
574 		if (cl_pos->timer_count) {
575 			if (--cl_pos->timer_count == 0) {
576 				dev_err(&dev->pdev->dev, "timer: connect/disconnect timeout.\n");
577 				mei_reset(dev);
578 				goto out;
579 			}
580 		}
581 	}
582 
583 	if (dev->iamthif_stall_timer) {
584 		if (--dev->iamthif_stall_timer == 0) {
585 			dev_err(&dev->pdev->dev, "timer: amthif  hanged.\n");
586 			mei_reset(dev);
587 			dev->iamthif_msg_buf_size = 0;
588 			dev->iamthif_msg_buf_index = 0;
589 			dev->iamthif_canceled = false;
590 			dev->iamthif_ioctl = true;
591 			dev->iamthif_state = MEI_IAMTHIF_IDLE;
592 			dev->iamthif_timer = 0;
593 
594 			mei_io_cb_free(dev->iamthif_current_cb);
595 			dev->iamthif_current_cb = NULL;
596 
597 			dev->iamthif_file_object = NULL;
598 			mei_amthif_run_next_cmd(dev);
599 		}
600 	}
601 
602 	if (dev->iamthif_timer) {
603 
604 		timeout = dev->iamthif_timer +
605 			mei_secs_to_jiffies(MEI_IAMTHIF_READ_TIMER);
606 
607 		dev_dbg(&dev->pdev->dev, "dev->iamthif_timer = %ld\n",
608 				dev->iamthif_timer);
609 		dev_dbg(&dev->pdev->dev, "timeout = %ld\n", timeout);
610 		dev_dbg(&dev->pdev->dev, "jiffies = %ld\n", jiffies);
611 		if (time_after(jiffies, timeout)) {
612 			/*
613 			 * User didn't read the AMTHI data on time (15sec)
614 			 * freeing AMTHI for other requests
615 			 */
616 
617 			dev_dbg(&dev->pdev->dev, "freeing AMTHI for other requests\n");
618 
619 			list_for_each_entry_safe(cb_pos, cb_next,
620 				&dev->amthif_rd_complete_list.list, list) {
621 
622 				cl_pos = cb_pos->file_object->private_data;
623 
624 				/* Finding the AMTHI entry. */
625 				if (cl_pos == &dev->iamthif_cl)
626 					list_del(&cb_pos->list);
627 			}
628 			mei_io_cb_free(dev->iamthif_current_cb);
629 			dev->iamthif_current_cb = NULL;
630 
631 			dev->iamthif_file_object->private_data = NULL;
632 			dev->iamthif_file_object = NULL;
633 			dev->iamthif_timer = 0;
634 			mei_amthif_run_next_cmd(dev);
635 
636 		}
637 	}
638 out:
639 	if (dev->dev_state != MEI_DEV_DISABLED)
640 		schedule_delayed_work(&dev->timer_work, 2 * HZ);
641 	mutex_unlock(&dev->device_lock);
642 }
643 
644