Lines Matching +full:autosuspend +full:- +full:delay

1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2003-2019, Intel Corporation. All rights reserved.
9 #include <linux/delay.h>
20 * mei_me_cl_init - initialize me client
26 INIT_LIST_HEAD(&me_cl->list); in mei_me_cl_init()
27 kref_init(&me_cl->refcnt); in mei_me_cl_init()
31 * mei_me_cl_get - increases me client refcount
35 * Locking: called under "dev->device_lock" lock
41 if (me_cl && kref_get_unless_zero(&me_cl->refcnt)) in mei_me_cl_get()
48 * mei_me_cl_release - free me client
50 * Locking: called under "dev->device_lock" lock
63 * mei_me_cl_put - decrease me client refcount and free client if necessary
65 * Locking: called under "dev->device_lock" lock
72 kref_put(&me_cl->refcnt, mei_me_cl_release); in mei_me_cl_put()
76 * __mei_me_cl_del - delete me client from the list and decrease
82 * Locking: dev->me_clients_rwsem
89 list_del_init(&me_cl->list); in __mei_me_cl_del()
94 * mei_me_cl_del - delete me client from the list and decrease
102 down_write(&dev->me_clients_rwsem); in mei_me_cl_del()
104 up_write(&dev->me_clients_rwsem); in mei_me_cl_del()
108 * mei_me_cl_add - add me client to the list
115 down_write(&dev->me_clients_rwsem); in mei_me_cl_add()
116 list_add(&me_cl->list, &dev->me_clients); in mei_me_cl_add()
117 up_write(&dev->me_clients_rwsem); in mei_me_cl_add()
121 * __mei_me_cl_by_uuid - locate me client by uuid
129 * Locking: dev->me_clients_rwsem
137 WARN_ON(!rwsem_is_locked(&dev->me_clients_rwsem)); in __mei_me_cl_by_uuid()
139 list_for_each_entry(me_cl, &dev->me_clients, list) { in __mei_me_cl_by_uuid()
140 pn = &me_cl->props.protocol_name; in __mei_me_cl_by_uuid()
149 * mei_me_cl_by_uuid - locate me client by uuid
157 * Locking: dev->me_clients_rwsem
164 down_read(&dev->me_clients_rwsem); in mei_me_cl_by_uuid()
166 up_read(&dev->me_clients_rwsem); in mei_me_cl_by_uuid()
172 * mei_me_cl_by_id - locate me client by client id
180 * Locking: dev->me_clients_rwsem
187 down_read(&dev->me_clients_rwsem); in mei_me_cl_by_id()
188 list_for_each_entry(__me_cl, &dev->me_clients, list) { in mei_me_cl_by_id()
189 if (__me_cl->client_id == client_id) { in mei_me_cl_by_id()
194 up_read(&dev->me_clients_rwsem); in mei_me_cl_by_id()
200 * __mei_me_cl_by_uuid_id - locate me client by client id and uuid
209 * Locking: dev->me_clients_rwsem
217 WARN_ON(!rwsem_is_locked(&dev->me_clients_rwsem)); in __mei_me_cl_by_uuid_id()
219 list_for_each_entry(me_cl, &dev->me_clients, list) { in __mei_me_cl_by_uuid_id()
220 pn = &me_cl->props.protocol_name; in __mei_me_cl_by_uuid_id()
222 me_cl->client_id == client_id) in __mei_me_cl_by_uuid_id()
231 * mei_me_cl_by_uuid_id - locate me client by client id and uuid
245 down_read(&dev->me_clients_rwsem); in mei_me_cl_by_uuid_id()
247 up_read(&dev->me_clients_rwsem); in mei_me_cl_by_uuid_id()
253 * mei_me_cl_rm_by_uuid - remove all me clients matching uuid
258 * Locking: called under "dev->device_lock" lock
264 dev_dbg(dev->dev, "remove %pUl\n", uuid); in mei_me_cl_rm_by_uuid()
266 down_write(&dev->me_clients_rwsem); in mei_me_cl_rm_by_uuid()
269 up_write(&dev->me_clients_rwsem); in mei_me_cl_rm_by_uuid()
273 * mei_me_cl_rm_by_uuid_id - remove all me clients matching client id
279 * Locking: called under "dev->device_lock" lock
285 dev_dbg(dev->dev, "remove %pUl %d\n", uuid, id); in mei_me_cl_rm_by_uuid_id()
287 down_write(&dev->me_clients_rwsem); in mei_me_cl_rm_by_uuid_id()
290 up_write(&dev->me_clients_rwsem); in mei_me_cl_rm_by_uuid_id()
294 * mei_me_cl_rm_all - remove all me clients
298 * Locking: called under "dev->device_lock" lock
304 down_write(&dev->me_clients_rwsem); in mei_me_cl_rm_all()
305 list_for_each_entry_safe(me_cl, next, &dev->me_clients, list) in mei_me_cl_rm_all()
307 up_write(&dev->me_clients_rwsem); in mei_me_cl_rm_all()
311 * mei_io_cb_free - free mei_cb_private related memory
320 list_del(&cb->list); in mei_io_cb_free()
321 kfree(cb->buf.data); in mei_io_cb_free()
326 * mei_tx_cb_queue - queue tx callback
328 * Locking: called under "dev->device_lock" lock
336 list_add_tail(&cb->list, head); in mei_tx_cb_enqueue()
337 cb->cl->tx_cb_queued++; in mei_tx_cb_enqueue()
341 * mei_tx_cb_dequeue - dequeue tx callback
343 * Locking: called under "dev->device_lock" lock
349 if (!WARN_ON(cb->cl->tx_cb_queued == 0)) in mei_tx_cb_dequeue()
350 cb->cl->tx_cb_queued--; in mei_tx_cb_dequeue()
356 * mei_io_cb_init - allocate and initialize io callback
374 INIT_LIST_HEAD(&cb->list); in mei_io_cb_init()
375 cb->fp = fp; in mei_io_cb_init()
376 cb->cl = cl; in mei_io_cb_init()
377 cb->buf_idx = 0; in mei_io_cb_init()
378 cb->fop_type = type; in mei_io_cb_init()
383 * mei_io_list_flush_cl - removes cbs belonging to the cl.
394 if (cl == cb->cl) { in mei_io_list_flush_cl()
395 list_del_init(&cb->list); in mei_io_list_flush_cl()
396 if (cb->fop_type == MEI_FOP_READ) in mei_io_list_flush_cl()
403 * mei_io_tx_list_free_cl - removes cb belonging to the cl and free them
414 if (cl == cb->cl) in mei_io_tx_list_free_cl()
420 * mei_io_list_free_fp - free cb from a list that matches file pointer
430 if (!fp || fp == cb->fp) in mei_io_list_free_fp()
435 * mei_cl_alloc_cb - a convenient wrapper for allocating read cb
457 cb->buf.data = kmalloc(roundup(length, MEI_SLOT_SIZE), GFP_KERNEL); in mei_cl_alloc_cb()
458 if (!cb->buf.data) { in mei_cl_alloc_cb()
462 cb->buf.size = length; in mei_cl_alloc_cb()
468 * mei_cl_enqueue_ctrl_wr_cb - a convenient wrapper for allocating
477 * Locking: called under "dev->device_lock" lock
493 list_add_tail(&cb->list, &cl->dev->ctrl_wr_list); in mei_cl_enqueue_ctrl_wr_cb()
498 * mei_cl_read_cb - find this cl's callback in the read list
510 list_for_each_entry(cb, &cl->rd_completed, list) in mei_cl_read_cb()
511 if (!fp || fp == cb->fp) in mei_cl_read_cb()
518 * mei_cl_flush_queues - flushes queue lists belonging to cl.
523 * Return: 0 on success, -EINVAL if cl or cl->dev is NULL.
529 if (WARN_ON(!cl || !cl->dev)) in mei_cl_flush_queues()
530 return -EINVAL; in mei_cl_flush_queues()
532 dev = cl->dev; in mei_cl_flush_queues()
535 mei_io_tx_list_free_cl(&cl->dev->write_list, cl); in mei_cl_flush_queues()
536 mei_io_tx_list_free_cl(&cl->dev->write_waiting_list, cl); in mei_cl_flush_queues()
537 mei_io_list_flush_cl(&cl->dev->ctrl_wr_list, cl); in mei_cl_flush_queues()
538 mei_io_list_flush_cl(&cl->dev->ctrl_rd_list, cl); in mei_cl_flush_queues()
539 mei_io_list_free_fp(&cl->rd_pending, fp); in mei_cl_flush_queues()
540 mei_io_list_free_fp(&cl->rd_completed, fp); in mei_cl_flush_queues()
546 * mei_cl_init - initializes cl.
554 init_waitqueue_head(&cl->wait); in mei_cl_init()
555 init_waitqueue_head(&cl->rx_wait); in mei_cl_init()
556 init_waitqueue_head(&cl->tx_wait); in mei_cl_init()
557 init_waitqueue_head(&cl->ev_wait); in mei_cl_init()
558 INIT_LIST_HEAD(&cl->rd_completed); in mei_cl_init()
559 INIT_LIST_HEAD(&cl->rd_pending); in mei_cl_init()
560 INIT_LIST_HEAD(&cl->link); in mei_cl_init()
561 cl->writing_state = MEI_IDLE; in mei_cl_init()
562 cl->state = MEI_FILE_UNINITIALIZED; in mei_cl_init()
563 cl->dev = dev; in mei_cl_init()
567 * mei_cl_allocate - allocates cl structure and sets it up.
586 * mei_cl_link - allocate host id in the host map
591 * -EINVAL on incorrect values
592 * -EMFILE if open count exceeded.
599 if (WARN_ON(!cl || !cl->dev)) in mei_cl_link()
600 return -EINVAL; in mei_cl_link()
602 dev = cl->dev; in mei_cl_link()
604 id = find_first_zero_bit(dev->host_clients_map, MEI_CLIENTS_MAX); in mei_cl_link()
606 dev_err(dev->dev, "id exceeded %d", MEI_CLIENTS_MAX); in mei_cl_link()
607 return -EMFILE; in mei_cl_link()
610 if (dev->open_handle_count >= MEI_MAX_OPEN_HANDLE_COUNT) { in mei_cl_link()
611 dev_err(dev->dev, "open_handle_count exceeded %d", in mei_cl_link()
613 return -EMFILE; in mei_cl_link()
616 dev->open_handle_count++; in mei_cl_link()
618 cl->host_client_id = id; in mei_cl_link()
619 list_add_tail(&cl->link, &dev->file_list); in mei_cl_link()
621 set_bit(id, dev->host_clients_map); in mei_cl_link()
623 cl->state = MEI_FILE_INITIALIZING; in mei_cl_link()
630 * mei_cl_unlink - remove host client from the list
644 if (WARN_ON(!cl->dev)) in mei_cl_unlink()
647 dev = cl->dev; in mei_cl_unlink()
651 if (dev->open_handle_count > 0) in mei_cl_unlink()
652 dev->open_handle_count--; in mei_cl_unlink()
655 if (cl->host_client_id) in mei_cl_unlink()
656 clear_bit(cl->host_client_id, dev->host_clients_map); in mei_cl_unlink()
658 list_del_init(&cl->link); in mei_cl_unlink()
660 cl->state = MEI_FILE_UNINITIALIZED; in mei_cl_unlink()
661 cl->writing_state = MEI_IDLE; in mei_cl_unlink()
663 WARN_ON(!list_empty(&cl->rd_completed) || in mei_cl_unlink()
664 !list_empty(&cl->rd_pending) || in mei_cl_unlink()
665 !list_empty(&cl->link)); in mei_cl_unlink()
673 dev->reset_count = 0; in mei_host_client_init()
675 schedule_work(&dev->bus_rescan_work); in mei_host_client_init()
677 pm_runtime_mark_last_busy(dev->dev); in mei_host_client_init()
678 dev_dbg(dev->dev, "rpm: autosuspend\n"); in mei_host_client_init()
679 pm_request_autosuspend(dev->dev); in mei_host_client_init()
683 * mei_hbuf_acquire - try to acquire host buffer
692 dev_dbg(dev->dev, "device is in pg\n"); in mei_hbuf_acquire()
696 if (!dev->hbuf_is_ready) { in mei_hbuf_acquire()
697 dev_dbg(dev->dev, "hbuf is not ready\n"); in mei_hbuf_acquire()
701 dev->hbuf_is_ready = false; in mei_hbuf_acquire()
707 * mei_cl_wake_all - wake up readers, writers and event waiters so
714 struct mei_device *dev = cl->dev; in mei_cl_wake_all()
717 if (waitqueue_active(&cl->rx_wait)) { in mei_cl_wake_all()
719 wake_up_interruptible(&cl->rx_wait); in mei_cl_wake_all()
722 if (waitqueue_active(&cl->tx_wait)) { in mei_cl_wake_all()
724 wake_up_interruptible(&cl->tx_wait); in mei_cl_wake_all()
727 if (waitqueue_active(&cl->ev_wait)) { in mei_cl_wake_all()
729 wake_up_interruptible(&cl->ev_wait); in mei_cl_wake_all()
732 if (waitqueue_active(&cl->wait)) { in mei_cl_wake_all()
734 wake_up(&cl->wait); in mei_cl_wake_all()
739 * mei_cl_set_disconnected - set disconnected state and clear
746 struct mei_device *dev = cl->dev; in mei_cl_set_disconnected()
748 if (cl->state == MEI_FILE_DISCONNECTED || in mei_cl_set_disconnected()
749 cl->state <= MEI_FILE_INITIALIZING) in mei_cl_set_disconnected()
752 cl->state = MEI_FILE_DISCONNECTED; in mei_cl_set_disconnected()
753 mei_io_tx_list_free_cl(&dev->write_list, cl); in mei_cl_set_disconnected()
754 mei_io_tx_list_free_cl(&dev->write_waiting_list, cl); in mei_cl_set_disconnected()
755 mei_io_list_flush_cl(&dev->ctrl_rd_list, cl); in mei_cl_set_disconnected()
756 mei_io_list_flush_cl(&dev->ctrl_wr_list, cl); in mei_cl_set_disconnected()
758 cl->rx_flow_ctrl_creds = 0; in mei_cl_set_disconnected()
759 cl->tx_flow_ctrl_creds = 0; in mei_cl_set_disconnected()
760 cl->timer_count = 0; in mei_cl_set_disconnected()
762 if (!cl->me_cl) in mei_cl_set_disconnected()
765 if (!WARN_ON(cl->me_cl->connect_count == 0)) in mei_cl_set_disconnected()
766 cl->me_cl->connect_count--; in mei_cl_set_disconnected()
768 if (cl->me_cl->connect_count == 0) in mei_cl_set_disconnected()
769 cl->me_cl->tx_flow_ctrl_creds = 0; in mei_cl_set_disconnected()
771 mei_me_cl_put(cl->me_cl); in mei_cl_set_disconnected()
772 cl->me_cl = NULL; in mei_cl_set_disconnected()
778 return -ENOENT; in mei_cl_set_connecting()
781 if (me_cl->props.fixed_address) { in mei_cl_set_connecting()
782 if (me_cl->connect_count) { in mei_cl_set_connecting()
784 return -EBUSY; in mei_cl_set_connecting()
788 cl->me_cl = me_cl; in mei_cl_set_connecting()
789 cl->state = MEI_FILE_CONNECTING; in mei_cl_set_connecting()
790 cl->me_cl->connect_count++; in mei_cl_set_connecting()
796 * mei_cl_send_disconnect - send disconnect request
808 dev = cl->dev; in mei_cl_send_disconnect()
811 cl->status = ret; in mei_cl_send_disconnect()
813 cl->state = MEI_FILE_DISCONNECT_REPLY; in mei_cl_send_disconnect()
817 list_move_tail(&cb->list, &dev->ctrl_rd_list); in mei_cl_send_disconnect()
818 cl->timer_count = MEI_CONNECT_TIMEOUT; in mei_cl_send_disconnect()
825 * mei_cl_irq_disconnect - processes close related operation from
826 * interrupt thread context - send disconnect request
837 struct mei_device *dev = cl->dev; in mei_cl_irq_disconnect()
845 return -EOVERFLOW; in mei_cl_irq_disconnect()
848 return -EMSGSIZE; in mei_cl_irq_disconnect()
852 list_move_tail(&cb->list, cmpl_list); in mei_cl_irq_disconnect()
858 * __mei_cl_disconnect - disconnect host client from the me one
871 dev = cl->dev; in __mei_cl_disconnect()
873 cl->state = MEI_FILE_DISCONNECTING; in __mei_cl_disconnect()
877 rets = -ENOMEM; in __mei_cl_disconnect()
889 mutex_unlock(&dev->device_lock); in __mei_cl_disconnect()
890 wait_event_timeout(cl->wait, in __mei_cl_disconnect()
891 cl->state == MEI_FILE_DISCONNECT_REPLY || in __mei_cl_disconnect()
892 cl->state == MEI_FILE_DISCONNECTED, in __mei_cl_disconnect()
894 mutex_lock(&dev->device_lock); in __mei_cl_disconnect()
896 rets = cl->status; in __mei_cl_disconnect()
897 if (cl->state != MEI_FILE_DISCONNECT_REPLY && in __mei_cl_disconnect()
898 cl->state != MEI_FILE_DISCONNECTED) { in __mei_cl_disconnect()
900 rets = -ETIME; in __mei_cl_disconnect()
914 * mei_cl_disconnect - disconnect host client from the me one
918 * Locking: called under "dev->device_lock" lock
927 if (WARN_ON(!cl || !cl->dev)) in mei_cl_disconnect()
928 return -ENODEV; in mei_cl_disconnect()
930 dev = cl->dev; in mei_cl_disconnect()
942 if (dev->dev_state == MEI_DEV_POWER_DOWN) { in mei_cl_disconnect()
948 rets = pm_runtime_get(dev->dev); in mei_cl_disconnect()
949 if (rets < 0 && rets != -EINPROGRESS) { in mei_cl_disconnect()
950 pm_runtime_put_noidle(dev->dev); in mei_cl_disconnect()
957 cl_dbg(dev, cl, "rpm: autosuspend\n"); in mei_cl_disconnect()
958 pm_runtime_mark_last_busy(dev->dev); in mei_cl_disconnect()
959 pm_runtime_put_autosuspend(dev->dev); in mei_cl_disconnect()
966 * mei_cl_is_other_connecting - checks if other
971 * Return: true if other client is connected, false - otherwise.
978 dev = cl->dev; in mei_cl_is_other_connecting()
980 list_for_each_entry(cb, &dev->ctrl_rd_list, list) { in mei_cl_is_other_connecting()
981 if (cb->fop_type == MEI_FOP_CONNECT && in mei_cl_is_other_connecting()
982 mei_cl_me_id(cl) == mei_cl_me_id(cb->cl)) in mei_cl_is_other_connecting()
990 * mei_cl_send_connect - send connect request
1002 dev = cl->dev; in mei_cl_send_connect()
1005 cl->status = ret; in mei_cl_send_connect()
1007 cl->state = MEI_FILE_DISCONNECT_REPLY; in mei_cl_send_connect()
1011 list_move_tail(&cb->list, &dev->ctrl_rd_list); in mei_cl_send_connect()
1012 cl->timer_count = MEI_CONNECT_TIMEOUT; in mei_cl_send_connect()
1018 * mei_cl_irq_connect - send connect request in irq_thread context
1029 struct mei_device *dev = cl->dev; in mei_cl_irq_connect()
1040 return -EOVERFLOW; in mei_cl_irq_connect()
1043 return -EMSGSIZE; in mei_cl_irq_connect()
1047 list_move_tail(&cb->list, cmpl_list); in mei_cl_irq_connect()
1053 * mei_cl_connect - connect host client to the me one
1059 * Locking: called under "dev->device_lock" lock
1070 if (WARN_ON(!cl || !cl->dev || !me_cl)) in mei_cl_connect()
1071 return -ENODEV; in mei_cl_connect()
1073 dev = cl->dev; in mei_cl_connect()
1080 cl->state = MEI_FILE_CONNECTED; in mei_cl_connect()
1085 rets = pm_runtime_get(dev->dev); in mei_cl_connect()
1086 if (rets < 0 && rets != -EINPROGRESS) { in mei_cl_connect()
1087 pm_runtime_put_noidle(dev->dev); in mei_cl_connect()
1094 rets = -ENOMEM; in mei_cl_connect()
1105 mutex_unlock(&dev->device_lock); in mei_cl_connect()
1106 wait_event_timeout(cl->wait, in mei_cl_connect()
1107 (cl->state == MEI_FILE_CONNECTED || in mei_cl_connect()
1108 cl->state == MEI_FILE_DISCONNECTED || in mei_cl_connect()
1109 cl->state == MEI_FILE_DISCONNECT_REQUIRED || in mei_cl_connect()
1110 cl->state == MEI_FILE_DISCONNECT_REPLY), in mei_cl_connect()
1112 mutex_lock(&dev->device_lock); in mei_cl_connect()
1115 if (cl->state == MEI_FILE_DISCONNECT_REQUIRED) { in mei_cl_connect()
1116 mei_io_list_flush_cl(&dev->ctrl_rd_list, cl); in mei_cl_connect()
1117 mei_io_list_flush_cl(&dev->ctrl_wr_list, cl); in mei_cl_connect()
1122 rets = -EFAULT; in mei_cl_connect()
1127 if (!cl->status) in mei_cl_connect()
1128 cl->status = -EFAULT; in mei_cl_connect()
1131 rets = cl->status; in mei_cl_connect()
1133 cl_dbg(dev, cl, "rpm: autosuspend\n"); in mei_cl_connect()
1134 pm_runtime_mark_last_busy(dev->dev); in mei_cl_connect()
1135 pm_runtime_put_autosuspend(dev->dev); in mei_cl_connect()
1147 * mei_cl_alloc_linked - allocate and link host client
1160 ret = -ENOMEM; in mei_cl_alloc_linked()
1175 * mei_cl_tx_flow_ctrl_creds - checks flow_control credits for cl.
1179 * Return: 1 if tx_flow_ctrl_creds >0, 0 - otherwise.
1183 if (WARN_ON(!cl || !cl->me_cl)) in mei_cl_tx_flow_ctrl_creds()
1184 return -EINVAL; in mei_cl_tx_flow_ctrl_creds()
1186 if (cl->tx_flow_ctrl_creds > 0) in mei_cl_tx_flow_ctrl_creds()
1193 if (cl->me_cl->tx_flow_ctrl_creds > 0) in mei_cl_tx_flow_ctrl_creds()
1200 * mei_cl_tx_flow_ctrl_creds_reduce - reduces transmit flow control credits
1207 * -EINVAL when ctrl credits are <= 0
1211 if (WARN_ON(!cl || !cl->me_cl)) in mei_cl_tx_flow_ctrl_creds_reduce()
1212 return -EINVAL; in mei_cl_tx_flow_ctrl_creds_reduce()
1218 if (WARN_ON(cl->me_cl->tx_flow_ctrl_creds <= 0)) in mei_cl_tx_flow_ctrl_creds_reduce()
1219 return -EINVAL; in mei_cl_tx_flow_ctrl_creds_reduce()
1220 cl->me_cl->tx_flow_ctrl_creds--; in mei_cl_tx_flow_ctrl_creds_reduce()
1222 if (WARN_ON(cl->tx_flow_ctrl_creds <= 0)) in mei_cl_tx_flow_ctrl_creds_reduce()
1223 return -EINVAL; in mei_cl_tx_flow_ctrl_creds_reduce()
1224 cl->tx_flow_ctrl_creds--; in mei_cl_tx_flow_ctrl_creds_reduce()
1230 * mei_cl_notify_fop2req - convert fop to proper request
1245 * mei_cl_notify_req2fop - convert notification request top file operation type
1260 * mei_cl_irq_notify - send notification request in irq_thread context
1271 struct mei_device *dev = cl->dev; in mei_cl_irq_notify()
1280 return -EOVERFLOW; in mei_cl_irq_notify()
1283 return -EMSGSIZE; in mei_cl_irq_notify()
1285 request = mei_cl_notify_fop2req(cb->fop_type); in mei_cl_irq_notify()
1288 cl->status = ret; in mei_cl_irq_notify()
1289 list_move_tail(&cb->list, cmpl_list); in mei_cl_irq_notify()
1293 list_move_tail(&cb->list, &dev->ctrl_rd_list); in mei_cl_irq_notify()
1298 * mei_cl_notify_request - send notification stop/start request
1304 * Locking: called under "dev->device_lock" lock
1316 if (WARN_ON(!cl || !cl->dev)) in mei_cl_notify_request()
1317 return -ENODEV; in mei_cl_notify_request()
1319 dev = cl->dev; in mei_cl_notify_request()
1321 if (!dev->hbm_f_ev_supported) { in mei_cl_notify_request()
1323 return -EOPNOTSUPP; in mei_cl_notify_request()
1327 return -ENODEV; in mei_cl_notify_request()
1329 rets = pm_runtime_get(dev->dev); in mei_cl_notify_request()
1330 if (rets < 0 && rets != -EINPROGRESS) { in mei_cl_notify_request()
1331 pm_runtime_put_noidle(dev->dev); in mei_cl_notify_request()
1339 rets = -ENOMEM; in mei_cl_notify_request()
1345 rets = -ENODEV; in mei_cl_notify_request()
1348 list_move_tail(&cb->list, &dev->ctrl_rd_list); in mei_cl_notify_request()
1351 mutex_unlock(&dev->device_lock); in mei_cl_notify_request()
1352 wait_event_timeout(cl->wait, in mei_cl_notify_request()
1353 cl->notify_en == request || in mei_cl_notify_request()
1354 cl->status || in mei_cl_notify_request()
1357 mutex_lock(&dev->device_lock); in mei_cl_notify_request()
1359 if (cl->notify_en != request && !cl->status) in mei_cl_notify_request()
1360 cl->status = -EFAULT; in mei_cl_notify_request()
1362 rets = cl->status; in mei_cl_notify_request()
1365 cl_dbg(dev, cl, "rpm: autosuspend\n"); in mei_cl_notify_request()
1366 pm_runtime_mark_last_busy(dev->dev); in mei_cl_notify_request()
1367 pm_runtime_put_autosuspend(dev->dev); in mei_cl_notify_request()
1374 * mei_cl_notify - raise notification
1378 * Locking: called under "dev->device_lock" lock
1384 if (!cl || !cl->dev) in mei_cl_notify()
1387 dev = cl->dev; in mei_cl_notify()
1389 if (!cl->notify_en) in mei_cl_notify()
1393 cl->notify_ev = true; in mei_cl_notify()
1395 wake_up_interruptible(&cl->ev_wait); in mei_cl_notify()
1397 if (cl->ev_async) in mei_cl_notify()
1398 kill_fasync(&cl->ev_async, SIGIO, POLL_PRI); in mei_cl_notify()
1403 * mei_cl_notify_get - get or wait for notification event
1409 * Locking: called under "dev->device_lock" lock
1420 if (WARN_ON(!cl || !cl->dev)) in mei_cl_notify_get()
1421 return -ENODEV; in mei_cl_notify_get()
1423 dev = cl->dev; in mei_cl_notify_get()
1425 if (!dev->hbm_f_ev_supported) { in mei_cl_notify_get()
1427 return -EOPNOTSUPP; in mei_cl_notify_get()
1431 return -ENODEV; in mei_cl_notify_get()
1433 if (cl->notify_ev) in mei_cl_notify_get()
1437 return -EAGAIN; in mei_cl_notify_get()
1439 mutex_unlock(&dev->device_lock); in mei_cl_notify_get()
1440 rets = wait_event_interruptible(cl->ev_wait, cl->notify_ev); in mei_cl_notify_get()
1441 mutex_lock(&dev->device_lock); in mei_cl_notify_get()
1447 *notify_ev = cl->notify_ev; in mei_cl_notify_get()
1448 cl->notify_ev = false; in mei_cl_notify_get()
1453 * mei_cl_read_start - the start read client message function.
1467 if (WARN_ON(!cl || !cl->dev)) in mei_cl_read_start()
1468 return -ENODEV; in mei_cl_read_start()
1470 dev = cl->dev; in mei_cl_read_start()
1473 return -ENODEV; in mei_cl_read_start()
1475 if (!mei_me_cl_is_active(cl->me_cl)) { in mei_cl_read_start()
1477 return -ENOTTY; in mei_cl_read_start()
1484 if (cl->rx_flow_ctrl_creds) in mei_cl_read_start()
1485 return -EBUSY; in mei_cl_read_start()
1489 return -ENOMEM; in mei_cl_read_start()
1491 rets = pm_runtime_get(dev->dev); in mei_cl_read_start()
1492 if (rets < 0 && rets != -EINPROGRESS) { in mei_cl_read_start()
1493 pm_runtime_put_noidle(dev->dev); in mei_cl_read_start()
1504 list_move_tail(&cb->list, &cl->rd_pending); in mei_cl_read_start()
1506 cl->rx_flow_ctrl_creds++; in mei_cl_read_start()
1509 cl_dbg(dev, cl, "rpm: autosuspend\n"); in mei_cl_read_start()
1510 pm_runtime_mark_last_busy(dev->dev); in mei_cl_read_start()
1511 pm_runtime_put_autosuspend(dev->dev); in mei_cl_read_start()
1520 * mei_msg_hdr_init - initialize mei message header
1527 mei_hdr->host_addr = mei_cl_host_addr(cb->cl); in mei_msg_hdr_init()
1528 mei_hdr->me_addr = mei_cl_me_id(cb->cl); in mei_msg_hdr_init()
1529 mei_hdr->length = 0; in mei_msg_hdr_init()
1530 mei_hdr->reserved = 0; in mei_msg_hdr_init()
1531 mei_hdr->msg_complete = 0; in mei_msg_hdr_init()
1532 mei_hdr->dma_ring = 0; in mei_msg_hdr_init()
1533 mei_hdr->internal = cb->internal; in mei_msg_hdr_init()
1537 * mei_cl_irq_write - write a message to device
1562 if (WARN_ON(!cl || !cl->dev)) in mei_cl_irq_write()
1563 return -ENODEV; in mei_cl_irq_write()
1565 dev = cl->dev; in mei_cl_irq_write()
1567 buf = &cb->buf; in mei_cl_irq_write()
1569 first_chunk = cb->buf_idx == 0; in mei_cl_irq_write()
1580 len = buf->size - cb->buf_idx; in mei_cl_irq_write()
1581 data = buf->data + cb->buf_idx; in mei_cl_irq_write()
1584 rets = -EOVERFLOW; in mei_cl_irq_write()
1612 len = hbuf_len - hdr_len; in mei_cl_irq_write()
1619 mei_dma_ring_write(dev, buf->data + cb->buf_idx, len); in mei_cl_irq_write()
1625 cl->status = 0; in mei_cl_irq_write()
1626 cl->writing_state = MEI_WRITING; in mei_cl_irq_write()
1627 cb->buf_idx += len; in mei_cl_irq_write()
1631 rets = -EIO; in mei_cl_irq_write()
1637 list_move_tail(&cb->list, &dev->write_waiting_list); in mei_cl_irq_write()
1642 cl->status = rets; in mei_cl_irq_write()
1643 list_move_tail(&cb->list, cmpl_list); in mei_cl_irq_write()
1648 * mei_cl_write - submit a write cb to mei device
1670 if (WARN_ON(!cl || !cl->dev)) in mei_cl_write()
1671 return -ENODEV; in mei_cl_write()
1674 return -EINVAL; in mei_cl_write()
1676 dev = cl->dev; in mei_cl_write()
1678 buf = &cb->buf; in mei_cl_write()
1679 len = buf->size; in mei_cl_write()
1683 blocking = cb->blocking; in mei_cl_write()
1684 data = buf->data; in mei_cl_write()
1686 rets = pm_runtime_get(dev->dev); in mei_cl_write()
1687 if (rets < 0 && rets != -EINPROGRESS) { in mei_cl_write()
1688 pm_runtime_put_noidle(dev->dev); in mei_cl_write()
1693 cb->buf_idx = 0; in mei_cl_write()
1694 cl->writing_state = MEI_IDLE; in mei_cl_write()
1717 rets = -EOVERFLOW; in mei_cl_write()
1739 len = hbuf_len - hdr_len; in mei_cl_write()
1744 mei_dma_ring_write(dev, buf->data, len); in mei_cl_write()
1755 cl->writing_state = MEI_WRITING; in mei_cl_write()
1756 cb->buf_idx = len; in mei_cl_write()
1758 len = buf->size; in mei_cl_write()
1762 mei_tx_cb_enqueue(cb, &dev->write_waiting_list); in mei_cl_write()
1764 mei_tx_cb_enqueue(cb, &dev->write_list); in mei_cl_write()
1767 if (blocking && cl->writing_state != MEI_WRITE_COMPLETE) { in mei_cl_write()
1769 mutex_unlock(&dev->device_lock); in mei_cl_write()
1770 rets = wait_event_interruptible(cl->tx_wait, in mei_cl_write()
1771 cl->writing_state == MEI_WRITE_COMPLETE || in mei_cl_write()
1773 mutex_lock(&dev->device_lock); in mei_cl_write()
1774 /* wait_event_interruptible returns -ERESTARTSYS */ in mei_cl_write()
1777 rets = -EINTR; in mei_cl_write()
1780 if (cl->writing_state != MEI_WRITE_COMPLETE) { in mei_cl_write()
1781 rets = -EFAULT; in mei_cl_write()
1788 cl_dbg(dev, cl, "rpm: autosuspend\n"); in mei_cl_write()
1789 pm_runtime_mark_last_busy(dev->dev); in mei_cl_write()
1790 pm_runtime_put_autosuspend(dev->dev); in mei_cl_write()
1799 * mei_cl_complete - processes completed operation for a client
1806 struct mei_device *dev = cl->dev; in mei_cl_complete()
1808 switch (cb->fop_type) { in mei_cl_complete()
1811 cl->writing_state = MEI_WRITE_COMPLETE; in mei_cl_complete()
1812 if (waitqueue_active(&cl->tx_wait)) { in mei_cl_complete()
1813 wake_up_interruptible(&cl->tx_wait); in mei_cl_complete()
1815 pm_runtime_mark_last_busy(dev->dev); in mei_cl_complete()
1816 pm_request_autosuspend(dev->dev); in mei_cl_complete()
1821 list_add_tail(&cb->list, &cl->rd_completed); in mei_cl_complete()
1823 !WARN_ON(!cl->rx_flow_ctrl_creds)) in mei_cl_complete()
1824 cl->rx_flow_ctrl_creds--; in mei_cl_complete()
1826 wake_up_interruptible(&cl->rx_wait); in mei_cl_complete()
1833 if (waitqueue_active(&cl->wait)) in mei_cl_complete()
1834 wake_up(&cl->wait); in mei_cl_complete()
1848 * mei_cl_all_disconnect - disconnect forcefully all connected clients
1856 list_for_each_entry(cl, &dev->file_list, link) in mei_cl_all_disconnect()