~ubuntu-branches/ubuntu/quantal/linux-linaro-mx51/quantal

« back to all changes in this revision

Viewing changes to drivers/staging/mei/interrupt.c

  • Committer: Package Import Robot
  • Author(s): John Rigby, John Rigby
  • Date: 2011-09-26 10:44:23 UTC
  • Revision ID: package-import@ubuntu.com-20110926104423-3o58a3c1bj7x00rs
Tags: 3.0.0-1007.9
[ John Rigby ]

Enable crypto modules and remove crypto-modules from
exclude-module files
LP: #826021

Show diffs side-by-side

added added

removed removed

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