aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc/mei/interrupt.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/misc/mei/interrupt.c')
-rw-r--r--drivers/misc/mei/interrupt.c205
1 files changed, 58 insertions, 147 deletions
diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c
index 2ad736989410..4b59cb742dee 100644
--- a/drivers/misc/mei/interrupt.c
+++ b/drivers/misc/mei/interrupt.c
@@ -31,32 +31,6 @@
31 31
32 32
33/** 33/**
34 * mei_cl_complete_handler - processes completed operation for a client
35 *
36 * @cl: private data of the file object.
37 * @cb: callback block.
38 */
39static void mei_cl_complete_handler(struct mei_cl *cl, struct mei_cl_cb *cb)
40{
41 if (cb->fop_type == MEI_FOP_WRITE) {
42 mei_io_cb_free(cb);
43 cb = NULL;
44 cl->writing_state = MEI_WRITE_COMPLETE;
45 if (waitqueue_active(&cl->tx_wait))
46 wake_up_interruptible(&cl->tx_wait);
47
48 } else if (cb->fop_type == MEI_FOP_READ &&
49 MEI_READING == cl->reading_state) {
50 cl->reading_state = MEI_READ_COMPLETE;
51 if (waitqueue_active(&cl->rx_wait))
52 wake_up_interruptible(&cl->rx_wait);
53 else
54 mei_cl_bus_rx_event(cl);
55
56 }
57}
58
59/**
60 * mei_irq_compl_handler - dispatch complete handelers 34 * mei_irq_compl_handler - dispatch complete handelers
61 * for the completed callbacks 35 * for the completed callbacks
62 * 36 *
@@ -78,7 +52,7 @@ void mei_irq_compl_handler(struct mei_device *dev, struct mei_cl_cb *compl_list)
78 if (cl == &dev->iamthif_cl) 52 if (cl == &dev->iamthif_cl)
79 mei_amthif_complete(dev, cb); 53 mei_amthif_complete(dev, cb);
80 else 54 else
81 mei_cl_complete_handler(cl, cb); 55 mei_cl_complete(cl, cb);
82 } 56 }
83} 57}
84EXPORT_SYMBOL_GPL(mei_irq_compl_handler); 58EXPORT_SYMBOL_GPL(mei_irq_compl_handler);
@@ -189,21 +163,21 @@ static int mei_cl_irq_read_msg(struct mei_device *dev,
189} 163}
190 164
191/** 165/**
192 * _mei_irq_thread_close - processes close related operation. 166 * mei_cl_irq_close - processes close related operation from
167 * interrupt thread context - send disconnect request
193 * 168 *
194 * @dev: the device structure. 169 * @cl: client
170 * @cb: callback block.
195 * @slots: free slots. 171 * @slots: free slots.
196 * @cb_pos: callback block.
197 * @cl: private data of the file object.
198 * @cmpl_list: complete list. 172 * @cmpl_list: complete list.
199 * 173 *
200 * returns 0, OK; otherwise, error. 174 * returns 0, OK; otherwise, error.
201 */ 175 */
202static int _mei_irq_thread_close(struct mei_device *dev, s32 *slots, 176static int mei_cl_irq_close(struct mei_cl *cl, struct mei_cl_cb *cb,
203 struct mei_cl_cb *cb_pos, 177 s32 *slots, struct mei_cl_cb *cmpl_list)
204 struct mei_cl *cl,
205 struct mei_cl_cb *cmpl_list)
206{ 178{
179 struct mei_device *dev = cl->dev;
180
207 u32 msg_slots = 181 u32 msg_slots =
208 mei_data2slots(sizeof(struct hbm_client_connect_request)); 182 mei_data2slots(sizeof(struct hbm_client_connect_request));
209 183
@@ -214,15 +188,15 @@ static int _mei_irq_thread_close(struct mei_device *dev, s32 *slots,
214 188
215 if (mei_hbm_cl_disconnect_req(dev, cl)) { 189 if (mei_hbm_cl_disconnect_req(dev, cl)) {
216 cl->status = 0; 190 cl->status = 0;
217 cb_pos->buf_idx = 0; 191 cb->buf_idx = 0;
218 list_move_tail(&cb_pos->list, &cmpl_list->list); 192 list_move_tail(&cb->list, &cmpl_list->list);
219 return -EIO; 193 return -EIO;
220 } 194 }
221 195
222 cl->state = MEI_FILE_DISCONNECTING; 196 cl->state = MEI_FILE_DISCONNECTING;
223 cl->status = 0; 197 cl->status = 0;
224 cb_pos->buf_idx = 0; 198 cb->buf_idx = 0;
225 list_move_tail(&cb_pos->list, &dev->ctrl_rd_list.list); 199 list_move_tail(&cb->list, &dev->ctrl_rd_list.list);
226 cl->timer_count = MEI_CONNECT_TIMEOUT; 200 cl->timer_count = MEI_CONNECT_TIMEOUT;
227 201
228 return 0; 202 return 0;
@@ -230,26 +204,26 @@ static int _mei_irq_thread_close(struct mei_device *dev, s32 *slots,
230 204
231 205
232/** 206/**
233 * _mei_irq_thread_read - processes read related operation. 207 * mei_cl_irq_close - processes client read related operation from the
208 * interrupt thread context - request for flow control credits
234 * 209 *
235 * @dev: the device structure. 210 * @cl: client
211 * @cb: callback block.
236 * @slots: free slots. 212 * @slots: free slots.
237 * @cb_pos: callback block.
238 * @cl: private data of the file object.
239 * @cmpl_list: complete list. 213 * @cmpl_list: complete list.
240 * 214 *
241 * returns 0, OK; otherwise, error. 215 * returns 0, OK; otherwise, error.
242 */ 216 */
243static int _mei_irq_thread_read(struct mei_device *dev, s32 *slots, 217static int mei_cl_irq_read(struct mei_cl *cl, struct mei_cl_cb *cb,
244 struct mei_cl_cb *cb_pos, 218 s32 *slots, struct mei_cl_cb *cmpl_list)
245 struct mei_cl *cl,
246 struct mei_cl_cb *cmpl_list)
247{ 219{
220 struct mei_device *dev = cl->dev;
221
248 u32 msg_slots = mei_data2slots(sizeof(struct hbm_flow_control)); 222 u32 msg_slots = mei_data2slots(sizeof(struct hbm_flow_control));
249 223
250 if (*slots < msg_slots) { 224 if (*slots < msg_slots) {
251 /* return the cancel routine */ 225 /* return the cancel routine */
252 list_del(&cb_pos->list); 226 list_del(&cb->list);
253 return -EMSGSIZE; 227 return -EMSGSIZE;
254 } 228 }
255 229
@@ -257,38 +231,38 @@ static int _mei_irq_thread_read(struct mei_device *dev, s32 *slots,
257 231
258 if (mei_hbm_cl_flow_control_req(dev, cl)) { 232 if (mei_hbm_cl_flow_control_req(dev, cl)) {
259 cl->status = -ENODEV; 233 cl->status = -ENODEV;
260 cb_pos->buf_idx = 0; 234 cb->buf_idx = 0;
261 list_move_tail(&cb_pos->list, &cmpl_list->list); 235 list_move_tail(&cb->list, &cmpl_list->list);
262 return -ENODEV; 236 return -ENODEV;
263 } 237 }
264 list_move_tail(&cb_pos->list, &dev->read_list.list); 238 list_move_tail(&cb->list, &dev->read_list.list);
265 239
266 return 0; 240 return 0;
267} 241}
268 242
269 243
270/** 244/**
271 * _mei_irq_thread_ioctl - processes ioctl related operation. 245 * mei_cl_irq_ioctl - processes client ioctl related operation from the
246 * interrupt thread context - send connection request
272 * 247 *
273 * @dev: the device structure. 248 * @cl: client
249 * @cb: callback block.
274 * @slots: free slots. 250 * @slots: free slots.
275 * @cb_pos: callback block.
276 * @cl: private data of the file object.
277 * @cmpl_list: complete list. 251 * @cmpl_list: complete list.
278 * 252 *
279 * returns 0, OK; otherwise, error. 253 * returns 0, OK; otherwise, error.
280 */ 254 */
281static int _mei_irq_thread_ioctl(struct mei_device *dev, s32 *slots, 255static int mei_cl_irq_ioctl(struct mei_cl *cl, struct mei_cl_cb *cb,
282 struct mei_cl_cb *cb_pos, 256 s32 *slots, struct mei_cl_cb *cmpl_list)
283 struct mei_cl *cl,
284 struct mei_cl_cb *cmpl_list)
285{ 257{
258 struct mei_device *dev = cl->dev;
259
286 u32 msg_slots = 260 u32 msg_slots =
287 mei_data2slots(sizeof(struct hbm_client_connect_request)); 261 mei_data2slots(sizeof(struct hbm_client_connect_request));
288 262
289 if (*slots < msg_slots) { 263 if (*slots < msg_slots) {
290 /* return the cancel routine */ 264 /* return the cancel routine */
291 list_del(&cb_pos->list); 265 list_del(&cb->list);
292 return -EMSGSIZE; 266 return -EMSGSIZE;
293 } 267 }
294 268
@@ -298,76 +272,17 @@ static int _mei_irq_thread_ioctl(struct mei_device *dev, s32 *slots,
298 272
299 if (mei_hbm_cl_connect_req(dev, cl)) { 273 if (mei_hbm_cl_connect_req(dev, cl)) {
300 cl->status = -ENODEV; 274 cl->status = -ENODEV;
301 cb_pos->buf_idx = 0; 275 cb->buf_idx = 0;
302 list_del(&cb_pos->list); 276 list_del(&cb->list);
303 return -ENODEV;
304 } else {
305 list_move_tail(&cb_pos->list, &dev->ctrl_rd_list.list);
306 cl->timer_count = MEI_CONNECT_TIMEOUT;
307 }
308 return 0;
309}
310
311/**
312 * mei_irq_thread_write_complete - write messages to device.
313 *
314 * @dev: the device structure.
315 * @slots: free slots.
316 * @cb: callback block.
317 * @cmpl_list: complete list.
318 *
319 * returns 0, OK; otherwise, error.
320 */
321static int mei_irq_thread_write_complete(struct mei_device *dev, s32 *slots,
322 struct mei_cl_cb *cb, struct mei_cl_cb *cmpl_list)
323{
324 struct mei_msg_hdr mei_hdr;
325 struct mei_cl *cl = cb->cl;
326 size_t len = cb->request_buffer.size - cb->buf_idx;
327 u32 msg_slots = mei_data2slots(len);
328
329 mei_hdr.host_addr = cl->host_client_id;
330 mei_hdr.me_addr = cl->me_client_id;
331 mei_hdr.reserved = 0;
332
333 if (*slots >= msg_slots) {
334 mei_hdr.length = len;
335 mei_hdr.msg_complete = 1;
336 /* Split the message only if we can write the whole host buffer */
337 } else if (*slots == dev->hbuf_depth) {
338 msg_slots = *slots;
339 len = (*slots * sizeof(u32)) - sizeof(struct mei_msg_hdr);
340 mei_hdr.length = len;
341 mei_hdr.msg_complete = 0;
342 } else {
343 /* wait for next time the host buffer is empty */
344 return 0;
345 }
346
347 dev_dbg(&dev->pdev->dev, "buf: size = %d idx = %lu\n",
348 cb->request_buffer.size, cb->buf_idx);
349 dev_dbg(&dev->pdev->dev, MEI_HDR_FMT, MEI_HDR_PRM(&mei_hdr));
350
351 *slots -= msg_slots;
352 if (mei_write_message(dev, &mei_hdr,
353 cb->request_buffer.data + cb->buf_idx)) {
354 cl->status = -ENODEV;
355 list_move_tail(&cb->list, &cmpl_list->list);
356 return -ENODEV; 277 return -ENODEV;
357 } 278 }
358 279
359 280 list_move_tail(&cb->list, &dev->ctrl_rd_list.list);
360 cl->status = 0; 281 cl->timer_count = MEI_CONNECT_TIMEOUT;
361 cb->buf_idx += mei_hdr.length;
362 if (mei_hdr.msg_complete) {
363 if (mei_cl_flow_ctrl_reduce(cl))
364 return -ENODEV;
365 list_move_tail(&cb->list, &dev->write_waiting_list.list);
366 }
367
368 return 0; 282 return 0;
369} 283}
370 284
285
371/** 286/**
372 * mei_irq_read_handler - bottom half read routine after ISR to 287 * mei_irq_read_handler - bottom half read routine after ISR to
373 * handle the read processing. 288 * handle the read processing.
@@ -481,7 +396,7 @@ int mei_irq_write_handler(struct mei_device *dev, struct mei_cl_cb *cmpl_list)
481{ 396{
482 397
483 struct mei_cl *cl; 398 struct mei_cl *cl;
484 struct mei_cl_cb *pos = NULL, *next = NULL; 399 struct mei_cl_cb *cb, *next;
485 struct mei_cl_cb *list; 400 struct mei_cl_cb *list;
486 s32 slots; 401 s32 slots;
487 int ret; 402 int ret;
@@ -498,19 +413,19 @@ int mei_irq_write_handler(struct mei_device *dev, struct mei_cl_cb *cmpl_list)
498 dev_dbg(&dev->pdev->dev, "complete all waiting for write cb.\n"); 413 dev_dbg(&dev->pdev->dev, "complete all waiting for write cb.\n");
499 414
500 list = &dev->write_waiting_list; 415 list = &dev->write_waiting_list;
501 list_for_each_entry_safe(pos, next, &list->list, list) { 416 list_for_each_entry_safe(cb, next, &list->list, list) {
502 cl = pos->cl; 417 cl = cb->cl;
503 if (cl == NULL) 418 if (cl == NULL)
504 continue; 419 continue;
505 420
506 cl->status = 0; 421 cl->status = 0;
507 list_del(&pos->list); 422 list_del(&cb->list);
508 if (MEI_WRITING == cl->writing_state && 423 if (MEI_WRITING == cl->writing_state &&
509 pos->fop_type == MEI_FOP_WRITE && 424 cb->fop_type == MEI_FOP_WRITE &&
510 cl != &dev->iamthif_cl) { 425 cl != &dev->iamthif_cl) {
511 dev_dbg(&dev->pdev->dev, "MEI WRITE COMPLETE\n"); 426 dev_dbg(&dev->pdev->dev, "MEI WRITE COMPLETE\n");
512 cl->writing_state = MEI_WRITE_COMPLETE; 427 cl->writing_state = MEI_WRITE_COMPLETE;
513 list_add_tail(&pos->list, &cmpl_list->list); 428 list_add_tail(&cb->list, &cmpl_list->list);
514 } 429 }
515 if (cl == &dev->iamthif_cl) { 430 if (cl == &dev->iamthif_cl) {
516 dev_dbg(&dev->pdev->dev, "check iamthif flow control.\n"); 431 dev_dbg(&dev->pdev->dev, "check iamthif flow control.\n");
@@ -552,25 +467,23 @@ int mei_irq_write_handler(struct mei_device *dev, struct mei_cl_cb *cmpl_list)
552 467
553 /* complete control write list CB */ 468 /* complete control write list CB */
554 dev_dbg(&dev->pdev->dev, "complete control write list cb.\n"); 469 dev_dbg(&dev->pdev->dev, "complete control write list cb.\n");
555 list_for_each_entry_safe(pos, next, &dev->ctrl_wr_list.list, list) { 470 list_for_each_entry_safe(cb, next, &dev->ctrl_wr_list.list, list) {
556 cl = pos->cl; 471 cl = cb->cl;
557 if (!cl) { 472 if (!cl) {
558 list_del(&pos->list); 473 list_del(&cb->list);
559 return -ENODEV; 474 return -ENODEV;
560 } 475 }
561 switch (pos->fop_type) { 476 switch (cb->fop_type) {
562 case MEI_FOP_CLOSE: 477 case MEI_FOP_CLOSE:
563 /* send disconnect message */ 478 /* send disconnect message */
564 ret = _mei_irq_thread_close(dev, &slots, pos, 479 ret = mei_cl_irq_close(cl, cb, &slots, cmpl_list);
565 cl, cmpl_list);
566 if (ret) 480 if (ret)
567 return ret; 481 return ret;
568 482
569 break; 483 break;
570 case MEI_FOP_READ: 484 case MEI_FOP_READ:
571 /* send flow control message */ 485 /* send flow control message */
572 ret = _mei_irq_thread_read(dev, &slots, pos, 486 ret = mei_cl_irq_read(cl, cb, &slots, cmpl_list);
573 cl, cmpl_list);
574 if (ret) 487 if (ret)
575 return ret; 488 return ret;
576 489
@@ -579,8 +492,7 @@ int mei_irq_write_handler(struct mei_device *dev, struct mei_cl_cb *cmpl_list)
579 /* connect message */ 492 /* connect message */
580 if (mei_cl_is_other_connecting(cl)) 493 if (mei_cl_is_other_connecting(cl))
581 continue; 494 continue;
582 ret = _mei_irq_thread_ioctl(dev, &slots, pos, 495 ret = mei_cl_irq_ioctl(cl, cb, &slots, cmpl_list);
583 cl, cmpl_list);
584 if (ret) 496 if (ret)
585 return ret; 497 return ret;
586 498
@@ -593,8 +505,8 @@ int mei_irq_write_handler(struct mei_device *dev, struct mei_cl_cb *cmpl_list)
593 } 505 }
594 /* complete write list CB */ 506 /* complete write list CB */
595 dev_dbg(&dev->pdev->dev, "complete write list cb.\n"); 507 dev_dbg(&dev->pdev->dev, "complete write list cb.\n");
596 list_for_each_entry_safe(pos, next, &dev->write_list.list, list) { 508 list_for_each_entry_safe(cb, next, &dev->write_list.list, list) {
597 cl = pos->cl; 509 cl = cb->cl;
598 if (cl == NULL) 510 if (cl == NULL)
599 continue; 511 continue;
600 if (mei_cl_flow_ctrl_creds(cl) <= 0) { 512 if (mei_cl_flow_ctrl_creds(cl) <= 0) {
@@ -605,14 +517,13 @@ int mei_irq_write_handler(struct mei_device *dev, struct mei_cl_cb *cmpl_list)
605 } 517 }
606 518
607 if (cl == &dev->iamthif_cl) 519 if (cl == &dev->iamthif_cl)
608 ret = mei_amthif_irq_write_complete(dev, &slots, 520 ret = mei_amthif_irq_write_complete(cl, cb,
609 pos, cmpl_list); 521 &slots, cmpl_list);
610 else 522 else
611 ret = mei_irq_thread_write_complete(dev, &slots, pos, 523 ret = mei_cl_irq_write_complete(cl, cb,
612 cmpl_list); 524 &slots, cmpl_list);
613 if (ret) 525 if (ret)
614 return ret; 526 return ret;
615
616 } 527 }
617 return 0; 528 return 0;
618} 529}