]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/misc/mei/interrupt.c
Merge branches 'fixes', 'misc', 'mmci', 'unstable/dma-for-next' and 'sa11x0' into...
[karo-tx-linux.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 handelers
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                         dev_err(&dev->pdev->dev, "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                         dev_dbg(&dev->pdev->dev, "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                                 dev_err(&dev->pdev->dev, "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                         dev_dbg(&dev->pdev->dev, "completed read H cl = %d, ME cl = %d, length = %lu\n",
147                                 cl->host_client_id,
148                                 cl->me_client_id,
149                                 cb->buf_idx);
150                         list_add_tail(&cb->list, &complete_list->list);
151                 }
152                 break;
153         }
154
155         dev_dbg(&dev->pdev->dev, "message read\n");
156         if (!buffer) {
157                 mei_read_slots(dev, dev->rd_msg_buf, mei_hdr->length);
158                 dev_dbg(&dev->pdev->dev, "discarding message " MEI_HDR_FMT "\n",
159                                 MEI_HDR_PRM(mei_hdr));
160         }
161
162         return 0;
163 }
164
165 /**
166  * mei_cl_irq_close - processes close related operation from
167  *      interrupt thread context - send disconnect request
168  *
169  * @cl: client
170  * @cb: callback block.
171  * @slots: free slots.
172  * @cmpl_list: complete list.
173  *
174  * returns 0, OK; otherwise, error.
175  */
176 static int mei_cl_irq_close(struct mei_cl *cl, struct mei_cl_cb *cb,
177                         s32 *slots, struct mei_cl_cb *cmpl_list)
178 {
179         struct mei_device *dev = cl->dev;
180
181         u32 msg_slots =
182                 mei_data2slots(sizeof(struct hbm_client_connect_request));
183
184         if (*slots < msg_slots)
185                 return -EMSGSIZE;
186
187         *slots -= msg_slots;
188
189         if (mei_hbm_cl_disconnect_req(dev, cl)) {
190                 cl->status = 0;
191                 cb->buf_idx = 0;
192                 list_move_tail(&cb->list, &cmpl_list->list);
193                 return -EIO;
194         }
195
196         cl->state = MEI_FILE_DISCONNECTING;
197         cl->status = 0;
198         cb->buf_idx = 0;
199         list_move_tail(&cb->list, &dev->ctrl_rd_list.list);
200         cl->timer_count = MEI_CONNECT_TIMEOUT;
201
202         return 0;
203 }
204
205
206 /**
207  * mei_cl_irq_close - processes client read related operation from the
208  *      interrupt thread context - request for flow control credits
209  *
210  * @cl: client
211  * @cb: callback block.
212  * @slots: free slots.
213  * @cmpl_list: complete list.
214  *
215  * returns 0, OK; otherwise, error.
216  */
217 static int mei_cl_irq_read(struct mei_cl *cl, struct mei_cl_cb *cb,
218                            s32 *slots, struct mei_cl_cb *cmpl_list)
219 {
220         struct mei_device *dev = cl->dev;
221
222         u32 msg_slots = mei_data2slots(sizeof(struct hbm_flow_control));
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         if (mei_hbm_cl_flow_control_req(dev, cl)) {
233                 cl->status = -ENODEV;
234                 cb->buf_idx = 0;
235                 list_move_tail(&cb->list, &cmpl_list->list);
236                 return -ENODEV;
237         }
238         list_move_tail(&cb->list, &dev->read_list.list);
239
240         return 0;
241 }
242
243
244 /**
245  * mei_cl_irq_ioctl - processes client ioctl related operation from the
246  *      interrupt thread context -   send connection request
247  *
248  * @cl: client
249  * @cb: callback block.
250  * @slots: free slots.
251  * @cmpl_list: complete list.
252  *
253  * returns 0, OK; otherwise, error.
254  */
255 static int mei_cl_irq_ioctl(struct mei_cl *cl, struct mei_cl_cb *cb,
256                            s32 *slots, struct mei_cl_cb *cmpl_list)
257 {
258         struct mei_device *dev = cl->dev;
259
260         u32 msg_slots =
261                 mei_data2slots(sizeof(struct hbm_client_connect_request));
262
263         if (*slots < msg_slots) {
264                 /* return the cancel routine */
265                 list_del(&cb->list);
266                 return -EMSGSIZE;
267         }
268
269         *slots -=  msg_slots;
270
271         cl->state = MEI_FILE_CONNECTING;
272
273         if (mei_hbm_cl_connect_req(dev, cl)) {
274                 cl->status = -ENODEV;
275                 cb->buf_idx = 0;
276                 list_del(&cb->list);
277                 return -ENODEV;
278         }
279
280         list_move_tail(&cb->list, &dev->ctrl_rd_list.list);
281         cl->timer_count = MEI_CONNECT_TIMEOUT;
282         return 0;
283 }
284
285
286 /**
287  * mei_irq_read_handler - bottom half read routine after ISR to
288  * handle the read processing.
289  *
290  * @dev: the device structure
291  * @cmpl_list: An instance of our list structure
292  * @slots: slots to read.
293  *
294  * returns 0 on success, <0 on failure.
295  */
296 int mei_irq_read_handler(struct mei_device *dev,
297                 struct mei_cl_cb *cmpl_list, s32 *slots)
298 {
299         struct mei_msg_hdr *mei_hdr;
300         struct mei_cl *cl_pos = NULL;
301         struct mei_cl *cl_next = NULL;
302         int ret = 0;
303
304         if (!dev->rd_msg_hdr) {
305                 dev->rd_msg_hdr = mei_read_hdr(dev);
306                 dev_dbg(&dev->pdev->dev, "slots =%08x.\n", *slots);
307                 (*slots)--;
308                 dev_dbg(&dev->pdev->dev, "slots =%08x.\n", *slots);
309         }
310         mei_hdr = (struct mei_msg_hdr *) &dev->rd_msg_hdr;
311         dev_dbg(&dev->pdev->dev, MEI_HDR_FMT, MEI_HDR_PRM(mei_hdr));
312
313         if (mei_hdr->reserved || !dev->rd_msg_hdr) {
314                 dev_dbg(&dev->pdev->dev, "corrupted message header.\n");
315                 ret = -EBADMSG;
316                 goto end;
317         }
318
319         if (mei_hdr->host_addr || mei_hdr->me_addr) {
320                 list_for_each_entry_safe(cl_pos, cl_next,
321                                         &dev->file_list, link) {
322                         dev_dbg(&dev->pdev->dev,
323                                         "list_for_each_entry_safe read host"
324                                         " client = %d, ME client = %d\n",
325                                         cl_pos->host_client_id,
326                                         cl_pos->me_client_id);
327                         if (mei_cl_hbm_equal(cl_pos, mei_hdr))
328                                 break;
329                 }
330
331                 if (&cl_pos->link == &dev->file_list) {
332                         dev_dbg(&dev->pdev->dev, "corrupted message header\n");
333                         ret = -EBADMSG;
334                         goto end;
335                 }
336         }
337         if (((*slots) * sizeof(u32)) < mei_hdr->length) {
338                 dev_err(&dev->pdev->dev,
339                                 "we can't read the message slots =%08x.\n",
340                                 *slots);
341                 /* we can't read the message */
342                 ret = -ERANGE;
343                 goto end;
344         }
345
346         /* decide where to read the message too */
347         if (!mei_hdr->host_addr) {
348                 dev_dbg(&dev->pdev->dev, "call mei_irq_thread_read_bus_message.\n");
349                 mei_hbm_dispatch(dev, mei_hdr);
350                 dev_dbg(&dev->pdev->dev, "end mei_irq_thread_read_bus_message.\n");
351         } else if (mei_hdr->host_addr == dev->iamthif_cl.host_client_id &&
352                    (MEI_FILE_CONNECTED == dev->iamthif_cl.state) &&
353                    (dev->iamthif_state == MEI_IAMTHIF_READING)) {
354
355                 dev_dbg(&dev->pdev->dev, "call mei_irq_thread_read_iamthif_message.\n");
356                 dev_dbg(&dev->pdev->dev, MEI_HDR_FMT, MEI_HDR_PRM(mei_hdr));
357
358                 ret = mei_amthif_irq_read_msg(dev, mei_hdr, cmpl_list);
359                 if (ret)
360                         goto end;
361         } else {
362                 dev_dbg(&dev->pdev->dev, "call mei_cl_irq_read_msg.\n");
363                 dev_dbg(&dev->pdev->dev, MEI_HDR_FMT, MEI_HDR_PRM(mei_hdr));
364                 ret = mei_cl_irq_read_msg(dev, mei_hdr, cmpl_list);
365                 if (ret)
366                         goto end;
367         }
368
369         /* reset the number of slots and header */
370         *slots = mei_count_full_read_slots(dev);
371         dev->rd_msg_hdr = 0;
372
373         if (*slots == -EOVERFLOW) {
374                 /* overflow - reset */
375                 dev_err(&dev->pdev->dev, "resetting due to slots overflow.\n");
376                 /* set the event since message has been read */
377                 ret = -ERANGE;
378                 goto end;
379         }
380 end:
381         return ret;
382 }
383 EXPORT_SYMBOL_GPL(mei_irq_read_handler);
384
385
386 /**
387  * mei_irq_write_handler -  dispatch write requests
388  *  after irq received
389  *
390  * @dev: the device structure
391  * @cmpl_list: An instance of our list structure
392  *
393  * returns 0 on success, <0 on failure.
394  */
395 int mei_irq_write_handler(struct mei_device *dev, struct mei_cl_cb *cmpl_list)
396 {
397
398         struct mei_cl *cl;
399         struct mei_cl_cb *cb, *next;
400         struct mei_cl_cb *list;
401         s32 slots;
402         int ret;
403
404         if (!mei_hbuf_is_ready(dev)) {
405                 dev_dbg(&dev->pdev->dev, "host buffer is not empty.\n");
406                 return 0;
407         }
408         slots = mei_hbuf_empty_slots(dev);
409         if (slots <= 0)
410                 return -EMSGSIZE;
411
412         /* complete all waiting for write CB */
413         dev_dbg(&dev->pdev->dev, "complete all waiting for write cb.\n");
414
415         list = &dev->write_waiting_list;
416         list_for_each_entry_safe(cb, next, &list->list, list) {
417                 cl = cb->cl;
418                 if (cl == NULL)
419                         continue;
420
421                 cl->status = 0;
422                 list_del(&cb->list);
423                 if (MEI_WRITING == cl->writing_state &&
424                     cb->fop_type == MEI_FOP_WRITE &&
425                     cl != &dev->iamthif_cl) {
426                         dev_dbg(&dev->pdev->dev, "MEI WRITE COMPLETE\n");
427                         cl->writing_state = MEI_WRITE_COMPLETE;
428                         list_add_tail(&cb->list, &cmpl_list->list);
429                 }
430                 if (cl == &dev->iamthif_cl) {
431                         dev_dbg(&dev->pdev->dev, "check iamthif flow control.\n");
432                         if (dev->iamthif_flow_control_pending) {
433                                 ret = mei_amthif_irq_read(dev, &slots);
434                                 if (ret)
435                                         return ret;
436                         }
437                 }
438         }
439
440         if (dev->wd_state == MEI_WD_STOPPING) {
441                 dev->wd_state = MEI_WD_IDLE;
442                 wake_up_interruptible(&dev->wait_stop_wd);
443         }
444
445         if (dev->wr_ext_msg.hdr.length) {
446                 mei_write_message(dev, &dev->wr_ext_msg.hdr,
447                                 dev->wr_ext_msg.data);
448                 slots -= mei_data2slots(dev->wr_ext_msg.hdr.length);
449                 dev->wr_ext_msg.hdr.length = 0;
450         }
451         if (dev->dev_state == MEI_DEV_ENABLED) {
452                 if (dev->wd_pending &&
453                     mei_cl_flow_ctrl_creds(&dev->wd_cl) > 0) {
454                         if (mei_wd_send(dev))
455                                 dev_dbg(&dev->pdev->dev, "wd send failed.\n");
456                         else if (mei_cl_flow_ctrl_reduce(&dev->wd_cl))
457                                 return -ENODEV;
458
459                         dev->wd_pending = false;
460
461                         if (dev->wd_state == MEI_WD_RUNNING)
462                                 slots -= mei_data2slots(MEI_WD_START_MSG_SIZE);
463                         else
464                                 slots -= mei_data2slots(MEI_WD_STOP_MSG_SIZE);
465                 }
466         }
467
468         /* complete control write list CB */
469         dev_dbg(&dev->pdev->dev, "complete control write list cb.\n");
470         list_for_each_entry_safe(cb, next, &dev->ctrl_wr_list.list, list) {
471                 cl = cb->cl;
472                 if (!cl) {
473                         list_del(&cb->list);
474                         return -ENODEV;
475                 }
476                 switch (cb->fop_type) {
477                 case MEI_FOP_CLOSE:
478                         /* send disconnect message */
479                         ret = mei_cl_irq_close(cl, cb, &slots, cmpl_list);
480                         if (ret)
481                                 return ret;
482
483                         break;
484                 case MEI_FOP_READ:
485                         /* send flow control message */
486                         ret = mei_cl_irq_read(cl, cb, &slots, cmpl_list);
487                         if (ret)
488                                 return ret;
489
490                         break;
491                 case MEI_FOP_IOCTL:
492                         /* connect message */
493                         if (mei_cl_is_other_connecting(cl))
494                                 continue;
495                         ret = mei_cl_irq_ioctl(cl, cb, &slots, cmpl_list);
496                         if (ret)
497                                 return ret;
498
499                         break;
500
501                 default:
502                         BUG();
503                 }
504
505         }
506         /* complete  write list CB */
507         dev_dbg(&dev->pdev->dev, "complete write list cb.\n");
508         list_for_each_entry_safe(cb, next, &dev->write_list.list, list) {
509                 cl = cb->cl;
510                 if (cl == NULL)
511                         continue;
512                 if (mei_cl_flow_ctrl_creds(cl) <= 0) {
513                         dev_dbg(&dev->pdev->dev,
514                                 "No flow control credentials for client %d, not sending.\n",
515                                 cl->host_client_id);
516                         continue;
517                 }
518
519                 if (cl == &dev->iamthif_cl)
520                         ret = mei_amthif_irq_write_complete(cl, cb,
521                                                 &slots, cmpl_list);
522                 else
523                         ret = mei_cl_irq_write_complete(cl, cb,
524                                                 &slots, cmpl_list);
525                 if (ret)
526                         return ret;
527         }
528         return 0;
529 }
530 EXPORT_SYMBOL_GPL(mei_irq_write_handler);
531
532
533
534 /**
535  * mei_timer - timer function.
536  *
537  * @work: pointer to the work_struct structure
538  *
539  * NOTE: This function is called by timer interrupt work
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         if (dev->dev_state != MEI_DEV_ENABLED) {
555                 if (dev->dev_state == MEI_DEV_INIT_CLIENTS) {
556                         if (dev->init_clients_timer) {
557                                 if (--dev->init_clients_timer == 0) {
558                                         dev_err(&dev->pdev->dev, "reset: init clients timeout hbm_state = %d.\n",
559                                                 dev->hbm_state);
560                                         mei_reset(dev, 1);
561                                 }
562                         }
563                 }
564                 goto out;
565         }
566         /*** connect/disconnect timeouts ***/
567         list_for_each_entry_safe(cl_pos, cl_next, &dev->file_list, link) {
568                 if (cl_pos->timer_count) {
569                         if (--cl_pos->timer_count == 0) {
570                                 dev_err(&dev->pdev->dev, "reset: connect/disconnect timeout.\n");
571                                 mei_reset(dev, 1);
572                                 goto out;
573                         }
574                 }
575         }
576
577         if (dev->iamthif_stall_timer) {
578                 if (--dev->iamthif_stall_timer == 0) {
579                         dev_err(&dev->pdev->dev, "reset: amthif  hanged.\n");
580                         mei_reset(dev, 1);
581                         dev->iamthif_msg_buf_size = 0;
582                         dev->iamthif_msg_buf_index = 0;
583                         dev->iamthif_canceled = false;
584                         dev->iamthif_ioctl = true;
585                         dev->iamthif_state = MEI_IAMTHIF_IDLE;
586                         dev->iamthif_timer = 0;
587
588                         mei_io_cb_free(dev->iamthif_current_cb);
589                         dev->iamthif_current_cb = NULL;
590
591                         dev->iamthif_file_object = NULL;
592                         mei_amthif_run_next_cmd(dev);
593                 }
594         }
595
596         if (dev->iamthif_timer) {
597
598                 timeout = dev->iamthif_timer +
599                         mei_secs_to_jiffies(MEI_IAMTHIF_READ_TIMER);
600
601                 dev_dbg(&dev->pdev->dev, "dev->iamthif_timer = %ld\n",
602                                 dev->iamthif_timer);
603                 dev_dbg(&dev->pdev->dev, "timeout = %ld\n", timeout);
604                 dev_dbg(&dev->pdev->dev, "jiffies = %ld\n", jiffies);
605                 if (time_after(jiffies, timeout)) {
606                         /*
607                          * User didn't read the AMTHI data on time (15sec)
608                          * freeing AMTHI for other requests
609                          */
610
611                         dev_dbg(&dev->pdev->dev, "freeing AMTHI for other requests\n");
612
613                         list_for_each_entry_safe(cb_pos, cb_next,
614                                 &dev->amthif_rd_complete_list.list, list) {
615
616                                 cl_pos = cb_pos->file_object->private_data;
617
618                                 /* Finding the AMTHI entry. */
619                                 if (cl_pos == &dev->iamthif_cl)
620                                         list_del(&cb_pos->list);
621                         }
622                         mei_io_cb_free(dev->iamthif_current_cb);
623                         dev->iamthif_current_cb = NULL;
624
625                         dev->iamthif_file_object->private_data = NULL;
626                         dev->iamthif_file_object = NULL;
627                         dev->iamthif_timer = 0;
628                         mei_amthif_run_next_cmd(dev);
629
630                 }
631         }
632 out:
633         schedule_delayed_work(&dev->timer_work, 2 * HZ);
634         mutex_unlock(&dev->device_lock);
635 }
636