Merge branch 'for-linus' of git://neil.brown.name/md
[firefly-linux-kernel-4.4.55.git] / drivers / staging / mei / interrupt.c
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/pci.h>
19 #include <linux/kthread.h>
20 #include <linux/interrupt.h>
21 #include <linux/fs.h>
22 #include <linux/jiffies.h>
23
24 #include "mei_dev.h"
25 #include "mei.h"
26 #include "hw.h"
27 #include "interface.h"
28
29
30 /**
31  * mei_interrupt_quick_handler - The ISR of the MEI device
32  *
33  * @irq: The irq number
34  * @dev_id: pointer to the device structure
35  *
36  * returns irqreturn_t
37  */
38 irqreturn_t mei_interrupt_quick_handler(int irq, void *dev_id)
39 {
40         struct mei_device *dev = (struct mei_device *) dev_id;
41         u32 csr_reg = mei_hcsr_read(dev);
42
43         if ((csr_reg & H_IS) != H_IS)
44                 return IRQ_NONE;
45
46         /* clear H_IS bit in H_CSR */
47         mei_reg_write(dev, H_CSR, csr_reg);
48
49         return IRQ_WAKE_THREAD;
50 }
51
52 /**
53  * _mei_cmpl - processes completed operation.
54  *
55  * @cl: private data of the file object.
56  * @cb_pos: callback block.
57  */
58 static void _mei_cmpl(struct mei_cl *cl, struct mei_cl_cb *cb_pos)
59 {
60         if (cb_pos->major_file_operations == MEI_WRITE) {
61                 mei_free_cb_private(cb_pos);
62                 cb_pos = NULL;
63                 cl->writing_state = MEI_WRITE_COMPLETE;
64                 if (waitqueue_active(&cl->tx_wait))
65                         wake_up_interruptible(&cl->tx_wait);
66
67         } else if (cb_pos->major_file_operations == MEI_READ &&
68                         MEI_READING == cl->reading_state) {
69                 cl->reading_state = MEI_READ_COMPLETE;
70                 if (waitqueue_active(&cl->rx_wait))
71                         wake_up_interruptible(&cl->rx_wait);
72
73         }
74 }
75
76 /**
77  * _mei_cmpl_iamthif - processes completed iamthif operation.
78  *
79  * @dev: the device structure.
80  * @cb_pos: callback block.
81  */
82 static void _mei_cmpl_iamthif(struct mei_device *dev, struct mei_cl_cb *cb_pos)
83 {
84         if (dev->iamthif_canceled != 1) {
85                 dev->iamthif_state = MEI_IAMTHIF_READ_COMPLETE;
86                 dev->iamthif_stall_timer = 0;
87                 memcpy(cb_pos->response_buffer.data,
88                                 dev->iamthif_msg_buf,
89                                 dev->iamthif_msg_buf_index);
90                 list_add_tail(&cb_pos->cb_list,
91                                 &dev->amthi_read_complete_list.mei_cb.cb_list);
92                 dev_dbg(&dev->pdev->dev, "amthi read completed.\n");
93                 dev->iamthif_timer = jiffies;
94                 dev_dbg(&dev->pdev->dev, "dev->iamthif_timer = %ld\n",
95                                 dev->iamthif_timer);
96         } else {
97                 mei_run_next_iamthif_cmd(dev);
98         }
99
100         dev_dbg(&dev->pdev->dev, "completing amthi call back.\n");
101         wake_up_interruptible(&dev->iamthif_cl.wait);
102 }
103
104
105 /**
106  * mei_irq_thread_read_amthi_message - bottom half read routine after ISR to
107  * handle the read amthi message data processing.
108  *
109  * @complete_list: An instance of our list structure
110  * @dev: the device structure
111  * @mei_hdr: header of amthi message
112  *
113  * returns 0 on success, <0 on failure.
114  */
115 static int mei_irq_thread_read_amthi_message(struct mei_io_list *complete_list,
116                 struct mei_device *dev,
117                 struct mei_msg_hdr *mei_hdr)
118 {
119         struct mei_cl *cl;
120         struct mei_cl_cb *cb;
121         unsigned char *buffer;
122
123         BUG_ON(mei_hdr->me_addr != dev->iamthif_cl.me_client_id);
124         BUG_ON(dev->iamthif_state != MEI_IAMTHIF_READING);
125
126         buffer = (unsigned char *) (dev->iamthif_msg_buf +
127                         dev->iamthif_msg_buf_index);
128         BUG_ON(dev->iamthif_mtu < dev->iamthif_msg_buf_index + mei_hdr->length);
129
130         mei_read_slots(dev, buffer, mei_hdr->length);
131
132         dev->iamthif_msg_buf_index += mei_hdr->length;
133
134         if (!mei_hdr->msg_complete)
135                 return 0;
136
137         dev_dbg(&dev->pdev->dev,
138                         "amthi_message_buffer_index =%d\n",
139                         mei_hdr->length);
140
141         dev_dbg(&dev->pdev->dev, "completed amthi read.\n ");
142         if (!dev->iamthif_current_cb)
143                 return -ENODEV;
144
145         cb = dev->iamthif_current_cb;
146         dev->iamthif_current_cb = NULL;
147
148         cl = (struct mei_cl *)cb->file_private;
149         if (!cl)
150                 return -ENODEV;
151
152         dev->iamthif_stall_timer = 0;
153         cb->information =       dev->iamthif_msg_buf_index;
154         cb->read_time = jiffies;
155         if (dev->iamthif_ioctl && cl == &dev->iamthif_cl) {
156                 /* found the iamthif cb */
157                 dev_dbg(&dev->pdev->dev, "complete the amthi read cb.\n ");
158                 dev_dbg(&dev->pdev->dev, "add the amthi read cb to complete.\n ");
159                 list_add_tail(&cb->cb_list,
160                                                 &complete_list->mei_cb.cb_list);
161         }
162         return 0;
163 }
164
165 /**
166  * _mei_irq_thread_state_ok - checks if mei header matches file private data
167  *
168  * @cl: private data of the file object
169  * @mei_hdr: header of mei client message
170  *
171  * returns !=0 if matches, 0 if no match.
172  */
173 static int _mei_irq_thread_state_ok(struct mei_cl *cl,
174                                 struct mei_msg_hdr *mei_hdr)
175 {
176         return (cl->host_client_id == mei_hdr->host_addr &&
177                 cl->me_client_id == mei_hdr->me_addr &&
178                 cl->state == MEI_FILE_CONNECTED &&
179                 MEI_READ_COMPLETE != cl->reading_state);
180 }
181
182 /**
183  * mei_irq_thread_read_client_message - bottom half read routine after ISR to
184  * handle the read mei client message data processing.
185  *
186  * @complete_list: An instance of our list structure
187  * @dev: the device structure
188  * @mei_hdr: header of mei client message
189  *
190  * returns 0 on success, <0 on failure.
191  */
192 static int mei_irq_thread_read_client_message(struct mei_io_list *complete_list,
193                 struct mei_device *dev,
194                 struct mei_msg_hdr *mei_hdr)
195 {
196         struct mei_cl *cl;
197         struct mei_cl_cb *cb_pos = NULL, *cb_next = NULL;
198         unsigned char *buffer = NULL;
199
200         dev_dbg(&dev->pdev->dev, "start client msg\n");
201         if (!(dev->read_list.status == 0 &&
202               !list_empty(&dev->read_list.mei_cb.cb_list)))
203                 goto quit;
204
205         list_for_each_entry_safe(cb_pos, cb_next,
206                         &dev->read_list.mei_cb.cb_list, cb_list) {
207                 cl = (struct mei_cl *)cb_pos->file_private;
208                 if (cl && _mei_irq_thread_state_ok(cl, mei_hdr)) {
209                         cl->reading_state = MEI_READING;
210                         buffer = (unsigned char *)
211                                 (cb_pos->response_buffer.data +
212                                 cb_pos->information);
213                         BUG_ON(cb_pos->response_buffer.size <
214                                         mei_hdr->length +
215                                         cb_pos->information);
216
217                         if (cb_pos->response_buffer.size <
218                                         mei_hdr->length + cb_pos->information) {
219                                 dev_dbg(&dev->pdev->dev, "message overflow.\n");
220                                 list_del(&cb_pos->cb_list);
221                                 return -ENOMEM;
222                         }
223                         if (buffer)
224                                 mei_read_slots(dev, buffer, mei_hdr->length);
225
226                         cb_pos->information += mei_hdr->length;
227                         if (mei_hdr->msg_complete) {
228                                 cl->status = 0;
229                                 list_del(&cb_pos->cb_list);
230                                 dev_dbg(&dev->pdev->dev,
231                                         "completed read host client = %d,"
232                                         "ME client = %d, "
233                                         "data length = %lu\n",
234                                         cl->host_client_id,
235                                         cl->me_client_id,
236                                         cb_pos->information);
237
238                                 *(cb_pos->response_buffer.data +
239                                         cb_pos->information) = '\0';
240                                 dev_dbg(&dev->pdev->dev, "cb_pos->res_buffer - %s\n",
241                                         cb_pos->response_buffer.data);
242                                 list_add_tail(&cb_pos->cb_list,
243                                         &complete_list->mei_cb.cb_list);
244                         }
245
246                         break;
247                 }
248
249         }
250
251 quit:
252         dev_dbg(&dev->pdev->dev, "message read\n");
253         if (!buffer) {
254                 mei_read_slots(dev, (unsigned char *) dev->rd_msg_buf,
255                                                 mei_hdr->length);
256                 dev_dbg(&dev->pdev->dev, "discarding message, header =%08x.\n",
257                                 *(u32 *) dev->rd_msg_buf);
258         }
259
260         return 0;
261 }
262
263 /**
264  * _mei_irq_thread_iamthif_read - prepares to read iamthif data.
265  *
266  * @dev: the device structure.
267  * @slots: free slots.
268  *
269  * returns 0, OK; otherwise, error.
270  */
271 static int _mei_irq_thread_iamthif_read(struct mei_device *dev, s32 *slots)
272 {
273
274         if (((*slots) * sizeof(u32)) >= (sizeof(struct mei_msg_hdr)
275                         + sizeof(struct hbm_flow_control))) {
276                 *slots -= (sizeof(struct mei_msg_hdr) +
277                                 sizeof(struct hbm_flow_control) + 3) / 4;
278                 if (!mei_send_flow_control(dev, &dev->iamthif_cl)) {
279                         dev_dbg(&dev->pdev->dev, "iamthif flow control failed\n");
280                 } else {
281                         dev_dbg(&dev->pdev->dev, "iamthif flow control success\n");
282                         dev->iamthif_state = MEI_IAMTHIF_READING;
283                         dev->iamthif_flow_control_pending = false;
284                         dev->iamthif_msg_buf_index = 0;
285                         dev->iamthif_msg_buf_size = 0;
286                         dev->iamthif_stall_timer = IAMTHIF_STALL_TIMER;
287                         dev->mei_host_buffer_is_empty =
288                                         mei_host_buffer_is_empty(dev);
289                 }
290                 return 0;
291         } else {
292                 return -EMSGSIZE;
293         }
294 }
295
296 /**
297  * _mei_irq_thread_close - processes close related operation.
298  *
299  * @dev: the device structure.
300  * @slots: free slots.
301  * @cb_pos: callback block.
302  * @cl: private data of the file object.
303  * @cmpl_list: complete list.
304  *
305  * returns 0, OK; otherwise, error.
306  */
307 static int _mei_irq_thread_close(struct mei_device *dev, s32 *slots,
308                                 struct mei_cl_cb *cb_pos,
309                                 struct mei_cl *cl,
310                                 struct mei_io_list *cmpl_list)
311 {
312         if ((*slots * sizeof(u32)) >= (sizeof(struct mei_msg_hdr) +
313                         sizeof(struct hbm_client_disconnect_request))) {
314                 *slots -= (sizeof(struct mei_msg_hdr) +
315                         sizeof(struct hbm_client_disconnect_request) + 3) / 4;
316
317                 if (!mei_disconnect(dev, cl)) {
318                         cl->status = 0;
319                         cb_pos->information = 0;
320                         list_move_tail(&cb_pos->cb_list,
321                                         &cmpl_list->mei_cb.cb_list);
322                         return -EMSGSIZE;
323                 } else {
324                         cl->state = MEI_FILE_DISCONNECTING;
325                         cl->status = 0;
326                         cb_pos->information = 0;
327                         list_move_tail(&cb_pos->cb_list,
328                                         &dev->ctrl_rd_list.mei_cb.cb_list);
329                         cl->timer_count = MEI_CONNECT_TIMEOUT;
330                 }
331         } else {
332                 /* return the cancel routine */
333                 return -EBADMSG;
334         }
335
336         return 0;
337 }
338
339 /**
340  * is_treat_specially_client - checks if the message belongs
341  * to the file private data.
342  *
343  * @cl: private data of the file object
344  * @rs: connect response bus message
345  *
346  */
347 static bool is_treat_specially_client(struct mei_cl *cl,
348                 struct hbm_client_connect_response *rs)
349 {
350
351         if (cl->host_client_id == rs->host_addr &&
352             cl->me_client_id == rs->me_addr) {
353                 if (!rs->status) {
354                         cl->state = MEI_FILE_CONNECTED;
355                         cl->status = 0;
356
357                 } else {
358                         cl->state = MEI_FILE_DISCONNECTED;
359                         cl->status = -ENODEV;
360                 }
361                 cl->timer_count = 0;
362
363                 return true;
364         }
365         return false;
366 }
367
368 /**
369  * mei_client_connect_response - connects to response irq routine
370  *
371  * @dev: the device structure
372  * @rs: connect response bus message
373  */
374 static void mei_client_connect_response(struct mei_device *dev,
375                 struct hbm_client_connect_response *rs)
376 {
377
378         struct mei_cl *cl;
379         struct mei_cl_cb *cb_pos = NULL, *cb_next = NULL;
380
381         dev_dbg(&dev->pdev->dev,
382                         "connect_response:\n"
383                         "ME Client = %d\n"
384                         "Host Client = %d\n"
385                         "Status = %d\n",
386                         rs->me_addr,
387                         rs->host_addr,
388                         rs->status);
389
390         /* if WD or iamthif client treat specially */
391
392         if (is_treat_specially_client(&(dev->wd_cl), rs)) {
393                 dev_dbg(&dev->pdev->dev, "dev->wd_timeout =%d.\n",
394                                 dev->wd_timeout);
395
396                 dev->wd_due_counter = (dev->wd_timeout) ? 1 : 0;
397
398                 dev_dbg(&dev->pdev->dev, "successfully connected to WD client.\n");
399
400                 /* Registering watchdog interface device once we got connection
401                    to the WD Client
402                 */
403                 if (watchdog_register_device(&amt_wd_dev)) {
404                         printk(KERN_ERR "mei: unable to register watchdog device.\n");
405                         dev->wd_interface_reg = false;
406                 } else {
407                         dev_dbg(&dev->pdev->dev, "successfully register watchdog interface.\n");
408                         dev->wd_interface_reg = true;
409                 }
410
411                 mei_host_init_iamthif(dev);
412                 return;
413         }
414
415         if (is_treat_specially_client(&(dev->iamthif_cl), rs)) {
416                 dev->iamthif_state = MEI_IAMTHIF_IDLE;
417                 return;
418         }
419         if (!dev->ctrl_rd_list.status &&
420             !list_empty(&dev->ctrl_rd_list.mei_cb.cb_list)) {
421                 list_for_each_entry_safe(cb_pos, cb_next,
422                         &dev->ctrl_rd_list.mei_cb.cb_list, cb_list) {
423                         cl = (struct mei_cl *)cb_pos->file_private;
424                         if (!cl) {
425                                 list_del(&cb_pos->cb_list);
426                                 return;
427                         }
428                         if (MEI_IOCTL == cb_pos->major_file_operations) {
429                                 if (is_treat_specially_client(cl, rs)) {
430                                         list_del(&cb_pos->cb_list);
431                                         cl->status = 0;
432                                         cl->timer_count = 0;
433                                         break;
434                                 }
435                         }
436                 }
437         }
438 }
439
440 /**
441  * mei_client_disconnect_response - disconnects from response irq routine
442  *
443  * @dev: the device structure
444  * @rs: disconnect response bus message
445  */
446 static void mei_client_disconnect_response(struct mei_device *dev,
447                                         struct hbm_client_connect_response *rs)
448 {
449         struct mei_cl *cl;
450         struct mei_cl_cb *cb_pos = NULL, *cb_next = NULL;
451
452         dev_dbg(&dev->pdev->dev,
453                         "disconnect_response:\n"
454                         "ME Client = %d\n"
455                         "Host Client = %d\n"
456                         "Status = %d\n",
457                         rs->me_addr,
458                         rs->host_addr,
459                         rs->status);
460
461         if (!dev->ctrl_rd_list.status &&
462             !list_empty(&dev->ctrl_rd_list.mei_cb.cb_list)) {
463                 list_for_each_entry_safe(cb_pos, cb_next,
464                                 &dev->ctrl_rd_list.mei_cb.cb_list, cb_list) {
465                         cl = (struct mei_cl *)cb_pos->file_private;
466
467                         if (!cl) {
468                                 list_del(&cb_pos->cb_list);
469                                 return;
470                         }
471
472                         dev_dbg(&dev->pdev->dev, "list_for_each_entry_safe in ctrl_rd_list.\n");
473                         if (cl->host_client_id == rs->host_addr &&
474                             cl->me_client_id == rs->me_addr) {
475
476                                 list_del(&cb_pos->cb_list);
477                                 if (!rs->status)
478                                         cl->state = MEI_FILE_DISCONNECTED;
479
480                                 cl->status = 0;
481                                 cl->timer_count = 0;
482                                 break;
483                         }
484                 }
485         }
486 }
487
488 /**
489  * same_flow_addr - tells if they have the same address.
490  *
491  * @file: private data of the file object.
492  * @flow: flow control.
493  *
494  * returns  !=0, same; 0,not.
495  */
496 static int same_flow_addr(struct mei_cl *cl, struct hbm_flow_control *flow)
497 {
498         return (cl->host_client_id == flow->host_addr &&
499                 cl->me_client_id == flow->me_addr);
500 }
501
502 /**
503  * add_single_flow_creds - adds single buffer credentials.
504  *
505  * @file: private data ot the file object.
506  * @flow: flow control.
507  */
508 static void add_single_flow_creds(struct mei_device *dev,
509                                   struct hbm_flow_control *flow)
510 {
511         struct mei_me_client *client;
512         int i;
513
514         for (i = 0; i < dev->me_clients_num; i++) {
515                 client = &dev->me_clients[i];
516                 if (client && flow->me_addr == client->client_id) {
517                         if (client->props.single_recv_buf) {
518                                 client->mei_flow_ctrl_creds++;
519                                 dev_dbg(&dev->pdev->dev, "recv flow ctrl msg ME %d (single).\n",
520                                     flow->me_addr);
521                                 dev_dbg(&dev->pdev->dev, "flow control credentials =%d.\n",
522                                     client->mei_flow_ctrl_creds);
523                         } else {
524                                 BUG();  /* error in flow control */
525                         }
526                 }
527         }
528 }
529
530 /**
531  * mei_client_flow_control_response - flow control response irq routine
532  *
533  * @dev: the device structure
534  * @flow_control: flow control response bus message
535  */
536 static void mei_client_flow_control_response(struct mei_device *dev,
537                 struct hbm_flow_control *flow_control)
538 {
539         struct mei_cl *cl_pos = NULL;
540         struct mei_cl *cl_next = NULL;
541
542         if (!flow_control->host_addr) {
543                 /* single receive buffer */
544                 add_single_flow_creds(dev, flow_control);
545         } else {
546                 /* normal connection */
547                 list_for_each_entry_safe(cl_pos, cl_next,
548                                 &dev->file_list, link) {
549                         dev_dbg(&dev->pdev->dev, "list_for_each_entry_safe in file_list\n");
550
551                         dev_dbg(&dev->pdev->dev, "cl of host client %d ME client %d.\n",
552                             cl_pos->host_client_id,
553                             cl_pos->me_client_id);
554                         dev_dbg(&dev->pdev->dev, "flow ctrl msg for host %d ME %d.\n",
555                             flow_control->host_addr,
556                             flow_control->me_addr);
557                         if (same_flow_addr(cl_pos, flow_control)) {
558                                 dev_dbg(&dev->pdev->dev, "recv ctrl msg for host  %d ME %d.\n",
559                                     flow_control->host_addr,
560                                     flow_control->me_addr);
561                                 cl_pos->mei_flow_ctrl_creds++;
562                                 dev_dbg(&dev->pdev->dev, "flow control credentials = %d.\n",
563                                     cl_pos->mei_flow_ctrl_creds);
564                                 break;
565                         }
566                 }
567         }
568 }
569
570 /**
571  * same_disconn_addr - tells if they have the same address
572  *
573  * @file: private data of the file object.
574  * @disconn: disconnection request.
575  *
576  * returns !=0, same; 0,not.
577  */
578 static int same_disconn_addr(struct mei_cl *cl,
579                              struct hbm_client_disconnect_request *disconn)
580 {
581         return (cl->host_client_id == disconn->host_addr &&
582                 cl->me_client_id == disconn->me_addr);
583 }
584
585 /**
586  * mei_client_disconnect_request - disconnects from request irq routine
587  *
588  * @dev: the device structure.
589  * @disconnect_req: disconnect request bus message.
590  */
591 static void mei_client_disconnect_request(struct mei_device *dev,
592                 struct hbm_client_disconnect_request *disconnect_req)
593 {
594         struct mei_msg_hdr *mei_hdr;
595         struct hbm_client_connect_response *disconnect_res;
596         struct mei_cl *cl_pos = NULL;
597         struct mei_cl *cl_next = NULL;
598
599         list_for_each_entry_safe(cl_pos, cl_next, &dev->file_list, link) {
600                 if (same_disconn_addr(cl_pos, disconnect_req)) {
601                         dev_dbg(&dev->pdev->dev, "disconnect request host client %d ME client %d.\n",
602                                         disconnect_req->host_addr,
603                                         disconnect_req->me_addr);
604                         cl_pos->state = MEI_FILE_DISCONNECTED;
605                         cl_pos->timer_count = 0;
606                         if (cl_pos == &dev->wd_cl) {
607                                 dev->wd_due_counter = 0;
608                                 dev->wd_pending = false;
609                         } else if (cl_pos == &dev->iamthif_cl)
610                                 dev->iamthif_timer = 0;
611
612                         /* prepare disconnect response */
613                         mei_hdr =
614                                 (struct mei_msg_hdr *) &dev->ext_msg_buf[0];
615                         mei_hdr->host_addr = 0;
616                         mei_hdr->me_addr = 0;
617                         mei_hdr->length =
618                                 sizeof(struct hbm_client_connect_response);
619                         mei_hdr->msg_complete = 1;
620                         mei_hdr->reserved = 0;
621
622                         disconnect_res =
623                                 (struct hbm_client_connect_response *)
624                                 &dev->ext_msg_buf[1];
625                         disconnect_res->host_addr = cl_pos->host_client_id;
626                         disconnect_res->me_addr = cl_pos->me_client_id;
627                         *(u8 *) (&disconnect_res->cmd) =
628                                 CLIENT_DISCONNECT_RES_CMD;
629                         disconnect_res->status = 0;
630                         dev->extra_write_index = 2;
631                         break;
632                 }
633         }
634 }
635
636
637 /**
638  * mei_irq_thread_read_bus_message - bottom half read routine after ISR to
639  * handle the read bus message cmd processing.
640  *
641  * @dev: the device structure
642  * @mei_hdr: header of bus message
643  */
644 static void mei_irq_thread_read_bus_message(struct mei_device *dev,
645                 struct mei_msg_hdr *mei_hdr)
646 {
647         struct mei_bus_message *mei_msg;
648         struct hbm_host_version_response *version_res;
649         struct hbm_client_connect_response *connect_res;
650         struct hbm_client_connect_response *disconnect_res;
651         struct hbm_flow_control *flow_control;
652         struct hbm_props_response *props_res;
653         struct hbm_host_enum_response *enum_res;
654         struct hbm_client_disconnect_request *disconnect_req;
655         struct hbm_host_stop_request *host_stop_req;
656         int res;
657
658         unsigned char *buffer;
659
660         /* read the message to our buffer */
661         buffer = (unsigned char *) dev->rd_msg_buf;
662         BUG_ON(mei_hdr->length >= sizeof(dev->rd_msg_buf));
663         mei_read_slots(dev, buffer, mei_hdr->length);
664         mei_msg = (struct mei_bus_message *) buffer;
665
666         switch (*(u8 *) mei_msg) {
667         case HOST_START_RES_CMD:
668                 version_res = (struct hbm_host_version_response *) mei_msg;
669                 if (version_res->host_version_supported) {
670                         dev->version.major_version = HBM_MAJOR_VERSION;
671                         dev->version.minor_version = HBM_MINOR_VERSION;
672                         if (dev->mei_state == MEI_INIT_CLIENTS &&
673                             dev->init_clients_state == MEI_START_MESSAGE) {
674                                 dev->init_clients_timer = 0;
675                                 mei_host_enum_clients_message(dev);
676                         } else {
677                                 dev->recvd_msg = false;
678                                 dev_dbg(&dev->pdev->dev, "IMEI reset due to received host start response bus message.\n");
679                                 mei_reset(dev, 1);
680                                 return;
681                         }
682                 } else {
683                         dev->version = version_res->me_max_version;
684                         /* send stop message */
685                         mei_hdr->host_addr = 0;
686                         mei_hdr->me_addr = 0;
687                         mei_hdr->length = sizeof(struct hbm_host_stop_request);
688                         mei_hdr->msg_complete = 1;
689                         mei_hdr->reserved = 0;
690
691                         host_stop_req = (struct hbm_host_stop_request *)
692                                                         &dev->wr_msg_buf[1];
693
694                         memset(host_stop_req,
695                                         0,
696                                         sizeof(struct hbm_host_stop_request));
697                         host_stop_req->cmd.cmd = HOST_STOP_REQ_CMD;
698                         host_stop_req->reason = DRIVER_STOP_REQUEST;
699                         mei_write_message(dev, mei_hdr,
700                                            (unsigned char *) (host_stop_req),
701                                            mei_hdr->length);
702                         dev_dbg(&dev->pdev->dev, "version mismatch.\n");
703                         return;
704                 }
705
706                 dev->recvd_msg = true;
707                 dev_dbg(&dev->pdev->dev, "host start response message received.\n");
708                 break;
709
710         case CLIENT_CONNECT_RES_CMD:
711                 connect_res =
712                         (struct hbm_client_connect_response *) mei_msg;
713                 mei_client_connect_response(dev, connect_res);
714                 dev_dbg(&dev->pdev->dev, "client connect response message received.\n");
715                 wake_up(&dev->wait_recvd_msg);
716                 break;
717
718         case CLIENT_DISCONNECT_RES_CMD:
719                 disconnect_res =
720                         (struct hbm_client_connect_response *) mei_msg;
721                 mei_client_disconnect_response(dev,      disconnect_res);
722                 dev_dbg(&dev->pdev->dev, "client disconnect response message received.\n");
723                 wake_up(&dev->wait_recvd_msg);
724                 break;
725
726         case MEI_FLOW_CONTROL_CMD:
727                 flow_control = (struct hbm_flow_control *) mei_msg;
728                 mei_client_flow_control_response(dev, flow_control);
729                 dev_dbg(&dev->pdev->dev, "client flow control response message received.\n");
730                 break;
731
732         case HOST_CLIENT_PROPERTIES_RES_CMD:
733                 props_res = (struct hbm_props_response *)mei_msg;
734                 if (props_res->status || !dev->me_clients) {
735                         dev_dbg(&dev->pdev->dev, "reset due to received host client properties response bus message wrong status.\n");
736                         mei_reset(dev, 1);
737                         return;
738                 }
739                if (dev->me_clients[dev->me_client_presentation_num]
740                                         .client_id == props_res->address) {
741
742                         dev->me_clients[dev->me_client_presentation_num].props
743                                                 = props_res->client_properties;
744
745                         if (dev->mei_state == MEI_INIT_CLIENTS &&
746                             dev->init_clients_state ==
747                                         MEI_CLIENT_PROPERTIES_MESSAGE) {
748                                 dev->me_client_index++;
749                                 dev->me_client_presentation_num++;
750
751                                 /** Send Client Propeties request **/
752                                 res = mei_host_client_properties(dev);
753                                 if (res < 0) {
754                                         dev_dbg(&dev->pdev->dev, "mei_host_client_properties() failed");
755                                         return;
756                                 } else if (!res) {
757                                         /*
758                                          * No more clients to send to.
759                                          * Clear Map for indicating now ME clients
760                                          * with associated host client
761                                          */
762                                         bitmap_zero(dev->host_clients_map, MEI_CLIENTS_MAX);
763                                         dev->open_handle_count = 0;
764
765                                         /*
766                                          * Reserving the first three client IDs
767                                          * Client Id 0 - Reserved for MEI Bus Message communications
768                                          * Client Id 1 - Reserved for Watchdog
769                                          * Client ID 2 - Reserved for AMTHI
770                                          */
771                                         bitmap_set(dev->host_clients_map, 0, 3);
772                                         dev->mei_state = MEI_ENABLED;
773
774                                         /* if wd initialization fails, initialization the AMTHI client,
775                                          * otherwise the AMTHI client will be initialized after the WD client connect response
776                                          * will be received
777                                          */
778                                         if (mei_wd_host_init(dev))
779                                                 mei_host_init_iamthif(dev);
780                                 }
781
782                         } else {
783                                 dev_dbg(&dev->pdev->dev, "reset due to received host client properties response bus message");
784                                 mei_reset(dev, 1);
785                                 return;
786                         }
787                 } else {
788                         dev_dbg(&dev->pdev->dev, "reset due to received host client properties response bus message for wrong client ID\n");
789                         mei_reset(dev, 1);
790                         return;
791                 }
792                 break;
793
794         case HOST_ENUM_RES_CMD:
795                 enum_res = (struct hbm_host_enum_response *) mei_msg;
796                 memcpy(dev->me_clients_map, enum_res->valid_addresses, 32);
797                 if (dev->mei_state == MEI_INIT_CLIENTS &&
798                     dev->init_clients_state == MEI_ENUM_CLIENTS_MESSAGE) {
799                                 dev->init_clients_timer = 0;
800                                 dev->me_client_presentation_num = 0;
801                                 dev->me_client_index = 0;
802                                 mei_allocate_me_clients_storage(dev);
803                                 dev->init_clients_state =
804                                         MEI_CLIENT_PROPERTIES_MESSAGE;
805                                 mei_host_client_properties(dev);
806                 } else {
807                         dev_dbg(&dev->pdev->dev, "reset due to received host enumeration clients response bus message.\n");
808                         mei_reset(dev, 1);
809                         return;
810                 }
811                 break;
812
813         case HOST_STOP_RES_CMD:
814                 dev->mei_state = MEI_DISABLED;
815                 dev_dbg(&dev->pdev->dev, "resetting because of FW stop response.\n");
816                 mei_reset(dev, 1);
817                 break;
818
819         case CLIENT_DISCONNECT_REQ_CMD:
820                 /* search for client */
821                 disconnect_req =
822                         (struct hbm_client_disconnect_request *) mei_msg;
823                 mei_client_disconnect_request(dev, disconnect_req);
824                 break;
825
826         case ME_STOP_REQ_CMD:
827                 /* prepare stop request */
828                 mei_hdr = (struct mei_msg_hdr *) &dev->ext_msg_buf[0];
829                 mei_hdr->host_addr = 0;
830                 mei_hdr->me_addr = 0;
831                 mei_hdr->length = sizeof(struct hbm_host_stop_request);
832                 mei_hdr->msg_complete = 1;
833                 mei_hdr->reserved = 0;
834                 host_stop_req =
835                         (struct hbm_host_stop_request *) &dev->ext_msg_buf[1];
836                 memset(host_stop_req, 0, sizeof(struct hbm_host_stop_request));
837                 host_stop_req->cmd.cmd = HOST_STOP_REQ_CMD;
838                 host_stop_req->reason = DRIVER_STOP_REQUEST;
839                 host_stop_req->reserved[0] = 0;
840                 host_stop_req->reserved[1] = 0;
841                 dev->extra_write_index = 2;
842                 break;
843
844         default:
845                 BUG();
846                 break;
847
848         }
849 }
850
851
852 /**
853  * _mei_hb_read - processes read related operation.
854  *
855  * @dev: the device structure.
856  * @slots: free slots.
857  * @cb_pos: callback block.
858  * @cl: private data of the file object.
859  * @cmpl_list: complete list.
860  *
861  * returns 0, OK; otherwise, error.
862  */
863 static int _mei_irq_thread_read(struct mei_device *dev, s32 *slots,
864                         struct mei_cl_cb *cb_pos,
865                         struct mei_cl *cl,
866                         struct mei_io_list *cmpl_list)
867 {
868         if ((*slots * sizeof(u32)) >= (sizeof(struct mei_msg_hdr) +
869                         sizeof(struct hbm_flow_control))) {
870                 *slots -= (sizeof(struct mei_msg_hdr) +
871                         sizeof(struct hbm_flow_control) + 3) / 4;
872                 if (!mei_send_flow_control(dev, cl)) {
873                         cl->status = -ENODEV;
874                         cb_pos->information = 0;
875                         list_move_tail(&cb_pos->cb_list,
876                                         &cmpl_list->mei_cb.cb_list);
877                         return -ENODEV;
878                 } else {
879                         list_move_tail(&cb_pos->cb_list,
880                                         &dev->read_list.mei_cb.cb_list);
881                 }
882         } else {
883                 /* return the cancel routine */
884                 list_del(&cb_pos->cb_list);
885                 return -EBADMSG;
886         }
887
888         return 0;
889 }
890
891
892 /**
893  * _mei_irq_thread_ioctl - processes ioctl related operation.
894  *
895  * @dev: the device structure.
896  * @slots: free slots.
897  * @cb_pos: callback block.
898  * @cl: private data of the file object.
899  * @cmpl_list: complete list.
900  *
901  * returns 0, OK; otherwise, error.
902  */
903 static int _mei_irq_thread_ioctl(struct mei_device *dev, s32 *slots,
904                         struct mei_cl_cb *cb_pos,
905                         struct mei_cl *cl,
906                         struct mei_io_list *cmpl_list)
907 {
908         if ((*slots * sizeof(u32)) >= (sizeof(struct mei_msg_hdr) +
909                         sizeof(struct hbm_client_connect_request))) {
910                 cl->state = MEI_FILE_CONNECTING;
911                 *slots -= (sizeof(struct mei_msg_hdr) +
912                         sizeof(struct hbm_client_connect_request) + 3) / 4;
913                 if (!mei_connect(dev, cl)) {
914                         cl->status = -ENODEV;
915                         cb_pos->information = 0;
916                         list_del(&cb_pos->cb_list);
917                         return -ENODEV;
918                 } else {
919                         list_move_tail(&cb_pos->cb_list,
920                                 &dev->ctrl_rd_list.mei_cb.cb_list);
921                         cl->timer_count = MEI_CONNECT_TIMEOUT;
922                 }
923         } else {
924                 /* return the cancel routine */
925                 list_del(&cb_pos->cb_list);
926                 return -EBADMSG;
927         }
928
929         return 0;
930 }
931
932 /**
933  * _mei_irq_thread_cmpl - processes completed and no-iamthif operation.
934  *
935  * @dev: the device structure.
936  * @slots: free slots.
937  * @cb_pos: callback block.
938  * @cl: private data of the file object.
939  * @cmpl_list: complete list.
940  *
941  * returns 0, OK; otherwise, error.
942  */
943 static int _mei_irq_thread_cmpl(struct mei_device *dev, s32 *slots,
944                         struct mei_cl_cb *cb_pos,
945                         struct mei_cl *cl,
946                         struct mei_io_list *cmpl_list)
947 {
948         struct mei_msg_hdr *mei_hdr;
949
950         if ((*slots * sizeof(u32)) >= (sizeof(struct mei_msg_hdr) +
951                         (cb_pos->request_buffer.size -
952                         cb_pos->information))) {
953                 mei_hdr = (struct mei_msg_hdr *) &dev->wr_msg_buf[0];
954                 mei_hdr->host_addr = cl->host_client_id;
955                 mei_hdr->me_addr = cl->me_client_id;
956                 mei_hdr->length = cb_pos->request_buffer.size -
957                                         cb_pos->information;
958                 mei_hdr->msg_complete = 1;
959                 mei_hdr->reserved = 0;
960                 dev_dbg(&dev->pdev->dev, "cb_pos->request_buffer.size =%d"
961                         "mei_hdr->msg_complete = %d\n",
962                                 cb_pos->request_buffer.size,
963                                 mei_hdr->msg_complete);
964                 dev_dbg(&dev->pdev->dev, "cb_pos->information  =%lu\n",
965                                 cb_pos->information);
966                 dev_dbg(&dev->pdev->dev, "mei_hdr->length  =%d\n",
967                                 mei_hdr->length);
968                 *slots -= (sizeof(struct mei_msg_hdr) +
969                                 mei_hdr->length + 3) / 4;
970                 if (!mei_write_message(dev, mei_hdr,
971                                 (unsigned char *)
972                                 (cb_pos->request_buffer.data +
973                                 cb_pos->information),
974                                 mei_hdr->length)) {
975                         cl->status = -ENODEV;
976                         list_move_tail(&cb_pos->cb_list,
977                                 &cmpl_list->mei_cb.cb_list);
978                         return -ENODEV;
979                 } else {
980                         if (mei_flow_ctrl_reduce(dev, cl))
981                                 return -ENODEV;
982                         cl->status = 0;
983                         cb_pos->information += mei_hdr->length;
984                         list_move_tail(&cb_pos->cb_list,
985                                 &dev->write_waiting_list.mei_cb.cb_list);
986                 }
987         } else if (*slots == ((dev->host_hw_state & H_CBD) >> 24)) {
988                 /* buffer is still empty */
989                 mei_hdr = (struct mei_msg_hdr *) &dev->wr_msg_buf[0];
990                 mei_hdr->host_addr = cl->host_client_id;
991                 mei_hdr->me_addr = cl->me_client_id;
992                 mei_hdr->length =
993                         (*slots * sizeof(u32)) - sizeof(struct mei_msg_hdr);
994                 mei_hdr->msg_complete = 0;
995                 mei_hdr->reserved = 0;
996
997                 (*slots) -= (sizeof(struct mei_msg_hdr) +
998                                 mei_hdr->length + 3) / 4;
999                 if (!mei_write_message(dev, mei_hdr,
1000                                         (unsigned char *)
1001                                         (cb_pos->request_buffer.data +
1002                                         cb_pos->information),
1003                                         mei_hdr->length)) {
1004                         cl->status = -ENODEV;
1005                         list_move_tail(&cb_pos->cb_list,
1006                                 &cmpl_list->mei_cb.cb_list);
1007                         return -ENODEV;
1008                 } else {
1009                         cb_pos->information += mei_hdr->length;
1010                         dev_dbg(&dev->pdev->dev,
1011                                         "cb_pos->request_buffer.size =%d"
1012                                         " mei_hdr->msg_complete = %d\n",
1013                                         cb_pos->request_buffer.size,
1014                                         mei_hdr->msg_complete);
1015                         dev_dbg(&dev->pdev->dev, "cb_pos->information  =%lu\n",
1016                                         cb_pos->information);
1017                         dev_dbg(&dev->pdev->dev, "mei_hdr->length  =%d\n",
1018                                         mei_hdr->length);
1019                 }
1020                 return -EMSGSIZE;
1021         } else {
1022                 return -EBADMSG;
1023         }
1024
1025         return 0;
1026 }
1027
1028 /**
1029  * _mei_irq_thread_cmpl_iamthif - processes completed iamthif operation.
1030  *
1031  * @dev: the device structure.
1032  * @slots: free slots.
1033  * @cb_pos: callback block.
1034  * @cl: private data of the file object.
1035  * @cmpl_list: complete list.
1036  *
1037  * returns 0, OK; otherwise, error.
1038  */
1039 static int _mei_irq_thread_cmpl_iamthif(struct mei_device *dev, s32 *slots,
1040                         struct mei_cl_cb *cb_pos,
1041                         struct mei_cl *cl,
1042                         struct mei_io_list *cmpl_list)
1043 {
1044         struct mei_msg_hdr *mei_hdr;
1045
1046         if ((*slots * sizeof(u32)) >= (sizeof(struct mei_msg_hdr) +
1047                         dev->iamthif_msg_buf_size -
1048                         dev->iamthif_msg_buf_index)) {
1049                 mei_hdr = (struct mei_msg_hdr *) &dev->wr_msg_buf[0];
1050                 mei_hdr->host_addr = cl->host_client_id;
1051                 mei_hdr->me_addr = cl->me_client_id;
1052                 mei_hdr->length = dev->iamthif_msg_buf_size -
1053                         dev->iamthif_msg_buf_index;
1054                 mei_hdr->msg_complete = 1;
1055                 mei_hdr->reserved = 0;
1056
1057                 *slots -= (sizeof(struct mei_msg_hdr) +
1058                                 mei_hdr->length + 3) / 4;
1059
1060                 if (!mei_write_message(dev, mei_hdr,
1061                                         (dev->iamthif_msg_buf +
1062                                         dev->iamthif_msg_buf_index),
1063                                         mei_hdr->length)) {
1064                         dev->iamthif_state = MEI_IAMTHIF_IDLE;
1065                         cl->status = -ENODEV;
1066                         list_del(&cb_pos->cb_list);
1067                         return -ENODEV;
1068                 } else {
1069                         if (mei_flow_ctrl_reduce(dev, cl))
1070                                 return -ENODEV;
1071                         dev->iamthif_msg_buf_index += mei_hdr->length;
1072                         cb_pos->information = dev->iamthif_msg_buf_index;
1073                         cl->status = 0;
1074                         dev->iamthif_state = MEI_IAMTHIF_FLOW_CONTROL;
1075                         dev->iamthif_flow_control_pending = true;
1076                         /* save iamthif cb sent to amthi client */
1077                         dev->iamthif_current_cb = cb_pos;
1078                         list_move_tail(&cb_pos->cb_list,
1079                                 &dev->write_waiting_list.mei_cb.cb_list);
1080
1081                 }
1082         } else if (*slots == ((dev->host_hw_state & H_CBD) >> 24)) {
1083                         /* buffer is still empty */
1084                 mei_hdr = (struct mei_msg_hdr *) &dev->wr_msg_buf[0];
1085                 mei_hdr->host_addr = cl->host_client_id;
1086                 mei_hdr->me_addr = cl->me_client_id;
1087                 mei_hdr->length =
1088                         (*slots * sizeof(u32)) - sizeof(struct mei_msg_hdr);
1089                 mei_hdr->msg_complete = 0;
1090                 mei_hdr->reserved = 0;
1091
1092                 *slots -= (sizeof(struct mei_msg_hdr) +
1093                                 mei_hdr->length + 3) / 4;
1094
1095                 if (!mei_write_message(dev, mei_hdr,
1096                                         (dev->iamthif_msg_buf +
1097                                         dev->iamthif_msg_buf_index),
1098                                         mei_hdr->length)) {
1099                         cl->status = -ENODEV;
1100                         list_del(&cb_pos->cb_list);
1101                 } else {
1102                         dev->iamthif_msg_buf_index += mei_hdr->length;
1103                 }
1104                 return -EMSGSIZE;
1105         } else {
1106                 return -EBADMSG;
1107         }
1108
1109         return 0;
1110 }
1111
1112 /**
1113  * mei_irq_thread_read_handler - bottom half read routine after ISR to
1114  * handle the read processing.
1115  *
1116  * @cmpl_list: An instance of our list structure
1117  * @dev: the device structure
1118  * @slots: slots to read.
1119  *
1120  * returns 0 on success, <0 on failure.
1121  */
1122 static int mei_irq_thread_read_handler(struct mei_io_list *cmpl_list,
1123                 struct mei_device *dev,
1124                 s32 *slots)
1125 {
1126         struct mei_msg_hdr *mei_hdr;
1127         struct mei_cl *cl_pos = NULL;
1128         struct mei_cl *cl_next = NULL;
1129         int ret = 0;
1130
1131         if (!dev->rd_msg_hdr) {
1132                 dev->rd_msg_hdr = mei_mecbrw_read(dev);
1133                 dev_dbg(&dev->pdev->dev, "slots =%08x.\n", *slots);
1134                 (*slots)--;
1135                 dev_dbg(&dev->pdev->dev, "slots =%08x.\n", *slots);
1136         }
1137         mei_hdr = (struct mei_msg_hdr *) &dev->rd_msg_hdr;
1138         dev_dbg(&dev->pdev->dev, "mei_hdr->length =%d\n", mei_hdr->length);
1139
1140         if (mei_hdr->reserved || !dev->rd_msg_hdr) {
1141                 dev_dbg(&dev->pdev->dev, "corrupted message header.\n");
1142                 ret = -EBADMSG;
1143                 goto end;
1144         }
1145
1146         if (mei_hdr->host_addr || mei_hdr->me_addr) {
1147                 list_for_each_entry_safe(cl_pos, cl_next,
1148                                         &dev->file_list, link) {
1149                         dev_dbg(&dev->pdev->dev,
1150                                         "list_for_each_entry_safe read host"
1151                                         " client = %d, ME client = %d\n",
1152                                         cl_pos->host_client_id,
1153                                         cl_pos->me_client_id);
1154                         if (cl_pos->host_client_id == mei_hdr->host_addr &&
1155                             cl_pos->me_client_id == mei_hdr->me_addr)
1156                                 break;
1157                 }
1158
1159                 if (&cl_pos->link == &dev->file_list) {
1160                         dev_dbg(&dev->pdev->dev, "corrupted message header\n");
1161                         ret = -EBADMSG;
1162                         goto end;
1163                 }
1164         }
1165         if (((*slots) * sizeof(u32)) < mei_hdr->length) {
1166                 dev_dbg(&dev->pdev->dev,
1167                                 "we can't read the message slots =%08x.\n",
1168                                 *slots);
1169                 /* we can't read the message */
1170                 ret = -ERANGE;
1171                 goto end;
1172         }
1173
1174         /* decide where to read the message too */
1175         if (!mei_hdr->host_addr) {
1176                 dev_dbg(&dev->pdev->dev, "call mei_irq_thread_read_bus_message.\n");
1177                 mei_irq_thread_read_bus_message(dev, mei_hdr);
1178                 dev_dbg(&dev->pdev->dev, "end mei_irq_thread_read_bus_message.\n");
1179         } else if (mei_hdr->host_addr == dev->iamthif_cl.host_client_id &&
1180                    (MEI_FILE_CONNECTED == dev->iamthif_cl.state) &&
1181                    (dev->iamthif_state == MEI_IAMTHIF_READING)) {
1182                 dev_dbg(&dev->pdev->dev, "call mei_irq_thread_read_iamthif_message.\n");
1183                 dev_dbg(&dev->pdev->dev, "mei_hdr->length =%d\n",
1184                                 mei_hdr->length);
1185                 ret = mei_irq_thread_read_amthi_message(cmpl_list,
1186                                                         dev, mei_hdr);
1187                 if (ret)
1188                         goto end;
1189
1190         } else {
1191                 dev_dbg(&dev->pdev->dev, "call mei_irq_thread_read_client_message.\n");
1192                 ret = mei_irq_thread_read_client_message(cmpl_list,
1193                                                          dev, mei_hdr);
1194                 if (ret)
1195                         goto end;
1196
1197         }
1198
1199         /* reset the number of slots and header */
1200         *slots = mei_count_full_read_slots(dev);
1201         dev->rd_msg_hdr = 0;
1202
1203         if (*slots == -EOVERFLOW) {
1204                 /* overflow - reset */
1205                 dev_dbg(&dev->pdev->dev, "resetting due to slots overflow.\n");
1206                 /* set the event since message has been read */
1207                 ret = -ERANGE;
1208                 goto end;
1209         }
1210 end:
1211         return ret;
1212 }
1213
1214
1215 /**
1216  * mei_irq_thread_write_handler - bottom half write routine after
1217  * ISR to handle the write processing.
1218  *
1219  * @cmpl_list: An instance of our list structure
1220  * @dev: the device structure
1221  * @slots: slots to write.
1222  *
1223  * returns 0 on success, <0 on failure.
1224  */
1225 static int mei_irq_thread_write_handler(struct mei_io_list *cmpl_list,
1226                 struct mei_device *dev,
1227                 s32 *slots)
1228 {
1229
1230         struct mei_cl *cl;
1231         struct mei_cl_cb *cb_pos = NULL, *cb_next = NULL;
1232         struct mei_io_list *list;
1233         int ret;
1234
1235         if (!mei_host_buffer_is_empty(dev)) {
1236                 dev_dbg(&dev->pdev->dev, "host buffer is not empty.\n");
1237                 return 0;
1238         }
1239         *slots = mei_count_empty_write_slots(dev);
1240         /* complete all waiting for write CB */
1241         dev_dbg(&dev->pdev->dev, "complete all waiting for write cb.\n");
1242
1243         list = &dev->write_waiting_list;
1244         if (!list->status && !list_empty(&list->mei_cb.cb_list)) {
1245                 list_for_each_entry_safe(cb_pos, cb_next,
1246                                 &list->mei_cb.cb_list, cb_list) {
1247                         cl = (struct mei_cl *)cb_pos->file_private;
1248                         if (cl) {
1249                                 cl->status = 0;
1250                                 list_del(&cb_pos->cb_list);
1251                                 if (MEI_WRITING == cl->writing_state &&
1252                                    (cb_pos->major_file_operations ==
1253                                                 MEI_WRITE) &&
1254                                    (cl != &dev->iamthif_cl)) {
1255                                         dev_dbg(&dev->pdev->dev,
1256                                                 "MEI WRITE COMPLETE\n");
1257                                         cl->writing_state =
1258                                                         MEI_WRITE_COMPLETE;
1259                                         list_add_tail(&cb_pos->cb_list,
1260                                                 &cmpl_list->mei_cb.cb_list);
1261                                 }
1262                                 if (cl == &dev->iamthif_cl) {
1263                                         dev_dbg(&dev->pdev->dev, "check iamthif flow control.\n");
1264                                         if (dev->iamthif_flow_control_pending) {
1265                                                 ret =
1266                                                 _mei_irq_thread_iamthif_read(
1267                                                                 dev, slots);
1268                                                 if (ret)
1269                                                         return ret;
1270                                         }
1271                                 }
1272                         }
1273
1274                 }
1275         }
1276
1277         if (dev->stop && !dev->wd_pending) {
1278                 dev->wd_stopped = true;
1279                 wake_up_interruptible(&dev->wait_stop_wd);
1280                 return 0;
1281         }
1282
1283         if (dev->extra_write_index) {
1284                 dev_dbg(&dev->pdev->dev, "extra_write_index =%d.\n",
1285                                 dev->extra_write_index);
1286                 mei_write_message(dev,
1287                                 (struct mei_msg_hdr *) &dev->ext_msg_buf[0],
1288                                 (unsigned char *) &dev->ext_msg_buf[1],
1289                                 (dev->extra_write_index - 1) * sizeof(u32));
1290                 *slots -= dev->extra_write_index;
1291                 dev->extra_write_index = 0;
1292         }
1293         if (dev->mei_state == MEI_ENABLED) {
1294                 if (dev->wd_pending &&
1295                         mei_flow_ctrl_creds(dev, &dev->wd_cl) > 0) {
1296                         if (mei_wd_send(dev))
1297                                 dev_dbg(&dev->pdev->dev, "wd send failed.\n");
1298                         else
1299                                 if (mei_flow_ctrl_reduce(dev, &dev->wd_cl))
1300                                         return -ENODEV;
1301
1302                         dev->wd_pending = false;
1303
1304                         if (dev->wd_timeout) {
1305                                 *slots -= (sizeof(struct mei_msg_hdr) +
1306                                          MEI_START_WD_DATA_SIZE + 3) / 4;
1307                                 dev->wd_due_counter = 2;
1308                         } else {
1309                                 *slots -= (sizeof(struct mei_msg_hdr) +
1310                                          MEI_WD_PARAMS_SIZE + 3) / 4;
1311                                 dev->wd_due_counter = 0;
1312                         }
1313
1314                 }
1315         }
1316         if (dev->stop)
1317                 return ~ENODEV;
1318
1319         /* complete control write list CB */
1320         if (!dev->ctrl_wr_list.status) {
1321                 /* complete control write list CB */
1322                 dev_dbg(&dev->pdev->dev, "complete control write list cb.\n");
1323                 list_for_each_entry_safe(cb_pos, cb_next,
1324                                 &dev->ctrl_wr_list.mei_cb.cb_list, cb_list) {
1325                         cl = (struct mei_cl *)
1326                                 cb_pos->file_private;
1327                         if (!cl) {
1328                                 list_del(&cb_pos->cb_list);
1329                                 return -ENODEV;
1330                         }
1331                         switch (cb_pos->major_file_operations) {
1332                         case MEI_CLOSE:
1333                                 /* send disconnect message */
1334                                 ret = _mei_irq_thread_close(dev, slots,
1335                                                      cb_pos, cl, cmpl_list);
1336                                 if (ret)
1337                                         return ret;
1338
1339                                 break;
1340                         case MEI_READ:
1341                                 /* send flow control message */
1342                                 ret = _mei_irq_thread_read(dev, slots,
1343                                                     cb_pos, cl, cmpl_list);
1344                                 if (ret)
1345                                         return ret;
1346
1347                                 break;
1348                         case MEI_IOCTL:
1349                                 /* connect message */
1350                                 if (!mei_other_client_is_connecting(dev,
1351                                                 cl))
1352                                         continue;
1353                                 ret = _mei_irq_thread_ioctl(dev, slots,
1354                                                      cb_pos, cl, cmpl_list);
1355                                 if (ret)
1356                                         return ret;
1357
1358                                 break;
1359
1360                         default:
1361                                 BUG();
1362                         }
1363
1364                 }
1365         }
1366         /* complete  write list CB */
1367         if (!dev->write_list.status &&
1368             !list_empty(&dev->write_list.mei_cb.cb_list)) {
1369                 dev_dbg(&dev->pdev->dev, "complete write list cb.\n");
1370                 list_for_each_entry_safe(cb_pos, cb_next,
1371                                 &dev->write_list.mei_cb.cb_list, cb_list) {
1372                         cl = (struct mei_cl *)cb_pos->file_private;
1373
1374                         if (cl) {
1375                                 if (cl != &dev->iamthif_cl) {
1376                                         if (!mei_flow_ctrl_creds(dev,
1377                                                 cl)) {
1378                                                 dev_dbg(&dev->pdev->dev,
1379                                                         "No flow control"
1380                                                     " credentials for client"
1381                                                     " %d, not sending.\n",
1382                                                     cl->host_client_id);
1383                                                 continue;
1384                                         }
1385                                         ret = _mei_irq_thread_cmpl(dev, slots,
1386                                                             cb_pos,
1387                                                             cl, cmpl_list);
1388                                         if (ret)
1389                                                 return ret;
1390
1391                                 } else if (cl == &dev->iamthif_cl) {
1392                                         /* IAMTHIF IOCTL */
1393                                         dev_dbg(&dev->pdev->dev, "complete amthi write cb.\n");
1394                                         if (!mei_flow_ctrl_creds(dev,
1395                                                         cl)) {
1396                                                 dev_dbg(&dev->pdev->dev,
1397                                                         "No flow control"
1398                                                     " credentials for amthi"
1399                                                     " client %d.\n",
1400                                                     cl->host_client_id);
1401                                                 continue;
1402                                         }
1403                                         ret = _mei_irq_thread_cmpl_iamthif(dev,
1404                                                                 slots,
1405                                                                 cb_pos,
1406                                                                 cl,
1407                                                                 cmpl_list);
1408                                         if (ret)
1409                                                 return ret;
1410
1411                                 }
1412                         }
1413
1414                 }
1415         }
1416         return 0;
1417 }
1418
1419
1420
1421 /**
1422  * mei_timer - timer function.
1423  *
1424  * @work: pointer to the work_struct structure
1425  *
1426  * NOTE: This function is called by timer interrupt work
1427  */
1428 void mei_timer(struct work_struct *work)
1429 {
1430         unsigned long timeout;
1431         struct mei_cl *cl_pos = NULL;
1432         struct mei_cl *cl_next = NULL;
1433         struct list_head *amthi_complete_list = NULL;
1434         struct mei_cl_cb  *cb_pos = NULL;
1435         struct mei_cl_cb  *cb_next = NULL;
1436
1437         struct mei_device *dev = container_of(work,
1438                                         struct mei_device, timer_work.work);
1439
1440
1441         mutex_lock(&dev->device_lock);
1442         if (dev->mei_state != MEI_ENABLED) {
1443                 if (dev->mei_state == MEI_INIT_CLIENTS) {
1444                         if (dev->init_clients_timer) {
1445                                 if (--dev->init_clients_timer == 0) {
1446                                         dev_dbg(&dev->pdev->dev, "IMEI reset due to init clients timeout ,init clients state = %d.\n",
1447                                                 dev->init_clients_state);
1448                                         mei_reset(dev, 1);
1449                                 }
1450                         }
1451                 }
1452                 goto out;
1453         }
1454         /*** connect/disconnect timeouts ***/
1455         list_for_each_entry_safe(cl_pos, cl_next, &dev->file_list, link) {
1456                 if (cl_pos->timer_count) {
1457                         if (--cl_pos->timer_count == 0) {
1458                                 dev_dbg(&dev->pdev->dev, "HECI reset due to connect/disconnect timeout.\n");
1459                                 mei_reset(dev, 1);
1460                                 goto out;
1461                         }
1462                 }
1463         }
1464
1465         if (dev->iamthif_stall_timer) {
1466                 if (--dev->iamthif_stall_timer == 0) {
1467                         dev_dbg(&dev->pdev->dev, "reseting because of hang to amthi.\n");
1468                         mei_reset(dev, 1);
1469                         dev->iamthif_msg_buf_size = 0;
1470                         dev->iamthif_msg_buf_index = 0;
1471                         dev->iamthif_canceled = false;
1472                         dev->iamthif_ioctl = true;
1473                         dev->iamthif_state = MEI_IAMTHIF_IDLE;
1474                         dev->iamthif_timer = 0;
1475
1476                         if (dev->iamthif_current_cb)
1477                                 mei_free_cb_private(dev->iamthif_current_cb);
1478
1479                         dev->iamthif_file_object = NULL;
1480                         dev->iamthif_current_cb = NULL;
1481                         mei_run_next_iamthif_cmd(dev);
1482                 }
1483         }
1484
1485         if (dev->iamthif_timer) {
1486
1487                 timeout = dev->iamthif_timer +
1488                                 msecs_to_jiffies(IAMTHIF_READ_TIMER);
1489
1490                 dev_dbg(&dev->pdev->dev, "dev->iamthif_timer = %ld\n",
1491                                 dev->iamthif_timer);
1492                 dev_dbg(&dev->pdev->dev, "timeout = %ld\n", timeout);
1493                 dev_dbg(&dev->pdev->dev, "jiffies = %ld\n", jiffies);
1494                 if (time_after(jiffies, timeout)) {
1495                         /*
1496                          * User didn't read the AMTHI data on time (15sec)
1497                          * freeing AMTHI for other requests
1498                          */
1499
1500                         dev_dbg(&dev->pdev->dev, "freeing AMTHI for other requests\n");
1501
1502                         amthi_complete_list = &dev->amthi_read_complete_list.
1503                                         mei_cb.cb_list;
1504
1505                         if (!list_empty(amthi_complete_list)) {
1506
1507                                 list_for_each_entry_safe(cb_pos, cb_next,
1508                                                         amthi_complete_list,
1509                                                         cb_list) {
1510
1511                                         cl_pos = cb_pos->file_object->private_data;
1512
1513                                         /* Finding the AMTHI entry. */
1514                                         if (cl_pos ==   &dev->iamthif_cl)
1515                                                 list_del(&cb_pos->cb_list);
1516                                 }
1517                         }
1518                         if (dev->iamthif_current_cb)
1519                                 mei_free_cb_private(dev->iamthif_current_cb);
1520
1521                         dev->iamthif_file_object->private_data = NULL;
1522                         dev->iamthif_file_object = NULL;
1523                         dev->iamthif_current_cb = NULL;
1524                         dev->iamthif_timer = 0;
1525                         mei_run_next_iamthif_cmd(dev);
1526
1527                 }
1528         }
1529 out:
1530          schedule_delayed_work(&dev->timer_work, 2 * HZ);
1531          mutex_unlock(&dev->device_lock);
1532 }
1533
1534 /**
1535  *  mei_interrupt_thread_handler - function called after ISR to handle the interrupt
1536  * processing.
1537  *
1538  * @irq: The irq number
1539  * @dev_id: pointer to the device structure
1540  *
1541  * returns irqreturn_t
1542  *
1543  */
1544 irqreturn_t mei_interrupt_thread_handler(int irq, void *dev_id)
1545 {
1546         struct mei_device *dev = (struct mei_device *) dev_id;
1547         struct mei_io_list complete_list;
1548         struct mei_cl_cb *cb_pos = NULL, *cb_next = NULL;
1549         struct mei_cl *cl;
1550         s32 slots;
1551         int rets;
1552         bool  bus_message_received;
1553
1554
1555         dev_dbg(&dev->pdev->dev, "function called after ISR to handle the interrupt processing.\n");
1556         /* initialize our complete list */
1557         mutex_lock(&dev->device_lock);
1558         mei_io_list_init(&complete_list);
1559         dev->host_hw_state = mei_hcsr_read(dev);
1560
1561         /* Ack the interrupt here
1562          * In case of MSI we don't go throuhg the quick handler */
1563         if (pci_dev_msi_enabled(dev->pdev))
1564                 mei_reg_write(dev, H_CSR, dev->host_hw_state);
1565
1566         dev->me_hw_state = mei_mecsr_read(dev);
1567
1568         /* check if ME wants a reset */
1569         if ((dev->me_hw_state & ME_RDY_HRA) == 0 &&
1570             dev->mei_state != MEI_RESETING &&
1571             dev->mei_state != MEI_INITIALIZING) {
1572                 dev_dbg(&dev->pdev->dev, "FW not ready.\n");
1573                 mei_reset(dev, 1);
1574                 mutex_unlock(&dev->device_lock);
1575                 return IRQ_HANDLED;
1576         }
1577
1578         /*  check if we need to start the dev */
1579         if ((dev->host_hw_state & H_RDY) == 0) {
1580                 if ((dev->me_hw_state & ME_RDY_HRA) == ME_RDY_HRA) {
1581                         dev_dbg(&dev->pdev->dev, "we need to start the dev.\n");
1582                         dev->host_hw_state |= (H_IE | H_IG | H_RDY);
1583                         mei_hcsr_set(dev);
1584                         dev->mei_state = MEI_INIT_CLIENTS;
1585                         dev_dbg(&dev->pdev->dev, "link is established start sending messages.\n");
1586                         /* link is established
1587                          * start sending messages.
1588                          */
1589                         mei_host_start_message(dev);
1590                         mutex_unlock(&dev->device_lock);
1591                         return IRQ_HANDLED;
1592                 } else {
1593                         dev_dbg(&dev->pdev->dev, "FW not ready.\n");
1594                         mutex_unlock(&dev->device_lock);
1595                         return IRQ_HANDLED;
1596                 }
1597         }
1598         /* check slots avalable for reading */
1599         slots = mei_count_full_read_slots(dev);
1600         dev_dbg(&dev->pdev->dev, "slots =%08x  extra_write_index =%08x.\n",
1601                 slots, dev->extra_write_index);
1602         while (slots > 0 && !dev->extra_write_index) {
1603                 dev_dbg(&dev->pdev->dev, "slots =%08x  extra_write_index =%08x.\n",
1604                                 slots, dev->extra_write_index);
1605                 dev_dbg(&dev->pdev->dev, "call mei_irq_thread_read_handler.\n");
1606                 rets = mei_irq_thread_read_handler(&complete_list, dev, &slots);
1607                 if (rets)
1608                         goto end;
1609         }
1610         rets = mei_irq_thread_write_handler(&complete_list, dev, &slots);
1611 end:
1612         dev_dbg(&dev->pdev->dev, "end of bottom half function.\n");
1613         dev->host_hw_state = mei_hcsr_read(dev);
1614         dev->mei_host_buffer_is_empty = mei_host_buffer_is_empty(dev);
1615
1616         bus_message_received = false;
1617         if (dev->recvd_msg && waitqueue_active(&dev->wait_recvd_msg)) {
1618                 dev_dbg(&dev->pdev->dev, "received waiting bus message\n");
1619                 bus_message_received = true;
1620         }
1621         mutex_unlock(&dev->device_lock);
1622         if (bus_message_received) {
1623                 dev_dbg(&dev->pdev->dev, "wake up dev->wait_recvd_msg\n");
1624                 wake_up_interruptible(&dev->wait_recvd_msg);
1625                 bus_message_received = false;
1626         }
1627         if (complete_list.status || list_empty(&complete_list.mei_cb.cb_list))
1628                 return IRQ_HANDLED;
1629
1630
1631         list_for_each_entry_safe(cb_pos, cb_next,
1632                         &complete_list.mei_cb.cb_list, cb_list) {
1633                 cl = (struct mei_cl *)cb_pos->file_private;
1634                 list_del(&cb_pos->cb_list);
1635                 if (cl) {
1636                         if (cl != &dev->iamthif_cl) {
1637                                 dev_dbg(&dev->pdev->dev, "completing call back.\n");
1638                                 _mei_cmpl(cl, cb_pos);
1639                                 cb_pos = NULL;
1640                         } else if (cl == &dev->iamthif_cl) {
1641                                 _mei_cmpl_iamthif(dev, cb_pos);
1642                         }
1643                 }
1644         }
1645         return IRQ_HANDLED;
1646 }