f38a32addad01fe2fe3e2bd7790d0c99707cdd6b
[firefly-linux-kernel-4.4.55.git] / drivers / misc / mei / interrupt.c
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_disconnect_rsp - send disconnection response message
165  *
166  * @cl: client
167  * @cb: callback block.
168  * @cmpl_list: complete list.
169  *
170  * returns 0, OK; otherwise, error.
171  */
172 static int mei_cl_irq_disconnect_rsp(struct mei_cl *cl, struct mei_cl_cb *cb,
173                                      struct mei_cl_cb *cmpl_list)
174 {
175         struct mei_device *dev = cl->dev;
176         u32 msg_slots;
177         int slots;
178         int ret;
179
180         slots = mei_hbuf_empty_slots(dev);
181         msg_slots = mei_data2slots(sizeof(struct hbm_client_connect_response));
182
183         if (slots < msg_slots)
184                 return -EMSGSIZE;
185
186         ret = mei_hbm_cl_disconnect_rsp(dev, cl);
187
188         cl->state = MEI_FILE_DISCONNECTED;
189         cl->status = 0;
190         list_del(&cb->list);
191         mei_io_cb_free(cb);
192
193         return ret;
194 }
195
196
197
198 /**
199  * mei_cl_irq_close - processes close related operation from
200  *      interrupt thread context - send disconnect request
201  *
202  * @cl: client
203  * @cb: callback block.
204  * @cmpl_list: complete list.
205  *
206  * returns 0, OK; otherwise, error.
207  */
208 static int mei_cl_irq_close(struct mei_cl *cl, struct mei_cl_cb *cb,
209                             struct mei_cl_cb *cmpl_list)
210 {
211         struct mei_device *dev = cl->dev;
212         u32 msg_slots;
213         int slots;
214
215         msg_slots = mei_data2slots(sizeof(struct hbm_client_connect_request));
216         slots = mei_hbuf_empty_slots(dev);
217
218         if (slots < msg_slots)
219                 return -EMSGSIZE;
220
221         if (mei_hbm_cl_disconnect_req(dev, cl)) {
222                 cl->status = 0;
223                 cb->buf_idx = 0;
224                 list_move_tail(&cb->list, &cmpl_list->list);
225                 return -EIO;
226         }
227
228         cl->state = MEI_FILE_DISCONNECTING;
229         cl->status = 0;
230         cb->buf_idx = 0;
231         list_move_tail(&cb->list, &dev->ctrl_rd_list.list);
232         cl->timer_count = MEI_CONNECT_TIMEOUT;
233
234         return 0;
235 }
236
237
238 /**
239  * mei_cl_irq_close - processes client read related operation from the
240  *      interrupt thread context - request for flow control credits
241  *
242  * @cl: client
243  * @cb: callback block.
244  * @cmpl_list: complete list.
245  *
246  * returns 0, OK; otherwise, error.
247  */
248 static int mei_cl_irq_read(struct mei_cl *cl, struct mei_cl_cb *cb,
249                            struct mei_cl_cb *cmpl_list)
250 {
251         struct mei_device *dev = cl->dev;
252         u32 msg_slots;
253         int slots;
254         int ret;
255
256         msg_slots = mei_data2slots(sizeof(struct hbm_flow_control));
257         slots = mei_hbuf_empty_slots(dev);
258
259         if (slots < msg_slots)
260                 return -EMSGSIZE;
261
262         ret = mei_hbm_cl_flow_control_req(dev, cl);
263         if (ret) {
264                 cl->status = ret;
265                 cb->buf_idx = 0;
266                 list_move_tail(&cb->list, &cmpl_list->list);
267                 return ret;
268         }
269
270         list_move_tail(&cb->list, &dev->read_list.list);
271
272         return 0;
273 }
274
275
276 /**
277  * mei_cl_irq_connect - send connect request in irq_thread context
278  *
279  * @cl: client
280  * @cb: callback block.
281  * @cmpl_list: complete list.
282  *
283  * returns 0, OK; otherwise, error.
284  */
285 static int mei_cl_irq_connect(struct mei_cl *cl, struct mei_cl_cb *cb,
286                               struct mei_cl_cb *cmpl_list)
287 {
288         struct mei_device *dev = cl->dev;
289         u32 msg_slots;
290         int slots;
291         int ret;
292
293         msg_slots = mei_data2slots(sizeof(struct hbm_client_connect_request));
294         slots = mei_hbuf_empty_slots(dev);
295
296         if (mei_cl_is_other_connecting(cl))
297                 return 0;
298
299         if (slots < msg_slots)
300                 return -EMSGSIZE;
301
302         cl->state = MEI_FILE_CONNECTING;
303
304         ret = mei_hbm_cl_connect_req(dev, cl);
305         if (ret) {
306                 cl->status = ret;
307                 cb->buf_idx = 0;
308                 list_del(&cb->list);
309                 return ret;
310         }
311
312         list_move_tail(&cb->list, &dev->ctrl_rd_list.list);
313         cl->timer_count = MEI_CONNECT_TIMEOUT;
314         return 0;
315 }
316
317
318 /**
319  * mei_irq_read_handler - bottom half read routine after ISR to
320  * handle the read processing.
321  *
322  * @dev: the device structure
323  * @cmpl_list: An instance of our list structure
324  * @slots: slots to read.
325  *
326  * returns 0 on success, <0 on failure.
327  */
328 int mei_irq_read_handler(struct mei_device *dev,
329                 struct mei_cl_cb *cmpl_list, s32 *slots)
330 {
331         struct mei_msg_hdr *mei_hdr;
332         struct mei_cl *cl;
333         int ret;
334
335         if (!dev->rd_msg_hdr) {
336                 dev->rd_msg_hdr = mei_read_hdr(dev);
337                 (*slots)--;
338                 dev_dbg(&dev->pdev->dev, "slots =%08x.\n", *slots);
339         }
340         mei_hdr = (struct mei_msg_hdr *) &dev->rd_msg_hdr;
341         dev_dbg(&dev->pdev->dev, MEI_HDR_FMT, MEI_HDR_PRM(mei_hdr));
342
343         if (mei_hdr->reserved || !dev->rd_msg_hdr) {
344                 dev_err(&dev->pdev->dev, "corrupted message header 0x%08X\n",
345                                 dev->rd_msg_hdr);
346                 ret = -EBADMSG;
347                 goto end;
348         }
349
350         if (mei_slots2data(*slots) < mei_hdr->length) {
351                 dev_err(&dev->pdev->dev, "less data available than length=%08x.\n",
352                                 *slots);
353                 /* we can't read the message */
354                 ret = -ENODATA;
355                 goto end;
356         }
357
358         /*  HBM message */
359         if (mei_hdr->host_addr == 0 && mei_hdr->me_addr == 0) {
360                 ret = mei_hbm_dispatch(dev, mei_hdr);
361                 if (ret) {
362                         dev_dbg(&dev->pdev->dev, "mei_hbm_dispatch failed ret = %d\n",
363                                         ret);
364                         goto end;
365                 }
366                 goto reset_slots;
367         }
368
369         /* find recipient cl */
370         list_for_each_entry(cl, &dev->file_list, link) {
371                 if (mei_cl_hbm_equal(cl, mei_hdr)) {
372                         cl_dbg(dev, cl, "got a message\n");
373                         break;
374                 }
375         }
376
377         /* if no recipient cl was found we assume corrupted header */
378         if (&cl->link == &dev->file_list) {
379                 dev_err(&dev->pdev->dev, "no destination client found 0x%08X\n",
380                                 dev->rd_msg_hdr);
381                 ret = -EBADMSG;
382                 goto end;
383         }
384
385         if (mei_hdr->host_addr == dev->iamthif_cl.host_client_id &&
386             MEI_FILE_CONNECTED == dev->iamthif_cl.state &&
387             dev->iamthif_state == MEI_IAMTHIF_READING) {
388
389                 ret = mei_amthif_irq_read_msg(dev, mei_hdr, cmpl_list);
390                 if (ret) {
391                         dev_err(&dev->pdev->dev, "mei_amthif_irq_read_msg failed = %d\n",
392                                         ret);
393                         goto end;
394                 }
395         } else {
396                 ret = mei_cl_irq_read_msg(dev, mei_hdr, cmpl_list);
397                 if (ret) {
398                         dev_err(&dev->pdev->dev, "mei_cl_irq_read_msg failed = %d\n",
399                                         ret);
400                         goto end;
401                 }
402         }
403
404 reset_slots:
405         /* reset the number of slots and header */
406         *slots = mei_count_full_read_slots(dev);
407         dev->rd_msg_hdr = 0;
408
409         if (*slots == -EOVERFLOW) {
410                 /* overflow - reset */
411                 dev_err(&dev->pdev->dev, "resetting due to slots overflow.\n");
412                 /* set the event since message has been read */
413                 ret = -ERANGE;
414                 goto end;
415         }
416 end:
417         return ret;
418 }
419 EXPORT_SYMBOL_GPL(mei_irq_read_handler);
420
421
422 /**
423  * mei_irq_write_handler -  dispatch write requests
424  *  after irq received
425  *
426  * @dev: the device structure
427  * @cmpl_list: An instance of our list structure
428  *
429  * returns 0 on success, <0 on failure.
430  */
431 int mei_irq_write_handler(struct mei_device *dev, struct mei_cl_cb *cmpl_list)
432 {
433
434         struct mei_cl *cl;
435         struct mei_cl_cb *cb, *next;
436         struct mei_cl_cb *list;
437         s32 slots;
438         int ret;
439
440
441         if (!mei_hbuf_acquire(dev))
442                 return 0;
443
444         slots = mei_hbuf_empty_slots(dev);
445         if (slots <= 0)
446                 return -EMSGSIZE;
447
448         /* complete all waiting for write CB */
449         dev_dbg(&dev->pdev->dev, "complete all waiting for write cb.\n");
450
451         list = &dev->write_waiting_list;
452         list_for_each_entry_safe(cb, next, &list->list, list) {
453                 cl = cb->cl;
454                 if (cl == NULL)
455                         continue;
456
457                 cl->status = 0;
458                 list_del(&cb->list);
459                 if (MEI_WRITING == cl->writing_state &&
460                     cb->fop_type == MEI_FOP_WRITE &&
461                     cl != &dev->iamthif_cl) {
462                         cl_dbg(dev, cl, "MEI WRITE COMPLETE\n");
463                         cl->writing_state = MEI_WRITE_COMPLETE;
464                         list_add_tail(&cb->list, &cmpl_list->list);
465                 }
466                 if (cl == &dev->iamthif_cl) {
467                         cl_dbg(dev, cl, "check iamthif flow control.\n");
468                         if (dev->iamthif_flow_control_pending) {
469                                 ret = mei_amthif_irq_read(dev, &slots);
470                                 if (ret)
471                                         return ret;
472                         }
473                 }
474         }
475
476         if (dev->wd_state == MEI_WD_STOPPING) {
477                 dev->wd_state = MEI_WD_IDLE;
478                 wake_up(&dev->wait_stop_wd);
479         }
480
481         if (mei_cl_is_connected(&dev->wd_cl)) {
482                 if (dev->wd_pending &&
483                     mei_cl_flow_ctrl_creds(&dev->wd_cl) > 0) {
484                         ret = mei_wd_send(dev);
485                         if (ret)
486                                 return ret;
487                         dev->wd_pending = false;
488                 }
489         }
490
491         /* complete control write list CB */
492         dev_dbg(&dev->pdev->dev, "complete control write list cb.\n");
493         list_for_each_entry_safe(cb, next, &dev->ctrl_wr_list.list, list) {
494                 cl = cb->cl;
495                 if (!cl) {
496                         list_del(&cb->list);
497                         return -ENODEV;
498                 }
499                 switch (cb->fop_type) {
500                 case MEI_FOP_CLOSE:
501                         /* send disconnect message */
502                         ret = mei_cl_irq_close(cl, cb, cmpl_list);
503                         if (ret)
504                                 return ret;
505
506                         break;
507                 case MEI_FOP_READ:
508                         /* send flow control message */
509                         ret = mei_cl_irq_read(cl, cb, cmpl_list);
510                         if (ret)
511                                 return ret;
512
513                         break;
514                 case MEI_FOP_CONNECT:
515                         /* connect message */
516                         ret = mei_cl_irq_connect(cl, cb, cmpl_list);
517                         if (ret)
518                                 return ret;
519
520                         break;
521                 case MEI_FOP_DISCONNECT_RSP:
522                         /* send disconnect resp */
523                         ret = mei_cl_irq_disconnect_rsp(cl, cb, cmpl_list);
524                         if (ret)
525                                 return ret;
526                         break;
527                 default:
528                         BUG();
529                 }
530
531         }
532         /* complete  write list CB */
533         dev_dbg(&dev->pdev->dev, "complete write list cb.\n");
534         list_for_each_entry_safe(cb, next, &dev->write_list.list, list) {
535                 cl = cb->cl;
536                 if (cl == NULL)
537                         continue;
538                 if (cl == &dev->iamthif_cl)
539                         ret = mei_amthif_irq_write(cl, cb, cmpl_list);
540                 else
541                         ret = mei_cl_irq_write(cl, cb, cmpl_list);
542                 if (ret)
543                         return ret;
544         }
545         return 0;
546 }
547 EXPORT_SYMBOL_GPL(mei_irq_write_handler);
548
549
550
551 /**
552  * mei_timer - timer function.
553  *
554  * @work: pointer to the work_struct structure
555  *
556  */
557 void mei_timer(struct work_struct *work)
558 {
559         unsigned long timeout;
560         struct mei_cl *cl;
561         struct mei_cl_cb  *cb_pos = NULL;
562         struct mei_cl_cb  *cb_next = NULL;
563
564         struct mei_device *dev = container_of(work,
565                                         struct mei_device, timer_work.work);
566
567
568         mutex_lock(&dev->device_lock);
569
570         /* Catch interrupt stalls during HBM init handshake */
571         if (dev->dev_state == MEI_DEV_INIT_CLIENTS &&
572             dev->hbm_state != MEI_HBM_IDLE) {
573
574                 if (dev->init_clients_timer) {
575                         if (--dev->init_clients_timer == 0) {
576                                 dev_err(&dev->pdev->dev, "timer: init clients timeout hbm_state = %d.\n",
577                                         dev->hbm_state);
578                                 mei_reset(dev);
579                                 goto out;
580                         }
581                 }
582         }
583
584         if (dev->dev_state != MEI_DEV_ENABLED)
585                 goto out;
586
587         /*** connect/disconnect timeouts ***/
588         list_for_each_entry(cl, &dev->file_list, link) {
589                 if (cl->timer_count) {
590                         if (--cl->timer_count == 0) {
591                                 dev_err(&dev->pdev->dev, "timer: connect/disconnect timeout.\n");
592                                 mei_reset(dev);
593                                 goto out;
594                         }
595                 }
596         }
597
598         if (!mei_cl_is_connected(&dev->iamthif_cl))
599                 goto out;
600
601         if (dev->iamthif_stall_timer) {
602                 if (--dev->iamthif_stall_timer == 0) {
603                         dev_err(&dev->pdev->dev, "timer: amthif  hanged.\n");
604                         mei_reset(dev);
605                         dev->iamthif_msg_buf_size = 0;
606                         dev->iamthif_msg_buf_index = 0;
607                         dev->iamthif_canceled = false;
608                         dev->iamthif_ioctl = true;
609                         dev->iamthif_state = MEI_IAMTHIF_IDLE;
610                         dev->iamthif_timer = 0;
611
612                         mei_io_cb_free(dev->iamthif_current_cb);
613                         dev->iamthif_current_cb = NULL;
614
615                         dev->iamthif_file_object = NULL;
616                         mei_amthif_run_next_cmd(dev);
617                 }
618         }
619
620         if (dev->iamthif_timer) {
621
622                 timeout = dev->iamthif_timer +
623                         mei_secs_to_jiffies(MEI_IAMTHIF_READ_TIMER);
624
625                 dev_dbg(&dev->pdev->dev, "dev->iamthif_timer = %ld\n",
626                                 dev->iamthif_timer);
627                 dev_dbg(&dev->pdev->dev, "timeout = %ld\n", timeout);
628                 dev_dbg(&dev->pdev->dev, "jiffies = %ld\n", jiffies);
629                 if (time_after(jiffies, timeout)) {
630                         /*
631                          * User didn't read the AMTHI data on time (15sec)
632                          * freeing AMTHI for other requests
633                          */
634
635                         dev_dbg(&dev->pdev->dev, "freeing AMTHI for other requests\n");
636
637                         list_for_each_entry_safe(cb_pos, cb_next,
638                                 &dev->amthif_rd_complete_list.list, list) {
639
640                                 cl = cb_pos->file_object->private_data;
641
642                                 /* Finding the AMTHI entry. */
643                                 if (cl == &dev->iamthif_cl)
644                                         list_del(&cb_pos->list);
645                         }
646                         mei_io_cb_free(dev->iamthif_current_cb);
647                         dev->iamthif_current_cb = NULL;
648
649                         dev->iamthif_file_object->private_data = NULL;
650                         dev->iamthif_file_object = NULL;
651                         dev->iamthif_timer = 0;
652                         mei_amthif_run_next_cmd(dev);
653
654                 }
655         }
656 out:
657         if (dev->dev_state != MEI_DEV_DISABLED)
658                 schedule_delayed_work(&dev->timer_work, 2 * HZ);
659         mutex_unlock(&dev->device_lock);
660 }
661