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