aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc/mei/client.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/misc/mei/client.c')
-rw-r--r--drivers/misc/mei/client.c145
1 files changed, 77 insertions, 68 deletions
diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c
index b0395601c6ae..68fe37b5bc52 100644
--- a/drivers/misc/mei/client.c
+++ b/drivers/misc/mei/client.c
@@ -377,19 +377,19 @@ static struct mei_cl_cb *mei_io_cb_init(struct mei_cl *cl,
377} 377}
378 378
379/** 379/**
380 * __mei_io_list_flush - removes and frees cbs belonging to cl. 380 * __mei_io_list_flush_cl - removes and frees cbs belonging to cl.
381 * 381 *
382 * @list: an instance of our list structure 382 * @head: an instance of our list structure
383 * @cl: host client, can be NULL for flushing the whole list 383 * @cl: host client, can be NULL for flushing the whole list
384 * @free: whether to free the cbs 384 * @free: whether to free the cbs
385 */ 385 */
386static void __mei_io_list_flush(struct mei_cl_cb *list, 386static void __mei_io_list_flush_cl(struct list_head *head,
387 struct mei_cl *cl, bool free) 387 const struct mei_cl *cl, bool free)
388{ 388{
389 struct mei_cl_cb *cb, *next; 389 struct mei_cl_cb *cb, *next;
390 390
391 /* enable removing everything if no cl is specified */ 391 /* enable removing everything if no cl is specified */
392 list_for_each_entry_safe(cb, next, &list->list, list) { 392 list_for_each_entry_safe(cb, next, head, list) {
393 if (!cl || mei_cl_cmp_id(cl, cb->cl)) { 393 if (!cl || mei_cl_cmp_id(cl, cb->cl)) {
394 list_del_init(&cb->list); 394 list_del_init(&cb->list);
395 if (free) 395 if (free)
@@ -399,25 +399,42 @@ static void __mei_io_list_flush(struct mei_cl_cb *list,
399} 399}
400 400
401/** 401/**
402 * mei_io_list_flush - removes list entry belonging to cl. 402 * mei_io_list_flush_cl - removes list entry belonging to cl.
403 * 403 *
404 * @list: An instance of our list structure 404 * @head: An instance of our list structure
405 * @cl: host client 405 * @cl: host client
406 */ 406 */
407void mei_io_list_flush(struct mei_cl_cb *list, struct mei_cl *cl) 407static inline void mei_io_list_flush_cl(struct list_head *head,
408 const struct mei_cl *cl)
408{ 409{
409 __mei_io_list_flush(list, cl, false); 410 __mei_io_list_flush_cl(head, cl, false);
410} 411}
411 412
412/** 413/**
413 * mei_io_list_free - removes cb belonging to cl and free them 414 * mei_io_list_free_cl - removes cb belonging to cl and free them
414 * 415 *
415 * @list: An instance of our list structure 416 * @head: An instance of our list structure
416 * @cl: host client 417 * @cl: host client
417 */ 418 */
418static inline void mei_io_list_free(struct mei_cl_cb *list, struct mei_cl *cl) 419static inline void mei_io_list_free_cl(struct list_head *head,
420 const struct mei_cl *cl)
419{ 421{
420 __mei_io_list_flush(list, cl, true); 422 __mei_io_list_flush_cl(head, cl, true);
423}
424
425/**
426 * mei_io_list_free_fp - free cb from a list that matches file pointer
427 *
428 * @head: io list
429 * @fp: file pointer (matching cb file object), may be NULL
430 */
431void mei_io_list_free_fp(struct list_head *head, const struct file *fp)
432{
433 struct mei_cl_cb *cb, *next;
434
435 list_for_each_entry_safe(cb, next, head, list)
436 if (!fp || fp == cb->fp)
437 mei_io_cb_free(cb);
421} 438}
422 439
423/** 440/**
@@ -479,7 +496,7 @@ struct mei_cl_cb *mei_cl_enqueue_ctrl_wr_cb(struct mei_cl *cl, size_t length,
479 if (!cb) 496 if (!cb)
480 return NULL; 497 return NULL;
481 498
482 list_add_tail(&cb->list, &cl->dev->ctrl_wr_list.list); 499 list_add_tail(&cb->list, &cl->dev->ctrl_wr_list);
483 return cb; 500 return cb;
484} 501}
485 502
@@ -504,27 +521,6 @@ struct mei_cl_cb *mei_cl_read_cb(const struct mei_cl *cl, const struct file *fp)
504} 521}
505 522
506/** 523/**
507 * mei_cl_read_cb_flush - free client's read pending and completed cbs
508 * for a specific file
509 *
510 * @cl: host client
511 * @fp: file pointer (matching cb file object), may be NULL
512 */
513void mei_cl_read_cb_flush(const struct mei_cl *cl, const struct file *fp)
514{
515 struct mei_cl_cb *cb, *next;
516
517 list_for_each_entry_safe(cb, next, &cl->rd_completed, list)
518 if (!fp || fp == cb->fp)
519 mei_io_cb_free(cb);
520
521
522 list_for_each_entry_safe(cb, next, &cl->rd_pending, list)
523 if (!fp || fp == cb->fp)
524 mei_io_cb_free(cb);
525}
526
527/**
528 * mei_cl_flush_queues - flushes queue lists belonging to cl. 524 * mei_cl_flush_queues - flushes queue lists belonging to cl.
529 * 525 *
530 * @cl: host client 526 * @cl: host client
@@ -542,18 +538,16 @@ int mei_cl_flush_queues(struct mei_cl *cl, const struct file *fp)
542 dev = cl->dev; 538 dev = cl->dev;
543 539
544 cl_dbg(dev, cl, "remove list entry belonging to cl\n"); 540 cl_dbg(dev, cl, "remove list entry belonging to cl\n");
545 mei_io_list_free(&cl->dev->write_list, cl); 541 mei_io_list_free_cl(&cl->dev->write_list, cl);
546 mei_io_list_free(&cl->dev->write_waiting_list, cl); 542 mei_io_list_free_cl(&cl->dev->write_waiting_list, cl);
547 mei_io_list_flush(&cl->dev->ctrl_wr_list, cl); 543 mei_io_list_flush_cl(&cl->dev->ctrl_wr_list, cl);
548 mei_io_list_flush(&cl->dev->ctrl_rd_list, cl); 544 mei_io_list_flush_cl(&cl->dev->ctrl_rd_list, cl);
549 mei_io_list_flush(&cl->dev->amthif_cmd_list, cl); 545 mei_io_list_free_fp(&cl->rd_pending, fp);
550 546 mei_io_list_free_fp(&cl->rd_completed, fp);
551 mei_cl_read_cb_flush(cl, fp);
552 547
553 return 0; 548 return 0;
554} 549}
555 550
556
557/** 551/**
558 * mei_cl_init - initializes cl. 552 * mei_cl_init - initializes cl.
559 * 553 *
@@ -756,7 +750,7 @@ static void mei_cl_wake_all(struct mei_cl *cl)
756 * 750 *
757 * @cl: host client 751 * @cl: host client
758 */ 752 */
759void mei_cl_set_disconnected(struct mei_cl *cl) 753static void mei_cl_set_disconnected(struct mei_cl *cl)
760{ 754{
761 struct mei_device *dev = cl->dev; 755 struct mei_device *dev = cl->dev;
762 756
@@ -765,15 +759,18 @@ void mei_cl_set_disconnected(struct mei_cl *cl)
765 return; 759 return;
766 760
767 cl->state = MEI_FILE_DISCONNECTED; 761 cl->state = MEI_FILE_DISCONNECTED;
768 mei_io_list_free(&dev->write_list, cl); 762 mei_io_list_free_cl(&dev->write_list, cl);
769 mei_io_list_free(&dev->write_waiting_list, cl); 763 mei_io_list_free_cl(&dev->write_waiting_list, cl);
770 mei_io_list_flush(&dev->ctrl_rd_list, cl); 764 mei_io_list_flush_cl(&dev->ctrl_rd_list, cl);
771 mei_io_list_flush(&dev->ctrl_wr_list, cl); 765 mei_io_list_flush_cl(&dev->ctrl_wr_list, cl);
766 mei_io_list_free_cl(&dev->amthif_cmd_list, cl);
772 mei_cl_wake_all(cl); 767 mei_cl_wake_all(cl);
773 cl->rx_flow_ctrl_creds = 0; 768 cl->rx_flow_ctrl_creds = 0;
774 cl->tx_flow_ctrl_creds = 0; 769 cl->tx_flow_ctrl_creds = 0;
775 cl->timer_count = 0; 770 cl->timer_count = 0;
776 771
772 mei_cl_bus_module_put(cl);
773
777 if (!cl->me_cl) 774 if (!cl->me_cl)
778 return; 775 return;
779 776
@@ -829,7 +826,7 @@ static int mei_cl_send_disconnect(struct mei_cl *cl, struct mei_cl_cb *cb)
829 return ret; 826 return ret;
830 } 827 }
831 828
832 list_move_tail(&cb->list, &dev->ctrl_rd_list.list); 829 list_move_tail(&cb->list, &dev->ctrl_rd_list);
833 cl->timer_count = MEI_CONNECT_TIMEOUT; 830 cl->timer_count = MEI_CONNECT_TIMEOUT;
834 mei_schedule_stall_timer(dev); 831 mei_schedule_stall_timer(dev);
835 832
@@ -847,7 +844,7 @@ static int mei_cl_send_disconnect(struct mei_cl *cl, struct mei_cl_cb *cb)
847 * Return: 0, OK; otherwise, error. 844 * Return: 0, OK; otherwise, error.
848 */ 845 */
849int mei_cl_irq_disconnect(struct mei_cl *cl, struct mei_cl_cb *cb, 846int mei_cl_irq_disconnect(struct mei_cl *cl, struct mei_cl_cb *cb,
850 struct mei_cl_cb *cmpl_list) 847 struct list_head *cmpl_list)
851{ 848{
852 struct mei_device *dev = cl->dev; 849 struct mei_device *dev = cl->dev;
853 u32 msg_slots; 850 u32 msg_slots;
@@ -862,7 +859,7 @@ int mei_cl_irq_disconnect(struct mei_cl *cl, struct mei_cl_cb *cb,
862 859
863 ret = mei_cl_send_disconnect(cl, cb); 860 ret = mei_cl_send_disconnect(cl, cb);
864 if (ret) 861 if (ret)
865 list_move_tail(&cb->list, &cmpl_list->list); 862 list_move_tail(&cb->list, cmpl_list);
866 863
867 return ret; 864 return ret;
868} 865}
@@ -984,7 +981,7 @@ static bool mei_cl_is_other_connecting(struct mei_cl *cl)
984 981
985 dev = cl->dev; 982 dev = cl->dev;
986 983
987 list_for_each_entry(cb, &dev->ctrl_rd_list.list, list) { 984 list_for_each_entry(cb, &dev->ctrl_rd_list, list) {
988 if (cb->fop_type == MEI_FOP_CONNECT && 985 if (cb->fop_type == MEI_FOP_CONNECT &&
989 mei_cl_me_id(cl) == mei_cl_me_id(cb->cl)) 986 mei_cl_me_id(cl) == mei_cl_me_id(cb->cl))
990 return true; 987 return true;
@@ -1015,7 +1012,7 @@ static int mei_cl_send_connect(struct mei_cl *cl, struct mei_cl_cb *cb)
1015 return ret; 1012 return ret;
1016 } 1013 }
1017 1014
1018 list_move_tail(&cb->list, &dev->ctrl_rd_list.list); 1015 list_move_tail(&cb->list, &dev->ctrl_rd_list);
1019 cl->timer_count = MEI_CONNECT_TIMEOUT; 1016 cl->timer_count = MEI_CONNECT_TIMEOUT;
1020 mei_schedule_stall_timer(dev); 1017 mei_schedule_stall_timer(dev);
1021 return 0; 1018 return 0;
@@ -1031,7 +1028,7 @@ static int mei_cl_send_connect(struct mei_cl *cl, struct mei_cl_cb *cb)
1031 * Return: 0, OK; otherwise, error. 1028 * Return: 0, OK; otherwise, error.
1032 */ 1029 */
1033int mei_cl_irq_connect(struct mei_cl *cl, struct mei_cl_cb *cb, 1030int mei_cl_irq_connect(struct mei_cl *cl, struct mei_cl_cb *cb,
1034 struct mei_cl_cb *cmpl_list) 1031 struct list_head *cmpl_list)
1035{ 1032{
1036 struct mei_device *dev = cl->dev; 1033 struct mei_device *dev = cl->dev;
1037 u32 msg_slots; 1034 u32 msg_slots;
@@ -1049,7 +1046,7 @@ int mei_cl_irq_connect(struct mei_cl *cl, struct mei_cl_cb *cb,
1049 1046
1050 rets = mei_cl_send_connect(cl, cb); 1047 rets = mei_cl_send_connect(cl, cb);
1051 if (rets) 1048 if (rets)
1052 list_move_tail(&cb->list, &cmpl_list->list); 1049 list_move_tail(&cb->list, cmpl_list);
1053 1050
1054 return rets; 1051 return rets;
1055} 1052}
@@ -1077,13 +1074,17 @@ int mei_cl_connect(struct mei_cl *cl, struct mei_me_client *me_cl,
1077 1074
1078 dev = cl->dev; 1075 dev = cl->dev;
1079 1076
1077 if (!mei_cl_bus_module_get(cl))
1078 return -ENODEV;
1079
1080 rets = mei_cl_set_connecting(cl, me_cl); 1080 rets = mei_cl_set_connecting(cl, me_cl);
1081 if (rets) 1081 if (rets)
1082 return rets; 1082 goto nortpm;
1083 1083
1084 if (mei_cl_is_fixed_address(cl)) { 1084 if (mei_cl_is_fixed_address(cl)) {
1085 cl->state = MEI_FILE_CONNECTED; 1085 cl->state = MEI_FILE_CONNECTED;
1086 return 0; 1086 rets = 0;
1087 goto nortpm;
1087 } 1088 }
1088 1089
1089 rets = pm_runtime_get(dev->dev); 1090 rets = pm_runtime_get(dev->dev);
@@ -1117,8 +1118,8 @@ int mei_cl_connect(struct mei_cl *cl, struct mei_me_client *me_cl,
1117 1118
1118 if (!mei_cl_is_connected(cl)) { 1119 if (!mei_cl_is_connected(cl)) {
1119 if (cl->state == MEI_FILE_DISCONNECT_REQUIRED) { 1120 if (cl->state == MEI_FILE_DISCONNECT_REQUIRED) {
1120 mei_io_list_flush(&dev->ctrl_rd_list, cl); 1121 mei_io_list_flush_cl(&dev->ctrl_rd_list, cl);
1121 mei_io_list_flush(&dev->ctrl_wr_list, cl); 1122 mei_io_list_flush_cl(&dev->ctrl_wr_list, cl);
1122 /* ignore disconnect return valuue; 1123 /* ignore disconnect return valuue;
1123 * in case of failure reset will be invoked 1124 * in case of failure reset will be invoked
1124 */ 1125 */
@@ -1270,7 +1271,7 @@ enum mei_cb_file_ops mei_cl_notify_req2fop(u8 req)
1270 * Return: 0 on such and error otherwise. 1271 * Return: 0 on such and error otherwise.
1271 */ 1272 */
1272int mei_cl_irq_notify(struct mei_cl *cl, struct mei_cl_cb *cb, 1273int mei_cl_irq_notify(struct mei_cl *cl, struct mei_cl_cb *cb,
1273 struct mei_cl_cb *cmpl_list) 1274 struct list_head *cmpl_list)
1274{ 1275{
1275 struct mei_device *dev = cl->dev; 1276 struct mei_device *dev = cl->dev;
1276 u32 msg_slots; 1277 u32 msg_slots;
@@ -1288,11 +1289,11 @@ int mei_cl_irq_notify(struct mei_cl *cl, struct mei_cl_cb *cb,
1288 ret = mei_hbm_cl_notify_req(dev, cl, request); 1289 ret = mei_hbm_cl_notify_req(dev, cl, request);
1289 if (ret) { 1290 if (ret) {
1290 cl->status = ret; 1291 cl->status = ret;
1291 list_move_tail(&cb->list, &cmpl_list->list); 1292 list_move_tail(&cb->list, cmpl_list);
1292 return ret; 1293 return ret;
1293 } 1294 }
1294 1295
1295 list_move_tail(&cb->list, &dev->ctrl_rd_list.list); 1296 list_move_tail(&cb->list, &dev->ctrl_rd_list);
1296 return 0; 1297 return 0;
1297} 1298}
1298 1299
@@ -1325,6 +1326,9 @@ int mei_cl_notify_request(struct mei_cl *cl,
1325 return -EOPNOTSUPP; 1326 return -EOPNOTSUPP;
1326 } 1327 }
1327 1328
1329 if (!mei_cl_is_connected(cl))
1330 return -ENODEV;
1331
1328 rets = pm_runtime_get(dev->dev); 1332 rets = pm_runtime_get(dev->dev);
1329 if (rets < 0 && rets != -EINPROGRESS) { 1333 if (rets < 0 && rets != -EINPROGRESS) {
1330 pm_runtime_put_noidle(dev->dev); 1334 pm_runtime_put_noidle(dev->dev);
@@ -1344,7 +1348,7 @@ int mei_cl_notify_request(struct mei_cl *cl,
1344 rets = -ENODEV; 1348 rets = -ENODEV;
1345 goto out; 1349 goto out;
1346 } 1350 }
1347 list_move_tail(&cb->list, &dev->ctrl_rd_list.list); 1351 list_move_tail(&cb->list, &dev->ctrl_rd_list);
1348 } 1352 }
1349 1353
1350 mutex_unlock(&dev->device_lock); 1354 mutex_unlock(&dev->device_lock);
@@ -1419,6 +1423,11 @@ int mei_cl_notify_get(struct mei_cl *cl, bool block, bool *notify_ev)
1419 1423
1420 dev = cl->dev; 1424 dev = cl->dev;
1421 1425
1426 if (!dev->hbm_f_ev_supported) {
1427 cl_dbg(dev, cl, "notifications not supported\n");
1428 return -EOPNOTSUPP;
1429 }
1430
1422 if (!mei_cl_is_connected(cl)) 1431 if (!mei_cl_is_connected(cl))
1423 return -ENODEV; 1432 return -ENODEV;
1424 1433
@@ -1519,7 +1528,7 @@ nortpm:
1519 * Return: 0, OK; otherwise error. 1528 * Return: 0, OK; otherwise error.
1520 */ 1529 */
1521int mei_cl_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb, 1530int mei_cl_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb,
1522 struct mei_cl_cb *cmpl_list) 1531 struct list_head *cmpl_list)
1523{ 1532{
1524 struct mei_device *dev; 1533 struct mei_device *dev;
1525 struct mei_msg_data *buf; 1534 struct mei_msg_data *buf;
@@ -1591,13 +1600,13 @@ int mei_cl_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb,
1591 } 1600 }
1592 1601
1593 if (mei_hdr.msg_complete) 1602 if (mei_hdr.msg_complete)
1594 list_move_tail(&cb->list, &dev->write_waiting_list.list); 1603 list_move_tail(&cb->list, &dev->write_waiting_list);
1595 1604
1596 return 0; 1605 return 0;
1597 1606
1598err: 1607err:
1599 cl->status = rets; 1608 cl->status = rets;
1600 list_move_tail(&cb->list, &cmpl_list->list); 1609 list_move_tail(&cb->list, cmpl_list);
1601 return rets; 1610 return rets;
1602} 1611}
1603 1612
@@ -1687,9 +1696,9 @@ int mei_cl_write(struct mei_cl *cl, struct mei_cl_cb *cb)
1687 1696
1688out: 1697out:
1689 if (mei_hdr.msg_complete) 1698 if (mei_hdr.msg_complete)
1690 list_add_tail(&cb->list, &dev->write_waiting_list.list); 1699 list_add_tail(&cb->list, &dev->write_waiting_list);
1691 else 1700 else
1692 list_add_tail(&cb->list, &dev->write_list.list); 1701 list_add_tail(&cb->list, &dev->write_list);
1693 1702
1694 cb = NULL; 1703 cb = NULL;
1695 if (blocking && cl->writing_state != MEI_WRITE_COMPLETE) { 1704 if (blocking && cl->writing_state != MEI_WRITE_COMPLETE) {