Merge branch 'for-linus' of git://git.kernel.dk/linux-block
[pandora-kernel.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                 mei_host_init_iamthif(dev);
400                 return;
401         }
402
403         if (is_treat_specially_client(&(dev->iamthif_cl), rs)) {
404                 dev->iamthif_state = MEI_IAMTHIF_IDLE;
405                 return;
406         }
407         if (!dev->ctrl_rd_list.status &&
408             !list_empty(&dev->ctrl_rd_list.mei_cb.cb_list)) {
409                 list_for_each_entry_safe(cb_pos, cb_next,
410                         &dev->ctrl_rd_list.mei_cb.cb_list, cb_list) {
411                         cl = (struct mei_cl *)cb_pos->file_private;
412                         if (!cl) {
413                                 list_del(&cb_pos->cb_list);
414                                 return;
415                         }
416                         if (MEI_IOCTL == cb_pos->major_file_operations) {
417                                 if (is_treat_specially_client(cl, rs)) {
418                                         list_del(&cb_pos->cb_list);
419                                         cl->status = 0;
420                                         cl->timer_count = 0;
421                                         break;
422                                 }
423                         }
424                 }
425         }
426 }
427
428 /**
429  * mei_client_disconnect_response - disconnects from response irq routine
430  *
431  * @dev: the device structure
432  * @rs: disconnect response bus message
433  */
434 static void mei_client_disconnect_response(struct mei_device *dev,
435                                         struct hbm_client_connect_response *rs)
436 {
437         struct mei_cl *cl;
438         struct mei_cl_cb *cb_pos = NULL, *cb_next = NULL;
439
440         dev_dbg(&dev->pdev->dev,
441                         "disconnect_response:\n"
442                         "ME Client = %d\n"
443                         "Host Client = %d\n"
444                         "Status = %d\n",
445                         rs->me_addr,
446                         rs->host_addr,
447                         rs->status);
448
449         if (!dev->ctrl_rd_list.status &&
450             !list_empty(&dev->ctrl_rd_list.mei_cb.cb_list)) {
451                 list_for_each_entry_safe(cb_pos, cb_next,
452                                 &dev->ctrl_rd_list.mei_cb.cb_list, cb_list) {
453                         cl = (struct mei_cl *)cb_pos->file_private;
454
455                         if (!cl) {
456                                 list_del(&cb_pos->cb_list);
457                                 return;
458                         }
459
460                         dev_dbg(&dev->pdev->dev, "list_for_each_entry_safe in ctrl_rd_list.\n");
461                         if (cl->host_client_id == rs->host_addr &&
462                             cl->me_client_id == rs->me_addr) {
463
464                                 list_del(&cb_pos->cb_list);
465                                 if (!rs->status)
466                                         cl->state = MEI_FILE_DISCONNECTED;
467
468                                 cl->status = 0;
469                                 cl->timer_count = 0;
470                                 break;
471                         }
472                 }
473         }
474 }
475
476 /**
477  * same_flow_addr - tells if they have the same address.
478  *
479  * @file: private data of the file object.
480  * @flow: flow control.
481  *
482  * returns  !=0, same; 0,not.
483  */
484 static int same_flow_addr(struct mei_cl *cl, struct hbm_flow_control *flow)
485 {
486         return (cl->host_client_id == flow->host_addr &&
487                 cl->me_client_id == flow->me_addr);
488 }
489
490 /**
491  * add_single_flow_creds - adds single buffer credentials.
492  *
493  * @file: private data ot the file object.
494  * @flow: flow control.
495  */
496 static void add_single_flow_creds(struct mei_device *dev,
497                                   struct hbm_flow_control *flow)
498 {
499         struct mei_me_client *client;
500         int i;
501
502         for (i = 0; i < dev->me_clients_num; i++) {
503                 client = &dev->me_clients[i];
504                 if (client && flow->me_addr == client->client_id) {
505                         if (client->props.single_recv_buf) {
506                                 client->mei_flow_ctrl_creds++;
507                                 dev_dbg(&dev->pdev->dev, "recv flow ctrl msg ME %d (single).\n",
508                                     flow->me_addr);
509                                 dev_dbg(&dev->pdev->dev, "flow control credentials =%d.\n",
510                                     client->mei_flow_ctrl_creds);
511                         } else {
512                                 BUG();  /* error in flow control */
513                         }
514                 }
515         }
516 }
517
518 /**
519  * mei_client_flow_control_response - flow control response irq routine
520  *
521  * @dev: the device structure
522  * @flow_control: flow control response bus message
523  */
524 static void mei_client_flow_control_response(struct mei_device *dev,
525                 struct hbm_flow_control *flow_control)
526 {
527         struct mei_cl *cl_pos = NULL;
528         struct mei_cl *cl_next = NULL;
529
530         if (!flow_control->host_addr) {
531                 /* single receive buffer */
532                 add_single_flow_creds(dev, flow_control);
533         } else {
534                 /* normal connection */
535                 list_for_each_entry_safe(cl_pos, cl_next,
536                                 &dev->file_list, link) {
537                         dev_dbg(&dev->pdev->dev, "list_for_each_entry_safe in file_list\n");
538
539                         dev_dbg(&dev->pdev->dev, "cl of host client %d ME client %d.\n",
540                             cl_pos->host_client_id,
541                             cl_pos->me_client_id);
542                         dev_dbg(&dev->pdev->dev, "flow ctrl msg for host %d ME %d.\n",
543                             flow_control->host_addr,
544                             flow_control->me_addr);
545                         if (same_flow_addr(cl_pos, flow_control)) {
546                                 dev_dbg(&dev->pdev->dev, "recv ctrl msg for host  %d ME %d.\n",
547                                     flow_control->host_addr,
548                                     flow_control->me_addr);
549                                 cl_pos->mei_flow_ctrl_creds++;
550                                 dev_dbg(&dev->pdev->dev, "flow control credentials = %d.\n",
551                                     cl_pos->mei_flow_ctrl_creds);
552                                 break;
553                         }
554                 }
555         }
556 }
557
558 /**
559  * same_disconn_addr - tells if they have the same address
560  *
561  * @file: private data of the file object.
562  * @disconn: disconnection request.
563  *
564  * returns !=0, same; 0,not.
565  */
566 static int same_disconn_addr(struct mei_cl *cl,
567                              struct hbm_client_disconnect_request *disconn)
568 {
569         return (cl->host_client_id == disconn->host_addr &&
570                 cl->me_client_id == disconn->me_addr);
571 }
572
573 /**
574  * mei_client_disconnect_request - disconnects from request irq routine
575  *
576  * @dev: the device structure.
577  * @disconnect_req: disconnect request bus message.
578  */
579 static void mei_client_disconnect_request(struct mei_device *dev,
580                 struct hbm_client_disconnect_request *disconnect_req)
581 {
582         struct mei_msg_hdr *mei_hdr;
583         struct hbm_client_connect_response *disconnect_res;
584         struct mei_cl *cl_pos = NULL;
585         struct mei_cl *cl_next = NULL;
586
587         list_for_each_entry_safe(cl_pos, cl_next, &dev->file_list, link) {
588                 if (same_disconn_addr(cl_pos, disconnect_req)) {
589                         dev_dbg(&dev->pdev->dev, "disconnect request host client %d ME client %d.\n",
590                                         disconnect_req->host_addr,
591                                         disconnect_req->me_addr);
592                         cl_pos->state = MEI_FILE_DISCONNECTED;
593                         cl_pos->timer_count = 0;
594                         if (cl_pos == &dev->wd_cl) {
595                                 dev->wd_due_counter = 0;
596                                 dev->wd_pending = false;
597                         } else if (cl_pos == &dev->iamthif_cl)
598                                 dev->iamthif_timer = 0;
599
600                         /* prepare disconnect response */
601                         mei_hdr =
602                                 (struct mei_msg_hdr *) &dev->ext_msg_buf[0];
603                         mei_hdr->host_addr = 0;
604                         mei_hdr->me_addr = 0;
605                         mei_hdr->length =
606                                 sizeof(struct hbm_client_connect_response);
607                         mei_hdr->msg_complete = 1;
608                         mei_hdr->reserved = 0;
609
610                         disconnect_res =
611                                 (struct hbm_client_connect_response *)
612                                 &dev->ext_msg_buf[1];
613                         disconnect_res->host_addr = cl_pos->host_client_id;
614                         disconnect_res->me_addr = cl_pos->me_client_id;
615                         *(u8 *) (&disconnect_res->cmd) =
616                                 CLIENT_DISCONNECT_RES_CMD;
617                         disconnect_res->status = 0;
618                         dev->extra_write_index = 2;
619                         break;
620                 }
621         }
622 }
623
624
625 /**
626  * mei_irq_thread_read_bus_message - bottom half read routine after ISR to
627  * handle the read bus message cmd processing.
628  *
629  * @dev: the device structure
630  * @mei_hdr: header of bus message
631  */
632 static void mei_irq_thread_read_bus_message(struct mei_device *dev,
633                 struct mei_msg_hdr *mei_hdr)
634 {
635         struct mei_bus_message *mei_msg;
636         struct hbm_host_version_response *version_res;
637         struct hbm_client_connect_response *connect_res;
638         struct hbm_client_connect_response *disconnect_res;
639         struct hbm_flow_control *flow_control;
640         struct hbm_props_response *props_res;
641         struct hbm_host_enum_response *enum_res;
642         struct hbm_client_disconnect_request *disconnect_req;
643         struct hbm_host_stop_request *host_stop_req;
644
645         unsigned char *buffer;
646
647         /* read the message to our buffer */
648         buffer = (unsigned char *) dev->rd_msg_buf;
649         BUG_ON(mei_hdr->length >= sizeof(dev->rd_msg_buf));
650         mei_read_slots(dev, buffer, mei_hdr->length);
651         mei_msg = (struct mei_bus_message *) buffer;
652
653         switch (*(u8 *) mei_msg) {
654         case HOST_START_RES_CMD:
655                 version_res = (struct hbm_host_version_response *) mei_msg;
656                 if (version_res->host_version_supported) {
657                         dev->version.major_version = HBM_MAJOR_VERSION;
658                         dev->version.minor_version = HBM_MINOR_VERSION;
659                         if (dev->mei_state == MEI_INIT_CLIENTS &&
660                             dev->init_clients_state == MEI_START_MESSAGE) {
661                                 dev->init_clients_timer = 0;
662                                 mei_host_enum_clients_message(dev);
663                         } else {
664                                 dev->recvd_msg = false;
665                                 dev_dbg(&dev->pdev->dev, "IMEI reset due to received host start response bus message.\n");
666                                 mei_reset(dev, 1);
667                                 return;
668                         }
669                 } else {
670                         dev->version = version_res->me_max_version;
671                         /* send stop message */
672                         mei_hdr->host_addr = 0;
673                         mei_hdr->me_addr = 0;
674                         mei_hdr->length = sizeof(struct hbm_host_stop_request);
675                         mei_hdr->msg_complete = 1;
676                         mei_hdr->reserved = 0;
677
678                         host_stop_req = (struct hbm_host_stop_request *)
679                                                         &dev->wr_msg_buf[1];
680
681                         memset(host_stop_req,
682                                         0,
683                                         sizeof(struct hbm_host_stop_request));
684                         host_stop_req->cmd.cmd = HOST_STOP_REQ_CMD;
685                         host_stop_req->reason = DRIVER_STOP_REQUEST;
686                         mei_write_message(dev, mei_hdr,
687                                            (unsigned char *) (host_stop_req),
688                                            mei_hdr->length);
689                         dev_dbg(&dev->pdev->dev, "version mismatch.\n");
690                         return;
691                 }
692
693                 dev->recvd_msg = true;
694                 dev_dbg(&dev->pdev->dev, "host start response message received.\n");
695                 break;
696
697         case CLIENT_CONNECT_RES_CMD:
698                 connect_res =
699                         (struct hbm_client_connect_response *) mei_msg;
700                 mei_client_connect_response(dev, connect_res);
701                 dev_dbg(&dev->pdev->dev, "client connect response message received.\n");
702                 wake_up(&dev->wait_recvd_msg);
703                 break;
704
705         case CLIENT_DISCONNECT_RES_CMD:
706                 disconnect_res =
707                         (struct hbm_client_connect_response *) mei_msg;
708                 mei_client_disconnect_response(dev,      disconnect_res);
709                 dev_dbg(&dev->pdev->dev, "client disconnect response message received.\n");
710                 wake_up(&dev->wait_recvd_msg);
711                 break;
712
713         case MEI_FLOW_CONTROL_CMD:
714                 flow_control = (struct hbm_flow_control *) mei_msg;
715                 mei_client_flow_control_response(dev, flow_control);
716                 dev_dbg(&dev->pdev->dev, "client flow control response message received.\n");
717                 break;
718
719         case HOST_CLIENT_PROPERTIES_RES_CMD:
720                 props_res = (struct hbm_props_response *)mei_msg;
721                 if (props_res->status || !dev->me_clients) {
722                         dev_dbg(&dev->pdev->dev, "reset due to received host client properties response bus message wrong status.\n");
723                         mei_reset(dev, 1);
724                         return;
725                 }
726                if (dev->me_clients[dev->me_client_presentation_num]
727                                         .client_id == props_res->address) {
728
729                         dev->me_clients[dev->me_client_presentation_num].props
730                                                 = props_res->client_properties;
731
732                         if (dev->mei_state == MEI_INIT_CLIENTS &&
733                             dev->init_clients_state ==
734                                         MEI_CLIENT_PROPERTIES_MESSAGE) {
735                                 dev->me_client_index++;
736                                 dev->me_client_presentation_num++;
737                                 mei_host_client_properties(dev);
738                         } else {
739                                 dev_dbg(&dev->pdev->dev, "reset due to received host client properties response bus message");
740                                 mei_reset(dev, 1);
741                                 return;
742                         }
743                 } else {
744                         dev_dbg(&dev->pdev->dev, "reset due to received host client properties response bus message for wrong client ID\n");
745                         mei_reset(dev, 1);
746                         return;
747                 }
748                 break;
749
750         case HOST_ENUM_RES_CMD:
751                 enum_res = (struct hbm_host_enum_response *) mei_msg;
752                 memcpy(dev->me_clients_map, enum_res->valid_addresses, 32);
753                 if (dev->mei_state == MEI_INIT_CLIENTS &&
754                     dev->init_clients_state == MEI_ENUM_CLIENTS_MESSAGE) {
755                                 dev->init_clients_timer = 0;
756                                 dev->me_client_presentation_num = 0;
757                                 dev->me_client_index = 0;
758                                 mei_allocate_me_clients_storage(dev);
759                                 dev->init_clients_state =
760                                         MEI_CLIENT_PROPERTIES_MESSAGE;
761                                 mei_host_client_properties(dev);
762                 } else {
763                         dev_dbg(&dev->pdev->dev, "reset due to received host enumeration clients response bus message.\n");
764                         mei_reset(dev, 1);
765                         return;
766                 }
767                 break;
768
769         case HOST_STOP_RES_CMD:
770                 dev->mei_state = MEI_DISABLED;
771                 dev_dbg(&dev->pdev->dev, "resetting because of FW stop response.\n");
772                 mei_reset(dev, 1);
773                 break;
774
775         case CLIENT_DISCONNECT_REQ_CMD:
776                 /* search for client */
777                 disconnect_req =
778                         (struct hbm_client_disconnect_request *) mei_msg;
779                 mei_client_disconnect_request(dev, disconnect_req);
780                 break;
781
782         case ME_STOP_REQ_CMD:
783                 /* prepare stop request */
784                 mei_hdr = (struct mei_msg_hdr *) &dev->ext_msg_buf[0];
785                 mei_hdr->host_addr = 0;
786                 mei_hdr->me_addr = 0;
787                 mei_hdr->length = sizeof(struct hbm_host_stop_request);
788                 mei_hdr->msg_complete = 1;
789                 mei_hdr->reserved = 0;
790                 host_stop_req =
791                         (struct hbm_host_stop_request *) &dev->ext_msg_buf[1];
792                 memset(host_stop_req, 0, sizeof(struct hbm_host_stop_request));
793                 host_stop_req->cmd.cmd = HOST_STOP_REQ_CMD;
794                 host_stop_req->reason = DRIVER_STOP_REQUEST;
795                 host_stop_req->reserved[0] = 0;
796                 host_stop_req->reserved[1] = 0;
797                 dev->extra_write_index = 2;
798                 break;
799
800         default:
801                 BUG();
802                 break;
803
804         }
805 }
806
807
808 /**
809  * _mei_hb_read - processes read related operation.
810  *
811  * @dev: the device structure.
812  * @slots: free slots.
813  * @cb_pos: callback block.
814  * @cl: private data of the file object.
815  * @cmpl_list: complete list.
816  *
817  * returns 0, OK; otherwise, error.
818  */
819 static int _mei_irq_thread_read(struct mei_device *dev, s32 *slots,
820                         struct mei_cl_cb *cb_pos,
821                         struct mei_cl *cl,
822                         struct mei_io_list *cmpl_list)
823 {
824         if ((*slots * sizeof(u32)) >= (sizeof(struct mei_msg_hdr) +
825                         sizeof(struct hbm_flow_control))) {
826                 *slots -= (sizeof(struct mei_msg_hdr) +
827                         sizeof(struct hbm_flow_control) + 3) / 4;
828                 if (!mei_send_flow_control(dev, cl)) {
829                         cl->status = -ENODEV;
830                         cb_pos->information = 0;
831                         list_move_tail(&cb_pos->cb_list,
832                                         &cmpl_list->mei_cb.cb_list);
833                         return -ENODEV;
834                 } else {
835                         list_move_tail(&cb_pos->cb_list,
836                                         &dev->read_list.mei_cb.cb_list);
837                 }
838         } else {
839                 /* return the cancel routine */
840                 list_del(&cb_pos->cb_list);
841                 return -EBADMSG;
842         }
843
844         return 0;
845 }
846
847
848 /**
849  * _mei_irq_thread_ioctl - processes ioctl related operation.
850  *
851  * @dev: the device structure.
852  * @slots: free slots.
853  * @cb_pos: callback block.
854  * @cl: private data of the file object.
855  * @cmpl_list: complete list.
856  *
857  * returns 0, OK; otherwise, error.
858  */
859 static int _mei_irq_thread_ioctl(struct mei_device *dev, s32 *slots,
860                         struct mei_cl_cb *cb_pos,
861                         struct mei_cl *cl,
862                         struct mei_io_list *cmpl_list)
863 {
864         if ((*slots * sizeof(u32)) >= (sizeof(struct mei_msg_hdr) +
865                         sizeof(struct hbm_client_connect_request))) {
866                 cl->state = MEI_FILE_CONNECTING;
867                 *slots -= (sizeof(struct mei_msg_hdr) +
868                         sizeof(struct hbm_client_connect_request) + 3) / 4;
869                 if (!mei_connect(dev, cl)) {
870                         cl->status = -ENODEV;
871                         cb_pos->information = 0;
872                         list_del(&cb_pos->cb_list);
873                         return -ENODEV;
874                 } else {
875                         list_move_tail(&cb_pos->cb_list,
876                                 &dev->ctrl_rd_list.mei_cb.cb_list);
877                         cl->timer_count = MEI_CONNECT_TIMEOUT;
878                 }
879         } else {
880                 /* return the cancel routine */
881                 list_del(&cb_pos->cb_list);
882                 return -EBADMSG;
883         }
884
885         return 0;
886 }
887
888 /**
889  * _mei_irq_thread_cmpl - processes completed and no-iamthif operation.
890  *
891  * @dev: the device structure.
892  * @slots: free slots.
893  * @cb_pos: callback block.
894  * @cl: private data of the file object.
895  * @cmpl_list: complete list.
896  *
897  * returns 0, OK; otherwise, error.
898  */
899 static int _mei_irq_thread_cmpl(struct mei_device *dev, s32 *slots,
900                         struct mei_cl_cb *cb_pos,
901                         struct mei_cl *cl,
902                         struct mei_io_list *cmpl_list)
903 {
904         struct mei_msg_hdr *mei_hdr;
905
906         if ((*slots * sizeof(u32)) >= (sizeof(struct mei_msg_hdr) +
907                         (cb_pos->request_buffer.size -
908                         cb_pos->information))) {
909                 mei_hdr = (struct mei_msg_hdr *) &dev->wr_msg_buf[0];
910                 mei_hdr->host_addr = cl->host_client_id;
911                 mei_hdr->me_addr = cl->me_client_id;
912                 mei_hdr->length = cb_pos->request_buffer.size -
913                                         cb_pos->information;
914                 mei_hdr->msg_complete = 1;
915                 mei_hdr->reserved = 0;
916                 dev_dbg(&dev->pdev->dev, "cb_pos->request_buffer.size =%d"
917                         "mei_hdr->msg_complete = %d\n",
918                                 cb_pos->request_buffer.size,
919                                 mei_hdr->msg_complete);
920                 dev_dbg(&dev->pdev->dev, "cb_pos->information  =%lu\n",
921                                 cb_pos->information);
922                 dev_dbg(&dev->pdev->dev, "mei_hdr->length  =%d\n",
923                                 mei_hdr->length);
924                 *slots -= (sizeof(struct mei_msg_hdr) +
925                                 mei_hdr->length + 3) / 4;
926                 if (!mei_write_message(dev, mei_hdr,
927                                 (unsigned char *)
928                                 (cb_pos->request_buffer.data +
929                                 cb_pos->information),
930                                 mei_hdr->length)) {
931                         cl->status = -ENODEV;
932                         list_move_tail(&cb_pos->cb_list,
933                                 &cmpl_list->mei_cb.cb_list);
934                         return -ENODEV;
935                 } else {
936                         if (mei_flow_ctrl_reduce(dev, cl))
937                                 return -ENODEV;
938                         cl->status = 0;
939                         cb_pos->information += mei_hdr->length;
940                         list_move_tail(&cb_pos->cb_list,
941                                 &dev->write_waiting_list.mei_cb.cb_list);
942                 }
943         } else if (*slots == ((dev->host_hw_state & H_CBD) >> 24)) {
944                 /* buffer is still empty */
945                 mei_hdr = (struct mei_msg_hdr *) &dev->wr_msg_buf[0];
946                 mei_hdr->host_addr = cl->host_client_id;
947                 mei_hdr->me_addr = cl->me_client_id;
948                 mei_hdr->length =
949                         (*slots * sizeof(u32)) - sizeof(struct mei_msg_hdr);
950                 mei_hdr->msg_complete = 0;
951                 mei_hdr->reserved = 0;
952
953                 (*slots) -= (sizeof(struct mei_msg_hdr) +
954                                 mei_hdr->length + 3) / 4;
955                 if (!mei_write_message(dev, mei_hdr,
956                                         (unsigned char *)
957                                         (cb_pos->request_buffer.data +
958                                         cb_pos->information),
959                                         mei_hdr->length)) {
960                         cl->status = -ENODEV;
961                         list_move_tail(&cb_pos->cb_list,
962                                 &cmpl_list->mei_cb.cb_list);
963                         return -ENODEV;
964                 } else {
965                         cb_pos->information += mei_hdr->length;
966                         dev_dbg(&dev->pdev->dev,
967                                         "cb_pos->request_buffer.size =%d"
968                                         " mei_hdr->msg_complete = %d\n",
969                                         cb_pos->request_buffer.size,
970                                         mei_hdr->msg_complete);
971                         dev_dbg(&dev->pdev->dev, "cb_pos->information  =%lu\n",
972                                         cb_pos->information);
973                         dev_dbg(&dev->pdev->dev, "mei_hdr->length  =%d\n",
974                                         mei_hdr->length);
975                 }
976                 return -EMSGSIZE;
977         } else {
978                 return -EBADMSG;
979         }
980
981         return 0;
982 }
983
984 /**
985  * _mei_irq_thread_cmpl_iamthif - processes completed iamthif operation.
986  *
987  * @dev: the device structure.
988  * @slots: free slots.
989  * @cb_pos: callback block.
990  * @cl: private data of the file object.
991  * @cmpl_list: complete list.
992  *
993  * returns 0, OK; otherwise, error.
994  */
995 static int _mei_irq_thread_cmpl_iamthif(struct mei_device *dev, s32 *slots,
996                         struct mei_cl_cb *cb_pos,
997                         struct mei_cl *cl,
998                         struct mei_io_list *cmpl_list)
999 {
1000         struct mei_msg_hdr *mei_hdr;
1001
1002         if ((*slots * sizeof(u32)) >= (sizeof(struct mei_msg_hdr) +
1003                         dev->iamthif_msg_buf_size -
1004                         dev->iamthif_msg_buf_index)) {
1005                 mei_hdr = (struct mei_msg_hdr *) &dev->wr_msg_buf[0];
1006                 mei_hdr->host_addr = cl->host_client_id;
1007                 mei_hdr->me_addr = cl->me_client_id;
1008                 mei_hdr->length = dev->iamthif_msg_buf_size -
1009                         dev->iamthif_msg_buf_index;
1010                 mei_hdr->msg_complete = 1;
1011                 mei_hdr->reserved = 0;
1012
1013                 *slots -= (sizeof(struct mei_msg_hdr) +
1014                                 mei_hdr->length + 3) / 4;
1015
1016                 if (!mei_write_message(dev, mei_hdr,
1017                                         (dev->iamthif_msg_buf +
1018                                         dev->iamthif_msg_buf_index),
1019                                         mei_hdr->length)) {
1020                         dev->iamthif_state = MEI_IAMTHIF_IDLE;
1021                         cl->status = -ENODEV;
1022                         list_del(&cb_pos->cb_list);
1023                         return -ENODEV;
1024                 } else {
1025                         if (mei_flow_ctrl_reduce(dev, cl))
1026                                 return -ENODEV;
1027                         dev->iamthif_msg_buf_index += mei_hdr->length;
1028                         cb_pos->information = dev->iamthif_msg_buf_index;
1029                         cl->status = 0;
1030                         dev->iamthif_state = MEI_IAMTHIF_FLOW_CONTROL;
1031                         dev->iamthif_flow_control_pending = true;
1032                         /* save iamthif cb sent to amthi client */
1033                         dev->iamthif_current_cb = cb_pos;
1034                         list_move_tail(&cb_pos->cb_list,
1035                                 &dev->write_waiting_list.mei_cb.cb_list);
1036
1037                 }
1038         } else if (*slots == ((dev->host_hw_state & H_CBD) >> 24)) {
1039                         /* buffer is still empty */
1040                 mei_hdr = (struct mei_msg_hdr *) &dev->wr_msg_buf[0];
1041                 mei_hdr->host_addr = cl->host_client_id;
1042                 mei_hdr->me_addr = cl->me_client_id;
1043                 mei_hdr->length =
1044                         (*slots * sizeof(u32)) - sizeof(struct mei_msg_hdr);
1045                 mei_hdr->msg_complete = 0;
1046                 mei_hdr->reserved = 0;
1047
1048                 *slots -= (sizeof(struct mei_msg_hdr) +
1049                                 mei_hdr->length + 3) / 4;
1050
1051                 if (!mei_write_message(dev, mei_hdr,
1052                                         (dev->iamthif_msg_buf +
1053                                         dev->iamthif_msg_buf_index),
1054                                         mei_hdr->length)) {
1055                         cl->status = -ENODEV;
1056                         list_del(&cb_pos->cb_list);
1057                 } else {
1058                         dev->iamthif_msg_buf_index += mei_hdr->length;
1059                 }
1060                 return -EMSGSIZE;
1061         } else {
1062                 return -EBADMSG;
1063         }
1064
1065         return 0;
1066 }
1067
1068 /**
1069  * mei_irq_thread_read_handler - bottom half read routine after ISR to
1070  * handle the read processing.
1071  *
1072  * @cmpl_list: An instance of our list structure
1073  * @dev: the device structure
1074  * @slots: slots to read.
1075  *
1076  * returns 0 on success, <0 on failure.
1077  */
1078 static int mei_irq_thread_read_handler(struct mei_io_list *cmpl_list,
1079                 struct mei_device *dev,
1080                 s32 *slots)
1081 {
1082         struct mei_msg_hdr *mei_hdr;
1083         struct mei_cl *cl_pos = NULL;
1084         struct mei_cl *cl_next = NULL;
1085         int ret = 0;
1086
1087         if (!dev->rd_msg_hdr) {
1088                 dev->rd_msg_hdr = mei_mecbrw_read(dev);
1089                 dev_dbg(&dev->pdev->dev, "slots =%08x.\n", *slots);
1090                 (*slots)--;
1091                 dev_dbg(&dev->pdev->dev, "slots =%08x.\n", *slots);
1092         }
1093         mei_hdr = (struct mei_msg_hdr *) &dev->rd_msg_hdr;
1094         dev_dbg(&dev->pdev->dev, "mei_hdr->length =%d\n", mei_hdr->length);
1095
1096         if (mei_hdr->reserved || !dev->rd_msg_hdr) {
1097                 dev_dbg(&dev->pdev->dev, "corrupted message header.\n");
1098                 ret = -EBADMSG;
1099                 goto end;
1100         }
1101
1102         if (mei_hdr->host_addr || mei_hdr->me_addr) {
1103                 list_for_each_entry_safe(cl_pos, cl_next,
1104                                         &dev->file_list, link) {
1105                         dev_dbg(&dev->pdev->dev,
1106                                         "list_for_each_entry_safe read host"
1107                                         " client = %d, ME client = %d\n",
1108                                         cl_pos->host_client_id,
1109                                         cl_pos->me_client_id);
1110                         if (cl_pos->host_client_id == mei_hdr->host_addr &&
1111                             cl_pos->me_client_id == mei_hdr->me_addr)
1112                                 break;
1113                 }
1114
1115                 if (&cl_pos->link == &dev->file_list) {
1116                         dev_dbg(&dev->pdev->dev, "corrupted message header\n");
1117                         ret = -EBADMSG;
1118                         goto end;
1119                 }
1120         }
1121         if (((*slots) * sizeof(u32)) < mei_hdr->length) {
1122                 dev_dbg(&dev->pdev->dev,
1123                                 "we can't read the message slots =%08x.\n",
1124                                 *slots);
1125                 /* we can't read the message */
1126                 ret = -ERANGE;
1127                 goto end;
1128         }
1129
1130         /* decide where to read the message too */
1131         if (!mei_hdr->host_addr) {
1132                 dev_dbg(&dev->pdev->dev, "call mei_irq_thread_read_bus_message.\n");
1133                 mei_irq_thread_read_bus_message(dev, mei_hdr);
1134                 dev_dbg(&dev->pdev->dev, "end mei_irq_thread_read_bus_message.\n");
1135         } else if (mei_hdr->host_addr == dev->iamthif_cl.host_client_id &&
1136                    (MEI_FILE_CONNECTED == dev->iamthif_cl.state) &&
1137                    (dev->iamthif_state == MEI_IAMTHIF_READING)) {
1138                 dev_dbg(&dev->pdev->dev, "call mei_irq_thread_read_iamthif_message.\n");
1139                 dev_dbg(&dev->pdev->dev, "mei_hdr->length =%d\n",
1140                                 mei_hdr->length);
1141                 ret = mei_irq_thread_read_amthi_message(cmpl_list,
1142                                                         dev, mei_hdr);
1143                 if (ret)
1144                         goto end;
1145
1146         } else {
1147                 dev_dbg(&dev->pdev->dev, "call mei_irq_thread_read_client_message.\n");
1148                 ret = mei_irq_thread_read_client_message(cmpl_list,
1149                                                          dev, mei_hdr);
1150                 if (ret)
1151                         goto end;
1152
1153         }
1154
1155         /* reset the number of slots and header */
1156         *slots = mei_count_full_read_slots(dev);
1157         dev->rd_msg_hdr = 0;
1158
1159         if (*slots == -EOVERFLOW) {
1160                 /* overflow - reset */
1161                 dev_dbg(&dev->pdev->dev, "resetting due to slots overflow.\n");
1162                 /* set the event since message has been read */
1163                 ret = -ERANGE;
1164                 goto end;
1165         }
1166 end:
1167         return ret;
1168 }
1169
1170
1171 /**
1172  * mei_irq_thread_write_handler - bottom half write routine after
1173  * ISR to handle the write processing.
1174  *
1175  * @cmpl_list: An instance of our list structure
1176  * @dev: the device structure
1177  * @slots: slots to write.
1178  *
1179  * returns 0 on success, <0 on failure.
1180  */
1181 static int mei_irq_thread_write_handler(struct mei_io_list *cmpl_list,
1182                 struct mei_device *dev,
1183                 s32 *slots)
1184 {
1185
1186         struct mei_cl *cl;
1187         struct mei_cl_cb *cb_pos = NULL, *cb_next = NULL;
1188         struct mei_io_list *list;
1189         int ret;
1190
1191         if (!mei_host_buffer_is_empty(dev)) {
1192                 dev_dbg(&dev->pdev->dev, "host buffer is not empty.\n");
1193                 return 0;
1194         }
1195         *slots = mei_count_empty_write_slots(dev);
1196         /* complete all waiting for write CB */
1197         dev_dbg(&dev->pdev->dev, "complete all waiting for write cb.\n");
1198
1199         list = &dev->write_waiting_list;
1200         if (!list->status && !list_empty(&list->mei_cb.cb_list)) {
1201                 list_for_each_entry_safe(cb_pos, cb_next,
1202                                 &list->mei_cb.cb_list, cb_list) {
1203                         cl = (struct mei_cl *)cb_pos->file_private;
1204                         if (cl) {
1205                                 cl->status = 0;
1206                                 list_del(&cb_pos->cb_list);
1207                                 if (MEI_WRITING == cl->writing_state &&
1208                                    (cb_pos->major_file_operations ==
1209                                                 MEI_WRITE) &&
1210                                    (cl != &dev->iamthif_cl)) {
1211                                         dev_dbg(&dev->pdev->dev,
1212                                                 "MEI WRITE COMPLETE\n");
1213                                         cl->writing_state =
1214                                                         MEI_WRITE_COMPLETE;
1215                                         list_add_tail(&cb_pos->cb_list,
1216                                                 &cmpl_list->mei_cb.cb_list);
1217                                 }
1218                                 if (cl == &dev->iamthif_cl) {
1219                                         dev_dbg(&dev->pdev->dev, "check iamthif flow control.\n");
1220                                         if (dev->iamthif_flow_control_pending) {
1221                                                 ret =
1222                                                 _mei_irq_thread_iamthif_read(
1223                                                                 dev, slots);
1224                                                 if (ret)
1225                                                         return ret;
1226                                         }
1227                                 }
1228                         }
1229
1230                 }
1231         }
1232
1233         if (dev->stop && !dev->wd_pending) {
1234                 dev->wd_stopped = true;
1235                 wake_up_interruptible(&dev->wait_stop_wd);
1236                 return 0;
1237         }
1238
1239         if (dev->extra_write_index) {
1240                 dev_dbg(&dev->pdev->dev, "extra_write_index =%d.\n",
1241                                 dev->extra_write_index);
1242                 mei_write_message(dev,
1243                                 (struct mei_msg_hdr *) &dev->ext_msg_buf[0],
1244                                 (unsigned char *) &dev->ext_msg_buf[1],
1245                                 (dev->extra_write_index - 1) * sizeof(u32));
1246                 *slots -= dev->extra_write_index;
1247                 dev->extra_write_index = 0;
1248         }
1249         if (dev->mei_state == MEI_ENABLED) {
1250                 if (dev->wd_pending &&
1251                         mei_flow_ctrl_creds(dev, &dev->wd_cl) > 0) {
1252                         if (mei_wd_send(dev))
1253                                 dev_dbg(&dev->pdev->dev, "wd send failed.\n");
1254                         else
1255                                 if (mei_flow_ctrl_reduce(dev, &dev->wd_cl))
1256                                         return -ENODEV;
1257
1258                         dev->wd_pending = false;
1259
1260                         if (dev->wd_timeout) {
1261                                 *slots -= (sizeof(struct mei_msg_hdr) +
1262                                          MEI_START_WD_DATA_SIZE + 3) / 4;
1263                                 dev->wd_due_counter = 2;
1264                         } else {
1265                                 *slots -= (sizeof(struct mei_msg_hdr) +
1266                                          MEI_WD_PARAMS_SIZE + 3) / 4;
1267                                 dev->wd_due_counter = 0;
1268                         }
1269
1270                 }
1271         }
1272         if (dev->stop)
1273                 return ~ENODEV;
1274
1275         /* complete control write list CB */
1276         if (!dev->ctrl_wr_list.status) {
1277                 /* complete control write list CB */
1278                 dev_dbg(&dev->pdev->dev, "complete control write list cb.\n");
1279                 list_for_each_entry_safe(cb_pos, cb_next,
1280                                 &dev->ctrl_wr_list.mei_cb.cb_list, cb_list) {
1281                         cl = (struct mei_cl *)
1282                                 cb_pos->file_private;
1283                         if (!cl) {
1284                                 list_del(&cb_pos->cb_list);
1285                                 return -ENODEV;
1286                         }
1287                         switch (cb_pos->major_file_operations) {
1288                         case MEI_CLOSE:
1289                                 /* send disconnect message */
1290                                 ret = _mei_irq_thread_close(dev, slots,
1291                                                      cb_pos, cl, cmpl_list);
1292                                 if (ret)
1293                                         return ret;
1294
1295                                 break;
1296                         case MEI_READ:
1297                                 /* send flow control message */
1298                                 ret = _mei_irq_thread_read(dev, slots,
1299                                                     cb_pos, cl, cmpl_list);
1300                                 if (ret)
1301                                         return ret;
1302
1303                                 break;
1304                         case MEI_IOCTL:
1305                                 /* connect message */
1306                                 if (!mei_other_client_is_connecting(dev,
1307                                                 cl))
1308                                         continue;
1309                                 ret = _mei_irq_thread_ioctl(dev, slots,
1310                                                      cb_pos, cl, cmpl_list);
1311                                 if (ret)
1312                                         return ret;
1313
1314                                 break;
1315
1316                         default:
1317                                 BUG();
1318                         }
1319
1320                 }
1321         }
1322         /* complete  write list CB */
1323         if (!dev->write_list.status &&
1324             !list_empty(&dev->write_list.mei_cb.cb_list)) {
1325                 dev_dbg(&dev->pdev->dev, "complete write list cb.\n");
1326                 list_for_each_entry_safe(cb_pos, cb_next,
1327                                 &dev->write_list.mei_cb.cb_list, cb_list) {
1328                         cl = (struct mei_cl *)cb_pos->file_private;
1329
1330                         if (cl) {
1331                                 if (cl != &dev->iamthif_cl) {
1332                                         if (!mei_flow_ctrl_creds(dev,
1333                                                 cl)) {
1334                                                 dev_dbg(&dev->pdev->dev,
1335                                                         "No flow control"
1336                                                     " credentials for client"
1337                                                     " %d, not sending.\n",
1338                                                     cl->host_client_id);
1339                                                 continue;
1340                                         }
1341                                         ret = _mei_irq_thread_cmpl(dev, slots,
1342                                                             cb_pos,
1343                                                             cl, cmpl_list);
1344                                         if (ret)
1345                                                 return ret;
1346
1347                                 } else if (cl == &dev->iamthif_cl) {
1348                                         /* IAMTHIF IOCTL */
1349                                         dev_dbg(&dev->pdev->dev, "complete amthi write cb.\n");
1350                                         if (!mei_flow_ctrl_creds(dev,
1351                                                         cl)) {
1352                                                 dev_dbg(&dev->pdev->dev,
1353                                                         "No flow control"
1354                                                     " credentials for amthi"
1355                                                     " client %d.\n",
1356                                                     cl->host_client_id);
1357                                                 continue;
1358                                         }
1359                                         ret = _mei_irq_thread_cmpl_iamthif(dev,
1360                                                                 slots,
1361                                                                 cb_pos,
1362                                                                 cl,
1363                                                                 cmpl_list);
1364                                         if (ret)
1365                                                 return ret;
1366
1367                                 }
1368                         }
1369
1370                 }
1371         }
1372         return 0;
1373 }
1374
1375
1376
1377 /**
1378  * mei_timer - timer function.
1379  *
1380  * @work: pointer to the work_struct structure
1381  *
1382  * NOTE: This function is called by timer interrupt work
1383  */
1384 void mei_wd_timer(struct work_struct *work)
1385 {
1386         unsigned long timeout;
1387         struct mei_cl *cl_pos = NULL;
1388         struct mei_cl *cl_next = NULL;
1389         struct list_head *amthi_complete_list = NULL;
1390         struct mei_cl_cb  *cb_pos = NULL;
1391         struct mei_cl_cb  *cb_next = NULL;
1392
1393         struct mei_device *dev = container_of(work,
1394                                         struct mei_device, wd_work.work);
1395
1396
1397         mutex_lock(&dev->device_lock);
1398         if (dev->mei_state != MEI_ENABLED) {
1399                 if (dev->mei_state == MEI_INIT_CLIENTS) {
1400                         if (dev->init_clients_timer) {
1401                                 if (--dev->init_clients_timer == 0) {
1402                                         dev_dbg(&dev->pdev->dev, "IMEI reset due to init clients timeout ,init clients state = %d.\n",
1403                                                 dev->init_clients_state);
1404                                         mei_reset(dev, 1);
1405                                 }
1406                         }
1407                 }
1408                 goto out;
1409         }
1410         /*** connect/disconnect timeouts ***/
1411         list_for_each_entry_safe(cl_pos, cl_next, &dev->file_list, link) {
1412                 if (cl_pos->timer_count) {
1413                         if (--cl_pos->timer_count == 0) {
1414                                 dev_dbg(&dev->pdev->dev, "HECI reset due to connect/disconnect timeout.\n");
1415                                 mei_reset(dev, 1);
1416                                 goto out;
1417                         }
1418                 }
1419         }
1420
1421         if (dev->wd_cl.state != MEI_FILE_CONNECTED)
1422                 goto out;
1423
1424         /* Watchdog */
1425         if (dev->wd_due_counter && !dev->wd_bypass) {
1426                 if (--dev->wd_due_counter == 0) {
1427                         if (dev->mei_host_buffer_is_empty &&
1428                             mei_flow_ctrl_creds(dev, &dev->wd_cl) > 0) {
1429                                 dev->mei_host_buffer_is_empty = false;
1430                                 dev_dbg(&dev->pdev->dev, "send watchdog.\n");
1431
1432                                 if (mei_wd_send(dev))
1433                                         dev_dbg(&dev->pdev->dev, "wd send failed.\n");
1434                                 else
1435                                         if (mei_flow_ctrl_reduce(dev, &dev->wd_cl))
1436                                                 goto out;
1437
1438                                 if (dev->wd_timeout)
1439                                         dev->wd_due_counter = 2;
1440                                 else
1441                                         dev->wd_due_counter = 0;
1442
1443                         } else
1444                                 dev->wd_pending = true;
1445
1446                 }
1447         }
1448         if (dev->iamthif_stall_timer) {
1449                 if (--dev->iamthif_stall_timer == 0) {
1450                         dev_dbg(&dev->pdev->dev, "reseting because of hang to amthi.\n");
1451                         mei_reset(dev, 1);
1452                         dev->iamthif_msg_buf_size = 0;
1453                         dev->iamthif_msg_buf_index = 0;
1454                         dev->iamthif_canceled = false;
1455                         dev->iamthif_ioctl = true;
1456                         dev->iamthif_state = MEI_IAMTHIF_IDLE;
1457                         dev->iamthif_timer = 0;
1458
1459                         if (dev->iamthif_current_cb)
1460                                 mei_free_cb_private(dev->iamthif_current_cb);
1461
1462                         dev->iamthif_file_object = NULL;
1463                         dev->iamthif_current_cb = NULL;
1464                         mei_run_next_iamthif_cmd(dev);
1465                 }
1466         }
1467
1468         if (dev->iamthif_timer) {
1469
1470                 timeout = dev->iamthif_timer +
1471                                 msecs_to_jiffies(IAMTHIF_READ_TIMER);
1472
1473                 dev_dbg(&dev->pdev->dev, "dev->iamthif_timer = %ld\n",
1474                                 dev->iamthif_timer);
1475                 dev_dbg(&dev->pdev->dev, "timeout = %ld\n", timeout);
1476                 dev_dbg(&dev->pdev->dev, "jiffies = %ld\n", jiffies);
1477                 if (time_after(jiffies, timeout)) {
1478                         /*
1479                          * User didn't read the AMTHI data on time (15sec)
1480                          * freeing AMTHI for other requests
1481                          */
1482
1483                         dev_dbg(&dev->pdev->dev, "freeing AMTHI for other requests\n");
1484
1485                         amthi_complete_list = &dev->amthi_read_complete_list.
1486                                         mei_cb.cb_list;
1487
1488                         if (!list_empty(amthi_complete_list)) {
1489
1490                                 list_for_each_entry_safe(cb_pos, cb_next,
1491                                                         amthi_complete_list,
1492                                                         cb_list) {
1493
1494                                         cl_pos = cb_pos->file_object->private_data;
1495
1496                                         /* Finding the AMTHI entry. */
1497                                         if (cl_pos ==   &dev->iamthif_cl)
1498                                                 list_del(&cb_pos->cb_list);
1499                                 }
1500                         }
1501                         if (dev->iamthif_current_cb)
1502                                 mei_free_cb_private(dev->iamthif_current_cb);
1503
1504                         dev->iamthif_file_object->private_data = NULL;
1505                         dev->iamthif_file_object = NULL;
1506                         dev->iamthif_current_cb = NULL;
1507                         dev->iamthif_timer = 0;
1508                         mei_run_next_iamthif_cmd(dev);
1509
1510                 }
1511         }
1512 out:
1513          schedule_delayed_work(&dev->wd_work, 2 * HZ);
1514          mutex_unlock(&dev->device_lock);
1515 }
1516
1517 /**
1518  *  mei_interrupt_thread_handler - function called after ISR to handle the interrupt
1519  * processing.
1520  *
1521  * @irq: The irq number
1522  * @dev_id: pointer to the device structure
1523  *
1524  * returns irqreturn_t
1525  *
1526  */
1527 irqreturn_t mei_interrupt_thread_handler(int irq, void *dev_id)
1528 {
1529         struct mei_device *dev = (struct mei_device *) dev_id;
1530         struct mei_io_list complete_list;
1531         struct mei_cl_cb *cb_pos = NULL, *cb_next = NULL;
1532         struct mei_cl *cl;
1533         s32 slots;
1534         int rets;
1535         bool  bus_message_received;
1536
1537
1538         dev_dbg(&dev->pdev->dev, "function called after ISR to handle the interrupt processing.\n");
1539         /* initialize our complete list */
1540         mutex_lock(&dev->device_lock);
1541         mei_io_list_init(&complete_list);
1542         dev->host_hw_state = mei_hcsr_read(dev);
1543         dev->me_hw_state = mei_mecsr_read(dev);
1544
1545         /* check if ME wants a reset */
1546         if ((dev->me_hw_state & ME_RDY_HRA) == 0 &&
1547             dev->mei_state != MEI_RESETING &&
1548             dev->mei_state != MEI_INITIALIZING) {
1549                 dev_dbg(&dev->pdev->dev, "FW not ready.\n");
1550                 mei_reset(dev, 1);
1551                 mutex_unlock(&dev->device_lock);
1552                 return IRQ_HANDLED;
1553         }
1554
1555         /*  check if we need to start the dev */
1556         if ((dev->host_hw_state & H_RDY) == 0) {
1557                 if ((dev->me_hw_state & ME_RDY_HRA) == ME_RDY_HRA) {
1558                         dev_dbg(&dev->pdev->dev, "we need to start the dev.\n");
1559                         dev->host_hw_state |= (H_IE | H_IG | H_RDY);
1560                         mei_hcsr_set(dev);
1561                         dev->mei_state = MEI_INIT_CLIENTS;
1562                         dev_dbg(&dev->pdev->dev, "link is established start sending messages.\n");
1563                         /* link is established
1564                          * start sending messages.
1565                          */
1566                         mei_host_start_message(dev);
1567                         mutex_unlock(&dev->device_lock);
1568                         return IRQ_HANDLED;
1569                 } else {
1570                         dev_dbg(&dev->pdev->dev, "FW not ready.\n");
1571                         mutex_unlock(&dev->device_lock);
1572                         return IRQ_HANDLED;
1573                 }
1574         }
1575         /* check slots avalable for reading */
1576         slots = mei_count_full_read_slots(dev);
1577         dev_dbg(&dev->pdev->dev, "slots =%08x  extra_write_index =%08x.\n",
1578                 slots, dev->extra_write_index);
1579         while (slots > 0 && !dev->extra_write_index) {
1580                 dev_dbg(&dev->pdev->dev, "slots =%08x  extra_write_index =%08x.\n",
1581                                 slots, dev->extra_write_index);
1582                 dev_dbg(&dev->pdev->dev, "call mei_irq_thread_read_handler.\n");
1583                 rets = mei_irq_thread_read_handler(&complete_list, dev, &slots);
1584                 if (rets)
1585                         goto end;
1586         }
1587         rets = mei_irq_thread_write_handler(&complete_list, dev, &slots);
1588 end:
1589         dev_dbg(&dev->pdev->dev, "end of bottom half function.\n");
1590         dev->host_hw_state = mei_hcsr_read(dev);
1591         dev->mei_host_buffer_is_empty = mei_host_buffer_is_empty(dev);
1592
1593         bus_message_received = false;
1594         if (dev->recvd_msg && waitqueue_active(&dev->wait_recvd_msg)) {
1595                 dev_dbg(&dev->pdev->dev, "received waiting bus message\n");
1596                 bus_message_received = true;
1597         }
1598         mutex_unlock(&dev->device_lock);
1599         if (bus_message_received) {
1600                 dev_dbg(&dev->pdev->dev, "wake up dev->wait_recvd_msg\n");
1601                 wake_up_interruptible(&dev->wait_recvd_msg);
1602                 bus_message_received = false;
1603         }
1604         if (complete_list.status || list_empty(&complete_list.mei_cb.cb_list))
1605                 return IRQ_HANDLED;
1606
1607
1608         list_for_each_entry_safe(cb_pos, cb_next,
1609                         &complete_list.mei_cb.cb_list, cb_list) {
1610                 cl = (struct mei_cl *)cb_pos->file_private;
1611                 list_del(&cb_pos->cb_list);
1612                 if (cl) {
1613                         if (cl != &dev->iamthif_cl) {
1614                                 dev_dbg(&dev->pdev->dev, "completing call back.\n");
1615                                 _mei_cmpl(cl, cb_pos);
1616                                 cb_pos = NULL;
1617                         } else if (cl == &dev->iamthif_cl) {
1618                                 _mei_cmpl_iamthif(dev, cb_pos);
1619                         }
1620                 }
1621         }
1622         return IRQ_HANDLED;
1623 }