packaging: release out (3.8.3)
[profile/ivi/kernel-adaptation-intel-automotive.git] / drivers / misc / mei / interrupt.c
1 /*
2  *
3  * Intel Management Engine Interface (Intel MEI) Linux driver
4  * Copyright (c) 2003-2012, Intel Corporation.
5  *
6  * This program is free software; you can redistribute it and/or modify it
7  * under the terms and conditions of the GNU General Public License,
8  * version 2, as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope it will be useful, but WITHOUT
11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
13  * more details.
14  *
15  */
16
17
18 #include <linux/pci.h>
19 #include <linux/kthread.h>
20 #include <linux/interrupt.h>
21 #include <linux/fs.h>
22 #include <linux/jiffies.h>
23
24 #include "mei_dev.h"
25 #include <linux/mei.h>
26 #include "hw.h"
27 #include "interface.h"
28
29
30 /**
31  * mei_interrupt_quick_handler - The ISR of the MEI device
32  *
33  * @irq: The irq number
34  * @dev_id: pointer to the device structure
35  *
36  * returns irqreturn_t
37  */
38 irqreturn_t mei_interrupt_quick_handler(int irq, void *dev_id)
39 {
40         struct mei_device *dev = (struct mei_device *) dev_id;
41         u32 csr_reg = mei_hcsr_read(dev);
42
43         if ((csr_reg & H_IS) != H_IS)
44                 return IRQ_NONE;
45
46         /* clear H_IS bit in H_CSR */
47         mei_reg_write(dev, H_CSR, csr_reg);
48
49         return IRQ_WAKE_THREAD;
50 }
51
52 /**
53  * _mei_cmpl - processes completed operation.
54  *
55  * @cl: private data of the file object.
56  * @cb_pos: callback block.
57  */
58 static void _mei_cmpl(struct mei_cl *cl, struct mei_cl_cb *cb_pos)
59 {
60         if (cb_pos->fop_type == MEI_FOP_WRITE) {
61                 mei_io_cb_free(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->fop_type == MEI_FOP_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_irq_thread_state_ok - checks if mei header matches file private data
78  *
79  * @cl: private data of the file object
80  * @mei_hdr: header of mei client message
81  *
82  * returns !=0 if matches, 0 if no match.
83  */
84 static int _mei_irq_thread_state_ok(struct mei_cl *cl,
85                                 struct mei_msg_hdr *mei_hdr)
86 {
87         return (cl->host_client_id == mei_hdr->host_addr &&
88                 cl->me_client_id == mei_hdr->me_addr &&
89                 cl->state == MEI_FILE_CONNECTED &&
90                 MEI_READ_COMPLETE != cl->reading_state);
91 }
92
93 /**
94  * mei_irq_thread_read_client_message - bottom half read routine after ISR to
95  * handle the read mei client message data processing.
96  *
97  * @complete_list: An instance of our list structure
98  * @dev: the device structure
99  * @mei_hdr: header of mei client message
100  *
101  * returns 0 on success, <0 on failure.
102  */
103 static int mei_irq_thread_read_client_message(struct mei_cl_cb *complete_list,
104                 struct mei_device *dev,
105                 struct mei_msg_hdr *mei_hdr)
106 {
107         struct mei_cl *cl;
108         struct mei_cl_cb *cb_pos = NULL, *cb_next = NULL;
109         unsigned char *buffer = NULL;
110
111         dev_dbg(&dev->pdev->dev, "start client msg\n");
112         if (list_empty(&dev->read_list.list))
113                 goto quit;
114
115         list_for_each_entry_safe(cb_pos, cb_next, &dev->read_list.list, list) {
116                 cl = cb_pos->cl;
117                 if (cl && _mei_irq_thread_state_ok(cl, mei_hdr)) {
118                         cl->reading_state = MEI_READING;
119                         buffer = cb_pos->response_buffer.data + cb_pos->buf_idx;
120
121                         if (cb_pos->response_buffer.size <
122                                         mei_hdr->length + cb_pos->buf_idx) {
123                                 dev_dbg(&dev->pdev->dev, "message overflow.\n");
124                                 list_del(&cb_pos->list);
125                                 return -ENOMEM;
126                         }
127                         if (buffer)
128                                 mei_read_slots(dev, buffer, mei_hdr->length);
129
130                         cb_pos->buf_idx += mei_hdr->length;
131                         if (mei_hdr->msg_complete) {
132                                 cl->status = 0;
133                                 list_del(&cb_pos->list);
134                                 dev_dbg(&dev->pdev->dev,
135                                         "completed read H cl = %d, ME cl = %d, length = %lu\n",
136                                         cl->host_client_id,
137                                         cl->me_client_id,
138                                         cb_pos->buf_idx);
139
140                                 list_add_tail(&cb_pos->list,
141                                                 &complete_list->list);
142                         }
143
144                         break;
145                 }
146
147         }
148
149 quit:
150         dev_dbg(&dev->pdev->dev, "message read\n");
151         if (!buffer) {
152                 mei_read_slots(dev, dev->rd_msg_buf, mei_hdr->length);
153                 dev_dbg(&dev->pdev->dev, "discarding message, header =%08x.\n",
154                                 *(u32 *) dev->rd_msg_buf);
155         }
156
157         return 0;
158 }
159
160 /**
161  * _mei_irq_thread_close - processes close related operation.
162  *
163  * @dev: the device structure.
164  * @slots: free slots.
165  * @cb_pos: callback block.
166  * @cl: private data of the file object.
167  * @cmpl_list: complete list.
168  *
169  * returns 0, OK; otherwise, error.
170  */
171 static int _mei_irq_thread_close(struct mei_device *dev, s32 *slots,
172                                 struct mei_cl_cb *cb_pos,
173                                 struct mei_cl *cl,
174                                 struct mei_cl_cb *cmpl_list)
175 {
176         if ((*slots * sizeof(u32)) < (sizeof(struct mei_msg_hdr) +
177                         sizeof(struct hbm_client_connect_request)))
178                 return -EBADMSG;
179
180         *slots -= mei_data2slots(sizeof(struct hbm_client_connect_request));
181
182         if (mei_disconnect(dev, cl)) {
183                 cl->status = 0;
184                 cb_pos->buf_idx = 0;
185                 list_move_tail(&cb_pos->list, &cmpl_list->list);
186                 return -EMSGSIZE;
187         } else {
188                 cl->state = MEI_FILE_DISCONNECTING;
189                 cl->status = 0;
190                 cb_pos->buf_idx = 0;
191                 list_move_tail(&cb_pos->list, &dev->ctrl_rd_list.list);
192                 cl->timer_count = MEI_CONNECT_TIMEOUT;
193         }
194
195         return 0;
196 }
197
198 /**
199  * is_treat_specially_client - checks if the message belongs
200  * to the file private data.
201  *
202  * @cl: private data of the file object
203  * @rs: connect response bus message
204  *
205  */
206 static bool is_treat_specially_client(struct mei_cl *cl,
207                 struct hbm_client_connect_response *rs)
208 {
209
210         if (cl->host_client_id == rs->host_addr &&
211             cl->me_client_id == rs->me_addr) {
212                 if (!rs->status) {
213                         cl->state = MEI_FILE_CONNECTED;
214                         cl->status = 0;
215
216                 } else {
217                         cl->state = MEI_FILE_DISCONNECTED;
218                         cl->status = -ENODEV;
219                 }
220                 cl->timer_count = 0;
221
222                 return true;
223         }
224         return false;
225 }
226
227 /**
228  * mei_client_connect_response - connects to response irq routine
229  *
230  * @dev: the device structure
231  * @rs: connect response bus message
232  */
233 static void mei_client_connect_response(struct mei_device *dev,
234                 struct hbm_client_connect_response *rs)
235 {
236
237         struct mei_cl *cl;
238         struct mei_cl_cb *pos = NULL, *next = NULL;
239
240         dev_dbg(&dev->pdev->dev,
241                         "connect_response:\n"
242                         "ME Client = %d\n"
243                         "Host Client = %d\n"
244                         "Status = %d\n",
245                         rs->me_addr,
246                         rs->host_addr,
247                         rs->status);
248
249         /* if WD or iamthif client treat specially */
250
251         if (is_treat_specially_client(&(dev->wd_cl), rs)) {
252                 dev_dbg(&dev->pdev->dev, "successfully connected to WD client.\n");
253                 mei_watchdog_register(dev);
254
255                 return;
256         }
257
258         if (is_treat_specially_client(&(dev->iamthif_cl), rs)) {
259                 dev->iamthif_state = MEI_IAMTHIF_IDLE;
260                 return;
261         }
262         list_for_each_entry_safe(pos, next, &dev->ctrl_rd_list.list, list) {
263
264                 cl = pos->cl;
265                 if (!cl) {
266                         list_del(&pos->list);
267                         return;
268                 }
269                 if (pos->fop_type == MEI_FOP_IOCTL) {
270                         if (is_treat_specially_client(cl, rs)) {
271                                 list_del(&pos->list);
272                                 cl->status = 0;
273                                 cl->timer_count = 0;
274                                 break;
275                         }
276                 }
277         }
278 }
279
280 /**
281  * mei_client_disconnect_response - disconnects from response irq routine
282  *
283  * @dev: the device structure
284  * @rs: disconnect response bus message
285  */
286 static void mei_client_disconnect_response(struct mei_device *dev,
287                                         struct hbm_client_connect_response *rs)
288 {
289         struct mei_cl *cl;
290         struct mei_cl_cb *pos = NULL, *next = NULL;
291
292         dev_dbg(&dev->pdev->dev,
293                         "disconnect_response:\n"
294                         "ME Client = %d\n"
295                         "Host Client = %d\n"
296                         "Status = %d\n",
297                         rs->me_addr,
298                         rs->host_addr,
299                         rs->status);
300
301         list_for_each_entry_safe(pos, next, &dev->ctrl_rd_list.list, list) {
302                 cl = pos->cl;
303
304                 if (!cl) {
305                         list_del(&pos->list);
306                         return;
307                 }
308
309                 dev_dbg(&dev->pdev->dev, "list_for_each_entry_safe in ctrl_rd_list.\n");
310                 if (cl->host_client_id == rs->host_addr &&
311                     cl->me_client_id == rs->me_addr) {
312
313                         list_del(&pos->list);
314                         if (!rs->status)
315                                 cl->state = MEI_FILE_DISCONNECTED;
316
317                         cl->status = 0;
318                         cl->timer_count = 0;
319                         break;
320                 }
321         }
322 }
323
324 /**
325  * same_flow_addr - tells if they have the same address.
326  *
327  * @file: private data of the file object.
328  * @flow: flow control.
329  *
330  * returns  !=0, same; 0,not.
331  */
332 static int same_flow_addr(struct mei_cl *cl, struct hbm_flow_control *flow)
333 {
334         return (cl->host_client_id == flow->host_addr &&
335                 cl->me_client_id == flow->me_addr);
336 }
337
338 /**
339  * add_single_flow_creds - adds single buffer credentials.
340  *
341  * @file: private data ot the file object.
342  * @flow: flow control.
343  */
344 static void add_single_flow_creds(struct mei_device *dev,
345                                   struct hbm_flow_control *flow)
346 {
347         struct mei_me_client *client;
348         int i;
349
350         for (i = 0; i < dev->me_clients_num; i++) {
351                 client = &dev->me_clients[i];
352                 if (client && flow->me_addr == client->client_id) {
353                         if (client->props.single_recv_buf) {
354                                 client->mei_flow_ctrl_creds++;
355                                 dev_dbg(&dev->pdev->dev, "recv flow ctrl msg ME %d (single).\n",
356                                     flow->me_addr);
357                                 dev_dbg(&dev->pdev->dev, "flow control credentials =%d.\n",
358                                     client->mei_flow_ctrl_creds);
359                         } else {
360                                 BUG();  /* error in flow control */
361                         }
362                 }
363         }
364 }
365
366 /**
367  * mei_client_flow_control_response - flow control response irq routine
368  *
369  * @dev: the device structure
370  * @flow_control: flow control response bus message
371  */
372 static void mei_client_flow_control_response(struct mei_device *dev,
373                 struct hbm_flow_control *flow_control)
374 {
375         struct mei_cl *cl_pos = NULL;
376         struct mei_cl *cl_next = NULL;
377
378         if (!flow_control->host_addr) {
379                 /* single receive buffer */
380                 add_single_flow_creds(dev, flow_control);
381         } else {
382                 /* normal connection */
383                 list_for_each_entry_safe(cl_pos, cl_next,
384                                 &dev->file_list, link) {
385                         dev_dbg(&dev->pdev->dev, "list_for_each_entry_safe in file_list\n");
386
387                         dev_dbg(&dev->pdev->dev, "cl of host client %d ME client %d.\n",
388                             cl_pos->host_client_id,
389                             cl_pos->me_client_id);
390                         dev_dbg(&dev->pdev->dev, "flow ctrl msg for host %d ME %d.\n",
391                             flow_control->host_addr,
392                             flow_control->me_addr);
393                         if (same_flow_addr(cl_pos, flow_control)) {
394                                 dev_dbg(&dev->pdev->dev, "recv ctrl msg for host  %d ME %d.\n",
395                                     flow_control->host_addr,
396                                     flow_control->me_addr);
397                                 cl_pos->mei_flow_ctrl_creds++;
398                                 dev_dbg(&dev->pdev->dev, "flow control credentials = %d.\n",
399                                     cl_pos->mei_flow_ctrl_creds);
400                                 break;
401                         }
402                 }
403         }
404 }
405
406 /**
407  * same_disconn_addr - tells if they have the same address
408  *
409  * @file: private data of the file object.
410  * @disconn: disconnection request.
411  *
412  * returns !=0, same; 0,not.
413  */
414 static int same_disconn_addr(struct mei_cl *cl,
415                              struct hbm_client_connect_request *req)
416 {
417         return (cl->host_client_id == req->host_addr &&
418                 cl->me_client_id == req->me_addr);
419 }
420
421 /**
422  * mei_client_disconnect_request - disconnects from request irq routine
423  *
424  * @dev: the device structure.
425  * @disconnect_req: disconnect request bus message.
426  */
427 static void mei_client_disconnect_request(struct mei_device *dev,
428                 struct hbm_client_connect_request *disconnect_req)
429 {
430         struct hbm_client_connect_response *disconnect_res;
431         struct mei_cl *pos, *next;
432         const size_t len = sizeof(struct hbm_client_connect_response);
433
434         list_for_each_entry_safe(pos, next, &dev->file_list, link) {
435                 if (same_disconn_addr(pos, disconnect_req)) {
436                         dev_dbg(&dev->pdev->dev, "disconnect request host client %d ME client %d.\n",
437                                         disconnect_req->host_addr,
438                                         disconnect_req->me_addr);
439                         pos->state = MEI_FILE_DISCONNECTED;
440                         pos->timer_count = 0;
441                         if (pos == &dev->wd_cl)
442                                 dev->wd_pending = false;
443                         else if (pos == &dev->iamthif_cl)
444                                 dev->iamthif_timer = 0;
445
446                         /* prepare disconnect response */
447                         (void)mei_hbm_hdr((u32 *)&dev->wr_ext_msg.hdr, len);
448                         disconnect_res =
449                                 (struct hbm_client_connect_response *)
450                                 &dev->wr_ext_msg.data;
451                         disconnect_res->hbm_cmd = CLIENT_DISCONNECT_RES_CMD;
452                         disconnect_res->host_addr = pos->host_client_id;
453                         disconnect_res->me_addr = pos->me_client_id;
454                         disconnect_res->status = 0;
455                         break;
456                 }
457         }
458 }
459
460 /**
461  * mei_irq_thread_read_bus_message - bottom half read routine after ISR to
462  * handle the read bus message cmd processing.
463  *
464  * @dev: the device structure
465  * @mei_hdr: header of bus message
466  */
467 static void mei_irq_thread_read_bus_message(struct mei_device *dev,
468                 struct mei_msg_hdr *mei_hdr)
469 {
470         struct mei_bus_message *mei_msg;
471         struct mei_me_client *me_client;
472         struct hbm_host_version_response *version_res;
473         struct hbm_client_connect_response *connect_res;
474         struct hbm_client_connect_response *disconnect_res;
475         struct hbm_client_connect_request *disconnect_req;
476         struct hbm_flow_control *flow_control;
477         struct hbm_props_response *props_res;
478         struct hbm_host_enum_response *enum_res;
479         struct hbm_host_stop_request *stop_req;
480
481         /* read the message to our buffer */
482         BUG_ON(mei_hdr->length >= sizeof(dev->rd_msg_buf));
483         mei_read_slots(dev, dev->rd_msg_buf, mei_hdr->length);
484         mei_msg = (struct mei_bus_message *)dev->rd_msg_buf;
485
486         switch (mei_msg->hbm_cmd) {
487         case HOST_START_RES_CMD:
488                 version_res = (struct hbm_host_version_response *) mei_msg;
489                 if (version_res->host_version_supported) {
490                         dev->version.major_version = HBM_MAJOR_VERSION;
491                         dev->version.minor_version = HBM_MINOR_VERSION;
492                         if (dev->dev_state == MEI_DEV_INIT_CLIENTS &&
493                             dev->init_clients_state == MEI_START_MESSAGE) {
494                                 dev->init_clients_timer = 0;
495                                 mei_host_enum_clients_message(dev);
496                         } else {
497                                 dev->recvd_msg = false;
498                                 dev_dbg(&dev->pdev->dev, "IMEI reset due to received host start response bus message.\n");
499                                 mei_reset(dev, 1);
500                                 return;
501                         }
502                 } else {
503                         u32 *buf = dev->wr_msg_buf;
504                         const size_t len = sizeof(struct hbm_host_stop_request);
505
506                         dev->version = version_res->me_max_version;
507
508                         /* send stop message */
509                         mei_hdr = mei_hbm_hdr(&buf[0], len);
510                         stop_req = (struct hbm_host_stop_request *)&buf[1];
511                         memset(stop_req, 0, len);
512                         stop_req->hbm_cmd = HOST_STOP_REQ_CMD;
513                         stop_req->reason = DRIVER_STOP_REQUEST;
514
515                         mei_write_message(dev, mei_hdr,
516                                         (unsigned char *)stop_req, len);
517                         dev_dbg(&dev->pdev->dev, "version mismatch.\n");
518                         return;
519                 }
520
521                 dev->recvd_msg = true;
522                 dev_dbg(&dev->pdev->dev, "host start response message received.\n");
523                 break;
524
525         case CLIENT_CONNECT_RES_CMD:
526                 connect_res = (struct hbm_client_connect_response *) mei_msg;
527                 mei_client_connect_response(dev, connect_res);
528                 dev_dbg(&dev->pdev->dev, "client connect response message received.\n");
529                 wake_up(&dev->wait_recvd_msg);
530                 break;
531
532         case CLIENT_DISCONNECT_RES_CMD:
533                 disconnect_res = (struct hbm_client_connect_response *) mei_msg;
534                 mei_client_disconnect_response(dev, disconnect_res);
535                 dev_dbg(&dev->pdev->dev, "client disconnect response message received.\n");
536                 wake_up(&dev->wait_recvd_msg);
537                 break;
538
539         case MEI_FLOW_CONTROL_CMD:
540                 flow_control = (struct hbm_flow_control *) mei_msg;
541                 mei_client_flow_control_response(dev, flow_control);
542                 dev_dbg(&dev->pdev->dev, "client flow control response message received.\n");
543                 break;
544
545         case HOST_CLIENT_PROPERTIES_RES_CMD:
546                 props_res = (struct hbm_props_response *)mei_msg;
547                 me_client = &dev->me_clients[dev->me_client_presentation_num];
548
549                 if (props_res->status || !dev->me_clients) {
550                         dev_dbg(&dev->pdev->dev, "reset due to received host client properties response bus message wrong status.\n");
551                         mei_reset(dev, 1);
552                         return;
553                 }
554
555                 if (me_client->client_id != props_res->address) {
556                         dev_err(&dev->pdev->dev,
557                                 "Host client properties reply mismatch\n");
558                         mei_reset(dev, 1);
559
560                         return;
561                 }
562
563                 if (dev->dev_state != MEI_DEV_INIT_CLIENTS ||
564                     dev->init_clients_state != MEI_CLIENT_PROPERTIES_MESSAGE) {
565                         dev_err(&dev->pdev->dev,
566                                 "Unexpected client properties reply\n");
567                         mei_reset(dev, 1);
568
569                         return;
570                 }
571
572                 me_client->props = props_res->client_properties;
573                 dev->me_client_index++;
574                 dev->me_client_presentation_num++;
575
576                 mei_host_client_enumerate(dev);
577
578                 break;
579
580         case HOST_ENUM_RES_CMD:
581                 enum_res = (struct hbm_host_enum_response *) mei_msg;
582                 memcpy(dev->me_clients_map, enum_res->valid_addresses, 32);
583                 if (dev->dev_state == MEI_DEV_INIT_CLIENTS &&
584                     dev->init_clients_state == MEI_ENUM_CLIENTS_MESSAGE) {
585                                 dev->init_clients_timer = 0;
586                                 dev->me_client_presentation_num = 0;
587                                 dev->me_client_index = 0;
588                                 mei_allocate_me_clients_storage(dev);
589                                 dev->init_clients_state =
590                                         MEI_CLIENT_PROPERTIES_MESSAGE;
591
592                                 mei_host_client_enumerate(dev);
593                 } else {
594                         dev_dbg(&dev->pdev->dev, "reset due to received host enumeration clients response bus message.\n");
595                         mei_reset(dev, 1);
596                         return;
597                 }
598                 break;
599
600         case HOST_STOP_RES_CMD:
601                 dev->dev_state = MEI_DEV_DISABLED;
602                 dev_dbg(&dev->pdev->dev, "resetting because of FW stop response.\n");
603                 mei_reset(dev, 1);
604                 break;
605
606         case CLIENT_DISCONNECT_REQ_CMD:
607                 /* search for client */
608                 disconnect_req = (struct hbm_client_connect_request *)mei_msg;
609                 mei_client_disconnect_request(dev, disconnect_req);
610                 break;
611
612         case ME_STOP_REQ_CMD:
613         {
614                 /* prepare stop request: sent in next interrupt event */
615
616                 const size_t len = sizeof(struct hbm_host_stop_request);
617
618                 mei_hdr = mei_hbm_hdr((u32 *)&dev->wr_ext_msg.hdr, len);
619                 stop_req = (struct hbm_host_stop_request *)&dev->wr_ext_msg.data;
620                 memset(stop_req, 0, len);
621                 stop_req->hbm_cmd = HOST_STOP_REQ_CMD;
622                 stop_req->reason = DRIVER_STOP_REQUEST;
623                 break;
624         }
625         default:
626                 BUG();
627                 break;
628
629         }
630 }
631
632
633 /**
634  * _mei_hb_read - processes read related operation.
635  *
636  * @dev: the device structure.
637  * @slots: free slots.
638  * @cb_pos: callback block.
639  * @cl: private data of the file object.
640  * @cmpl_list: complete list.
641  *
642  * returns 0, OK; otherwise, error.
643  */
644 static int _mei_irq_thread_read(struct mei_device *dev, s32 *slots,
645                         struct mei_cl_cb *cb_pos,
646                         struct mei_cl *cl,
647                         struct mei_cl_cb *cmpl_list)
648 {
649         if ((*slots * sizeof(u32)) < (sizeof(struct mei_msg_hdr) +
650                         sizeof(struct hbm_flow_control))) {
651                 /* return the cancel routine */
652                 list_del(&cb_pos->list);
653                 return -EBADMSG;
654         }
655
656         *slots -= mei_data2slots(sizeof(struct hbm_flow_control));
657
658         if (mei_send_flow_control(dev, cl)) {
659                 cl->status = -ENODEV;
660                 cb_pos->buf_idx = 0;
661                 list_move_tail(&cb_pos->list, &cmpl_list->list);
662                 return -ENODEV;
663         }
664         list_move_tail(&cb_pos->list, &dev->read_list.list);
665
666         return 0;
667 }
668
669
670 /**
671  * _mei_irq_thread_ioctl - processes ioctl related operation.
672  *
673  * @dev: the device structure.
674  * @slots: free slots.
675  * @cb_pos: callback block.
676  * @cl: private data of the file object.
677  * @cmpl_list: complete list.
678  *
679  * returns 0, OK; otherwise, error.
680  */
681 static int _mei_irq_thread_ioctl(struct mei_device *dev, s32 *slots,
682                         struct mei_cl_cb *cb_pos,
683                         struct mei_cl *cl,
684                         struct mei_cl_cb *cmpl_list)
685 {
686         if ((*slots * sizeof(u32)) < (sizeof(struct mei_msg_hdr) +
687                         sizeof(struct hbm_client_connect_request))) {
688                 /* return the cancel routine */
689                 list_del(&cb_pos->list);
690                 return -EBADMSG;
691         }
692
693         cl->state = MEI_FILE_CONNECTING;
694          *slots -= mei_data2slots(sizeof(struct hbm_client_connect_request));
695         if (mei_connect(dev, cl)) {
696                 cl->status = -ENODEV;
697                 cb_pos->buf_idx = 0;
698                 list_del(&cb_pos->list);
699                 return -ENODEV;
700         } else {
701                 list_move_tail(&cb_pos->list, &dev->ctrl_rd_list.list);
702                 cl->timer_count = MEI_CONNECT_TIMEOUT;
703         }
704         return 0;
705 }
706
707 /**
708  * mei_irq_thread_write_complete - write messages to device.
709  *
710  * @dev: the device structure.
711  * @slots: free slots.
712  * @cb: callback block.
713  * @cmpl_list: complete list.
714  *
715  * returns 0, OK; otherwise, error.
716  */
717 static int mei_irq_thread_write_complete(struct mei_device *dev, s32 *slots,
718                         struct mei_cl_cb *cb, struct mei_cl_cb *cmpl_list)
719 {
720         struct mei_msg_hdr *mei_hdr;
721         struct mei_cl *cl = cb->cl;
722         size_t len = cb->request_buffer.size - cb->buf_idx;
723         size_t msg_slots = mei_data2slots(len);
724
725         mei_hdr = (struct mei_msg_hdr *)&dev->wr_msg_buf[0];
726         mei_hdr->host_addr = cl->host_client_id;
727         mei_hdr->me_addr = cl->me_client_id;
728         mei_hdr->reserved = 0;
729
730         if (*slots >= msg_slots) {
731                 mei_hdr->length = len;
732                 mei_hdr->msg_complete = 1;
733         /* Split the message only if we can write the whole host buffer */
734         } else if (*slots == dev->hbuf_depth) {
735                 msg_slots = *slots;
736                 len = (*slots * sizeof(u32)) - sizeof(struct mei_msg_hdr);
737                 mei_hdr->length = len;
738                 mei_hdr->msg_complete = 0;
739         } else {
740                 /* wait for next time the host buffer is empty */
741                 return 0;
742         }
743
744         dev_dbg(&dev->pdev->dev, "buf: size = %d idx = %lu\n",
745                         cb->request_buffer.size, cb->buf_idx);
746         dev_dbg(&dev->pdev->dev, "msg: len = %d complete = %d\n",
747                         mei_hdr->length, mei_hdr->msg_complete);
748
749         *slots -=  msg_slots;
750         if (mei_write_message(dev, mei_hdr,
751                 cb->request_buffer.data + cb->buf_idx, len)) {
752                 cl->status = -ENODEV;
753                 list_move_tail(&cb->list, &cmpl_list->list);
754                 return -ENODEV;
755         }
756
757         if (mei_flow_ctrl_reduce(dev, cl))
758                 return -ENODEV;
759
760         cl->status = 0;
761         cb->buf_idx += mei_hdr->length;
762         if (mei_hdr->msg_complete)
763                 list_move_tail(&cb->list, &dev->write_waiting_list.list);
764
765         return 0;
766 }
767
768 /**
769  * mei_irq_thread_read_handler - bottom half read routine after ISR to
770  * handle the read processing.
771  *
772  * @cmpl_list: An instance of our list structure
773  * @dev: the device structure
774  * @slots: slots to read.
775  *
776  * returns 0 on success, <0 on failure.
777  */
778 static int mei_irq_thread_read_handler(struct mei_cl_cb *cmpl_list,
779                 struct mei_device *dev,
780                 s32 *slots)
781 {
782         struct mei_msg_hdr *mei_hdr;
783         struct mei_cl *cl_pos = NULL;
784         struct mei_cl *cl_next = NULL;
785         int ret = 0;
786
787         if (!dev->rd_msg_hdr) {
788                 dev->rd_msg_hdr = mei_mecbrw_read(dev);
789                 dev_dbg(&dev->pdev->dev, "slots =%08x.\n", *slots);
790                 (*slots)--;
791                 dev_dbg(&dev->pdev->dev, "slots =%08x.\n", *slots);
792         }
793         mei_hdr = (struct mei_msg_hdr *) &dev->rd_msg_hdr;
794         dev_dbg(&dev->pdev->dev, "mei_hdr->length =%d\n", mei_hdr->length);
795
796         if (mei_hdr->reserved || !dev->rd_msg_hdr) {
797                 dev_dbg(&dev->pdev->dev, "corrupted message header.\n");
798                 ret = -EBADMSG;
799                 goto end;
800         }
801
802         if (mei_hdr->host_addr || mei_hdr->me_addr) {
803                 list_for_each_entry_safe(cl_pos, cl_next,
804                                         &dev->file_list, link) {
805                         dev_dbg(&dev->pdev->dev,
806                                         "list_for_each_entry_safe read host"
807                                         " client = %d, ME client = %d\n",
808                                         cl_pos->host_client_id,
809                                         cl_pos->me_client_id);
810                         if (cl_pos->host_client_id == mei_hdr->host_addr &&
811                             cl_pos->me_client_id == mei_hdr->me_addr)
812                                 break;
813                 }
814
815                 if (&cl_pos->link == &dev->file_list) {
816                         dev_dbg(&dev->pdev->dev, "corrupted message header\n");
817                         ret = -EBADMSG;
818                         goto end;
819                 }
820         }
821         if (((*slots) * sizeof(u32)) < mei_hdr->length) {
822                 dev_dbg(&dev->pdev->dev,
823                                 "we can't read the message slots =%08x.\n",
824                                 *slots);
825                 /* we can't read the message */
826                 ret = -ERANGE;
827                 goto end;
828         }
829
830         /* decide where to read the message too */
831         if (!mei_hdr->host_addr) {
832                 dev_dbg(&dev->pdev->dev, "call mei_irq_thread_read_bus_message.\n");
833                 mei_irq_thread_read_bus_message(dev, mei_hdr);
834                 dev_dbg(&dev->pdev->dev, "end mei_irq_thread_read_bus_message.\n");
835         } else if (mei_hdr->host_addr == dev->iamthif_cl.host_client_id &&
836                    (MEI_FILE_CONNECTED == dev->iamthif_cl.state) &&
837                    (dev->iamthif_state == MEI_IAMTHIF_READING)) {
838                 dev_dbg(&dev->pdev->dev, "call mei_irq_thread_read_iamthif_message.\n");
839                 dev_dbg(&dev->pdev->dev, "mei_hdr->length =%d\n",
840                                 mei_hdr->length);
841
842                 ret = mei_amthif_irq_read_message(cmpl_list, dev, mei_hdr);
843                 if (ret)
844                         goto end;
845
846         } else {
847                 dev_dbg(&dev->pdev->dev, "call mei_irq_thread_read_client_message.\n");
848                 ret = mei_irq_thread_read_client_message(cmpl_list,
849                                                          dev, mei_hdr);
850                 if (ret)
851                         goto end;
852
853         }
854
855         /* reset the number of slots and header */
856         *slots = mei_count_full_read_slots(dev);
857         dev->rd_msg_hdr = 0;
858
859         if (*slots == -EOVERFLOW) {
860                 /* overflow - reset */
861                 dev_dbg(&dev->pdev->dev, "resetting due to slots overflow.\n");
862                 /* set the event since message has been read */
863                 ret = -ERANGE;
864                 goto end;
865         }
866 end:
867         return ret;
868 }
869
870
871 /**
872  * mei_irq_thread_write_handler - bottom half write routine after
873  * ISR to handle the write processing.
874  *
875  * @dev: the device structure
876  * @cmpl_list: An instance of our list structure
877  *
878  * returns 0 on success, <0 on failure.
879  */
880 static int mei_irq_thread_write_handler(struct mei_device *dev,
881                                 struct mei_cl_cb *cmpl_list)
882 {
883
884         struct mei_cl *cl;
885         struct mei_cl_cb *pos = NULL, *next = NULL;
886         struct mei_cl_cb *list;
887         s32 slots;
888         int ret;
889
890         if (!mei_hbuf_is_empty(dev)) {
891                 dev_dbg(&dev->pdev->dev, "host buffer is not empty.\n");
892                 return 0;
893         }
894         slots = mei_hbuf_empty_slots(dev);
895         if (slots <= 0)
896                 return -EMSGSIZE;
897
898         /* complete all waiting for write CB */
899         dev_dbg(&dev->pdev->dev, "complete all waiting for write cb.\n");
900
901         list = &dev->write_waiting_list;
902         list_for_each_entry_safe(pos, next, &list->list, list) {
903                 cl = pos->cl;
904                 if (cl == NULL)
905                         continue;
906
907                 cl->status = 0;
908                 list_del(&pos->list);
909                 if (MEI_WRITING == cl->writing_state &&
910                     pos->fop_type == MEI_FOP_WRITE &&
911                     cl != &dev->iamthif_cl) {
912                         dev_dbg(&dev->pdev->dev, "MEI WRITE COMPLETE\n");
913                         cl->writing_state = MEI_WRITE_COMPLETE;
914                         list_add_tail(&pos->list, &cmpl_list->list);
915                 }
916                 if (cl == &dev->iamthif_cl) {
917                         dev_dbg(&dev->pdev->dev, "check iamthif flow control.\n");
918                         if (dev->iamthif_flow_control_pending) {
919                                 ret = mei_amthif_irq_read(dev, &slots);
920                                 if (ret)
921                                         return ret;
922                         }
923                 }
924         }
925
926         if (dev->wd_state == MEI_WD_STOPPING) {
927                 dev->wd_state = MEI_WD_IDLE;
928                 wake_up_interruptible(&dev->wait_stop_wd);
929         }
930
931         if (dev->wr_ext_msg.hdr.length) {
932                 mei_write_message(dev, &dev->wr_ext_msg.hdr,
933                         dev->wr_ext_msg.data, dev->wr_ext_msg.hdr.length);
934                 slots -= mei_data2slots(dev->wr_ext_msg.hdr.length);
935                 dev->wr_ext_msg.hdr.length = 0;
936         }
937         if (dev->dev_state == MEI_DEV_ENABLED) {
938                 if (dev->wd_pending &&
939                     mei_flow_ctrl_creds(dev, &dev->wd_cl) > 0) {
940                         if (mei_wd_send(dev))
941                                 dev_dbg(&dev->pdev->dev, "wd send failed.\n");
942                         else if (mei_flow_ctrl_reduce(dev, &dev->wd_cl))
943                                 return -ENODEV;
944
945                         dev->wd_pending = false;
946
947                         if (dev->wd_state == MEI_WD_RUNNING)
948                                 slots -= mei_data2slots(MEI_WD_START_MSG_SIZE);
949                         else
950                                 slots -= mei_data2slots(MEI_WD_STOP_MSG_SIZE);
951                 }
952         }
953
954         /* complete control write list CB */
955         dev_dbg(&dev->pdev->dev, "complete control write list cb.\n");
956         list_for_each_entry_safe(pos, next, &dev->ctrl_wr_list.list, list) {
957                 cl = pos->cl;
958                 if (!cl) {
959                         list_del(&pos->list);
960                         return -ENODEV;
961                 }
962                 switch (pos->fop_type) {
963                 case MEI_FOP_CLOSE:
964                         /* send disconnect message */
965                         ret = _mei_irq_thread_close(dev, &slots, pos,
966                                                 cl, cmpl_list);
967                         if (ret)
968                                 return ret;
969
970                         break;
971                 case MEI_FOP_READ:
972                         /* send flow control message */
973                         ret = _mei_irq_thread_read(dev, &slots, pos,
974                                                 cl, cmpl_list);
975                         if (ret)
976                                 return ret;
977
978                         break;
979                 case MEI_FOP_IOCTL:
980                         /* connect message */
981                         if (mei_other_client_is_connecting(dev, cl))
982                                 continue;
983                         ret = _mei_irq_thread_ioctl(dev, &slots, pos,
984                                                 cl, cmpl_list);
985                         if (ret)
986                                 return ret;
987
988                         break;
989
990                 default:
991                         BUG();
992                 }
993
994         }
995         /* complete  write list CB */
996         dev_dbg(&dev->pdev->dev, "complete write list cb.\n");
997         list_for_each_entry_safe(pos, next, &dev->write_list.list, list) {
998                 cl = pos->cl;
999                 if (cl == NULL)
1000                         continue;
1001                 if (mei_flow_ctrl_creds(dev, cl) <= 0) {
1002                         dev_dbg(&dev->pdev->dev,
1003                                 "No flow control credentials for client %d, not sending.\n",
1004                                 cl->host_client_id);
1005                         continue;
1006                 }
1007
1008                 if (cl == &dev->iamthif_cl)
1009                         ret = mei_amthif_irq_write_complete(dev, &slots,
1010                                                         pos, cmpl_list);
1011                 else
1012                         ret = mei_irq_thread_write_complete(dev, &slots, pos,
1013                                                 cmpl_list);
1014                 if (ret)
1015                         return ret;
1016
1017         }
1018         return 0;
1019 }
1020
1021
1022
1023 /**
1024  * mei_timer - timer function.
1025  *
1026  * @work: pointer to the work_struct structure
1027  *
1028  * NOTE: This function is called by timer interrupt work
1029  */
1030 void mei_timer(struct work_struct *work)
1031 {
1032         unsigned long timeout;
1033         struct mei_cl *cl_pos = NULL;
1034         struct mei_cl *cl_next = NULL;
1035         struct mei_cl_cb  *cb_pos = NULL;
1036         struct mei_cl_cb  *cb_next = NULL;
1037
1038         struct mei_device *dev = container_of(work,
1039                                         struct mei_device, timer_work.work);
1040
1041
1042         mutex_lock(&dev->device_lock);
1043         if (dev->dev_state != MEI_DEV_ENABLED) {
1044                 if (dev->dev_state == MEI_DEV_INIT_CLIENTS) {
1045                         if (dev->init_clients_timer) {
1046                                 if (--dev->init_clients_timer == 0) {
1047                                         dev_dbg(&dev->pdev->dev, "IMEI reset due to init clients timeout ,init clients state = %d.\n",
1048                                                 dev->init_clients_state);
1049                                         mei_reset(dev, 1);
1050                                 }
1051                         }
1052                 }
1053                 goto out;
1054         }
1055         /*** connect/disconnect timeouts ***/
1056         list_for_each_entry_safe(cl_pos, cl_next, &dev->file_list, link) {
1057                 if (cl_pos->timer_count) {
1058                         if (--cl_pos->timer_count == 0) {
1059                                 dev_dbg(&dev->pdev->dev, "HECI reset due to connect/disconnect timeout.\n");
1060                                 mei_reset(dev, 1);
1061                                 goto out;
1062                         }
1063                 }
1064         }
1065
1066         if (dev->iamthif_stall_timer) {
1067                 if (--dev->iamthif_stall_timer == 0) {
1068                         dev_dbg(&dev->pdev->dev, "resetting because of hang to amthi.\n");
1069                         mei_reset(dev, 1);
1070                         dev->iamthif_msg_buf_size = 0;
1071                         dev->iamthif_msg_buf_index = 0;
1072                         dev->iamthif_canceled = false;
1073                         dev->iamthif_ioctl = true;
1074                         dev->iamthif_state = MEI_IAMTHIF_IDLE;
1075                         dev->iamthif_timer = 0;
1076
1077                         mei_io_cb_free(dev->iamthif_current_cb);
1078                         dev->iamthif_current_cb = NULL;
1079
1080                         dev->iamthif_file_object = NULL;
1081                         mei_amthif_run_next_cmd(dev);
1082                 }
1083         }
1084
1085         if (dev->iamthif_timer) {
1086
1087                 timeout = dev->iamthif_timer +
1088                         mei_secs_to_jiffies(MEI_IAMTHIF_READ_TIMER);
1089
1090                 dev_dbg(&dev->pdev->dev, "dev->iamthif_timer = %ld\n",
1091                                 dev->iamthif_timer);
1092                 dev_dbg(&dev->pdev->dev, "timeout = %ld\n", timeout);
1093                 dev_dbg(&dev->pdev->dev, "jiffies = %ld\n", jiffies);
1094                 if (time_after(jiffies, timeout)) {
1095                         /*
1096                          * User didn't read the AMTHI data on time (15sec)
1097                          * freeing AMTHI for other requests
1098                          */
1099
1100                         dev_dbg(&dev->pdev->dev, "freeing AMTHI for other requests\n");
1101
1102                         list_for_each_entry_safe(cb_pos, cb_next,
1103                                 &dev->amthif_rd_complete_list.list, list) {
1104
1105                                 cl_pos = cb_pos->file_object->private_data;
1106
1107                                 /* Finding the AMTHI entry. */
1108                                 if (cl_pos == &dev->iamthif_cl)
1109                                         list_del(&cb_pos->list);
1110                         }
1111                         mei_io_cb_free(dev->iamthif_current_cb);
1112                         dev->iamthif_current_cb = NULL;
1113
1114                         dev->iamthif_file_object->private_data = NULL;
1115                         dev->iamthif_file_object = NULL;
1116                         dev->iamthif_timer = 0;
1117                         mei_amthif_run_next_cmd(dev);
1118
1119                 }
1120         }
1121 out:
1122         schedule_delayed_work(&dev->timer_work, 2 * HZ);
1123         mutex_unlock(&dev->device_lock);
1124 }
1125
1126 /**
1127  *  mei_interrupt_thread_handler - function called after ISR to handle the interrupt
1128  * processing.
1129  *
1130  * @irq: The irq number
1131  * @dev_id: pointer to the device structure
1132  *
1133  * returns irqreturn_t
1134  *
1135  */
1136 irqreturn_t mei_interrupt_thread_handler(int irq, void *dev_id)
1137 {
1138         struct mei_device *dev = (struct mei_device *) dev_id;
1139         struct mei_cl_cb complete_list;
1140         struct mei_cl_cb *cb_pos = NULL, *cb_next = NULL;
1141         struct mei_cl *cl;
1142         s32 slots;
1143         int rets;
1144         bool  bus_message_received;
1145
1146
1147         dev_dbg(&dev->pdev->dev, "function called after ISR to handle the interrupt processing.\n");
1148         /* initialize our complete list */
1149         mutex_lock(&dev->device_lock);
1150         mei_io_list_init(&complete_list);
1151         dev->host_hw_state = mei_hcsr_read(dev);
1152
1153         /* Ack the interrupt here
1154          * In case of MSI we don't go through the quick handler */
1155         if (pci_dev_msi_enabled(dev->pdev))
1156                 mei_reg_write(dev, H_CSR, dev->host_hw_state);
1157
1158         dev->me_hw_state = mei_mecsr_read(dev);
1159
1160         /* check if ME wants a reset */
1161         if ((dev->me_hw_state & ME_RDY_HRA) == 0 &&
1162             dev->dev_state != MEI_DEV_RESETING &&
1163             dev->dev_state != MEI_DEV_INITIALIZING) {
1164                 dev_dbg(&dev->pdev->dev, "FW not ready.\n");
1165                 mei_reset(dev, 1);
1166                 mutex_unlock(&dev->device_lock);
1167                 return IRQ_HANDLED;
1168         }
1169
1170         /*  check if we need to start the dev */
1171         if ((dev->host_hw_state & H_RDY) == 0) {
1172                 if ((dev->me_hw_state & ME_RDY_HRA) == ME_RDY_HRA) {
1173                         dev_dbg(&dev->pdev->dev, "we need to start the dev.\n");
1174                         dev->host_hw_state |= (H_IE | H_IG | H_RDY);
1175                         mei_hcsr_set(dev);
1176                         dev->dev_state = MEI_DEV_INIT_CLIENTS;
1177                         dev_dbg(&dev->pdev->dev, "link is established start sending messages.\n");
1178                         /* link is established
1179                          * start sending messages.
1180                          */
1181                         mei_host_start_message(dev);
1182                         mutex_unlock(&dev->device_lock);
1183                         return IRQ_HANDLED;
1184                 } else {
1185                         dev_dbg(&dev->pdev->dev, "FW not ready.\n");
1186                         mutex_unlock(&dev->device_lock);
1187                         return IRQ_HANDLED;
1188                 }
1189         }
1190         /* check slots available for reading */
1191         slots = mei_count_full_read_slots(dev);
1192         while (slots > 0) {
1193                 /* we have urgent data to send so break the read */
1194                 if (dev->wr_ext_msg.hdr.length)
1195                         break;
1196                 dev_dbg(&dev->pdev->dev, "slots =%08x\n", slots);
1197                 dev_dbg(&dev->pdev->dev, "call mei_irq_thread_read_handler.\n");
1198                 rets = mei_irq_thread_read_handler(&complete_list, dev, &slots);
1199                 if (rets)
1200                         goto end;
1201         }
1202         rets = mei_irq_thread_write_handler(dev, &complete_list);
1203 end:
1204         dev_dbg(&dev->pdev->dev, "end of bottom half function.\n");
1205         dev->host_hw_state = mei_hcsr_read(dev);
1206         dev->mei_host_buffer_is_empty = mei_hbuf_is_empty(dev);
1207
1208         bus_message_received = false;
1209         if (dev->recvd_msg && waitqueue_active(&dev->wait_recvd_msg)) {
1210                 dev_dbg(&dev->pdev->dev, "received waiting bus message\n");
1211                 bus_message_received = true;
1212         }
1213         mutex_unlock(&dev->device_lock);
1214         if (bus_message_received) {
1215                 dev_dbg(&dev->pdev->dev, "wake up dev->wait_recvd_msg\n");
1216                 wake_up_interruptible(&dev->wait_recvd_msg);
1217                 bus_message_received = false;
1218         }
1219         if (list_empty(&complete_list.list))
1220                 return IRQ_HANDLED;
1221
1222
1223         list_for_each_entry_safe(cb_pos, cb_next, &complete_list.list, list) {
1224                 cl = cb_pos->cl;
1225                 list_del(&cb_pos->list);
1226                 if (cl) {
1227                         if (cl != &dev->iamthif_cl) {
1228                                 dev_dbg(&dev->pdev->dev, "completing call back.\n");
1229                                 _mei_cmpl(cl, cb_pos);
1230                                 cb_pos = NULL;
1231                         } else if (cl == &dev->iamthif_cl) {
1232                                 mei_amthif_complete(dev, cb_pos);
1233                         }
1234                 }
1235         }
1236         return IRQ_HANDLED;
1237 }