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